New translation system and filtering/group for Library Items #1
@ -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>
 | 
			
		||||
 | 
			
		||||
@ -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
									
								
							
							
						
						
									
										26
									
								
								src/components/Switch.tsx
									
									
									
									
									
										Normal 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>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
@ -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 {
 | 
			
		||||
 | 
			
		||||
@ -238,6 +238,7 @@ export type GetLibraryItemsPreviewQuery = {
 | 
			
		||||
        title: string;
 | 
			
		||||
        subtitle: string;
 | 
			
		||||
        slug: string;
 | 
			
		||||
        root_item: boolean;
 | 
			
		||||
        thumbnail: {
 | 
			
		||||
          __typename: "UploadFileEntityResponse";
 | 
			
		||||
          data: {
 | 
			
		||||
 | 
			
		||||
@ -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"]
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user