diff --git a/.env.sample b/.env.sample index 975e871..f8fc24e 100644 --- a/.env.sample +++ b/.env.sample @@ -14,6 +14,7 @@ AUTOSCROLL_TIMEOUT= NEXT_PUBLIC_DISABLE_REGISTRATION= NEXT_PUBLIC_DISABLE_LOGIN= RE_ARCHIVE_LIMIT= +NEXT_PUBLIC_MAX_UPLOAD_SIZE= # AWS S3 Settings SPACES_KEY= diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1 @@ +{} diff --git a/components/AnnouncementBar.tsx b/components/AnnouncementBar.tsx index 6e46eea..e20d3d9 100644 --- a/components/AnnouncementBar.tsx +++ b/components/AnnouncementBar.tsx @@ -9,7 +9,7 @@ type Props = { export default function AnnouncementBar({ toggleAnnouncementBar }: Props) { return ( -
+
🎉️{" "} diff --git a/components/Checkbox.tsx b/components/Checkbox.tsx index feb351c..5c95bbe 100644 --- a/components/Checkbox.tsx +++ b/components/Checkbox.tsx @@ -12,23 +12,17 @@ type Props = { export default function Checkbox({ label, state, className, onClick }: Props) { return ( ); } diff --git a/components/CollectionCard.tsx b/components/CollectionCard.tsx index c382f6e..97e0b63 100644 --- a/components/CollectionCard.tsx +++ b/components/CollectionCard.tsx @@ -2,30 +2,25 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faEllipsis, faGlobe, faLink } from "@fortawesome/free-solid-svg-icons"; import Link from "next/link"; import { CollectionIncludingMembersAndLinkCount } from "@/types/global"; -import Dropdown from "./Dropdown"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import ProfilePhoto from "./ProfilePhoto"; import { faCalendarDays } from "@fortawesome/free-regular-svg-icons"; -import useModalStore from "@/store/modals"; import usePermissions from "@/hooks/usePermissions"; -import { useTheme } from "next-themes"; +import useLocalSettingsStore from "@/store/localSettings"; +import getPublicUserData from "@/lib/client/getPublicUserData"; +import useAccountStore from "@/store/account"; +import EditCollectionModal from "./ModalContent/EditCollectionModal"; +import EditCollectionSharingModal from "./ModalContent/EditCollectionSharingModal"; +import DeleteCollectionModal from "./ModalContent/DeleteCollectionModal"; type Props = { collection: CollectionIncludingMembersAndLinkCount; className?: string; }; -type DropdownTrigger = - | { - x: number; - y: number; - } - | false; - export default function CollectionCard({ collection, className }: Props) { - const { setModal } = useModalStore(); - - const { theme } = useTheme(); + const { settings } = useLocalSettingsStore(); + const { account } = useAccountStore(); const formattedDate = new Date(collection.createdAt as string).toLocaleString( "en-US", @@ -36,144 +31,183 @@ export default function CollectionCard({ collection, className }: Props) { } ); - const [expandDropdown, setExpandDropdown] = useState(false); - const permissions = usePermissions(collection.id as number); + const [collectionOwner, setCollectionOwner] = useState({ + id: null as unknown as number, + name: "", + username: "", + image: "", + }); + + useEffect(() => { + const fetchOwner = async () => { + if (collection && collection.ownerId !== account.id) { + const owner = await getPublicUserData(collection.ownerId as number); + setCollectionOwner(owner); + } else if (collection && collection.ownerId === account.id) { + setCollectionOwner({ + id: account.id as number, + name: account.name, + username: account.username as string, + image: account.image as string, + }); + } + }; + + fetchOwner(); + }, [collection]); + + const [editCollectionModal, setEditCollectionModal] = useState(false); + const [editCollectionSharingModal, setEditCollectionSharingModal] = + useState(false); + const [deleteCollectionModal, setDeleteCollectionModal] = useState(false); + return ( - <> +
+
+
+ +
+
    + {permissions === true ? ( +
  • +
    { + (document?.activeElement as HTMLElement)?.blur(); + setEditCollectionModal(true); + }} + > + Edit Collection Info +
    +
  • + ) : undefined} +
  • +
    { + (document?.activeElement as HTMLElement)?.blur(); + setEditCollectionSharingModal(true); + }} + > + {permissions === true ? "Share and Collaborate" : "View Team"} +
    +
  • +
  • +
    { + (document?.activeElement as HTMLElement)?.blur(); + setDeleteCollectionModal(true); + }} + > + {permissions === true ? "Delete Collection" : "Leave Collection"} +
    +
  • +
+
setEditCollectionSharingModal(true)} + > + {collectionOwner.id ? ( + + ) : undefined} + {collection.members + .sort((a, b) => (a.userId as number) - (b.userId as number)) + .map((e, i) => { + return ( + + ); + }) + .slice(0, 3)} + {collection.members.length - 3 > 0 ? ( +
+
+ +{collection.members.length - 3} +
+
+ ) : null} +
+ -
setExpandDropdown({ x: e.clientX, y: e.clientY })} - id={"expand-dropdown" + collection.id} - className="inline-flex absolute top-5 right-5 rounded-md cursor-pointer hover:bg-slate-200 hover:dark:bg-neutral-700 duration-100 p-1" - > - -
- -

- {collection.name} -

-
-
- {collection.members - .sort((a, b) => (a.userId as number) - (b.userId as number)) - .map((e, i) => { - return ( - - ); - }) - .slice(0, 4)} - {collection.members.length - 4 > 0 ? ( -
- +{collection.members.length - 4} -
- ) : null} -
-
-
+
+
+

+ {collection.name} +

+
+
+ +
+
+
{collection.isPublic ? ( ) : undefined} {collection._count && collection._count.links}
-
- -

{formattedDate}

+
+

+ {" "} + {formattedDate} +

- -
- {expandDropdown ? ( - { - collection && - setModal({ - modal: "COLLECTION", - state: true, - method: "UPDATE", - isOwner: permissions === true, - active: collection, - }); - setExpandDropdown(false); - }, - } - : undefined, - { - name: permissions === true ? "Share/Collaborate" : "View Team", - onClick: () => { - collection && - setModal({ - modal: "COLLECTION", - state: true, - method: "UPDATE", - isOwner: permissions === true, - active: collection, - defaultIndex: permissions === true ? 1 : 0, - }); - setExpandDropdown(false); - }, - }, - - { - name: - permissions === true ? "Delete Collection" : "Leave Collection", - onClick: () => { - collection && - setModal({ - modal: "COLLECTION", - state: true, - method: "UPDATE", - isOwner: permissions === true, - active: collection, - defaultIndex: permissions === true ? 2 : 1, - }); - setExpandDropdown(false); - }, - }, - ]} - onClickOutside={(e: Event) => { - const target = e.target as HTMLInputElement; - if (target.id !== "expand-dropdown" + collection.id) - setExpandDropdown(false); - }} - className="w-fit" +
+ + {editCollectionModal ? ( + setEditCollectionModal(false)} + activeCollection={collection} /> - ) : null} - + ) : undefined} + {editCollectionSharingModal ? ( + setEditCollectionSharingModal(false)} + activeCollection={collection} + /> + ) : undefined} + {deleteCollectionModal ? ( + setDeleteCollectionModal(false)} + activeCollection={collection} + /> + ) : undefined} +
); } diff --git a/components/DashboardItem.tsx b/components/DashboardItem.tsx index 3de882e..70ffd55 100644 --- a/components/DashboardItem.tsx +++ b/components/DashboardItem.tsx @@ -10,19 +10,12 @@ type Props = { export default function dashboardItem({ name, value, icon }: Props) { return (
-
- +
+
-

- {name} -

-

- {value} -

+

{name}

+

{value}

); diff --git a/components/Dropdown.tsx b/components/Dropdown.tsx index ac1ee59..4a48ab7 100644 --- a/components/Dropdown.tsx +++ b/components/Dropdown.tsx @@ -78,13 +78,13 @@ export default function Dropdown({ onClickOutside={onClickOutside} className={`${ className || "" - } py-1 shadow-md border border-sky-100 dark:border-neutral-700 bg-gray-50 dark:bg-neutral-800 rounded-md flex flex-col z-20`} + } py-1 shadow-md border border-neutral-content bg-base-200 rounded-md flex flex-col z-20`} > {items.map((e, i) => { const inner = e && (
-
-

{e.name}

+
+

{e.name}

); diff --git a/components/FilterSearchDropdown.tsx b/components/FilterSearchDropdown.tsx index 90648e0..012a370 100644 --- a/components/FilterSearchDropdown.tsx +++ b/components/FilterSearchDropdown.tsx @@ -1,9 +1,8 @@ -import React, { SetStateAction } from "react"; -import ClickAwayHandler from "./ClickAwayHandler"; -import Checkbox from "./Checkbox"; +import React from "react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faFilter } from "@fortawesome/free-solid-svg-icons"; type Props = { - setFilterDropdown: (value: SetStateAction) => void; setSearchFilter: Function; searchFilter: { name: boolean; @@ -15,64 +14,123 @@ type Props = { }; export default function FilterSearchDropdown({ - setFilterDropdown, setSearchFilter, searchFilter, }: Props) { return ( - { - const target = e.target as HTMLInputElement; - if (target.id !== "filter-dropdown") setFilterDropdown(false); - }} - className="absolute top-8 right-0 border border-sky-100 dark:border-neutral-700 shadow-md bg-gray-50 dark:bg-neutral-800 rounded-md p-2 z-20 w-40" - > -

- Filter by -

-
- - setSearchFilter({ ...searchFilter, name: !searchFilter.name }) - } - /> - - setSearchFilter({ ...searchFilter, url: !searchFilter.url }) - } - /> - - setSearchFilter({ - ...searchFilter, - description: !searchFilter.description, - }) - } - /> - - setSearchFilter({ - ...searchFilter, - textContent: !searchFilter.textContent, - }) - } - /> - - setSearchFilter({ ...searchFilter, tags: !searchFilter.tags }) - } +
+
+
- +
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
+
); } diff --git a/components/InputSelect/CollectionSelection.tsx b/components/InputSelect/CollectionSelection.tsx index 991557f..71dc075 100644 --- a/components/InputSelect/CollectionSelection.tsx +++ b/components/InputSelect/CollectionSelection.tsx @@ -1,9 +1,9 @@ import useCollectionStore from "@/store/collections"; import { useRouter } from "next/router"; import { useEffect, useState } from "react"; -import Select from "react-select"; import { styles } from "./styles"; import { Options } from "./types"; +import CreatableSelect from "react-select/creatable"; type Props = { onChange: any; @@ -43,8 +43,8 @@ export default function CollectionSelection({ onChange, defaultValue }: Props) { }, [collections]); return ( -