From f1bd48be83371969690028599972c758f18a1795 Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 27 Jun 2023 02:03:40 +0330 Subject: [PATCH] added toasts popups + improved login/signup page + many more changes and improvements --- components/LinkCard.tsx | 48 +++-- .../Modal/Collection/CollectionInfo.tsx | 27 ++- .../Modal/Collection/DeleteCollection.tsx | 9 +- .../Modal/Collection/TeamManagement.tsx | 26 ++- components/Modal/Link/EditLink.tsx | 24 ++- components/Modal/Link/LinkDetails.tsx | 4 +- components/Modal/User/ChangePassword.tsx | 81 +++++---- components/Modal/User/PrivacySettings.tsx | 22 ++- components/Modal/User/ProfileSettings.tsx | 26 ++- components/ModalManagement.tsx | 2 +- components/Search.tsx | 3 +- components/SubmitButton.tsx | 19 +- hooks/useLinks.tsx | 2 - lib/client/addMemberToCollection.ts | 8 +- lib/client/getPublicUserDataByEmail.ts | 4 +- package.json | 1 + pages/_app.tsx | 6 + pages/api/auth/[...nextauth].ts | 2 - pages/api/auth/register.ts | 10 +- pages/login.tsx | 88 +++++---- pages/register.tsx | 167 ++++++++++++------ .../migration.sql | 0 prisma/schema.prisma | 2 +- store/account.ts | 11 +- store/collections.ts | 21 +-- store/links.ts | 25 +-- styles/globals.css | 13 ++ yarn.lock | 12 ++ 28 files changed, 464 insertions(+), 199 deletions(-) rename prisma/migrations/{20230614043921_init => 20230625202057_init}/migration.sql (100%) diff --git a/components/LinkCard.tsx b/components/LinkCard.tsx index 2eb9e7f..7462056 100644 --- a/components/LinkCard.tsx +++ b/components/LinkCard.tsx @@ -13,6 +13,7 @@ import useAccountStore from "@/store/account"; import useModalStore from "@/store/modals"; import { faCalendarDays } from "@fortawesome/free-regular-svg-icons"; import usePermissions from "@/hooks/usePermissions"; +import { toast } from "react-hot-toast"; type Props = { link: LinkIncludingShortenedCollectionAndTags; @@ -48,6 +49,35 @@ export default function LinkCard({ link, count, className }: Props) { const { removeLink, updateLink } = useLinkStore(); + const pinLink = async () => { + const isAlreadyPinned = link?.pinnedBy && link.pinnedBy[0]; + + const load = toast.loading("Applying..."); + + setExpandDropdown(false); + + const response = await updateLink({ + ...link, + pinnedBy: isAlreadyPinned ? undefined : [{ id: account.id }], + }); + + toast.dismiss(load); + + response.ok && + toast.success(`Link ${isAlreadyPinned ? "Unpinned!" : "Pinned!"}`); + }; + + const deleteLink = async () => { + const load = toast.loading("Deleting..."); + + const response = await removeLink(link); + + toast.dismiss(load); + + response.ok && toast.success(`Link Deleted.`); + setExpandDropdown(false); + }; + const url = new URL(link.url); const formattedDate = new Date(link.createdAt as string).toLocaleString( "en-US", @@ -97,7 +127,7 @@ export default function LinkCard({ link, count, className }: Props) { width={64} height={64} alt="" - className="blur-sm absolute w-16 group-hover:scale-50 group-hover:blur-none group-hover:opacity-100 duration-100 rounded-md bottom-5 right-5 opacity-60 select-none" + className="blur-sm absolute w-16 group-hover:opacity-80 duration-100 rounded-md bottom-5 right-5 opacity-60 select-none" draggable="false" onError={(e) => { const target = e.target as HTMLElement; @@ -141,16 +171,7 @@ export default function LinkCard({ link, count, className }: Props) { link?.pinnedBy && link.pinnedBy[0] ? "Unpin" : "Pin to Dashboard", - onClick: () => { - updateLink({ - ...link, - pinnedBy: - link?.pinnedBy && link.pinnedBy[0] - ? undefined - : [{ id: account.id }], - }); - setExpandDropdown(false); - }, + onClick: pinLink, } : undefined, permissions === true || permissions?.canUpdate @@ -173,10 +194,7 @@ export default function LinkCard({ link, count, className }: Props) { permissions === true || permissions?.canDelete ? { name: "Delete", - onClick: () => { - removeLink(link); - setExpandDropdown(false); - }, + onClick: deleteLink, } : undefined, ]} diff --git a/components/Modal/Collection/CollectionInfo.tsx b/components/Modal/Collection/CollectionInfo.tsx index 5f8dd7b..3e88c2d 100644 --- a/components/Modal/Collection/CollectionInfo.tsx +++ b/components/Modal/Collection/CollectionInfo.tsx @@ -1,4 +1,4 @@ -import { Dispatch, SetStateAction } from "react"; +import { Dispatch, SetStateAction, useState } from "react"; import { faFolder, faPenToSquare, @@ -10,6 +10,7 @@ import RequiredBadge from "../../RequiredBadge"; import SubmitButton from "@/components/SubmitButton"; import { HexColorPicker } from "react-colorful"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { toast } from "react-hot-toast"; type Props = { toggleCollectionModal: Function; @@ -26,18 +27,33 @@ export default function CollectionInfo({ collection, method, }: Props) { + const [submitLoader, setSubmitLoader] = useState(false); const { updateCollection, addCollection } = useCollectionStore(); const submit = async () => { if (!collection) return null; - let response = null; + setSubmitLoader(true); + + const load = toast.loading( + method === "UPDATE" ? "Applying..." : "Creating..." + ); + + let response; if (method === "CREATE") response = await addCollection(collection); - else if (method === "UPDATE") response = await updateCollection(collection); - else console.log("Unknown method."); + else response = await updateCollection(collection); - if (response) toggleCollectionModal(); + toast.dismiss(load); + + if (response.ok) { + toast.success( + `Collection ${method === "UPDATE" ? "Saved!" : "Created!"}` + ); + toggleCollectionModal(); + } else toast.error(response.data as string); + + setSubmitLoader(false); }; return ( @@ -102,6 +118,7 @@ export default function CollectionInfo({ { if (permissions === true) if (collection.name !== inputField) return null; + const load = toast.loading("Deleting..."); + const response = await removeCollection(collection.id as number); - if (response) { + + toast.dismiss(load); + + if (response.ok) { + toast.success("Collection Deleted."); toggleDeleteCollectionModal(); router.push("/collections"); } diff --git a/components/Modal/Collection/TeamManagement.tsx b/components/Modal/Collection/TeamManagement.tsx index 02a3efd..bf33868 100644 --- a/components/Modal/Collection/TeamManagement.tsx +++ b/components/Modal/Collection/TeamManagement.tsx @@ -14,6 +14,7 @@ import Checkbox from "../../Checkbox"; import SubmitButton from "@/components/SubmitButton"; import ProfilePhoto from "@/components/ProfilePhoto"; import usePermissions from "@/hooks/usePermissions"; +import { toast } from "react-hot-toast"; type Props = { toggleCollectionModal: Function; @@ -69,16 +70,30 @@ export default function TeamManagement({ }); }; + const [submitLoader, setSubmitLoader] = useState(false); + const submit = async () => { if (!collection) return null; - let response = null; + setSubmitLoader(true); + + const load = toast.loading( + method === "UPDATE" ? "Applying..." : "Creating..." + ); + + let response; if (method === "CREATE") response = await addCollection(collection); - else if (method === "UPDATE") response = await updateCollection(collection); - else console.log("Unknown method."); + else response = await updateCollection(collection); - if (response) toggleCollectionModal(); + toast.dismiss(load); + + if (response.ok) { + toast.success("Collection Saved!"); + toggleCollectionModal(); + } else toast.error(response.data as string); + + setSubmitLoader(false); }; return ( @@ -111,7 +126,7 @@ export default function TeamManagement({ try { navigator.clipboard .writeText(publicCollectionURL) - .then(() => console.log("Copied!")); + .then(() => toast.success("Copied!")); } catch (err) { console.log(err); } @@ -379,6 +394,7 @@ export default function TeamManagement({ {permissions === true && ( ( @@ -88,12 +91,26 @@ export default function EditLink({ }; const submit = async () => { + setSubmitLoader(true); + let response; + const load = toast.loading( + method === "UPDATE" ? "Applying..." : "Creating..." + ); if (method === "UPDATE") response = await updateLink(link); - else if (method === "CREATE") response = await addLink(link); + else response = await addLink(link); - response && toggleLinkModal(); + toast.dismiss(load); + + if (response.ok) { + toast.success(`Link ${method === "UPDATE" ? "Saved!" : "Created!"}`); + toggleLinkModal(); + } else toast.error(response.data as string); + + setSubmitLoader(false); + + return response; }; return ( @@ -188,7 +205,8 @@ export default function EditLink({ onClick={submit} label={method === "CREATE" ? "Add" : "Save"} icon={method === "CREATE" ? faPlus : faPenToSquare} - className="mx-auto mt-2" + loading={submitLoader} + className={`mx-auto mt-2`} /> ); diff --git a/components/Modal/Link/LinkDetails.tsx b/components/Modal/Link/LinkDetails.tsx index 20031b2..1aab780 100644 --- a/components/Modal/Link/LinkDetails.tsx +++ b/components/Modal/Link/LinkDetails.tsx @@ -116,12 +116,12 @@ export default function LinkDetails({ link }: Props) { return (
{!imageError && ( -