More filtering options in Library

This commit is contained in:
DrMint 2022-03-05 13:15:43 +01:00
parent 8684640ef4
commit 7c8fb24d67
6 changed files with 104 additions and 26 deletions

View File

@ -30,7 +30,7 @@ export default function LibraryItemsPreview(
{item.thumbnail.data ? (
<Img
image={item.thumbnail.data.attributes}
quality={ImageQuality.Medium}
quality={ImageQuality.Small}
/>
) : (
<div className="w-full aspect-[21/29.7] bg-light rounded-lg"></div>

View File

@ -13,22 +13,22 @@ export type SelectOption = {
label: string;
};
export function selectOptionsIncludes(
options: SelectOption[],
newOption: SelectOption
) {
options.map((option) => {
if (option.label === newOption.label) return true;
});
return false;
}
export default function Select(props: SelectProps): JSX.Element {
const [selected, setSelected] = useState(
props.selected ? props.selected : props.allowEmpty ? -1 : 0
);
const [opened, setOpened] = useState(false);
useEffect(() => {
if (props.onChange) {
if (selected >= 0) {
props.onChange(props.options[selected].name);
} else {
props.onChange("");
}
}
}, [props, selected]);
return (
<div
className={`relative transition-[filter] ${
@ -45,10 +45,7 @@ export default function Select(props: SelectProps): JSX.Element {
</p>
{selected >= 0 && props.allowEmpty && (
<span
onClick={() => {
setSelected(-1);
props.onChange && props.onChange("");
}}
onClick={() => setSelected(-1)}
className="material-icons !text-xs"
>
close
@ -73,7 +70,6 @@ export default function Select(props: SelectProps): JSX.Element {
onClick={() => {
setOpened(false);
setSelected(index);
props.onChange && props.onChange(props.options[index].name);
}}
>
{option.label}

26
src/components/Switch.tsx Normal file
View File

@ -0,0 +1,26 @@
import { Dispatch, SetStateAction } from "react";
export type SwitchProps = {
setState: Dispatch<SetStateAction<boolean>>;
state: boolean;
className?: string;
};
export default function Select(props: SwitchProps): JSX.Element {
return (
<div
className={`h-6 w-12 rounded-full border-2 border-mid grid transition-colors relative cursor-pointer ${
props.className
} ${props.state ? "bg-mid" : "bg-light"}`}
onClick={() => {
props.setState(!props.state);
}}
>
<div
className={`bg-dark aspect-square rounded-full absolute top-0 bottom-0 left-0 transition-transform ${
props.state && "translate-x-[115%]"
}`}
></div>
</div>
);
}

View File

@ -126,7 +126,6 @@ query getChronologyItems($language_code: String) {
query getLibraryItemsPreview($language_code: String) {
libraryItems(
filters: { root_item: { eq: true } }
pagination: { limit: -1 }
) {
data {
@ -135,6 +134,7 @@ query getLibraryItemsPreview($language_code: String) {
title
subtitle
slug
root_item
thumbnail {
data {
attributes {

View File

@ -238,6 +238,7 @@ export type GetLibraryItemsPreviewQuery = {
title: string;
subtitle: string;
slug: string;
root_item: boolean;
thumbnail: {
__typename: "UploadFileEntityResponse";
data: {

View File

@ -17,6 +17,7 @@ import LibraryItemsPreview from "components/Library/LibraryItemsPreview";
import Select from "components/Select";
import { useEffect, useState } from "react";
import { prettyDate, prettyinlineTitle } from "queries/helpers";
import Switch from "components/Switch";
type LibraryProps = {
libraryItems: GetLibraryItemsPreviewQuery;
@ -31,21 +32,31 @@ type GroupLibraryItems = Map<
export default function Library(props: LibraryProps): JSX.Element {
const langui = props.langui.websiteInterfaces.data[0].attributes;
const [showSubitems, setShowSubitems] = useState<boolean>(false);
const [sortingMethod, setSortingMethod] = useState<string>("title");
const [groupingMethod, setGroupingMethod] = useState<string>("");
const [filteredItems, setFilteredItems] = useState<
LibraryProps["libraryItems"]["libraryItems"]["data"]
>(filterItems(showSubitems, props.libraryItems.libraryItems.data));
const [sortedItems, setSortedItem] = useState<
LibraryProps["libraryItems"]["libraryItems"]["data"]
>(sortBy("title", props.libraryItems.libraryItems.data));
const [sortingMethod, setSortingMethod] = useState<string>("title");
>(sortBy(groupingMethod, filteredItems));
const [groups, setGroups] = useState<GroupLibraryItems>(
getGroups("", sortedItems)
);
const [groupingMethod, setGroupingMethod] = useState<string>("");
useEffect(() => {
setFilteredItems(
filterItems(showSubitems, props.libraryItems.libraryItems.data)
);
}, [showSubitems, props.libraryItems.libraryItems.data]);
useEffect(() => {
setSortedItem(sortBy(sortingMethod, props.libraryItems.libraryItems.data));
}, [props.libraryItems.libraryItems.data, sortingMethod]);
setSortedItem(sortBy(sortingMethod, filteredItems));
}, [filteredItems, sortingMethod]);
useEffect(() => {
setGroups(getGroups(groupingMethod, sortedItems));
@ -85,6 +96,11 @@ export default function Library(props: LibraryProps): JSX.Element {
onChange={setSortingMethod}
/>
</div>
<div className="flex flex-row gap-2 place-items-center">
<p className="flex-shrink-0">Show subitems:</p>
<Switch state={showSubitems} setState={setShowSubitems} />
</div>
</SubPanel>
);
const contentPanel = (
@ -93,10 +109,10 @@ export default function Library(props: LibraryProps): JSX.Element {
<>
{items.length > 0 && (
<>
<h2 className="text-2xl pb-2">{name}</h2>
<h2 className="text-2xl pb-2 pt-10 first-of-type:pt-0">{name}</h2>
<div
key={name}
className="grid gap-8 items-end mobile:grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(13rem,1fr))] pb-12"
className="grid gap-8 items-end mobile:grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(13rem,1fr))] pb-12 border-b-[3px] border-dotted last-of-type:border-0"
>
{items.map((item) => (
<LibraryItemsPreview key={item.id} item={item.attributes} />
@ -168,7 +184,26 @@ function getGroups(
groupType.get("Video")?.push(item);
break;
case "ComponentMetadataOther":
groupType.get("Other")?.push(item);
switch (
item.attributes.metadata[0].subtype.data.attributes.slug
) {
case "audio-case":
groupType.get("Audio")?.push(item);
break;
case "video-case":
groupType.get("Video")?.push(item);
break;
case "game-case":
groupType.get("Game")?.push(item);
break;
default:
groupType.get("Other")?.push(item);
break;
}
break;
}
} else {
@ -210,6 +245,26 @@ function getGroups(
}
}
function filterItems(
showSubitems: boolean,
items: LibraryProps["libraryItems"]["libraryItems"]["data"]
): LibraryProps["libraryItems"]["libraryItems"]["data"] {
return [...items].filter((item) => {
let result = true;
if (!showSubitems && !item.attributes.root_item) result = false;
if (
item.attributes.metadata.length > 0 &&
item.attributes.metadata[0].__typename === "ComponentMetadataOther" &&
(item.attributes.metadata[0].subtype.data.attributes.slug ===
"variant-set" ||
item.attributes.metadata[0].subtype.data.attributes.slug ===
"relation-set")
)
result = false;
return result;
});
}
function sortBy(
orderByType: string,
items: LibraryProps["libraryItems"]["libraryItems"]["data"]