diff --git a/components/CompactLinkCard.tsx b/components/CompactLinkCard.tsx new file mode 100644 index 0000000..b2c013e --- /dev/null +++ b/components/CompactLinkCard.tsx @@ -0,0 +1,164 @@ +import { + CollectionIncludingMembersAndLinkCount, + LinkIncludingShortenedCollectionAndTags, +} from "@/types/global"; +import { faFolder, faEllipsis } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { useEffect, useState } from "react"; +import Image from "next/image"; +import Dropdown from "./Dropdown"; +import useLinkStore from "@/store/links"; +import useCollectionStore from "@/store/collections"; +import useAccountStore from "@/store/account"; +import useModalStore from "@/store/modals"; + +type Props = { + link: LinkIncludingShortenedCollectionAndTags; + count: number; + className?: string; +}; + +export default function LinkCard({ link, count, className }: Props) { + const { setModal } = useModalStore(); + + const [expandDropdown, setExpandDropdown] = useState(false); + + const { collections } = useCollectionStore(); + + const { account } = useAccountStore(); + + const [collection, setCollection] = + useState( + collections.find( + (e) => e.id === link.collection.id + ) as CollectionIncludingMembersAndLinkCount + ); + + useEffect(() => { + setCollection( + collections.find( + (e) => e.id === link.collection.id + ) as CollectionIncludingMembersAndLinkCount + ); + }, [collections]); + + const { removeLink, updateLink } = useLinkStore(); + + const url = new URL(link.url); + const formattedDate = new Date(link.createdAt as string).toLocaleString( + "en-US", + { + year: "numeric", + month: "short", + day: "numeric", + } + ); + + return ( +
+
setExpandDropdown(!expandDropdown)} + id={"expand-dropdown" + link.id} + className="text-gray-500 inline-flex rounded-md cursor-pointer hover:bg-slate-200 absolute right-5 top-5 z-10 duration-100 p-1" + > + +
+ +
console.log("hi!")} + className="flex items-start gap-5 sm:gap-10 h-full w-full" + > + { + const target = e.target as HTMLElement; + target.style.opacity = "0"; + }} + /> + +
+
+
+

{count + 1}.

+

+ {link.name} +

+
+
+
+ +

+ {collection?.name} +

+
+
+

{formattedDate}

+
+
+
+ {expandDropdown ? ( + { + updateLink({ + ...link, + pinnedBy: + link?.pinnedBy && link.pinnedBy[0] + ? undefined + : [{ id: account.id }], + }); + setExpandDropdown(false); + }, + }, + { + name: "Edit", + onClick: () => { + setModal({ + modal: "LINK", + state: true, + method: "UPDATE", + active: link, + }); + setExpandDropdown(false); + }, + }, + { + name: "Delete", + onClick: () => { + removeLink(link); + setExpandDropdown(false); + }, + }, + ]} + onClickOutside={(e: Event) => { + const target = e.target as HTMLInputElement; + if (target.id !== "expand-dropdown" + link.id) + setExpandDropdown(false); + }} + className="absolute top-12 right-5 w-36" + /> + ) : null} +
+ ); +} diff --git a/components/Modal/Collection/index.tsx b/components/Modal/Collection/index.tsx index 6be92c8..20314c6 100644 --- a/components/Modal/Collection/index.tsx +++ b/components/Modal/Collection/index.tsx @@ -5,13 +5,21 @@ import TeamManagement from "./TeamManagement"; import { useState } from "react"; import DeleteCollection from "./DeleteCollection"; -type Props = { - toggleCollectionModal: Function; - activeCollection: CollectionIncludingMembersAndLinkCount; - method: "CREATE" | "UPDATE"; - className?: string; - defaultIndex?: number; -}; +type Props = + | { + toggleCollectionModal: Function; + activeCollection: CollectionIncludingMembersAndLinkCount; + method: "UPDATE"; + className?: string; + defaultIndex?: number; + } + | { + toggleCollectionModal: Function; + activeCollection?: CollectionIncludingMembersAndLinkCount; + method: "CREATE"; + className?: string; + defaultIndex?: number; + }; export default function CollectionModal({ className, @@ -21,7 +29,15 @@ export default function CollectionModal({ method, }: Props) { const [collection, setCollection] = - useState(activeCollection); + useState( + activeCollection || { + name: "", + description: "", + color: "#0ea5e9", + isPublic: false, + members: [], + } + ); return (
diff --git a/components/Modal/LinkModal.tsx b/components/Modal/LinkModal.tsx index 858801a..d4d4a6c 100644 --- a/components/Modal/LinkModal.tsx +++ b/components/Modal/LinkModal.tsx @@ -57,7 +57,7 @@ export default function EditLink({ (e) => e.id == Number(router.query.id) ); - if (currentCollection) + if (currentCollection && currentCollection.ownerId) setLink({ ...link, collection: { diff --git a/components/Navbar.tsx b/components/Navbar.tsx index 6d8a77a..290b9d2 100644 --- a/components/Navbar.tsx +++ b/components/Navbar.tsx @@ -1,10 +1,6 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { signOut } from "next-auth/react"; -import { - faPlus, - faChevronDown, - faBars, -} from "@fortawesome/free-solid-svg-icons"; +import { faPlus, faBars } from "@fortawesome/free-solid-svg-icons"; import { useEffect, useState } from "react"; import Dropdown from "@/components/Dropdown"; import ClickAwayHandler from "@/components/ClickAwayHandler"; @@ -67,7 +63,7 @@ export default function Navbar() {
setProfileDropdown(!profileDropdown)} id="profile-dropdown" > @@ -75,22 +71,12 @@ export default function Navbar() { src={account.profilePic} className="sm:group-hover:h-8 sm:group-hover:w-8 duration-100" /> -
-

- {account.name} -

- -
+ {account.name} +

{profileDropdown ? ( diff --git a/pages/dashboard.tsx b/pages/dashboard.tsx index 83e35c4..10f5248 100644 --- a/pages/dashboard.tsx +++ b/pages/dashboard.tsx @@ -7,7 +7,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import MainLayout from "@/layouts/MainLayout"; import useLinkStore from "@/store/links"; import useTagStore from "@/store/tags"; -import LinkCard from "@/components/LinkCard"; +import CompactLinkCard from "@/components/CompactLinkCard"; import Link from "next/link"; import CollectionCard from "@/components/CollectionCard"; import { Disclosure, Transition } from "@headlessui/react"; @@ -39,6 +39,10 @@ export default function Dashboard() { useLinks({ pinnedOnly: true, sort: 0 }); + useEffect(() => { + console.log(links); + }, [links]); + useEffect(() => { setNumberOfLinks( collections.reduce( @@ -145,11 +149,11 @@ export default function Dashboard() { leaveFrom="transform opacity-100 translate-y-0" leaveTo="transform opacity-0 -translate-y-3" > - + {links - .filter((e) => e.pinnedBy) + .filter((e) => e.pinnedBy && e.pinnedBy[0]) .map((e, i) => ( - + ))} diff --git a/public/android-chrome-192x192.png b/public/android-chrome-192x192.png index 7e10908..e20c59d 100644 Binary files a/public/android-chrome-192x192.png and b/public/android-chrome-192x192.png differ diff --git a/public/android-chrome-512x512.png b/public/android-chrome-512x512.png index 7dd4183..6e77e38 100644 Binary files a/public/android-chrome-512x512.png and b/public/android-chrome-512x512.png differ diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png index 02568a1..962a140 100644 Binary files a/public/apple-touch-icon.png and b/public/apple-touch-icon.png differ diff --git a/public/favicon-16x16.png b/public/favicon-16x16.png index 4045c7d..5fae853 100644 Binary files a/public/favicon-16x16.png and b/public/favicon-16x16.png differ diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png index 99c3808..0fa9a5b 100644 Binary files a/public/favicon-32x32.png and b/public/favicon-32x32.png differ diff --git a/public/favicon.ico b/public/favicon.ico index 9844cef..65bcb6d 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/public/icon.png b/public/icon.png index ef4dfaf..e61f111 100644 Binary files a/public/icon.png and b/public/icon.png differ diff --git a/store/modals.ts b/store/modals.ts index f2de102..f8c4970 100644 --- a/store/modals.ts +++ b/store/modals.ts @@ -27,10 +27,17 @@ type Modal = | { modal: "COLLECTION"; state: boolean; - method: "CREATE" | "UPDATE"; + method: "UPDATE"; active: CollectionIncludingMembersAndLinkCount; defaultIndex?: number; } + | { + modal: "COLLECTION"; + state: boolean; + method: "CREATE"; + active?: CollectionIncludingMembersAndLinkCount; + defaultIndex?: number; + } | null; type ModalsStore = { diff --git a/types/global.ts b/types/global.ts index ec21ed6..b8e2161 100644 --- a/types/global.ts +++ b/types/global.ts @@ -28,10 +28,11 @@ export interface Member { } export interface CollectionIncludingMembersAndLinkCount - extends Omit { + extends Omit { id?: number; + ownerId?: number; createdAt?: string; - _count: { links: number }; + _count?: { links: number }; members: Member[]; }