diff --git a/components/CollectionCard.tsx b/components/CollectionCard.tsx index 9a82380..a31f64c 100644 --- a/components/CollectionCard.tsx +++ b/components/CollectionCard.tsx @@ -5,10 +5,9 @@ import { CollectionIncludingMembers } from "@/types/global"; import useLinkStore from "@/store/links"; import Dropdown from "./Dropdown"; import { useState } from "react"; -import Modal from "@/components/Modal"; -import CollectionModal from "@/components/Modal/Collection"; import ProfilePhoto from "./ProfilePhoto"; import { faCalendarDays } from "@fortawesome/free-regular-svg-icons"; +import useModalStore from "@/store/modals"; type Props = { collection: CollectionIncludingMembers; @@ -16,6 +15,8 @@ type Props = { }; export default function CollectionCard({ collection, className }: Props) { + const { setModal } = useModalStore(); + const { links } = useLinkStore(); const formattedDate = new Date(collection.createdAt as string).toLocaleString( "en-US", @@ -27,21 +28,6 @@ export default function CollectionCard({ collection, className }: Props) { ); const [expandDropdown, setExpandDropdown] = useState(false); - const [editCollectionModal, setEditCollectionModal] = useState(false); - const [collectionMembersModal, setCollectionMembersModal] = useState(false); - const [deleteCollectionModal, setDeleteCollectionModal] = useState(false); - - const toggleEditCollectionModal = () => { - setEditCollectionModal(!editCollectionModal); - }; - - const toggleCollectionMembersModal = () => { - setCollectionMembersModal(!collectionMembersModal); - }; - - const toggleDeleteCollectionModal = () => { - setDeleteCollectionModal(!deleteCollectionModal); - }; return (
{ - toggleEditCollectionModal(); + setModal({ + modal: "COLLECTION", + state: true, + method: "UPDATE", + active: collection, + }); setExpandDropdown(false); }, }, { name: "Share/Collaborate", onClick: () => { - toggleCollectionMembersModal(); + setModal({ + modal: "COLLECTION", + state: true, + method: "UPDATE", + active: collection, + defaultIndex: 1, + }); setExpandDropdown(false); }, }, { name: "Delete Collection", onClick: () => { - toggleDeleteCollectionModal(); + setModal({ + modal: "COLLECTION", + state: true, + method: "UPDATE", + active: collection, + defaultIndex: 2, + }); setExpandDropdown(false); }, }, @@ -130,35 +133,6 @@ export default function CollectionCard({ collection, className }: Props) { className="absolute top-[3.2rem] right-5 z-10 w-36" /> ) : null} - {editCollectionModal ? ( - - - - ) : null} - {collectionMembersModal ? ( - - - - ) : null} - {deleteCollectionModal ? ( - - - - ) : null}
); } diff --git a/components/LinkCard.tsx b/components/LinkCard.tsx index 3f9512c..0d49d7b 100644 --- a/components/LinkCard.tsx +++ b/components/LinkCard.tsx @@ -13,10 +13,9 @@ import { useEffect, useState } from "react"; import Image from "next/image"; import Dropdown from "./Dropdown"; import useLinkStore from "@/store/links"; -import Modal from "./Modal"; -import LinkModal from "./Modal/LinkModal"; import Link from "next/link"; import useCollectionStore from "@/store/collections"; +import useModalStore from "@/store/modals"; type Props = { link: LinkIncludingCollectionAndTags; @@ -25,8 +24,9 @@ type Props = { }; export default function LinkCard({ link, count, className }: Props) { + const { setModal } = useModalStore(); + const [expandDropdown, setExpandDropdown] = useState(false); - const [editModal, setEditModal] = useState(false); const { collections } = useCollectionStore(); @@ -56,25 +56,11 @@ export default function LinkCard({ link, count, className }: Props) { } ); - const toggleEditModal = () => { - setEditModal(!editModal); - }; - return (
- {editModal ? ( - - - - ) : null} - { - setEditModal(true); + setModal({ + modal: "LINK", + state: true, + method: "UPDATE", + active: link, + }); setExpandDropdown(false); }, }, diff --git a/components/Modal/User/ProfileSettings.tsx b/components/Modal/User/ProfileSettings.tsx index 03db59f..b229375 100644 --- a/components/Modal/User/ProfileSettings.tsx +++ b/components/Modal/User/ProfileSettings.tsx @@ -80,7 +80,7 @@ export default function ProfileSettings({
{profileStatus && ( diff --git a/components/ModalManagement.tsx b/components/ModalManagement.tsx new file mode 100644 index 0000000..bad08cb --- /dev/null +++ b/components/ModalManagement.tsx @@ -0,0 +1,51 @@ +import useModalStore from "@/store/modals"; +import Modal from "./Modal"; +import LinkModal from "./Modal/LinkModal"; +import { + AccountSettings, + CollectionIncludingMembers, + LinkIncludingCollectionAndTags, +} from "@/types/global"; +import CollectionModal from "./Modal/Collection"; +import UserModal from "./Modal/User"; + +export default function ModalManagement() { + const { modal, setModal } = useModalStore(); + + const toggleModal = () => { + setModal(null); + }; + + if (modal && modal.modal === "LINK") + return ( + + + + ); + else if (modal && modal.modal === "COLLECTION") + return ( + + + + ); + else if (modal && modal.modal === "ACCOUNT") + return ( + + + + ); + else return <>; +} diff --git a/components/Navbar.tsx b/components/Navbar.tsx index 49367b2..6d8a77a 100644 --- a/components/Navbar.tsx +++ b/components/Navbar.tsx @@ -7,23 +7,21 @@ import { } from "@fortawesome/free-solid-svg-icons"; import { useEffect, useState } from "react"; import Dropdown from "@/components/Dropdown"; -import Modal from "@/components/Modal"; -import LinkModal from "@/components/Modal/LinkModal"; import ClickAwayHandler from "@/components/ClickAwayHandler"; import Sidebar from "@/components/Sidebar"; import { useRouter } from "next/router"; import Search from "@/components/Search"; -import UserModal from "@/components/Modal/User"; import useAccountStore from "@/store/account"; import ProfilePhoto from "@/components/ProfilePhoto"; +import useModalStore from "@/store/modals"; export default function Navbar() { + const { setModal } = useModalStore(); + const { account } = useAccountStore(); const [profileDropdown, setProfileDropdown] = useState(false); - const [linkModal, setLinkModal] = useState(false); - const [settingsModal, setSettingsModal] = useState(false); const [sidebar, setSidebar] = useState(false); const router = useRouter(); @@ -38,14 +36,6 @@ export default function Navbar() { setSidebar(!sidebar); }; - const toggleLinkModal = () => { - setLinkModal(!linkModal); - }; - - const toggleSettingsModal = () => { - setSettingsModal(!settingsModal); - }; - return (
{ + setModal({ + modal: "LINK", + state: true, + method: "CREATE", + }); + }} className="inline-flex gap-1 relative sm:w-[7.2rem] items-center font-semibold select-none cursor-pointer p-[0.687rem] sm:p-2 sm:px-3 rounded-md sm:rounded-full hover:bg-sky-100 text-sky-500 sm:text-white sm:bg-sky-500 sm:hover:bg-sky-400 duration-100 group" > { - toggleSettingsModal(); + setModal({ + modal: "ACCOUNT", + state: true, + method: "CREATE", + active: account, + }); setProfileDropdown(!profileDropdown); }, }, @@ -122,21 +123,6 @@ export default function Navbar() { /> ) : null} - {linkModal ? ( - - - - ) : null} - - {settingsModal ? ( - - - - ) : null} - {sidebar ? (
diff --git a/layouts/MainLayout.tsx b/layouts/MainLayout.tsx index 8737fd4..6e099d0 100644 --- a/layouts/MainLayout.tsx +++ b/layouts/MainLayout.tsx @@ -5,6 +5,7 @@ import { useSession } from "next-auth/react"; import Loader from "../components/Loader"; import useRedirect from "@/hooks/useRedirect"; import { useRouter } from "next/router"; +import ModalManagement from "@/components/ModalManagement"; interface Props { children: ReactNode; @@ -18,16 +19,20 @@ export default function MainLayout({ children }: Props) { if (status === "authenticated" && !redirect && routeExists) return ( -
-
- -
+ <> + -
- - {children} +
+
+ +
+ +
+ + {children} +
-
+ ); else if ((status === "unauthenticated" && !redirect) || !routeExists) return <>{children}; diff --git a/pages/collections/[id].tsx b/pages/collections/[id].tsx index 29be60d..40b606c 100644 --- a/pages/collections/[id].tsx +++ b/pages/collections/[id].tsx @@ -1,8 +1,5 @@ import Dropdown from "@/components/Dropdown"; import LinkCard from "@/components/LinkCard"; -import Modal from "@/components/Modal"; -import LinkModal from "@/components/Modal/LinkModal"; -import CollectionModal from "@/components/Modal/Collection"; import useCollectionStore from "@/store/collections"; import useLinkStore from "@/store/links"; import { CollectionIncludingMembers } from "@/types/global"; @@ -18,8 +15,11 @@ import MainLayout from "@/layouts/MainLayout"; import { useSession } from "next-auth/react"; import ProfilePhoto from "@/components/ProfilePhoto"; import SortLinkDropdown from "@/components/SortLinkDropdown"; +import useModalStore from "@/store/modals"; export default function Index() { + const { setModal } = useModalStore(); + const router = useRouter(); const { links } = useLinkStore(); @@ -28,10 +28,6 @@ export default function Index() { const { data } = useSession(); const [expandDropdown, setExpandDropdown] = useState(false); - const [linkModal, setLinkModal] = useState(false); - const [collectionInfoModal, setCollectionInfoModal] = useState(false); - const [collectionMembersModal, setCollectionMembersModal] = useState(false); - const [deleteCollectionModal, setDeleteCollectionModal] = useState(false); const [sortDropdown, setSortDropdown] = useState(false); const [sortBy, setSortBy] = useState("Name (A-Z)"); @@ -40,22 +36,6 @@ export default function Index() { const [sortedLinks, setSortedLinks] = useState(links); - const toggleLinkModal = () => { - setLinkModal(!linkModal); - }; - - const toggleCollectionInfoModal = () => { - setCollectionInfoModal(!collectionInfoModal); - }; - - const toggleCollectionMembersModal = () => { - setCollectionMembersModal(!collectionMembersModal); - }; - - const toggleDeleteCollectionModal = () => { - setDeleteCollectionModal(!deleteCollectionModal); - }; - const handleSortChange = (event: ChangeEvent) => { setSortBy(event.target.value); }; @@ -124,7 +104,16 @@ export default function Index() { }`} >
+ activeCollection && + setModal({ + modal: "COLLECTION", + state: true, + method: "UPDATE", + active: activeCollection, + defaultIndex: 1, + }) + } className="flex justify-center sm:justify-end items-center w-fit mx-auto sm:mr-0 sm:ml-auto group cursor-pointer" >
{ - toggleLinkModal(); + setModal({ + modal: "LINK", + state: true, + method: "CREATE", + }); setExpandDropdown(false); }, }, { name: "Edit Collection Info", onClick: () => { - toggleCollectionInfoModal(); + activeCollection && + setModal({ + modal: "COLLECTION", + state: true, + method: "UPDATE", + active: activeCollection, + }); setExpandDropdown(false); }, }, { name: "Share/Collaborate", onClick: () => { - toggleCollectionMembersModal(); + activeCollection && + setModal({ + modal: "COLLECTION", + state: true, + method: "UPDATE", + active: activeCollection, + defaultIndex: 1, + }); setExpandDropdown(false); }, }, { name: "Delete Collection", onClick: () => { - toggleDeleteCollectionModal(); + activeCollection && + setModal({ + modal: "COLLECTION", + state: true, + method: "UPDATE", + active: activeCollection, + defaultIndex: 2, + }); setExpandDropdown(false); }, }, @@ -237,47 +250,6 @@ export default function Index() { className="absolute top-8 right-0 z-10 w-40" /> ) : null} - - {linkModal ? ( - - - - ) : null} - - {collectionInfoModal && activeCollection ? ( - - - - ) : null} - - {collectionMembersModal && activeCollection ? ( - - - - ) : null} - - {deleteCollectionModal && activeCollection ? ( - - - - ) : null}
diff --git a/pages/collections/index.tsx b/pages/collections/index.tsx index 5f205c1..3c81f78 100644 --- a/pages/collections/index.tsx +++ b/pages/collections/index.tsx @@ -9,12 +9,11 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import CollectionCard from "@/components/CollectionCard"; import Dropdown from "@/components/Dropdown"; import { ChangeEvent, useEffect, useState } from "react"; -import Modal from "@/components/Modal"; import MainLayout from "@/layouts/MainLayout"; import ClickAwayHandler from "@/components/ClickAwayHandler"; import RadioButton from "@/components/RadioButton"; -import CollectionModal from "@/components/Modal/Collection"; import { useSession } from "next-auth/react"; +import useModalStore from "@/store/modals"; export default function Collections() { const { collections } = useCollectionStore(); @@ -23,13 +22,9 @@ export default function Collections() { const [sortBy, setSortBy] = useState("Name (A-Z)"); const [sortedCollections, setSortedCollections] = useState(collections); - const [collectionModal, setCollectionModal] = useState(false); - const session = useSession(); - const toggleCollectionModal = () => { - setCollectionModal(!collectionModal); - }; + const { setModal } = useModalStore(); const handleSortChange = (event: ChangeEvent) => { setSortBy(event.target.value); @@ -109,7 +104,19 @@ export default function Collections() { { name: "New Collection", onClick: () => { - toggleCollectionModal(); + setModal({ + modal: "COLLECTION", + state: true, + method: "CREATE", + active: { + name: "", + description: "", + color: "#0ea5e9", + isPublic: false, + ownerId: session.data?.user.id as number, + members: [], + }, + }); setExpandDropdown(false); }, }, @@ -198,7 +205,21 @@ export default function Collections() {
{ + setModal({ + modal: "COLLECTION", + state: true, + method: "CREATE", + active: { + name: "", + description: "", + color: "#0ea5e9", + isPublic: false, + ownerId: session.data?.user.id as number, + members: [], + }, + }); + }} >

New Collection @@ -210,23 +231,6 @@ export default function Collections() {

- - {collectionModal ? ( - - - - ) : null} ); } diff --git a/store/modals.ts b/store/modals.ts new file mode 100644 index 0000000..c88c845 --- /dev/null +++ b/store/modals.ts @@ -0,0 +1,48 @@ +import { + AccountSettings, + CollectionIncludingMembers, + LinkIncludingCollectionAndTags, +} from "@/types/global"; +import { create } from "zustand"; + +type Modal = + | { + modal: "ACCOUNT"; + state: boolean; + active: AccountSettings; + defaultIndex?: number; + } + | { + modal: "LINK"; + state: boolean; + method: "CREATE"; + active?: LinkIncludingCollectionAndTags; + } + | { + modal: "LINK"; + state: boolean; + method: "UPDATE"; + active: LinkIncludingCollectionAndTags; + } + | { + modal: "COLLECTION"; + state: boolean; + method: "CREATE" | "UPDATE"; + active: CollectionIncludingMembers; + defaultIndex?: number; + } + | null; + +type ModalsStore = { + modal: Modal; + setModal: (modal: Modal) => void; +}; + +const useLocalSettingsStore = create((set) => ({ + modal: null, + setModal: (modal: Modal) => { + set({ modal }); + }, +})); + +export default useLocalSettingsStore;