diff --git a/src/components/library/LibraryMangaGrid.tsx b/src/components/library/LibraryMangaGrid.tsx index f725ca951d..262753705d 100644 --- a/src/components/library/LibraryMangaGrid.tsx +++ b/src/components/library/LibraryMangaGrid.tsx @@ -48,6 +48,32 @@ function filterManga(mangas: IMangaCard[]): IMangaCard[] { && queryFilter(query, manga)); } +function toReadSort(a: IMangaCard, b: IMangaCard): number { + if (!a.unreadCount) return -1; + if (!b.unreadCount) return 1; + return a.unreadCount > b.unreadCount ? 1 : -1; +} + +function toSortAlph(a: IMangaCard, b: IMangaCard): number { + return a.title < b.title ? 1 : -1; +} + +function toSortID(a: IMangaCard, b: IMangaCard): number { + return a.id > b.id ? 1 : -1; +} + +function sortManga(mangas: IMangaCard[]): IMangaCard[] { + const { sorts, sortDesc } = useLibraryOptions(); + return (sorts === 'sortID' || sorts === undefined) && !sortDesc ? mangas : mangas.sort((a, b) => { + const c = sortDesc === true ? b : a; + const d = sortDesc === true ? a : b; + if (sorts === 'sortToRead') { return toReadSort(c, d); } + if (sorts === 'sortAlph') { return toSortAlph(c, d); } + if (sorts === 'sortID' || sorts === undefined) { return toSortID(c, d); } + return 1; + }); +} + export default function LibraryMangaGrid(props: IMangaGridProps) { const { mangas, isLoading, hasNextPage, lastPageNum, setLastPageNum, message, @@ -55,12 +81,13 @@ export default function LibraryMangaGrid(props: IMangaGridProps) { const { active, query } = useLibraryOptions(); const filteredManga = filterManga(mangas); + const sortedManga = sortManga(filteredManga); const showFilteredOutMessage = (active || query) && filteredManga.length === 0 && mangas.length > 0; return ( (event: { target: { checked: boolean; }; }) => { + setSorts(event.target.checked ? name : undefined); + }; + + const handleOrderChange = () => (event: { target: { checked: boolean; }; }) => { + setSortDesc(event.target.checked); + }; + + return ( + + } label="Asc/Desc" /> + } label="Sort by left to read" /> + } label="Sort alphbetical" /> + } label="Sort by ID" /> + + ); +} + export default function LibraryOptions() { const [filtersOpen, setFiltersOpen] = React.useState(false); + const [sortsOpen, setSortsOpen] = React.useState(false); const { active } = useLibraryOptions(); return ( <> @@ -50,6 +77,26 @@ export default function LibraryOptions() { + setSortsOpen(!filtersOpen)} + color={active ? 'warning' : 'default'} + > + + + + setSortsOpen(false)} + PaperProps={{ + style: { + maxWidth: 600, padding: '1em', marginLeft: 'auto', marginRight: 'auto', + }, + }} + > + + + ); } diff --git a/src/util/useLibraryOptions.ts b/src/util/useLibraryOptions.ts index 57934fb948..c18da98d74 100644 --- a/src/util/useLibraryOptions.ts +++ b/src/util/useLibraryOptions.ts @@ -10,22 +10,38 @@ import { BooleanParam, useQueryParam, StringParam } from 'use-query-params'; interface IUseLibraryOptions { downloaded: NullAndUndefined - setDownloaded: (downloaded: NullAndUndefined)=>void + setDownloaded: (downloaded: NullAndUndefined) => void unread: NullAndUndefined setUnread: (unread: NullAndUndefined) => void query: NullAndUndefined setQuery: (query: NullAndUndefined) => void active: boolean + sorts: NullAndUndefined + setSorts: (sorts: NullAndUndefined) => void + sortDesc: NullAndUndefined + setSortDesc: (sortDesc: NullAndUndefined) => void } export default function useLibraryOptions(): IUseLibraryOptions { const [downloaded, setDownloaded] = useQueryParam('downloaded', BooleanParam); const [unread, setUnread] = useQueryParam('unread', BooleanParam); const [query, setQuery] = useQueryParam('query', StringParam); + const [sorts, setSorts] = useQueryParam('sorts', StringParam); + const [sortDesc, setSortDesc] = useQueryParam('sortDesc', BooleanParam); // eslint-disable-next-line eqeqeq const active = !(unread == undefined) || !(downloaded == undefined); return { - downloaded, setDownloaded, unread, setUnread, query, setQuery, active, + downloaded, + setDownloaded, + unread, + setUnread, + query, + setQuery, + active, + sorts, + setSorts, + sortDesc, + setSortDesc, }; }