import { CollectionIncludingMembersAndLinkCount, LinkIncludingShortenedCollectionAndTags, } from "@/types/global"; import { faFolder, faEllipsis, faLink, } 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"; import { faCalendarDays } from "@fortawesome/free-regular-svg-icons"; import usePermissions from "@/hooks/usePermissions"; import { toast } from "react-hot-toast"; import isValidUrl from "@/lib/client/isValidUrl"; type Props = { link: LinkIncludingShortenedCollectionAndTags; count: number; className?: string; }; export default function LinkCard({ link, count, className }: Props) { const { setModal } = useModalStore(); const permissions = usePermissions(link.collection.id as number); const [expandDropdown, setExpandDropdown] = useState(false); const { collections } = useCollectionStore(); const { links } = useLinkStore(); const { account } = useAccountStore(); let shortendURL; try { shortendURL = new URL(link.url).host.toLowerCase(); } catch (error) { console.log(error); } 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, links]); 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 = isValidUrl(link.url) ? new URL(link.url) : undefined; const formattedDate = new Date(link.createdAt as string).toLocaleString( "en-US", { year: "numeric", month: "short", day: "numeric", } ); return (
{(permissions === true || permissions?.canUpdate || permissions?.canDelete) && (
setExpandDropdown(!expandDropdown)} id={"expand-dropdown" + link.id} className="text-gray-500 dark:text-gray-300 inline-flex rounded-md cursor-pointer hover:bg-slate-200 dark:hover:bg-neutral-700 absolute right-5 top-5 z-10 duration-100 p-1" >
)}
{ setModal({ modal: "LINK", state: true, method: "UPDATE", isOwnerOrMod: permissions === true || (permissions?.canUpdate as boolean), active: link, }); }} className="flex items-start gap-5 sm:gap-10 h-full w-full p-5" > {url && ( { const target = e.target as HTMLElement; target.style.display = "none"; }} /> )}

{count + 1}

{link.name || link.description}

{collection?.name}

{shortendURL}

{formattedDate}

{expandDropdown ? ( { setModal({ modal: "LINK", state: true, method: "UPDATE", isOwnerOrMod: permissions === true || permissions?.canUpdate, active: link, defaultIndex: 1, }); setExpandDropdown(false); }, } : undefined, permissions === true || permissions?.canDelete ? { name: "Delete", onClick: deleteLink, } : undefined, ]} 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}
); }