dropdown menu on user profile
This commit is contained in:
@@ -1 +1 @@
|
|||||||
{}
|
{ "singleQuote": true}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<script type="module" src="/src/main.tsx"></script>
|
<script type="module" src="./src/main.tsx"></script>
|
||||||
|
<script src="./node_modules/preline/dist/preline.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
20
client/package-lock.json
generated
20
client/package-lock.json
generated
@@ -13,6 +13,7 @@
|
|||||||
"@types/socket.io-client": "^1.4.36",
|
"@types/socket.io-client": "^1.4.36",
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.7.7",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
|
"preline": "^2.5.1",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-hook-form": "^7.53.0",
|
"react-hook-form": "^7.53.0",
|
||||||
@@ -1065,6 +1066,16 @@
|
|||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@popperjs/core": {
|
||||||
|
"version": "2.11.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
|
||||||
|
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/popperjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@remix-run/router": {
|
"node_modules/@remix-run/router": {
|
||||||
"version": "1.19.2",
|
"version": "1.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.2.tgz",
|
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.2.tgz",
|
||||||
@@ -3575,6 +3586,15 @@
|
|||||||
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
|
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/preline": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/preline/-/preline-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-fEXOsz0xLfTm5sJmNanourrMjwjcgGtaVNg8Pt6GzUbZ/oXHIdcR94LBdeE0Ea0pBPFOOHzEL5LQwSbAvCJEfw==",
|
||||||
|
"license": "Licensed under MIT and Preline UI Fair Use License",
|
||||||
|
"dependencies": {
|
||||||
|
"@popperjs/core": "^2.11.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/prelude-ls": {
|
"node_modules/prelude-ls": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
"@types/socket.io-client": "^1.4.36",
|
"@types/socket.io-client": "^1.4.36",
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.7.7",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
|
"preline": "^2.5.1",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-hook-form": "^7.53.0",
|
"react-hook-form": "^7.53.0",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useForm, SubmitHandler } from "react-hook-form";
|
import { useForm, SubmitHandler } from 'react-hook-form';
|
||||||
import { sendContact, sendRequestHistorical } from "../../socket/socket.tsx";
|
import { sendContact, sendRequestHistorical } from '../../socket/socket.tsx';
|
||||||
import { Dispatch, SetStateAction, useEffect } from "react";
|
import { Dispatch, SetStateAction, useEffect } from 'react';
|
||||||
|
|
||||||
type Input = {
|
type Input = {
|
||||||
contact: string;
|
contact: string;
|
||||||
@@ -21,9 +21,9 @@ interface ContactInputProps {
|
|||||||
function ContactForm({ contact, setContact, setMessages }: ContactInputProps) {
|
function ContactForm({ contact, setContact, setMessages }: ContactInputProps) {
|
||||||
const { register, handleSubmit, reset } = useForm<Input>();
|
const { register, handleSubmit, reset } = useForm<Input>();
|
||||||
|
|
||||||
let storedContact: string | null = "";
|
let storedContact: string | null = '';
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
storedContact = storedContact = localStorage.getItem("contact");
|
storedContact = storedContact = localStorage.getItem('contact');
|
||||||
if (storedContact) {
|
if (storedContact) {
|
||||||
setContact(storedContact);
|
setContact(storedContact);
|
||||||
sendRequestHistorical(storedContact);
|
sendRequestHistorical(storedContact);
|
||||||
@@ -33,11 +33,11 @@ function ContactForm({ contact, setContact, setMessages }: ContactInputProps) {
|
|||||||
const submitContact: SubmitHandler<Input> = (data) => {
|
const submitContact: SubmitHandler<Input> = (data) => {
|
||||||
setMessages([]);
|
setMessages([]);
|
||||||
sendRequestHistorical(data.contact);
|
sendRequestHistorical(data.contact);
|
||||||
localStorage.setItem("contact", data.contact);
|
localStorage.setItem('contact', data.contact);
|
||||||
setContact(data.contact);
|
setContact(data.contact);
|
||||||
sendContact(data.contact); //TODO zapisz w bazie danych te kontakty
|
sendContact(data.contact); //TODO zapisz w bazie danych te kontakty
|
||||||
console.log("Contact submitted:", data.contact);
|
console.log('Contact submitted:', data.contact);
|
||||||
reset({ contact: "" });
|
reset({ contact: '' });
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -45,11 +45,11 @@ function ContactForm({ contact, setContact, setMessages }: ContactInputProps) {
|
|||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<form onSubmit={handleSubmit(submitContact)}>
|
<form onSubmit={handleSubmit(submitContact)}>
|
||||||
<input
|
<input
|
||||||
className="text-black bg-green-100 pl-2 shadow-lg rounded-md h-8 mb-2 mt-2"
|
className="text-black bg-green-50 pl-2 shadow-lg rounded-md h-8 mb-2 mt-2"
|
||||||
type="text"
|
type="text"
|
||||||
autoFocus={!!contact}
|
autoFocus={!!contact}
|
||||||
placeholder="Enter contact"
|
placeholder="Enter contact"
|
||||||
{...register("contact", {
|
{...register('contact', {
|
||||||
// valid username length (validated on signup)
|
// valid username length (validated on signup)
|
||||||
minLength: 4,
|
minLength: 4,
|
||||||
maxLength: 20,
|
maxLength: 20,
|
||||||
|
|||||||
@@ -1,34 +1,49 @@
|
|||||||
import zdjecie from "../../../assets/walter.png";
|
import zdjecie from '../../../assets/walter.png';
|
||||||
import Cookies from "js-cookie";
|
import logoutIcon from '../../../assets/logout.svg';
|
||||||
import { useOutletContext } from "react-router-dom";
|
import Cookies from 'js-cookie';
|
||||||
import { UsernameType } from "../../utils/ProtectedRoutes.tsx";
|
import { useOutletContext } from 'react-router-dom';
|
||||||
|
import { UsernameType } from '../../utils/ProtectedRoutes.tsx';
|
||||||
function UserProfile() {
|
function UserProfile() {
|
||||||
const { username }: UsernameType = useOutletContext();
|
const { username }: UsernameType = useOutletContext();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className="m-3 rounded-full w-12 h-12 overflow-hidden ">
|
<div className="hs-dropdown relative inline-flex">
|
||||||
<img
|
<div className="m-3 rounded-full w-12 h-12 overflow-hidden hs-dropdown-toggle cursor-pointer">
|
||||||
className="w-full h-full object-cover"
|
<img
|
||||||
src={zdjecie}
|
className="w-full h-full object-cover"
|
||||||
alt="user profile"
|
src={zdjecie}
|
||||||
draggable={false}
|
alt="user profile"
|
||||||
/>
|
draggable={false}
|
||||||
|
aria-haspopup="menu"
|
||||||
|
aria-expanded="false"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className="hs-dropdown-menu transition-[opacity,margin] duration-100 hs-dropdown-open:opacity-100 opacity-0 hidden min-w-60 bg-green-50 shadow-md rounded-md mt-2 after:h-4 after:absolute after:-bottom-4 after:start-0 after:w-full before:h-4 before:absolute before:-top-4 before:start-0 before:w-full"
|
||||||
|
role="menu"
|
||||||
|
aria-orientation="vertical"
|
||||||
|
>
|
||||||
|
<div className="p-1 space-y-0.5 flex">
|
||||||
|
<a
|
||||||
|
className="flex items-center gap-x-3.5 py-2 px-3 rounded-md text-sm text-black hover:bg-gray-100 focus:outline-none focus:bg-gray-100"
|
||||||
|
onClick={() => {
|
||||||
|
Cookies.remove('token');
|
||||||
|
window.location.reload();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Log out
|
||||||
|
</a>
|
||||||
|
<img className="w-5" src={logoutIcon} alt="Logout" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="text-center text-gray-200">
|
<div className="text-center text-gray-200">
|
||||||
<p>{username}</p>
|
<p>{username}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
onClick={() => {
|
|
||||||
Cookies.remove("token");
|
|
||||||
window.location.reload();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
remove cookies
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
/** @type {import('tailwindcss').Config} */
|
/** @type {import('tailwindcss').Config} */
|
||||||
export default {
|
export default {
|
||||||
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
|
content: [
|
||||||
|
"./index.html",
|
||||||
|
"./src/**/*.{js,ts,jsx,tsx}",
|
||||||
|
"node_modules/preline/dist/*.js",
|
||||||
|
],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {},
|
extend: {},
|
||||||
},
|
},
|
||||||
plugins: [require("@tailwindcss/forms")],
|
plugins: [require("@tailwindcss/forms"), require("preline/plugin")],
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user