changed from input to textbox to keep text formatting, added daisyUI, refactored dropdown menu

This commit is contained in:
slawk0
2024-11-15 22:44:02 +01:00
parent 5ba57cefac
commit 88307104a2
6 changed files with 254 additions and 75 deletions

View File

@@ -1,12 +1,15 @@
import { sendMessage } from '../../socket/socket.tsx';
import { useForm, SubmitHandler } from 'react-hook-form';
type Input = {
message: string;
};
type MessaFormProps = {
contact: string;
};
function messageForm({ contact }: MessaFormProps) {
function MessageForm({ contact }: MessaFormProps) {
const {
register,
handleSubmit,
@@ -17,46 +20,59 @@ function messageForm({ contact }: MessaFormProps) {
// Sending message
const submitMessage: SubmitHandler<Input> = (data) => {
console.log(contact);
// block sending empty message
// Block sending empty message
if (!data.message) {
return;
}
// for (let i = 0; i <= 200; i++) {
// let ii = i.toString();
// sendMessage(ii, contact);
// }
sendMessage(data.message, contact);
sendMessage(data.message, contact);
reset({ message: '' });
};
const adjustSize = (event) => {
const textarea = event.target;
// Adjust height
textarea.style.height = 'auto';
const maxHeight = 500;
if (textarea.scrollHeight > maxHeight) {
textarea.style.height = `${maxHeight}px`;
textarea.style.overflowY = 'auto';
} else {
textarea.style.height = `${textarea.scrollHeight}px`;
textarea.style.overflowY = 'hidden';
}
};
return (
<>
<form onSubmit={handleSubmit(submitMessage)}>
<div className="flex">
<input
className=" bg-green-50 text-black rounded-md w-full ml-1 mr-1 size-10"
type="text"
autoFocus={!!contact}
disabled={!contact}
placeholder="Enter message"
{...register('message', {
maxLength: 500,
minLength: 1,
})}
/>
{errors?.message?.type === 'maxLength' && (
<p>Maximum length of the message is 500</p>
)}
<button
className="text-black bg-green-500 hover:bg-green-400 font-bold py-2 px-4 rounded mr-1 w-24 "
type="submit"
>
Send
</button>
</div>
</form>
</>
<form onSubmit={handleSubmit(submitMessage)}>
<div className="flex items-end">
<textarea
className="resize-none overflow-y-hidden bg-green-50 text-black rounded-md w-full ml-1 mr-1 size-10"
autoFocus={!!contact}
disabled={!contact}
placeholder="Enter message"
onInput={adjustSize}
rows={1}
{...register('message', {
maxLength: 2000,
minLength: 1,
})}
/>
{errors?.message?.type === 'maxLength' && (
<p>Maximum length of the message is 2000</p>
)}
<button
className="text-black bg-green-500 hover:bg-green-400 font-bold py-2 px-4 rounded mr-1 w-24"
type="submit"
>
Send
</button>
</div>
</form>
);
}
export default messageForm;
export default MessageForm;

View File

@@ -126,14 +126,17 @@ function MessagesArea({
}, [messages]);
const messageList = messages.map((msg: ChatMessages) => (
<li className="ml-2 rounded p-1 hover:bg-gray-800" key={msg.message_id}>
<li
className="whitespace-pre-wrap ml-2 rounded p-1 hover:bg-gray-800"
key={msg.message_id}
>
{msg.message_id} {msg.sender}: {msg.message}
</li>
));
return (
<div ref={containerRef} className="flex flex-col h-full overflow-y-auto">
<p className="text-center text-gray-400">{errorMessage}</p>
<p className=" text-center text-gray-400">{errorMessage}</p>
<ul className="flex-grow list-none">
{isLoading ? <LoadingWheel /> : null}
{messageList}

View File

@@ -3,58 +3,49 @@ import logoutIcon from '../../../assets/logout.svg';
import Cookies from 'js-cookie';
import { useOutletContext } from 'react-router-dom';
import { UsernameType } from '../../utils/ProtectedRoutes.tsx';
import { useState } from 'react';
function UserProfile() {
const { username }: UsernameType = useOutletContext();
const [isOpen, setIsOpen] = useState(false);
const toggleDropdown = () => {
setIsOpen(!isOpen);
};
function logout() {
Cookies.remove('token');
window.location.reload();
}
return (
<div className="relative inline-block">
<div className="dropdown dropdown-top">
<div
className="flex items-center cursor-pointer hs-dropdown-toggle"
onClick={toggleDropdown}
tabIndex={0}
className="flex items-center cursor-pointer"
role="button"
>
<div className="flex items-center justify-center m-3 w-12 h-12 overflow-hidden">
<img src={zdjecie} alt="Profile image" className="w-8 h-8 invert" />
</div>
<div className="text-gray-200">
<p>{username}</p>
</div>
</div>
{isOpen && (
<div className="absolute bottom-full left-0 mb-2 w-48 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5">
<div
className="py-1"
role="menu"
aria-orientation="vertical"
aria-labelledby="options-menu"
<ul
tabIndex={0}
className="m-2 dropdown-content menu p-2 shadow bg-gray-50 rounded-md w-52"
>
<li>
<a
className="flex items-center px-4 py-2 text-sm text-black hover:bg-gray-200"
onClick={logout}
>
<a
className="bg-green-50 cursor-pointer px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 flex"
role="menuitem"
onClick={logout}
>
<img
className="w-5 mr-2"
draggable={false}
src={logoutIcon}
alt="log out ico"
/>
<p>Log out</p>
</a>
</div>
</div>
)}
<img
className="w-5 mr-2"
draggable={false}
src={logoutIcon}
alt="Log out icon"
/>
<p>Log out</p>
</a>
</li>
</ul>
</div>
);
}

View File

@@ -1,12 +1,21 @@
import daisyui from 'daisyui';
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
"node_modules/preline/dist/*.js",
'./index.html',
'./src/**/*.{js,ts,jsx,tsx}',
'node_modules/preline/dist/*.js',
],
theme: {
extend: {},
},
plugins: [require("@tailwindcss/forms"), require("preline/plugin")],
daisyui: {
themes: [],
},
plugins: [
require('@tailwindcss/forms'),
require('preline/plugin'),
require('daisyui'),
],
};

162
package-lock.json generated
View File

@@ -8,7 +8,8 @@
"name": "relay",
"version": "0.0.1",
"devDependencies": {
"concurrently": "^9.0.1"
"concurrently": "^9.0.1",
"daisyui": "^4.12.14"
}
},
"node_modules/ansi-regex": {
@@ -37,6 +38,16 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/camelcase-css": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
"integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 6"
}
},
"node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@@ -128,6 +139,60 @@
"url": "https://github.com/open-cli-tools/concurrently?sponsor=1"
}
},
"node_modules/css-selector-tokenizer": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz",
"integrity": "sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==",
"dev": true,
"license": "MIT",
"dependencies": {
"cssesc": "^3.0.0",
"fastparse": "^1.1.2"
}
},
"node_modules/cssesc": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
"dev": true,
"license": "MIT",
"bin": {
"cssesc": "bin/cssesc"
},
"engines": {
"node": ">=4"
}
},
"node_modules/culori": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/culori/-/culori-3.3.0.tgz",
"integrity": "sha512-pHJg+jbuFsCjz9iclQBqyL3B2HLCBF71BwVNujUYEvCeQMvV97R59MNK3R2+jgJ3a1fcZgI9B3vYgz8lzr/BFQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
}
},
"node_modules/daisyui": {
"version": "4.12.14",
"resolved": "https://registry.npmjs.org/daisyui/-/daisyui-4.12.14.tgz",
"integrity": "sha512-hA27cdBasdwd4/iEjn+aidoCrRroDuo3G5W9NDKaVCJI437Mm/3eSL/2u7MkZ0pt8a+TrYF3aT2pFVemTS3how==",
"dev": true,
"license": "MIT",
"dependencies": {
"css-selector-tokenizer": "^0.8",
"culori": "^3",
"picocolors": "^1",
"postcss-js": "^4"
},
"engines": {
"node": ">=16.9.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/daisyui"
}
},
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
@@ -145,6 +210,13 @@
"node": ">=6"
}
},
"node_modules/fastparse": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
"integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==",
"dev": true,
"license": "MIT"
},
"node_modules/get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
@@ -182,6 +254,83 @@
"dev": true,
"license": "MIT"
},
"node_modules/nanoid": {
"version": "3.3.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"peer": true,
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"dev": true,
"license": "ISC"
},
"node_modules/postcss": {
"version": "8.4.49",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz",
"integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"nanoid": "^3.3.7",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
"engines": {
"node": "^10 || ^12 || >=14"
}
},
"node_modules/postcss-js": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
"integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
"dev": true,
"license": "MIT",
"dependencies": {
"camelcase-css": "^2.0.1"
},
"engines": {
"node": "^12 || ^14 || >= 16"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
"peerDependencies": {
"postcss": "^8.4.21"
}
},
"node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
@@ -212,6 +361,17 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"dev": true,
"license": "BSD-3-Clause",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",

View File

@@ -8,8 +8,8 @@
"install:all": "concurrently \"npm install\" \"cd client && npm install\" \"cd server && npm install\"",
"build": "npm run build"
},
"devDependencies": {
"concurrently": "^9.0.1"
"concurrently": "^9.0.1",
"daisyui": "^4.12.14"
}
}