From dc19638f2cbbf6a2d48b9750651b99d69a2dad9c Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 28 May 2023 09:25:49 +0330 Subject: [PATCH] many improvements + added public page --- components/CollectionCard.tsx | 8 +- .../Modal/Collection/CollectionInfo.tsx | 107 ++++++++++++ .../{ => Collection}/DeleteCollection.tsx | 0 .../TeamManagement.tsx} | 163 ++++++------------ components/Modal/UserSettings.tsx | 2 +- layouts/AuthRedirect.tsx | 36 ++-- .../collections/updateCollection.ts | 1 + pages/collections/[id].tsx | 56 +++--- pages/collections/index.tsx | 4 +- pages/links.tsx | 6 +- pages/public/collections/[id].tsx | 5 + 11 files changed, 229 insertions(+), 159 deletions(-) create mode 100644 components/Modal/Collection/CollectionInfo.tsx rename components/Modal/{ => Collection}/DeleteCollection.tsx (100%) rename components/Modal/{CollectionModal.tsx => Collection/TeamManagement.tsx} (71%) create mode 100644 pages/public/collections/[id].tsx diff --git a/components/CollectionCard.tsx b/components/CollectionCard.tsx index 60b12883..7bb05288 100644 --- a/components/CollectionCard.tsx +++ b/components/CollectionCard.tsx @@ -11,8 +11,8 @@ import useLinkStore from "@/store/links"; import Dropdown from "./Dropdown"; import { useState } from "react"; import Modal from "@/components/Modal"; -import CollectionModal from "@/components/Modal/CollectionModal"; -import DeleteCollection from "@/components/Modal/DeleteCollection"; +import CollectionInfo from "@/components/Modal/Collection/CollectionInfo"; +import DeleteCollection from "@/components/Modal/Collection/DeleteCollection"; import ProfilePhoto from "./ProfilePhoto"; export default function ({ @@ -63,7 +63,7 @@ export default function ({
{collection.members - .sort((a, b) => (a.user.id as number) - (b.user.id as number)) + .sort((a, b) => (a.userId as number) - (b.userId as number)) .map((e, i) => { return ( - +// This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3. +// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +// You should have received a copy of the GNU General Public License along with this program. If not, see . + +import React, { useState } from "react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { + faClose, + faPenToSquare, + faPlus, + faTrashCan, + faUser, + faUserPlus, +} from "@fortawesome/free-solid-svg-icons"; +import useCollectionStore from "@/store/collections"; +import { CollectionIncludingMembers, Member } from "@/types/global"; +import { useSession } from "next-auth/react"; +import Modal from "@/components/Modal"; +import DeleteCollection from "@/components/Modal/Collection/DeleteCollection"; +import RequiredBadge from "../../RequiredBadge"; +import addMemberToCollection from "@/lib/client/addMemberToCollection"; +import ImageWithFallback from "../../ImageWithFallback"; +import Checkbox from "../../Checkbox"; + +type Props = { + toggleCollectionModal: Function; + activeCollection: CollectionIncludingMembers; + method: "CREATE" | "UPDATE"; +}; + +export default function CollectionInfo({ + toggleCollectionModal, + activeCollection, + method, +}: Props) { + const [collection, setCollection] = + useState(activeCollection); + + const { updateCollection, addCollection } = useCollectionStore(); + + const submit = async () => { + if (!collection) return null; + + let response = null; + + if (method === "CREATE") response = await addCollection(collection); + else if (method === "UPDATE") response = await updateCollection(collection); + else console.log("Unknown method."); + + if (response) toggleCollectionModal(); + }; + + return ( +
+

+ {method === "CREATE" ? "Add" : "Edit"} Collection +

+ +
+
+

+ Name + +

+ + setCollection({ ...collection, name: e.target.value }) + } + type="text" + placeholder="e.g. Example Collection" + className="w-full rounded-md p-3 border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100" + /> +
+ +
+

Description

+ + />
) : null} diff --git a/layouts/AuthRedirect.tsx b/layouts/AuthRedirect.tsx index 132a2da6..2f879c4b 100644 --- a/layouts/AuthRedirect.tsx +++ b/layouts/AuthRedirect.tsx @@ -22,22 +22,26 @@ export default function ({ children }: Props) { getInitialData(); useEffect(() => { - if ( - status === "authenticated" && - (router.pathname === "/login" || router.pathname === "/register") - ) { - router.push("/").then(() => { - setRedirect(false); - }); - } else if ( - status === "unauthenticated" && - !(router.pathname === "/login" || router.pathname === "/register") - ) { - router.push("/login").then(() => { - setRedirect(false); - }); - } else if (status === "loading") setRedirect(true); - else setRedirect(false); + if (!router.pathname.startsWith("/public")) { + if ( + status === "authenticated" && + (router.pathname === "/login" || router.pathname === "/register") + ) { + router.push("/").then(() => { + setRedirect(false); + }); + } else if ( + status === "unauthenticated" && + !(router.pathname === "/login" || router.pathname === "/register") + ) { + router.push("/login").then(() => { + setRedirect(false); + }); + } else if (status === "loading") setRedirect(true); + else setRedirect(false); + } else { + setRedirect(false); + } }, [status]); if (status !== "loading" && !redirect) return <>{children}; diff --git a/lib/api/controllers/collections/updateCollection.ts b/lib/api/controllers/collections/updateCollection.ts index ff172f54..1e6f4369 100644 --- a/lib/api/controllers/collections/updateCollection.ts +++ b/lib/api/controllers/collections/updateCollection.ts @@ -51,6 +51,7 @@ export default async function ( select: { email: true, name: true, + id: true, }, }, }, diff --git a/pages/collections/[id].tsx b/pages/collections/[id].tsx index 3ccffa45..2e5e2c65 100644 --- a/pages/collections/[id].tsx +++ b/pages/collections/[id].tsx @@ -7,8 +7,8 @@ import Dropdown from "@/components/Dropdown"; import LinkList from "@/components/LinkList"; import Modal from "@/components/Modal"; import LinkModal from "@/components/Modal/LinkModal"; -import CollectionModal from "@/components/Modal/CollectionModal"; -import DeleteCollection from "@/components/Modal/DeleteCollection"; +import CollectionInfo from "@/components/Modal/Collection/CollectionInfo"; +import DeleteCollection from "@/components/Modal/Collection/DeleteCollection"; import useCollectionStore from "@/store/collections"; import useLinkStore from "@/store/links"; import { CollectionIncludingMembers } from "@/types/global"; @@ -25,6 +25,7 @@ import RadioButton from "@/components/RadioButton"; import ClickAwayHandler from "@/components/ClickAwayHandler"; import { useSession } from "next-auth/react"; import ProfilePhoto from "@/components/ProfilePhoto"; +import TeamManagement from "@/components/Modal/Collection/TeamManagement"; export default function () { const router = useRouter(); @@ -36,7 +37,8 @@ export default function () { const [expandDropdown, setExpandDropdown] = useState(false); const [linkModal, setLinkModal] = useState(false); - const [editCollectionModal, setEditCollectionModal] = 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)"); @@ -50,8 +52,12 @@ export default function () { setLinkModal(!linkModal); }; - const toggleEditCollectionModal = () => { - setEditCollectionModal(!editCollectionModal); + const toggleCollectionInfoModal = () => { + setCollectionInfoModal(!collectionInfoModal); + }; + + const toggleCollectionMembersModal = () => { + setCollectionMembersModal(!collectionMembersModal); }; const toggleDeleteCollectionModal = () => { @@ -122,7 +128,10 @@ export default function () { activeCollection.members[0] && "mr-3" }`} > -
+
{activeCollection?.members - .sort( - (a, b) => (a.user.id as number) - (b.user.id as number) - ) + .sort((a, b) => (a.userId as number) - (b.userId as number)) .map((e, i) => { return ( { - toggleEditCollectionModal(); + toggleCollectionInfoModal(); setExpandDropdown(false); }, }, { - name: `${ - activeCollection?.ownerId === data?.user.id - ? "Manage" - : "View" - } Team`, + name: "Share/Collaborate", onClick: () => { - toggleEditCollectionModal(); + toggleCollectionMembersModal(); setExpandDropdown(false); }, }, @@ -279,7 +282,7 @@ export default function () { if (target.id !== "expand-dropdown") setExpandDropdown(false); }} - className="absolute top-8 right-0 z-10 w-36" + className="absolute top-8 right-0 z-10 w-40" /> ) : null} @@ -292,16 +295,25 @@ export default function () { ) : null} - {editCollectionModal && activeCollection ? ( - - + ) : null} + {collectionMembersModal && activeCollection ? ( + + + + ) : null} + {deleteCollectionModal && activeCollection ? ( - - new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime() + new Date(b.createdAt as string).getTime() - + new Date(a.createdAt as string).getTime() ) ); else if (sortBy === "Date (Oldest First)") setSortedLinks( linksArray.sort( (a, b) => - new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime() + new Date(a.createdAt as string).getTime() - + new Date(b.createdAt as string).getTime() ) ); }, [links, sortBy]); diff --git a/pages/public/collections/[id].tsx b/pages/public/collections/[id].tsx new file mode 100644 index 00000000..6f6ae037 --- /dev/null +++ b/pages/public/collections/[id].tsx @@ -0,0 +1,5 @@ +import React from "react"; + +export default function PublicCollections() { + return
Hello
; +}