diff --git a/components/Modal/AddCollection.tsx b/components/Modal/AddCollection.tsx index 899e282..239a235 100644 --- a/components/Modal/AddCollection.tsx +++ b/components/Modal/AddCollection.tsx @@ -135,109 +135,113 @@ export default function AddCollection({ toggleCollectionModal }: Props) { return (
+ { + const updatedMembers = newCollection.members.filter( + (member) => { + return member.email !== e.email; + } + ); + setNewCollection({ + ...newCollection, + members: updatedMembers, + }); + }} + />

{e.name}

{e.email}

-
- { - const updatedMembers = newCollection.members.filter( - (member) => { - return member.email !== e.email; - } - ); - setNewCollection({ - ...newCollection, - members: updatedMembers, - }); - }} - /> -

Permissions

-

(Click to toggle.)

+
+
+

Permissions

+

(Click to toggle.)

+
-
); diff --git a/components/Modal/EditCollection.tsx b/components/Modal/EditCollection.tsx index e69de29..2049622 100644 --- a/components/Modal/EditCollection.tsx +++ b/components/Modal/EditCollection.tsx @@ -0,0 +1,267 @@ +// Copyright (C) 2022-present Daniel31x13 +// 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, faPlus } from "@fortawesome/free-solid-svg-icons"; +import useCollectionStore from "@/store/collections"; +import { ExtendedCollection, NewCollection } from "@/types/global"; +import { useSession } from "next-auth/react"; + +type Props = { + toggleCollectionModal: Function; + collection: ExtendedCollection; +}; + +export default function EditCollection({ + toggleCollectionModal, + collection, +}: Props) { + const [activeCollection, setActiveCollection] = + useState(collection); + + const [memberEmail, setMemberEmail] = useState(""); + + // const { addCollection } = useCollectionStore(); + + const session = useSession(); + + const submitCollection = async () => { + console.log(activeCollection); + + // const response = await addCollection(newCollection as NewCollection); + + // if (response) toggleCollectionModal(); + }; + + const getUserByEmail = async (email: string) => { + const response = await fetch(`/api/routes/users?email=${email}`); + + const data = await response.json(); + + return data.response; + }; + + return ( +
+

Edit Collection

+ +
+

Name

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

Description

+ + setActiveCollection({ + ...activeCollection, + description: e.target.value, + }) + } + type="text" + placeholder="Collection description (Optional)" + className="w-56 sm:w-96 rounded-md p-3 border-sky-100 border-solid border text-sm outline-none focus:border-sky-500 duration-100" + /> +
+ +
+ +
+

Members

+ { + setMemberEmail(e.target.value); + }} + onKeyDown={async (e) => { + const checkIfMemberAlreadyExists = activeCollection.members.find( + (e) => e.user.email === memberEmail + ); + + const ownerEmail = session.data?.user.email; + + if ( + e.key === "Enter" && + // no duplicate members + !checkIfMemberAlreadyExists && + // member can't be empty + memberEmail.trim() !== "" && + // member can't be the owner + memberEmail.trim() !== ownerEmail + ) { + // Lookup, get data/err, list ... + const user = await getUserByEmail(memberEmail.trim()); + + if (user.email) { + const newMember = { + collectionId: activeCollection.id, + userId: user.id, + canCreate: false, + canUpdate: false, + canDelete: false, + user: { + name: user.name, + email: user.email, + }, + }; + + setActiveCollection({ + ...activeCollection, + members: [...activeCollection.members, newMember], + }); + + setMemberEmail(""); + } + } + }} + type="text" + placeholder="Email (Optional)" + className="w-56 sm:w-96 rounded-md p-3 border-sky-100 border-solid border text-sm outline-none focus:border-sky-500 duration-100" + /> +
+ + {activeCollection.members[0] ? ( +

+ (All Members will have Read access to this collection.) +

+ ) : null} + + {activeCollection.members.map((e, i) => { + return ( +
+ { + const updatedMembers = activeCollection.members.filter( + (member) => { + return member.user.email !== e.user.email; + } + ); + setActiveCollection({ + ...activeCollection, + members: updatedMembers, + }); + }} + /> +
+

{e.user.name}

+

{e.user.email}

+
+
+
+

Permissions

+

(Click to toggle.)

+
+ +
+ + + + + +
+
+
+ ); + })} + +
+ + Add Collection +
+
+ ); +} diff --git a/lib/api/controllers/collections/getCollections.ts b/lib/api/controllers/collections/getCollections.ts index a494b8b..3e1ab30 100644 --- a/lib/api/controllers/collections/getCollections.ts +++ b/lib/api/controllers/collections/getCollections.ts @@ -14,7 +14,16 @@ export default async function (userId: number) { ], }, include: { - members: true, + members: { + include: { + user: { + select: { + email: true, + name: true, + }, + }, + }, + }, }, }); diff --git a/lib/api/controllers/users/getUsers.ts b/lib/api/controllers/users/getUsers.ts index f1780a4..1da4aee 100644 --- a/lib/api/controllers/users/getUsers.ts +++ b/lib/api/controllers/users/getUsers.ts @@ -13,6 +13,7 @@ export default async function (email: string) { }); const unsensitiveUserInfo = { + id: user?.id, name: user?.name, email: user?.email, createdAt: user?.createdAt, diff --git a/pages/collections/[id].tsx b/pages/collections/[id].tsx index 748a427..d6c5653 100644 --- a/pages/collections/[id].tsx +++ b/pages/collections/[id].tsx @@ -7,9 +7,10 @@ import Dropdown from "@/components/Dropdown"; import LinkList from "@/components/LinkList"; import Modal from "@/components/Modal"; import AddLink from "@/components/Modal/AddLink"; +import EditCollection from "@/components/Modal/EditCollection"; import useCollectionStore from "@/store/collections"; import useLinkStore from "@/store/links"; -import { ExtendedLink } from "@/types/global"; +import { ExtendedCollection, ExtendedLink } from "@/types/global"; import { faAdd, faEllipsis, @@ -30,7 +31,9 @@ export default function () { const [expandDropdown, setExpandDropdown] = useState(false); const [linkModal, setLinkModal] = useState(false); - const [activeCollection, setActiveCollection] = useState(); + const [collectionModal, setCollectionModal] = useState(false); + const [activeCollection, setActiveCollection] = + useState(); const [linksByCollection, setLinksByCollection] = useState(links); @@ -38,6 +41,10 @@ export default function () { setLinkModal(!linkModal); }; + const toggleCollectionModal = () => { + setCollectionModal(!collectionModal); + }; + useEffect(() => { setLinksByCollection( links.filter((e) => e.collection.id === Number(router.query.id)) @@ -82,6 +89,10 @@ export default function () { { name: "Edit Collection", icon: , + onClick: () => { + toggleCollectionModal(); + setExpandDropdown(false); + }, }, { name: "Delete Collection", @@ -101,6 +112,15 @@ export default function () { ) : null} + + {collectionModal && activeCollection ? ( + + + + ) : null}
{linksByCollection.map((e, i) => { diff --git a/prisma/migrations/20230424185742_/migration.sql b/prisma/migrations/20230427184353_init/migration.sql similarity index 100% rename from prisma/migrations/20230424185742_/migration.sql rename to prisma/migrations/20230427184353_init/migration.sql diff --git a/types/global.ts b/types/global.ts index 21500a9..5da7f89 100644 --- a/types/global.ts +++ b/types/global.ts @@ -3,7 +3,7 @@ // 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 { Collection, Link, Tag, UsersAndCollections } from "@prisma/client"; +import { Collection, Link, Tag } from "@prisma/client"; export interface ExtendedLink extends Link { tags: Tag[]; @@ -34,5 +34,15 @@ export interface NewCollection { } export interface ExtendedCollection extends Collection { - members: UsersAndCollections[]; + members: { + collectionId: number; + userId: number; + canCreate: boolean; + canUpdate: boolean; + canDelete: boolean; + user: { + name: string; + email: string; + }; + }[]; }