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 ? ( {item.thumbnail.data ? (
<Img <Img
image={item.thumbnail.data.attributes} image={item.thumbnail.data.attributes}
quality={ImageQuality.Medium} quality={ImageQuality.Small}
/> />
) : ( ) : (
<div className="w-full aspect-[21/29.7] bg-light rounded-lg"></div> <div className="w-full aspect-[21/29.7] bg-light rounded-lg"></div>

View File

@ -13,22 +13,22 @@ export type SelectOption = {
label: string; 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 { export default function Select(props: SelectProps): JSX.Element {
const [selected, setSelected] = useState( const [selected, setSelected] = useState(
props.selected ? props.selected : props.allowEmpty ? -1 : 0 props.selected ? props.selected : props.allowEmpty ? -1 : 0
); );
const [opened, setOpened] = useState(false); const [opened, setOpened] = useState(false);
useEffect(() => {
if (props.onChange) {
if (selected >= 0) {
props.onChange(props.options[selected].name);
} else {
props.onChange("");
}
}
}, [props, selected]);
return ( return (
<div <div
className={`relative transition-[filter] ${ className={`relative transition-[filter] ${
@ -45,10 +45,7 @@ export default function Select(props: SelectProps): JSX.Element {
</p> </p>
{selected >= 0 && props.allowEmpty && ( {selected >= 0 && props.allowEmpty && (
<span <span
onClick={() => { onClick={() => setSelected(-1)}
setSelected(-1);
props.onChange && props.onChange("");
}}
className="material-icons !text-xs" className="material-icons !text-xs"
> >
close close
@ -73,7 +70,6 @@ export default function Select(props: SelectProps): JSX.Element {
onClick={() => { onClick={() => {
setOpened(false); setOpened(false);
setSelected(index); setSelected(index);
props.onChange && props.onChange(props.options[index].name);
}} }}
> >
{option.label} {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) { query getLibraryItemsPreview($language_code: String) {
libraryItems( libraryItems(
filters: { root_item: { eq: true } }
pagination: { limit: -1 } pagination: { limit: -1 }
) { ) {
data { data {
@ -135,6 +134,7 @@ query getLibraryItemsPreview($language_code: String) {
title title
subtitle subtitle
slug slug
root_item
thumbnail { thumbnail {
data { data {
attributes { attributes {

View File

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

View File

@ -17,6 +17,7 @@ import LibraryItemsPreview from "components/Library/LibraryItemsPreview";
import Select from "components/Select"; import Select from "components/Select";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { prettyDate, prettyinlineTitle } from "queries/helpers"; import { prettyDate, prettyinlineTitle } from "queries/helpers";
import Switch from "components/Switch";
type LibraryProps = { type LibraryProps = {
libraryItems: GetLibraryItemsPreviewQuery; libraryItems: GetLibraryItemsPreviewQuery;
@ -31,21 +32,31 @@ type GroupLibraryItems = Map<
export default function Library(props: LibraryProps): JSX.Element { export default function Library(props: LibraryProps): JSX.Element {
const langui = props.langui.websiteInterfaces.data[0].attributes; 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< const [sortedItems, setSortedItem] = useState<
LibraryProps["libraryItems"]["libraryItems"]["data"] LibraryProps["libraryItems"]["libraryItems"]["data"]
>(sortBy("title", props.libraryItems.libraryItems.data)); >(sortBy(groupingMethod, filteredItems));
const [sortingMethod, setSortingMethod] = useState<string>("title");
const [groups, setGroups] = useState<GroupLibraryItems>( const [groups, setGroups] = useState<GroupLibraryItems>(
getGroups("", sortedItems) getGroups("", sortedItems)
); );
const [groupingMethod, setGroupingMethod] = useState<string>(""); useEffect(() => {
setFilteredItems(
filterItems(showSubitems, props.libraryItems.libraryItems.data)
);
}, [showSubitems, props.libraryItems.libraryItems.data]);
useEffect(() => { useEffect(() => {
setSortedItem(sortBy(sortingMethod, props.libraryItems.libraryItems.data)); setSortedItem(sortBy(sortingMethod, filteredItems));
}, [props.libraryItems.libraryItems.data, sortingMethod]); }, [filteredItems, sortingMethod]);
useEffect(() => { useEffect(() => {
setGroups(getGroups(groupingMethod, sortedItems)); setGroups(getGroups(groupingMethod, sortedItems));
@ -85,6 +96,11 @@ export default function Library(props: LibraryProps): JSX.Element {
onChange={setSortingMethod} onChange={setSortingMethod}
/> />
</div> </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> </SubPanel>
); );
const contentPanel = ( const contentPanel = (
@ -93,10 +109,10 @@ export default function Library(props: LibraryProps): JSX.Element {
<> <>
{items.length > 0 && ( {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 <div
key={name} 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) => ( {items.map((item) => (
<LibraryItemsPreview key={item.id} item={item.attributes} /> <LibraryItemsPreview key={item.id} item={item.attributes} />
@ -168,7 +184,26 @@ function getGroups(
groupType.get("Video")?.push(item); groupType.get("Video")?.push(item);
break; break;
case "ComponentMetadataOther": 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; break;
} }
} else { } 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( function sortBy(
orderByType: string, orderByType: string,
items: LibraryProps["libraryItems"]["libraryItems"]["data"] items: LibraryProps["libraryItems"]["libraryItems"]["data"]