much cleaner sorting logic

This commit is contained in:
Daniel 2023-06-14 08:10:23 +03:30
parent 8d094f320a
commit 6323badbaf
16 changed files with 135 additions and 282 deletions

View File

@ -8,7 +8,7 @@ type Props = {
searchFilter: { searchFilter: {
name: boolean; name: boolean;
url: boolean; url: boolean;
title: boolean; description: boolean;
collection: boolean; collection: boolean;
tags: boolean; tags: boolean;
}; };
@ -44,10 +44,13 @@ export default function FilterSearchDropdown({
} }
/> />
<Checkbox <Checkbox
label="Title" label="Description"
state={searchFilter.title} state={searchFilter.description}
onClick={() => onClick={() =>
setSearchFilter({ ...searchFilter, title: !searchFilter.title }) setSearchFilter({
...searchFilter,
description: !searchFilter.description,
})
} }
/> />
<Checkbox <Checkbox

View File

@ -111,7 +111,7 @@ export default function LinkCard({ link, count, className }: Props) {
</p> </p>
</div> </div>
<p className="text-gray-500 text-sm font-medium line-clamp-3 w-4/5"> <p className="text-gray-500 text-sm font-medium line-clamp-3 w-4/5">
{link.title} {link.description}
</p> </p>
<div className="flex gap-3 items-center flex-wrap my-3"> <div className="flex gap-3 items-center flex-wrap my-3">
<Link href={`/collections/${link.collection.id}`}> <Link href={`/collections/${link.collection.id}`}>

View File

@ -36,7 +36,7 @@ export default function EditLink({
: { : {
name: "", name: "",
url: "", url: "",
title: "", description: "",
tags: [], tags: [],
collection: { collection: {
name: "", name: "",
@ -106,7 +106,7 @@ export default function EditLink({
{method === "UPDATE" ? ( {method === "UPDATE" ? (
<p className="text-gray-500"> <p className="text-gray-500">
<b>{shortendURL}</b> | {link.title} <b>{shortendURL}</b> | {link.description}
</p> </p>
) : null} ) : null}

View File

@ -55,7 +55,9 @@ export default function LinkCard({ link, count }: Props) {
<p className="text-lg text-sky-500 font-bold">{link.name}</p> <p className="text-lg text-sky-500 font-bold">{link.name}</p>
</div> </div>
<p className="text-gray-500 text-sm font-medium">{link.title}</p> <p className="text-gray-500 text-sm font-medium">
{link.description}
</p>
<div className="flex gap-2 items-center flex-wrap mt-2"> <div className="flex gap-2 items-center flex-wrap mt-2">
<p className="text-gray-500">{formattedDate}</p> <p className="text-gray-500">{formattedDate}</p>

View File

@ -1,18 +1,19 @@
import React, { ChangeEvent } from "react"; import React, { Dispatch, SetStateAction } from "react";
import ClickAwayHandler from "./ClickAwayHandler"; import ClickAwayHandler from "./ClickAwayHandler";
import RadioButton from "./RadioButton"; import RadioButton from "./RadioButton";
import { Sort } from "@/types/global"; import { Sort } from "@/types/global";
type Props = { type Props = {
handleSortChange: (e: Sort) => void;
sortBy: Sort; sortBy: Sort;
setSort: Dispatch<SetStateAction<Sort>>;
toggleSortDropdown: Function; toggleSortDropdown: Function;
}; };
export default function SortLinkDropdown({ export default function SortDropdown({
handleSortChange,
sortBy, sortBy,
toggleSortDropdown, toggleSortDropdown,
setSort,
}: Props) { }: Props) {
return ( return (
<ClickAwayHandler <ClickAwayHandler
@ -27,37 +28,37 @@ export default function SortLinkDropdown({
<RadioButton <RadioButton
label="Name (A-Z)" label="Name (A-Z)"
state={sortBy === Sort.NameAZ} state={sortBy === Sort.NameAZ}
onClick={() => handleSortChange(Sort.NameAZ)} onClick={() => setSort(Sort.NameAZ)}
/> />
<RadioButton <RadioButton
label="Name (Z-A)" label="Name (Z-A)"
state={sortBy === Sort.NameZA} state={sortBy === Sort.NameZA}
onClick={() => handleSortChange(Sort.NameZA)} onClick={() => setSort(Sort.NameZA)}
/> />
<RadioButton <RadioButton
label="Title (A-Z)" label="Description (A-Z)"
state={sortBy === Sort.TitleAZ} state={sortBy === Sort.DescriptionAZ}
onClick={() => handleSortChange(Sort.TitleAZ)} onClick={() => setSort(Sort.DescriptionAZ)}
/> />
<RadioButton <RadioButton
label="Title (Z-A)" label="Description (Z-A)"
state={sortBy === Sort.TitleZA} state={sortBy === Sort.DescriptionZA}
onClick={() => handleSortChange(Sort.TitleZA)} onClick={() => setSort(Sort.DescriptionZA)}
/> />
<RadioButton <RadioButton
label="Date (Newest First)" label="Date (Newest First)"
state={sortBy === Sort.DateNewestFirst} state={sortBy === Sort.DateNewestFirst}
onClick={() => handleSortChange(Sort.DateNewestFirst)} onClick={() => setSort(Sort.DateNewestFirst)}
/> />
<RadioButton <RadioButton
label="Date (Oldest First)" label="Date (Oldest First)"
state={sortBy === Sort.DateOldestFirst} state={sortBy === Sort.DateOldestFirst}
onClick={() => handleSortChange(Sort.DateOldestFirst)} onClick={() => setSort(Sort.DateOldestFirst)}
/> />
</div> </div>
</ClickAwayHandler> </ClickAwayHandler>

52
hooks/useSort.tsx Normal file
View File

@ -0,0 +1,52 @@
import {
CollectionIncludingMembers,
LinkIncludingCollectionAndTags,
Sort,
} from "@/types/global";
import { SetStateAction, useEffect } from "react";
type Props<
T extends CollectionIncludingMembers | LinkIncludingCollectionAndTags
> = {
sortBy: Sort;
data: T[];
setData: (value: SetStateAction<T[]>) => void;
};
export default function useSort<
T extends CollectionIncludingMembers | LinkIncludingCollectionAndTags
>({ sortBy, data, setData }: Props<T>) {
useEffect(() => {
const dataArray = [...data];
if (sortBy === Sort.NameAZ)
setData(dataArray.sort((a, b) => a.name.localeCompare(b.name)));
else if (sortBy === Sort.DescriptionAZ)
setData(
dataArray.sort((a, b) => a.description.localeCompare(b.description))
);
else if (sortBy === Sort.NameZA)
setData(dataArray.sort((a, b) => b.name.localeCompare(a.name)));
else if (sortBy === Sort.DescriptionZA)
setData(
dataArray.sort((a, b) => b.description.localeCompare(a.description))
);
else if (sortBy === Sort.DateNewestFirst)
setData(
dataArray.sort(
(a, b) =>
new Date(b.createdAt as string).getTime() -
new Date(a.createdAt as string).getTime()
)
);
else if (sortBy === Sort.DateOldestFirst)
setData(
dataArray.sort(
(a, b) =>
new Date(a.createdAt as string).getTime() -
new Date(b.createdAt as string).getTime()
)
);
}, [sortBy, data]);
}

View File

@ -72,7 +72,7 @@ export default async function postLink(
}, },
})), })),
}, },
title, description: title,
}, },
include: { tags: true, collection: true }, include: { tags: true, collection: true },
}); });

View File

@ -14,7 +14,7 @@ export default async function getCollection(collectionId: number) {
id: true, id: true,
name: true, name: true,
url: true, url: true,
title: true, description: true,
collectionId: true, collectionId: true,
createdAt: true, createdAt: true,
}, },

View File

@ -14,8 +14,9 @@ import { useEffect, useState } from "react";
import MainLayout from "@/layouts/MainLayout"; import MainLayout from "@/layouts/MainLayout";
import { useSession } from "next-auth/react"; import { useSession } from "next-auth/react";
import ProfilePhoto from "@/components/ProfilePhoto"; import ProfilePhoto from "@/components/ProfilePhoto";
import SortLinkDropdown from "@/components/SortLinkDropdown"; import SortDropdown from "@/components/SortDropdown";
import useModalStore from "@/store/modals"; import useModalStore from "@/store/modals";
import useSort from "@/hooks/useSort";
export default function Index() { export default function Index() {
const { setModal } = useModalStore(); const { setModal } = useModalStore();
@ -36,46 +37,13 @@ export default function Index() {
const [sortedLinks, setSortedLinks] = useState(links); const [sortedLinks, setSortedLinks] = useState(links);
const handleSortChange = (e: Sort) => { useSort({ sortBy, setData: setSortedLinks, data: links });
setSortBy(e);
};
useEffect(() => { useEffect(() => {
setActiveCollection( setActiveCollection(
collections.find((e) => e.id === Number(router.query.id)) collections.find((e) => e.id === Number(router.query.id))
); );
}, [router, collections]);
// Sorting logic
const linksArray = [
...links.filter((e) => e.collection.id === Number(router.query.id)),
];
if (sortBy === Sort.NameAZ)
setSortedLinks(linksArray.sort((a, b) => a.name.localeCompare(b.name)));
else if (sortBy === Sort.TitleAZ)
setSortedLinks(linksArray.sort((a, b) => a.title.localeCompare(b.title)));
else if (sortBy === Sort.NameZA)
setSortedLinks(linksArray.sort((a, b) => b.name.localeCompare(a.name)));
else if (sortBy === Sort.TitleZA)
setSortedLinks(linksArray.sort((a, b) => b.title.localeCompare(a.title)));
else if (sortBy === Sort.DateNewestFirst)
setSortedLinks(
linksArray.sort(
(a, b) =>
new Date(b.createdAt as string).getTime() -
new Date(a.createdAt as string).getTime()
)
);
else if (sortBy === Sort.DateOldestFirst)
setSortedLinks(
linksArray.sort(
(a, b) =>
new Date(a.createdAt as string).getTime() -
new Date(b.createdAt as string).getTime()
)
);
}, [links, router, collections, sortBy]);
return ( return (
<MainLayout> <MainLayout>
@ -166,9 +134,9 @@ export default function Index() {
</div> </div>
{sortDropdown ? ( {sortDropdown ? (
<SortLinkDropdown <SortDropdown
handleSortChange={handleSortChange}
sortBy={sortBy} sortBy={sortBy}
setSort={setSortBy}
toggleSortDropdown={() => setSortDropdown(!sortDropdown)} toggleSortDropdown={() => setSortDropdown(!sortDropdown)}
/> />
) : null} ) : null}

View File

@ -8,68 +8,26 @@ import {
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import CollectionCard from "@/components/CollectionCard"; import CollectionCard from "@/components/CollectionCard";
import Dropdown from "@/components/Dropdown"; import Dropdown from "@/components/Dropdown";
import { ChangeEvent, useEffect, useState } from "react"; import { useState } from "react";
import MainLayout from "@/layouts/MainLayout"; import MainLayout from "@/layouts/MainLayout";
import ClickAwayHandler from "@/components/ClickAwayHandler";
import RadioButton from "@/components/RadioButton";
import { useSession } from "next-auth/react"; import { useSession } from "next-auth/react";
import useModalStore from "@/store/modals"; import useModalStore from "@/store/modals";
import SortDropdown from "@/components/SortDropdown";
import { Sort } from "@/types/global";
import useSort from "@/hooks/useSort";
export default function Collections() { export default function Collections() {
const { collections } = useCollectionStore(); const { collections } = useCollectionStore();
const [expandDropdown, setExpandDropdown] = useState(false); const [expandDropdown, setExpandDropdown] = useState(false);
const [sortDropdown, setSortDropdown] = useState(false); const [sortDropdown, setSortDropdown] = useState(false);
const [sortBy, setSortBy] = useState("Name (A-Z)"); const [sortBy, setSortBy] = useState<Sort>(Sort.NameAZ);
const [sortedCollections, setSortedCollections] = useState(collections); const [sortedCollections, setSortedCollections] = useState(collections);
const session = useSession(); const session = useSession();
const { setModal } = useModalStore(); const { setModal } = useModalStore();
const handleSortChange = (event: ChangeEvent<HTMLInputElement>) => { useSort({ sortBy, setData: setSortedCollections, data: collections });
setSortBy(event.target.value);
};
useEffect(() => {
const collectionsArray = [...collections];
if (sortBy === "Name (A-Z)")
setSortedCollections(
collectionsArray.sort((a, b) => a.name.localeCompare(b.name))
);
else if (sortBy === "Description (A-Z)")
setSortedCollections(
collectionsArray.sort((a, b) =>
a.description.localeCompare(b.description)
)
);
else if (sortBy === "Name (Z-A)")
setSortedCollections(
collectionsArray.sort((a, b) => b.name.localeCompare(a.name))
);
else if (sortBy === "Description (Z-A)")
setSortedCollections(
collectionsArray.sort((a, b) =>
b.description.localeCompare(a.description)
)
);
else if (sortBy === "Date (Newest First)")
setSortedCollections(
collectionsArray.sort(
(a, b) =>
new Date(b.createdAt as string).getTime() -
new Date(a.createdAt as string).getTime()
)
);
else if (sortBy === "Date (Oldest First)")
setSortedCollections(
collectionsArray.sort(
(a, b) =>
new Date(a.createdAt as string).getTime() -
new Date(b.createdAt as string).getTime()
)
);
}, [collections, sortBy]);
return ( return (
<MainLayout> <MainLayout>
@ -146,54 +104,11 @@ export default function Collections() {
</div> </div>
{sortDropdown ? ( {sortDropdown ? (
<ClickAwayHandler <SortDropdown
onClickOutside={(e: Event) => { sortBy={sortBy}
const target = e.target as HTMLInputElement; setSort={setSortBy}
if (target.id !== "sort-dropdown") setSortDropdown(false); toggleSortDropdown={() => setSortDropdown(!sortDropdown)}
}}
className="absolute top-8 right-0 shadow-md bg-gray-50 rounded-md p-2 z-10 border border-sky-100 w-48"
>
<p className="mb-2 text-sky-900 text-center font-semibold">
Sort by
</p>
<div className="flex flex-col gap-2">
<RadioButton
label="Name (A-Z)"
state={sortBy === "Name (A-Z)"}
onClick={handleSortChange}
/> />
<RadioButton
label="Name (Z-A)"
state={sortBy === "Name (Z-A)"}
onClick={handleSortChange}
/>
<RadioButton
label="Description (A-Z)"
state={sortBy === "Description (A-Z)"}
onClick={handleSortChange}
/>
<RadioButton
label="Description (Z-A)"
state={sortBy === "Description (Z-A)"}
onClick={handleSortChange}
/>
<RadioButton
label="Date (Newest First)"
state={sortBy === "Date (Newest First)"}
onClick={handleSortChange}
/>
<RadioButton
label="Date (Oldest First)"
state={sortBy === "Date (Oldest First)"}
onClick={handleSortChange}
/>
</div>
</ClickAwayHandler>
) : null} ) : null}
</div> </div>
</div> </div>

View File

@ -1,11 +1,12 @@
import LinkCard from "@/components/LinkCard"; import LinkCard from "@/components/LinkCard";
import SortLinkDropdown from "@/components/SortLinkDropdown"; import SortDropdown from "@/components/SortDropdown";
import useSort from "@/hooks/useSort";
import MainLayout from "@/layouts/MainLayout"; import MainLayout from "@/layouts/MainLayout";
import useLinkStore from "@/store/links"; import useLinkStore from "@/store/links";
import { Sort } from "@/types/global"; import { Sort } from "@/types/global";
import { faLink, faSort } from "@fortawesome/free-solid-svg-icons"; import { faLink, faSort } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { ChangeEvent, useEffect, useState } from "react"; import { useState } from "react";
export default function Links() { export default function Links() {
const { links } = useLinkStore(); const { links } = useLinkStore();
@ -14,38 +15,7 @@ export default function Links() {
const [sortBy, setSortBy] = useState<Sort>(Sort.NameAZ); const [sortBy, setSortBy] = useState<Sort>(Sort.NameAZ);
const [sortedLinks, setSortedLinks] = useState(links); const [sortedLinks, setSortedLinks] = useState(links);
const handleSortChange = (e: Sort) => { useSort({ sortBy, setData: setSortedLinks, data: links });
setSortBy(e);
};
useEffect(() => {
const linksArray = [...links];
if (sortBy === Sort.NameAZ)
setSortedLinks(linksArray.sort((a, b) => a.name.localeCompare(b.name)));
else if (sortBy === Sort.TitleAZ)
setSortedLinks(linksArray.sort((a, b) => a.title.localeCompare(b.title)));
else if (sortBy === Sort.NameZA)
setSortedLinks(linksArray.sort((a, b) => b.name.localeCompare(a.name)));
else if (sortBy === Sort.TitleZA)
setSortedLinks(linksArray.sort((a, b) => b.title.localeCompare(a.title)));
else if (sortBy === Sort.DateNewestFirst)
setSortedLinks(
linksArray.sort(
(a, b) =>
new Date(b.createdAt as string).getTime() -
new Date(a.createdAt as string).getTime()
)
);
else if (sortBy === Sort.DateOldestFirst)
setSortedLinks(
linksArray.sort(
(a, b) =>
new Date(a.createdAt as string).getTime() -
new Date(b.createdAt as string).getTime()
)
);
}, [links, sortBy]);
return ( return (
<MainLayout> <MainLayout>
@ -75,9 +45,9 @@ export default function Links() {
</div> </div>
{sortDropdown ? ( {sortDropdown ? (
<SortLinkDropdown <SortDropdown
handleSortChange={handleSortChange}
sortBy={sortBy} sortBy={sortBy}
setSort={setSortBy}
toggleSortDropdown={() => setSortDropdown(!sortDropdown)} toggleSortDropdown={() => setSortDropdown(!sortDropdown)}
/> />
) : null} ) : null}

View File

@ -1,18 +1,19 @@
import FilterSearchDropdown from "@/components/FilterSearchDropdown"; import FilterSearchDropdown from "@/components/FilterSearchDropdown";
import LinkCard from "@/components/LinkCard"; import LinkCard from "@/components/LinkCard";
import SortLinkDropdown from "@/components/SortLinkDropdown"; import SortDropdown from "@/components/SortDropdown";
import useSort from "@/hooks/useSort";
import MainLayout from "@/layouts/MainLayout"; import MainLayout from "@/layouts/MainLayout";
import useLinkStore from "@/store/links"; import useLinkStore from "@/store/links";
import { Sort } from "@/types/global"; import { Sort } from "@/types/global";
import { faFilter, faSearch, faSort } from "@fortawesome/free-solid-svg-icons"; import { faFilter, faSearch, faSort } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { ChangeEvent, useEffect, useState } from "react"; import { useEffect, useState } from "react";
type SearchFilter = { type SearchFilter = {
name: boolean; name: boolean;
url: boolean; url: boolean;
title: boolean; description: boolean;
collection: boolean; collection: boolean;
tags: boolean; tags: boolean;
}; };
@ -29,7 +30,7 @@ export default function Links() {
const [searchFilter, setSearchFilter] = useState<SearchFilter>({ const [searchFilter, setSearchFilter] = useState<SearchFilter>({
name: true, name: true,
url: true, url: true,
title: true, description: true,
collection: true, collection: true,
tags: true, tags: true,
}); });
@ -37,20 +38,20 @@ export default function Links() {
const [filterDropdown, setFilterDropdown] = useState(false); const [filterDropdown, setFilterDropdown] = useState(false);
const [sortDropdown, setSortDropdown] = useState(false); const [sortDropdown, setSortDropdown] = useState(false);
const [sortBy, setSortBy] = useState<Sort>(Sort.NameAZ); const [sortBy, setSortBy] = useState<Sort>(Sort.NameAZ);
const [sortedLinks, setSortedLinks] = useState(links);
const handleSortChange = (e: Sort) => { const [filteredLinks, setFilteredLinks] = useState(links);
setSortBy(e); const [sortedLinks, setSortedLinks] = useState(filteredLinks);
};
useSort({ sortBy, setData: setSortedLinks, data: links });
useEffect(() => { useEffect(() => {
const linksArray = [ setFilteredLinks([
...links.filter((link) => { ...sortedLinks.filter((link) => {
if ( if (
(searchFilter.name && link.name.toLowerCase().includes(routeQuery)) || (searchFilter.name && link.name.toLowerCase().includes(routeQuery)) ||
(searchFilter.url && link.url.toLowerCase().includes(routeQuery)) || (searchFilter.url && link.url.toLowerCase().includes(routeQuery)) ||
(searchFilter.title && (searchFilter.description &&
link.title.toLowerCase().includes(routeQuery)) || link.description.toLowerCase().includes(routeQuery)) ||
(searchFilter.collection && (searchFilter.collection &&
link.collection.name.toLowerCase().includes(routeQuery)) || link.collection.name.toLowerCase().includes(routeQuery)) ||
(searchFilter.tags && (searchFilter.tags &&
@ -60,33 +61,8 @@ export default function Links() {
) )
return true; return true;
}), }),
]; ]);
}, [searchFilter, sortedLinks, router]);
if (sortBy === Sort.NameAZ)
setSortedLinks(linksArray.sort((a, b) => a.name.localeCompare(b.name)));
else if (sortBy === Sort.TitleAZ)
setSortedLinks(linksArray.sort((a, b) => a.title.localeCompare(b.title)));
else if (sortBy === Sort.NameZA)
setSortedLinks(linksArray.sort((a, b) => b.name.localeCompare(a.name)));
else if (sortBy === Sort.TitleZA)
setSortedLinks(linksArray.sort((a, b) => b.title.localeCompare(a.title)));
else if (sortBy === Sort.DateNewestFirst)
setSortedLinks(
linksArray.sort(
(a, b) =>
new Date(b.createdAt as string).getTime() -
new Date(a.createdAt as string).getTime()
)
);
else if (sortBy === Sort.DateOldestFirst)
setSortedLinks(
linksArray.sort(
(a, b) =>
new Date(a.createdAt as string).getTime() -
new Date(b.createdAt as string).getTime()
)
);
}, [links, searchFilter, sortBy, router]);
return ( return (
<MainLayout> <MainLayout>
@ -141,17 +117,17 @@ export default function Links() {
</div> </div>
{sortDropdown ? ( {sortDropdown ? (
<SortLinkDropdown <SortDropdown
handleSortChange={handleSortChange}
sortBy={sortBy} sortBy={sortBy}
setSort={setSortBy}
toggleSortDropdown={() => setSortDropdown(!sortDropdown)} toggleSortDropdown={() => setSortDropdown(!sortDropdown)}
/> />
) : null} ) : null}
</div> </div>
</div> </div>
</div> </div>
{sortedLinks[0] ? ( {filteredLinks[0] ? (
sortedLinks.map((e, i) => { filteredLinks.map((e, i) => {
return <LinkCard key={i} link={e} count={i} />; return <LinkCard key={i} link={e} count={i} />;
}) })
) : ( ) : (

View File

@ -3,12 +3,13 @@ import useLinkStore from "@/store/links";
import { faHashtag, faSort } from "@fortawesome/free-solid-svg-icons"; import { faHashtag, faSort } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { ChangeEvent, useEffect, useState } from "react"; import { useEffect, useState } from "react";
import MainLayout from "@/layouts/MainLayout"; import MainLayout from "@/layouts/MainLayout";
import { Tag } from "@prisma/client"; import { Tag } from "@prisma/client";
import useTagStore from "@/store/tags"; import useTagStore from "@/store/tags";
import SortLinkDropdown from "@/components/SortLinkDropdown"; import SortDropdown from "@/components/SortDropdown";
import { Sort } from "@/types/global"; import { Sort } from "@/types/global";
import useSort from "@/hooks/useSort";
export default function Index() { export default function Index() {
const router = useRouter(); const router = useRouter();
@ -23,46 +24,11 @@ export default function Index() {
const [sortedLinks, setSortedLinks] = useState(links); const [sortedLinks, setSortedLinks] = useState(links);
const handleSortChange = (e: Sort) => { useSort({ sortBy, setData: setSortedLinks, data: links });
setSortBy(e);
};
useEffect(() => { useEffect(() => {
setActiveTag(tags.find((e) => e.id === Number(router.query.id))); setActiveTag(tags.find((e) => e.id === Number(router.query.id)));
}, [router, tags]);
// Sorting logic
const linksArray = [
...links.filter((e) =>
e.tags.some((e) => e.id === Number(router.query.id))
),
];
if (sortBy === Sort.NameAZ)
setSortedLinks(linksArray.sort((a, b) => a.name.localeCompare(b.name)));
else if (sortBy === Sort.TitleAZ)
setSortedLinks(linksArray.sort((a, b) => a.title.localeCompare(b.title)));
else if (sortBy === Sort.NameZA)
setSortedLinks(linksArray.sort((a, b) => b.name.localeCompare(a.name)));
else if (sortBy === Sort.TitleZA)
setSortedLinks(linksArray.sort((a, b) => b.title.localeCompare(a.title)));
else if (sortBy === Sort.DateNewestFirst)
setSortedLinks(
linksArray.sort(
(a, b) =>
new Date(b.createdAt as string).getTime() -
new Date(a.createdAt as string).getTime()
)
);
else if (sortBy === Sort.DateOldestFirst)
setSortedLinks(
linksArray.sort(
(a, b) =>
new Date(a.createdAt as string).getTime() -
new Date(b.createdAt as string).getTime()
)
);
}, [links, router, tags, sortBy]);
return ( return (
<MainLayout> <MainLayout>
@ -94,9 +60,9 @@ export default function Index() {
</div> </div>
{sortDropdown ? ( {sortDropdown ? (
<SortLinkDropdown <SortDropdown
handleSortChange={handleSortChange}
sortBy={sortBy} sortBy={sortBy}
setSort={setSortBy}
toggleSortDropdown={() => setSortDropdown(!sortDropdown)} toggleSortDropdown={() => setSortDropdown(!sortDropdown)}
/> />
) : null} ) : null}

View File

@ -40,7 +40,7 @@ CREATE TABLE "Link" (
"id" SERIAL NOT NULL, "id" SERIAL NOT NULL,
"name" TEXT NOT NULL, "name" TEXT NOT NULL,
"url" TEXT NOT NULL, "url" TEXT NOT NULL,
"title" TEXT NOT NULL, "description" TEXT NOT NULL DEFAULT '',
"collectionId" INTEGER NOT NULL, "collectionId" INTEGER NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

View File

@ -58,7 +58,7 @@ model Link {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
name String name String
url String url String
title String description String @default("")
pinnedBy User[] pinnedBy User[]

View File

@ -46,8 +46,8 @@ export interface PublicCollectionIncludingLinks
export enum Sort { export enum Sort {
NameAZ, NameAZ,
NameZA, NameZA,
TitleAZ, DescriptionAZ,
TitleZA, DescriptionZA,
DateNewestFirst, DateNewestFirst,
DateOldestFirst, DateOldestFirst,
} }