Fixed key problems + search function
This commit is contained in:
parent
50e988f64f
commit
fa96469ebf
|
@ -46,11 +46,13 @@ export function AppLayout(props: Immutable<Props>): JSX.Element {
|
||||||
const sensibilitySwipe = 1.1;
|
const sensibilitySwipe = 1.1;
|
||||||
|
|
||||||
useMemo(() => {
|
useMemo(() => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
router.events?.on("routeChangeStart", () => {
|
router.events?.on("routeChangeStart", () => {
|
||||||
appLayout.setConfigPanelOpen(false);
|
appLayout.setConfigPanelOpen(false);
|
||||||
appLayout.setMainPanelOpen(false);
|
appLayout.setMainPanelOpen(false);
|
||||||
appLayout.setSubPanelOpen(false);
|
appLayout.setSubPanelOpen(false);
|
||||||
});
|
});
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
router.events?.on("hashChangeStart", () => {
|
router.events?.on("hashChangeStart", () => {
|
||||||
appLayout.setSubPanelOpen(false);
|
appLayout.setSubPanelOpen(false);
|
||||||
});
|
});
|
||||||
|
@ -425,7 +427,9 @@ export function AppLayout(props: Immutable<Props>): JSX.Element {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<span className="material-icons !text-base">text_decrease</span>
|
<span className="material-icons !text-base">
|
||||||
|
text_decrease
|
||||||
|
</span>
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
className="rounded-l-none rounded-r-none border-x-0"
|
className="rounded-l-none rounded-r-none border-x-0"
|
||||||
|
@ -449,7 +453,9 @@ export function AppLayout(props: Immutable<Props>): JSX.Element {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<span className="material-icons !text-base">text_increase</span>
|
<span className="material-icons !text-base">
|
||||||
|
text_increase
|
||||||
|
</span>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { AppStaticProps } from "graphql/getAppStaticProps";
|
import { AppStaticProps } from "graphql/getAppStaticProps";
|
||||||
import { prettyLanguage } from "helpers/formatters";
|
import { prettyLanguage } from "helpers/formatters";
|
||||||
import { Immutable } from "helpers/types";
|
import { Immutable } from "helpers/types";
|
||||||
import { Dispatch, SetStateAction } from "react";
|
import { Dispatch, Fragment, SetStateAction } from "react";
|
||||||
import { ToolTip } from "../ToolTip";
|
import { ToolTip } from "../ToolTip";
|
||||||
import { Button } from "./Button";
|
import { Button } from "./Button";
|
||||||
|
|
||||||
|
@ -21,17 +21,16 @@ export function LanguageSwitcher(props: Immutable<Props>): JSX.Element {
|
||||||
content={
|
content={
|
||||||
<div className={`flex flex-col gap-2 ${className}`}>
|
<div className={`flex flex-col gap-2 ${className}`}>
|
||||||
{[...locales].map(([locale, value], index) => (
|
{[...locales].map(([locale, value], index) => (
|
||||||
<>
|
<Fragment key={index}>
|
||||||
{locale && (
|
{locale && (
|
||||||
<Button
|
<Button
|
||||||
key={index}
|
|
||||||
active={value === localesIndex}
|
active={value === localesIndex}
|
||||||
onClick={() => setLocalesIndex(value)}
|
onClick={() => setLocalesIndex(value)}
|
||||||
>
|
>
|
||||||
{prettyLanguage(locale, props.languages)}
|
{prettyLanguage(locale, props.languages)}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { arrayMove } from "helpers/others";
|
import { arrayMove } from "helpers/others";
|
||||||
import { Immutable } from "helpers/types";
|
import { Immutable } from "helpers/types";
|
||||||
import { useEffect, useState } from "react";
|
import { Fragment, useEffect, useState } from "react";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
className?: string;
|
className?: string;
|
||||||
|
@ -25,7 +25,7 @@ export function OrderableList(props: Immutable<Props>): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<div className="grid gap-2">
|
<div className="grid gap-2">
|
||||||
{[...items].map(([key, value], index) => (
|
{[...items].map(([key, value], index) => (
|
||||||
<>
|
<Fragment key={key}>
|
||||||
{props.insertLabels?.get(index) && (
|
{props.insertLabels?.get(index) && (
|
||||||
<p>{props.insertLabels.get(index)}</p>
|
<p>{props.insertLabels.get(index)}</p>
|
||||||
)}
|
)}
|
||||||
|
@ -60,7 +60,6 @@ export function OrderableList(props: Immutable<Props>): JSX.Element {
|
||||||
border-[1px] transition-all hover:text-light hover:bg-dark
|
border-[1px] transition-all hover:text-light hover:bg-dark
|
||||||
hover:drop-shadow-shade-lg border-dark bg-light text-dark
|
hover:drop-shadow-shade-lg border-dark bg-light text-dark
|
||||||
rounded-full cursor-grab select-none px-1 py-2 pr-4 gap-2"
|
rounded-full cursor-grab select-none px-1 py-2 pr-4 gap-2"
|
||||||
key={key}
|
|
||||||
draggable
|
draggable
|
||||||
>
|
>
|
||||||
<div className="grid grid-rows-[.8em_.8em] place-items-center">
|
<div className="grid grid-rows-[.8em_.8em] place-items-center">
|
||||||
|
@ -87,7 +86,7 @@ export function OrderableList(props: Immutable<Props>): JSX.Element {
|
||||||
</div>
|
</div>
|
||||||
{value}
|
{value}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Immutable } from "helpers/types";
|
import { Immutable } from "helpers/types";
|
||||||
import { Dispatch, SetStateAction, useState } from "react";
|
import { Dispatch, Fragment, SetStateAction, useState } from "react";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
setState: Dispatch<SetStateAction<number>>;
|
setState: Dispatch<SetStateAction<number>>;
|
||||||
|
@ -47,12 +47,12 @@ export function Select(props: Immutable<Props>): JSX.Element {
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{props.options.map((option, index) => (
|
{props.options.map((option, index) => (
|
||||||
<>
|
<Fragment key={index}>
|
||||||
{index !== props.state && (
|
{index !== props.state && (
|
||||||
<div
|
<div
|
||||||
className="bg-light hover:bg-mid transition-colors
|
className="bg-light hover:bg-mid transition-colors
|
||||||
cursor-pointer p-1 last-of-type:rounded-b-[1em]"
|
cursor-pointer p-1 last-of-type:rounded-b-[1em]"
|
||||||
key={index}
|
|
||||||
id={option}
|
id={option}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setOpened(false);
|
setOpened(false);
|
||||||
|
@ -62,7 +62,7 @@ export function Select(props: Immutable<Props>): JSX.Element {
|
||||||
{option}
|
{option}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,23 +5,25 @@ interface Props {
|
||||||
setState: Dispatch<SetStateAction<boolean>>;
|
setState: Dispatch<SetStateAction<boolean>>;
|
||||||
state: boolean;
|
state: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
disabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Switch(props: Immutable<Props>): JSX.Element {
|
export function Switch(props: Immutable<Props>): JSX.Element {
|
||||||
|
const { state, setState, className, disabled } = props;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`h-6 w-12 rounded-full border-2 border-mid grid
|
className={`h-6 w-12 rounded-full border-2 border-mid grid
|
||||||
transition-colors relative cursor-pointer ${props.className} ${
|
transition-colors relative ${
|
||||||
props.state ? "bg-mid" : "bg-light"
|
disabled ? "cursor-not-allowed" : "cursor-pointer"
|
||||||
}`}
|
} ${className} ${state ? "bg-mid" : "bg-light"}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
props.setState(!props.state);
|
if (!disabled) setState(!state);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={`bg-dark aspect-square rounded-full absolute
|
className={`bg-dark aspect-square rounded-full absolute
|
||||||
top-0 bottom-0 left-0 transition-transform ${
|
top-0 bottom-0 left-0 transition-transform ${
|
||||||
props.state && "translate-x-[115%]"
|
state && "translate-x-[115%]"
|
||||||
}`}
|
}`}
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { isInteger } from "helpers/numbers";
|
||||||
import { getStatusDescription } from "helpers/others";
|
import { getStatusDescription } from "helpers/others";
|
||||||
import { Immutable } from "helpers/types";
|
import { Immutable } from "helpers/types";
|
||||||
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
||||||
|
import { Fragment } from "react";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
openLightBox: (images: string[], index?: number) => void;
|
openLightBox: (images: string[], index?: number) => void;
|
||||||
|
@ -121,15 +122,14 @@ export function ScanSet(props: Immutable<Props>): JSX.Element {
|
||||||
<p className="font-headers">{"Scanners"}:</p>
|
<p className="font-headers">{"Scanners"}:</p>
|
||||||
<div className="grid place-items-center place-content-center gap-2">
|
<div className="grid place-items-center place-content-center gap-2">
|
||||||
{selectedScan.scanners.data.map((scanner) => (
|
{selectedScan.scanners.data.map((scanner) => (
|
||||||
<>
|
<Fragment key={scanner.id}>
|
||||||
{scanner.attributes && (
|
{scanner.attributes && (
|
||||||
<RecorderChip
|
<RecorderChip
|
||||||
key={scanner.id}
|
|
||||||
langui={langui}
|
langui={langui}
|
||||||
recorder={scanner.attributes}
|
recorder={scanner.attributes}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -140,15 +140,14 @@ export function ScanSet(props: Immutable<Props>): JSX.Element {
|
||||||
<p className="font-headers">{"Cleaners"}:</p>
|
<p className="font-headers">{"Cleaners"}:</p>
|
||||||
<div className="grid place-items-center place-content-center gap-2">
|
<div className="grid place-items-center place-content-center gap-2">
|
||||||
{selectedScan.cleaners.data.map((cleaner) => (
|
{selectedScan.cleaners.data.map((cleaner) => (
|
||||||
<>
|
<Fragment key={cleaner.id}>
|
||||||
{cleaner.attributes && (
|
{cleaner.attributes && (
|
||||||
<RecorderChip
|
<RecorderChip
|
||||||
key={cleaner.id}
|
|
||||||
langui={langui}
|
langui={langui}
|
||||||
recorder={cleaner.attributes}
|
recorder={cleaner.attributes}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -160,15 +159,14 @@ export function ScanSet(props: Immutable<Props>): JSX.Element {
|
||||||
<p className="font-headers">{"Typesetters"}:</p>
|
<p className="font-headers">{"Typesetters"}:</p>
|
||||||
<div className="grid place-items-center place-content-center gap-2">
|
<div className="grid place-items-center place-content-center gap-2">
|
||||||
{selectedScan.typesetters.data.map((typesetter) => (
|
{selectedScan.typesetters.data.map((typesetter) => (
|
||||||
<>
|
<Fragment key={typesetter.id}>
|
||||||
{typesetter.attributes && (
|
{typesetter.attributes && (
|
||||||
<RecorderChip
|
<RecorderChip
|
||||||
key={typesetter.id}
|
|
||||||
langui={langui}
|
langui={langui}
|
||||||
recorder={typesetter.attributes}
|
recorder={typesetter.attributes}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { getAssetURL, ImageQuality } from "helpers/img";
|
||||||
import { getStatusDescription } from "helpers/others";
|
import { getStatusDescription } from "helpers/others";
|
||||||
import { Immutable } from "helpers/types";
|
import { Immutable } from "helpers/types";
|
||||||
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
||||||
|
import { Fragment } from "react";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
openLightBox: (images: string[], index?: number) => void;
|
openLightBox: (images: string[], index?: number) => void;
|
||||||
|
@ -87,15 +88,14 @@ export function ScanSetCover(props: Immutable<Props>): JSX.Element {
|
||||||
<p className="font-headers">{"Scanners"}:</p>
|
<p className="font-headers">{"Scanners"}:</p>
|
||||||
<div className="grid place-items-center place-content-center gap-2">
|
<div className="grid place-items-center place-content-center gap-2">
|
||||||
{selectedScan.scanners.data.map((scanner) => (
|
{selectedScan.scanners.data.map((scanner) => (
|
||||||
<>
|
<Fragment key={scanner.id}>
|
||||||
{scanner.attributes && (
|
{scanner.attributes && (
|
||||||
<RecorderChip
|
<RecorderChip
|
||||||
key={scanner.id}
|
|
||||||
langui={langui}
|
langui={langui}
|
||||||
recorder={scanner.attributes}
|
recorder={scanner.attributes}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -106,15 +106,14 @@ export function ScanSetCover(props: Immutable<Props>): JSX.Element {
|
||||||
<p className="font-headers">{"Cleaners"}:</p>
|
<p className="font-headers">{"Cleaners"}:</p>
|
||||||
<div className="grid place-items-center place-content-center gap-2">
|
<div className="grid place-items-center place-content-center gap-2">
|
||||||
{selectedScan.cleaners.data.map((cleaner) => (
|
{selectedScan.cleaners.data.map((cleaner) => (
|
||||||
<>
|
<Fragment key={cleaner.id}>
|
||||||
{cleaner.attributes && (
|
{cleaner.attributes && (
|
||||||
<RecorderChip
|
<RecorderChip
|
||||||
key={cleaner.id}
|
|
||||||
langui={langui}
|
langui={langui}
|
||||||
recorder={cleaner.attributes}
|
recorder={cleaner.attributes}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -126,15 +125,14 @@ export function ScanSetCover(props: Immutable<Props>): JSX.Element {
|
||||||
<p className="font-headers">{"Typesetters"}:</p>
|
<p className="font-headers">{"Typesetters"}:</p>
|
||||||
<div className="grid place-items-center place-content-center gap-2">
|
<div className="grid place-items-center place-content-center gap-2">
|
||||||
{selectedScan.typesetters.data.map((typesetter) => (
|
{selectedScan.typesetters.data.map((typesetter) => (
|
||||||
<>
|
<Fragment key={typesetter.id}>
|
||||||
{typesetter.attributes && (
|
{typesetter.attributes && (
|
||||||
<RecorderChip
|
<RecorderChip
|
||||||
key={typesetter.id}
|
|
||||||
langui={langui}
|
langui={langui}
|
||||||
recorder={typesetter.attributes}
|
recorder={typesetter.attributes}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { slugify } from "helpers/formatters";
|
import { slugify } from "helpers/formatters";
|
||||||
import { Immutable } from "helpers/types";
|
import { Immutable } from "helpers/types";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
import { Fragment } from "react";
|
||||||
import { preprocessMarkDawn } from "./Markdawn";
|
import { preprocessMarkDawn } from "./Markdawn";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
@ -39,11 +40,8 @@ function TOCLevel(props: LevelProps): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<ol className="pl-4 text-left">
|
<ol className="pl-4 text-left">
|
||||||
{tocchildren.map((child, childIndex) => (
|
{tocchildren.map((child, childIndex) => (
|
||||||
<>
|
<Fragment key={child.slug}>
|
||||||
<li
|
<li className="my-2 overflow-x-hidden w-full text-ellipsis whitespace-nowrap">
|
||||||
key={child.slug}
|
|
||||||
className="my-2 overflow-x-hidden w-full text-ellipsis whitespace-nowrap"
|
|
||||||
>
|
|
||||||
<span className="text-dark">{`${parentNumbering}${
|
<span className="text-dark">{`${parentNumbering}${
|
||||||
childIndex + 1
|
childIndex + 1
|
||||||
}.`}</span>{" "}
|
}.`}</span>{" "}
|
||||||
|
@ -55,7 +53,7 @@ function TOCLevel(props: LevelProps): JSX.Element {
|
||||||
tocchildren={child.children}
|
tocchildren={child.children}
|
||||||
parentNumbering={`${parentNumbering}${childIndex + 1}.`}
|
parentNumbering={`${parentNumbering}${childIndex + 1}.`}
|
||||||
/>
|
/>
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</ol>
|
</ol>
|
||||||
);
|
);
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { prettySlug } from "helpers/formatters";
|
||||||
import { getStatusDescription } from "helpers/others";
|
import { getStatusDescription } from "helpers/others";
|
||||||
import { Immutable, PostWithTranslations } from "helpers/types";
|
import { Immutable, PostWithTranslations } from "helpers/types";
|
||||||
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
||||||
|
import { Fragment } from "react";
|
||||||
import { AppLayout } from "./AppLayout";
|
import { AppLayout } from "./AppLayout";
|
||||||
import { Chip } from "./Chip";
|
import { Chip } from "./Chip";
|
||||||
import { HorizontalLine } from "./HorizontalLine";
|
import { HorizontalLine } from "./HorizontalLine";
|
||||||
|
@ -97,15 +98,14 @@ export function PostPage(props: Immutable<Props>): JSX.Element {
|
||||||
<p className="font-headers">{"Authors"}:</p>
|
<p className="font-headers">{"Authors"}:</p>
|
||||||
<div className="grid place-items-center place-content-center gap-2">
|
<div className="grid place-items-center place-content-center gap-2">
|
||||||
{post.authors.data.map((author) => (
|
{post.authors.data.map((author) => (
|
||||||
<>
|
<Fragment key={author.id}>
|
||||||
{author.attributes && (
|
{author.attributes && (
|
||||||
<RecorderChip
|
<RecorderChip
|
||||||
key={author.id}
|
|
||||||
langui={langui}
|
langui={langui}
|
||||||
recorder={author.attributes}
|
recorder={author.attributes}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { RecorderChipFragment } from "graphql/generated";
|
||||||
import { AppStaticProps } from "graphql/getAppStaticProps";
|
import { AppStaticProps } from "graphql/getAppStaticProps";
|
||||||
import { ImageQuality } from "helpers/img";
|
import { ImageQuality } from "helpers/img";
|
||||||
import { Immutable } from "helpers/types";
|
import { Immutable } from "helpers/types";
|
||||||
|
import { Fragment } from "react";
|
||||||
import { Img } from "./Img";
|
import { Img } from "./Img";
|
||||||
import { Markdawn } from "./Markdown/Markdawn";
|
import { Markdawn } from "./Markdown/Markdawn";
|
||||||
import { ToolTip } from "./ToolTip";
|
import { ToolTip } from "./ToolTip";
|
||||||
|
@ -33,13 +34,11 @@ export function RecorderChip(props: Immutable<Props>): JSX.Element {
|
||||||
<div className="flex flex-row flex-wrap gap-1">
|
<div className="flex flex-row flex-wrap gap-1">
|
||||||
<p>{langui.languages}:</p>
|
<p>{langui.languages}:</p>
|
||||||
{recorder.languages.data.map((language) => (
|
{recorder.languages.data.map((language) => (
|
||||||
<>
|
<Fragment key={language.attributes?.code}>
|
||||||
{language.attributes && (
|
{language.attributes && (
|
||||||
<Chip key={language.attributes.code}>
|
<Chip>{language.attributes.code.toUpperCase()}</Chip>
|
||||||
{language.attributes.code.toUpperCase()}
|
|
||||||
</Chip>
|
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {
|
||||||
import { AppStaticProps } from "graphql/getAppStaticProps";
|
import { AppStaticProps } from "graphql/getAppStaticProps";
|
||||||
import { getStatusDescription } from "helpers/others";
|
import { getStatusDescription } from "helpers/others";
|
||||||
import { Immutable } from "helpers/types";
|
import { Immutable } from "helpers/types";
|
||||||
|
import { Fragment } from "react";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
item: NonNullable<GetChronologyItemsQuery["chronologyItems"]>["data"][number];
|
item: NonNullable<GetChronologyItemsQuery["chronologyItems"]>["data"][number];
|
||||||
|
@ -92,13 +93,13 @@ export function ChronologyItemComponent(props: Immutable<Props>): JSX.Element {
|
||||||
|
|
||||||
<div className="col-start-2 row-start-1 row-span-2 grid gap-4">
|
<div className="col-start-2 row-start-1 row-span-2 grid gap-4">
|
||||||
{props.item.attributes.events?.map((event) => (
|
{props.item.attributes.events?.map((event) => (
|
||||||
<>
|
<Fragment key={event?.id}>
|
||||||
{event && (
|
{event && (
|
||||||
<div className="m-0" key={event.id}>
|
<div className="m-0">
|
||||||
{event.translations?.map((translation) => (
|
{event.translations?.map((translation, translationIndex) => (
|
||||||
<>
|
<Fragment key={translationIndex}>
|
||||||
{translation && (
|
{translation && (
|
||||||
<>
|
<Fragment>
|
||||||
<div
|
<div
|
||||||
className="place-items-start
|
className="place-items-start
|
||||||
place-content-start grid grid-flow-col gap-2"
|
place-content-start grid grid-flow-col gap-2"
|
||||||
|
@ -140,9 +141,9 @@ export function ChronologyItemComponent(props: Immutable<Props>): JSX.Element {
|
||||||
) : (
|
) : (
|
||||||
""
|
""
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
<p className="text-dark text-xs grid place-self-start grid-flow-col gap-1 mt-1">
|
<p className="text-dark text-xs grid place-self-start grid-flow-col gap-1 mt-1">
|
||||||
|
@ -157,7 +158,7 @@ export function ChronologyItemComponent(props: Immutable<Props>): JSX.Element {
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -20,7 +20,7 @@ import {
|
||||||
GetStaticPathsResult,
|
GetStaticPathsResult,
|
||||||
GetStaticPropsContext,
|
GetStaticPropsContext,
|
||||||
} from "next";
|
} from "next";
|
||||||
import { useState } from "react";
|
import { Fragment, useState } from "react";
|
||||||
|
|
||||||
interface Props extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
channel: NonNullable<
|
channel: NonNullable<
|
||||||
|
@ -67,10 +67,9 @@ export default function Channel(props: Props): JSX.Element {
|
||||||
pb-12 border-b-[3px] border-dotted last-of-type:border-0"
|
pb-12 border-b-[3px] border-dotted last-of-type:border-0"
|
||||||
>
|
>
|
||||||
{channel?.videos?.data.map((video) => (
|
{channel?.videos?.data.map((video) => (
|
||||||
<>
|
<Fragment key={video.id}>
|
||||||
{video.attributes && (
|
{video.attributes && (
|
||||||
<PreviewCard
|
<PreviewCard
|
||||||
key={video.id}
|
|
||||||
href={`/archives/videos/v/${video.attributes.uid}`}
|
href={`/archives/videos/v/${video.attributes.uid}`}
|
||||||
title={video.attributes.title}
|
title={video.attributes.title}
|
||||||
thumbnail={getVideoThumbnailURL(video.attributes.uid)}
|
thumbnail={getVideoThumbnailURL(video.attributes.uid)}
|
||||||
|
@ -88,7 +87,7 @@ export default function Channel(props: Props): JSX.Element {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</ContentPanel>
|
</ContentPanel>
|
||||||
|
|
|
@ -18,7 +18,7 @@ import { getReadySdk } from "graphql/sdk";
|
||||||
import { prettyDate } from "helpers/formatters";
|
import { prettyDate } from "helpers/formatters";
|
||||||
import { getVideoThumbnailURL } from "helpers/videos";
|
import { getVideoThumbnailURL } from "helpers/videos";
|
||||||
import { GetStaticPropsContext } from "next";
|
import { GetStaticPropsContext } from "next";
|
||||||
import { useState } from "react";
|
import { Fragment, useState } from "react";
|
||||||
|
|
||||||
interface Props extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
videos: NonNullable<GetVideosPreviewQuery["videos"]>["data"];
|
videos: NonNullable<GetVideosPreviewQuery["videos"]>["data"];
|
||||||
|
@ -88,10 +88,9 @@ export default function Videos(props: Props): JSX.Element {
|
||||||
pb-12 border-b-[3px] border-dotted last-of-type:border-0"
|
pb-12 border-b-[3px] border-dotted last-of-type:border-0"
|
||||||
>
|
>
|
||||||
{paginatedVideos[page].map((video) => (
|
{paginatedVideos[page].map((video) => (
|
||||||
<>
|
<Fragment key={video.id}>
|
||||||
{video.attributes && (
|
{video.attributes && (
|
||||||
<PreviewCard
|
<PreviewCard
|
||||||
key={video.id}
|
|
||||||
href={`/archives/videos/v/${video.attributes.uid}`}
|
href={`/archives/videos/v/${video.attributes.uid}`}
|
||||||
title={video.attributes.title}
|
title={video.attributes.title}
|
||||||
thumbnail={getVideoThumbnailURL(video.attributes.uid)}
|
thumbnail={getVideoThumbnailURL(video.attributes.uid)}
|
||||||
|
@ -109,7 +108,7 @@ export default function Videos(props: Props): JSX.Element {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ import {
|
||||||
GetStaticPathsResult,
|
GetStaticPathsResult,
|
||||||
GetStaticPropsContext,
|
GetStaticPropsContext,
|
||||||
} from "next";
|
} from "next";
|
||||||
|
import { Fragment } from "react";
|
||||||
|
|
||||||
interface Props extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
content: ContentWithTranslations;
|
content: ContentWithTranslations;
|
||||||
|
@ -116,15 +117,14 @@ export default function Content(props: Immutable<Props>): JSX.Element {
|
||||||
<div className="grid place-items-center place-content-center gap-2">
|
<div className="grid place-items-center place-content-center gap-2">
|
||||||
{selectedTranslation.text_set.transcribers.data.map(
|
{selectedTranslation.text_set.transcribers.data.map(
|
||||||
(recorder) => (
|
(recorder) => (
|
||||||
<>
|
<Fragment key={recorder.id}>
|
||||||
{recorder.attributes && (
|
{recorder.attributes && (
|
||||||
<RecorderChip
|
<RecorderChip
|
||||||
key={recorder.id}
|
|
||||||
langui={langui}
|
langui={langui}
|
||||||
recorder={recorder.attributes}
|
recorder={recorder.attributes}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -138,15 +138,14 @@ export default function Content(props: Immutable<Props>): JSX.Element {
|
||||||
<div className="grid place-items-center place-content-center gap-2">
|
<div className="grid place-items-center place-content-center gap-2">
|
||||||
{selectedTranslation.text_set.translators.data.map(
|
{selectedTranslation.text_set.translators.data.map(
|
||||||
(recorder) => (
|
(recorder) => (
|
||||||
<>
|
<Fragment key={recorder.id}>
|
||||||
{recorder.attributes && (
|
{recorder.attributes && (
|
||||||
<RecorderChip
|
<RecorderChip
|
||||||
key={recorder.id}
|
|
||||||
langui={langui}
|
langui={langui}
|
||||||
recorder={recorder.attributes}
|
recorder={recorder.attributes}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -160,15 +159,14 @@ export default function Content(props: Immutable<Props>): JSX.Element {
|
||||||
<div className="grid place-items-center place-content-center gap-2">
|
<div className="grid place-items-center place-content-center gap-2">
|
||||||
{selectedTranslation.text_set.proofreaders.data.map(
|
{selectedTranslation.text_set.proofreaders.data.map(
|
||||||
(recorder) => (
|
(recorder) => (
|
||||||
<>
|
<Fragment key={recorder.id}>
|
||||||
{recorder.attributes && (
|
{recorder.attributes && (
|
||||||
<RecorderChip
|
<RecorderChip
|
||||||
key={recorder.id}
|
|
||||||
langui={langui}
|
langui={langui}
|
||||||
recorder={recorder.attributes}
|
recorder={recorder.attributes}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { getReadySdk } from "graphql/sdk";
|
||||||
import { prettyinlineTitle, prettySlug } from "helpers/formatters";
|
import { prettyinlineTitle, prettySlug } from "helpers/formatters";
|
||||||
import { Immutable } from "helpers/types";
|
import { Immutable } from "helpers/types";
|
||||||
import { GetStaticPropsContext } from "next";
|
import { GetStaticPropsContext } from "next";
|
||||||
import { useEffect, useState } from "react";
|
import { Fragment, useEffect, useState } from "react";
|
||||||
|
|
||||||
interface Props extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
contents: NonNullable<GetContentsQuery["contents"]>["data"];
|
contents: NonNullable<GetContentsQuery["contents"]>["data"];
|
||||||
|
@ -30,9 +30,12 @@ export default function Contents(props: Immutable<Props>): JSX.Element {
|
||||||
const [keepInfoVisible, setKeepInfoVisible] = useState(false);
|
const [keepInfoVisible, setKeepInfoVisible] = useState(false);
|
||||||
|
|
||||||
const [combineRelatedContent, setCombineRelatedContent] = useState(true);
|
const [combineRelatedContent, setCombineRelatedContent] = useState(true);
|
||||||
|
const [effectiveCombineRelatedContent, setEffectiveCombineRelatedContent] =
|
||||||
|
useState(true);
|
||||||
|
const [searchName, setSearchName] = useState("");
|
||||||
|
|
||||||
const [filteredItems, setFilteredItems] = useState(
|
const [filteredItems, setFilteredItems] = useState(
|
||||||
filterContents(combineRelatedContent, contents)
|
filterContents(contents, combineRelatedContent, searchName)
|
||||||
);
|
);
|
||||||
|
|
||||||
const [groups, setGroups] = useState<GroupContentItems>(
|
const [groups, setGroups] = useState<GroupContentItems>(
|
||||||
|
@ -40,8 +43,20 @@ export default function Contents(props: Immutable<Props>): JSX.Element {
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setFilteredItems(filterContents(combineRelatedContent, contents));
|
if (searchName.length > 1) {
|
||||||
}, [combineRelatedContent, contents]);
|
setEffectiveCombineRelatedContent(false);
|
||||||
|
} else {
|
||||||
|
setEffectiveCombineRelatedContent(combineRelatedContent);
|
||||||
|
}
|
||||||
|
setFilteredItems(
|
||||||
|
filterContents(contents, effectiveCombineRelatedContent, searchName)
|
||||||
|
);
|
||||||
|
}, [
|
||||||
|
effectiveCombineRelatedContent,
|
||||||
|
contents,
|
||||||
|
searchName,
|
||||||
|
combineRelatedContent,
|
||||||
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setGroups(getGroups(langui, groupingMethod, filteredItems));
|
setGroups(getGroups(langui, groupingMethod, filteredItems));
|
||||||
|
@ -55,6 +70,18 @@ export default function Contents(props: Immutable<Props>): JSX.Element {
|
||||||
description={langui.contents_description}
|
description={langui.contents_description}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<input
|
||||||
|
className="w-full mb-6"
|
||||||
|
type="text"
|
||||||
|
name="name"
|
||||||
|
id="name"
|
||||||
|
placeholder="Search title..."
|
||||||
|
onChange={(event) => {
|
||||||
|
const input = event.target as HTMLInputElement;
|
||||||
|
setSearchName(input.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<div className="flex flex-row gap-2 place-items-center">
|
<div className="flex flex-row gap-2 place-items-center">
|
||||||
<p className="flex-shrink-0">{langui.group_by}:</p>
|
<p className="flex-shrink-0">{langui.group_by}:</p>
|
||||||
<Select
|
<Select
|
||||||
|
@ -66,11 +93,18 @@ export default function Contents(props: Immutable<Props>): JSX.Element {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-row gap-2 place-items-center coarse:hidden">
|
<div
|
||||||
|
className={`flex flex-row gap-2 place-items-center coarse:hidden ${
|
||||||
|
searchName.length > 1
|
||||||
|
? "text-dark grayscale contrast-75 brightness-150"
|
||||||
|
: ""
|
||||||
|
}`}
|
||||||
|
>
|
||||||
<p className="flex-shrink-0">{langui.combine_related_contents}:</p>
|
<p className="flex-shrink-0">{langui.combine_related_contents}:</p>
|
||||||
<Switch
|
<Switch
|
||||||
setState={setCombineRelatedContent}
|
setState={setCombineRelatedContent}
|
||||||
state={combineRelatedContent}
|
state={combineRelatedContent}
|
||||||
|
disabled={searchName.length > 1}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -83,9 +117,9 @@ export default function Contents(props: Immutable<Props>): JSX.Element {
|
||||||
const contentPanel = (
|
const contentPanel = (
|
||||||
<ContentPanel width={ContentPanelWidthSizes.large}>
|
<ContentPanel width={ContentPanelWidthSizes.large}>
|
||||||
{[...groups].map(([name, items]) => (
|
{[...groups].map(([name, items]) => (
|
||||||
<>
|
<Fragment key={name}>
|
||||||
{items.length > 0 && (
|
{items.length > 0 && (
|
||||||
<>
|
<Fragment>
|
||||||
{name && (
|
{name && (
|
||||||
<h2
|
<h2
|
||||||
key={`h2${name}`}
|
key={`h2${name}`}
|
||||||
|
@ -94,7 +128,7 @@ export default function Contents(props: Immutable<Props>): JSX.Element {
|
||||||
>
|
>
|
||||||
{name}
|
{name}
|
||||||
<Chip>{`${items.reduce((currentSum, item) => {
|
<Chip>{`${items.reduce((currentSum, item) => {
|
||||||
if (combineRelatedContent) {
|
if (effectiveCombineRelatedContent) {
|
||||||
if (item.attributes?.group?.data?.attributes?.combine) {
|
if (item.attributes?.group?.data?.attributes?.combine) {
|
||||||
return (
|
return (
|
||||||
currentSum +
|
currentSum +
|
||||||
|
@ -117,10 +151,9 @@ export default function Contents(props: Immutable<Props>): JSX.Element {
|
||||||
desktop:grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))]"
|
desktop:grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))]"
|
||||||
>
|
>
|
||||||
{items.map((item) => (
|
{items.map((item) => (
|
||||||
<>
|
<Fragment key={item.id}>
|
||||||
{item.attributes && (
|
{item.attributes && (
|
||||||
<PreviewCard
|
<PreviewCard
|
||||||
key={item.id}
|
|
||||||
href={`/contents/${item.attributes.slug}`}
|
href={`/contents/${item.attributes.slug}`}
|
||||||
pre_title={item.attributes.translations?.[0]?.pre_title}
|
pre_title={item.attributes.translations?.[0]?.pre_title}
|
||||||
title={
|
title={
|
||||||
|
@ -131,7 +164,7 @@ export default function Contents(props: Immutable<Props>): JSX.Element {
|
||||||
thumbnail={item.attributes.thumbnail?.data?.attributes}
|
thumbnail={item.attributes.thumbnail?.data?.attributes}
|
||||||
thumbnailAspectRatio="3/2"
|
thumbnailAspectRatio="3/2"
|
||||||
stackNumber={
|
stackNumber={
|
||||||
combineRelatedContent &&
|
effectiveCombineRelatedContent &&
|
||||||
item.attributes.group?.data?.attributes?.combine
|
item.attributes.group?.data?.attributes?.combine
|
||||||
? item.attributes.group.data.attributes.contents
|
? item.attributes.group.data.attributes.contents
|
||||||
?.data.length
|
?.data.length
|
||||||
|
@ -155,12 +188,12 @@ export default function Contents(props: Immutable<Props>): JSX.Element {
|
||||||
keepInfoVisible={keepInfoVisible}
|
keepInfoVisible={keepInfoVisible}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</ContentPanel>
|
</ContentPanel>
|
||||||
);
|
);
|
||||||
|
@ -271,17 +304,33 @@ function getGroups(
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterContents(
|
function filterContents(
|
||||||
|
contents: Immutable<Props["contents"]>,
|
||||||
combineRelatedContent: boolean,
|
combineRelatedContent: boolean,
|
||||||
contents: Immutable<Props["contents"]>
|
searchName: string
|
||||||
): Immutable<Props["contents"]> {
|
): Immutable<Props["contents"]> {
|
||||||
if (combineRelatedContent) {
|
return contents.filter((content) => {
|
||||||
return [...contents].filter(
|
if (
|
||||||
(content) =>
|
combineRelatedContent &&
|
||||||
!content.attributes?.group?.data?.attributes ||
|
content.attributes?.group?.data?.attributes?.combine &&
|
||||||
!content.attributes.group.data.attributes.combine ||
|
content.attributes.group.data.attributes.contents?.data[0].id !==
|
||||||
content.attributes.group.data.attributes.contents?.data[0].id ===
|
|
||||||
content.id
|
content.id
|
||||||
);
|
) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return contents;
|
if (searchName.length > 1) {
|
||||||
|
if (
|
||||||
|
prettyinlineTitle(
|
||||||
|
content.attributes?.translations?.[0]?.pre_title,
|
||||||
|
content.attributes?.translations?.[0]?.title,
|
||||||
|
content.attributes?.translations?.[0]?.subtitle
|
||||||
|
)
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(searchName.toLowerCase())
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ import {
|
||||||
GetStaticPathsResult,
|
GetStaticPathsResult,
|
||||||
GetStaticPropsContext,
|
GetStaticPropsContext,
|
||||||
} from "next";
|
} from "next";
|
||||||
import { useState } from "react";
|
import { Fragment, useState } from "react";
|
||||||
|
|
||||||
interface Props extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
item: NonNullable<
|
item: NonNullable<
|
||||||
|
@ -185,18 +185,14 @@ export default function LibrarySlug(props: Immutable<Props>): JSX.Element {
|
||||||
{item?.urls && item.urls.length ? (
|
{item?.urls && item.urls.length ? (
|
||||||
<div className="flex flex-row place-items-center gap-3">
|
<div className="flex flex-row place-items-center gap-3">
|
||||||
<p>{langui.available_at}</p>
|
<p>{langui.available_at}</p>
|
||||||
{item.urls.map((url) => (
|
{item.urls.map((url, index) => (
|
||||||
<>
|
<Fragment key={index}>
|
||||||
{url?.url && (
|
{url?.url && (
|
||||||
<Button
|
<Button href={url.url} target={"_blank"}>
|
||||||
href={url.url}
|
|
||||||
key={url.url}
|
|
||||||
target={"_blank"}
|
|
||||||
>
|
|
||||||
{prettyURL(url.url)}
|
{prettyURL(url.url)}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
@ -215,10 +211,9 @@ export default function LibrarySlug(props: Immutable<Props>): JSX.Element {
|
||||||
grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))]"
|
grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))]"
|
||||||
>
|
>
|
||||||
{item.gallery.data.map((galleryItem, index) => (
|
{item.gallery.data.map((galleryItem, index) => (
|
||||||
<>
|
<Fragment key={galleryItem.id}>
|
||||||
{galleryItem.attributes && (
|
{galleryItem.attributes && (
|
||||||
<div
|
<div
|
||||||
key={galleryItem.id}
|
|
||||||
className="relative aspect-square hover:scale-[1.02]
|
className="relative aspect-square hover:scale-[1.02]
|
||||||
transition-transform cursor-pointer"
|
transition-transform cursor-pointer"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
@ -244,7 +239,7 @@ export default function LibrarySlug(props: Immutable<Props>): JSX.Element {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -405,10 +400,9 @@ export default function LibrarySlug(props: Immutable<Props>): JSX.Element {
|
||||||
grid-cols-[repeat(auto-fill,minmax(15rem,1fr))] w-full"
|
grid-cols-[repeat(auto-fill,minmax(15rem,1fr))] w-full"
|
||||||
>
|
>
|
||||||
{item.subitems.data.map((subitem) => (
|
{item.subitems.data.map((subitem) => (
|
||||||
<>
|
<Fragment key={subitem.id}>
|
||||||
{subitem.attributes && (
|
{subitem.attributes && (
|
||||||
<PreviewCard
|
<PreviewCard
|
||||||
key={subitem.id}
|
|
||||||
href={`/library/${subitem.attributes.slug}`}
|
href={`/library/${subitem.attributes.slug}`}
|
||||||
title={subitem.attributes.title}
|
title={subitem.attributes.title}
|
||||||
subtitle={subitem.attributes.subtitle}
|
subtitle={subitem.attributes.subtitle}
|
||||||
|
@ -433,7 +427,7 @@ export default function LibrarySlug(props: Immutable<Props>): JSX.Element {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -23,6 +23,7 @@ import {
|
||||||
GetStaticPathsResult,
|
GetStaticPathsResult,
|
||||||
GetStaticPropsContext,
|
GetStaticPropsContext,
|
||||||
} from "next";
|
} from "next";
|
||||||
|
import { Fragment } from "react";
|
||||||
|
|
||||||
interface Props extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
item: NonNullable<
|
item: NonNullable<
|
||||||
|
@ -89,10 +90,9 @@ export default function LibrarySlug(props: Immutable<Props>): JSX.Element {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{item?.contents?.data.map((content) => (
|
{item?.contents?.data.map((content) => (
|
||||||
<>
|
<Fragment key={content.id}>
|
||||||
{content.attributes?.scan_set?.[0] && (
|
{content.attributes?.scan_set?.[0] && (
|
||||||
<ScanSet
|
<ScanSet
|
||||||
key={content.id}
|
|
||||||
scanSet={content.attributes.scan_set}
|
scanSet={content.attributes.scan_set}
|
||||||
openLightBox={openLightBox}
|
openLightBox={openLightBox}
|
||||||
slug={content.attributes.slug}
|
slug={content.attributes.slug}
|
||||||
|
@ -102,7 +102,7 @@ export default function LibrarySlug(props: Immutable<Props>): JSX.Element {
|
||||||
content={content.attributes.content}
|
content={content.attributes.content}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</ContentPanel>
|
</ContentPanel>
|
||||||
);
|
);
|
||||||
|
|
|
@ -20,7 +20,7 @@ import {
|
||||||
import { convertPrice } from "helpers/numbers";
|
import { convertPrice } from "helpers/numbers";
|
||||||
import { Immutable } from "helpers/types";
|
import { Immutable } from "helpers/types";
|
||||||
import { GetStaticPropsContext } from "next";
|
import { GetStaticPropsContext } from "next";
|
||||||
import { useEffect, useState } from "react";
|
import { Fragment, useEffect, useState } from "react";
|
||||||
|
|
||||||
interface Props extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
items: NonNullable<GetLibraryItemsPreviewQuery["libraryItems"]>["data"];
|
items: NonNullable<GetLibraryItemsPreviewQuery["libraryItems"]>["data"];
|
||||||
|
@ -31,6 +31,7 @@ type GroupLibraryItems = Map<string, Immutable<Props["items"]>>;
|
||||||
export default function Library(props: Immutable<Props>): JSX.Element {
|
export default function Library(props: Immutable<Props>): JSX.Element {
|
||||||
const { langui, items: libraryItems, currencies } = props;
|
const { langui, items: libraryItems, currencies } = props;
|
||||||
|
|
||||||
|
const [searchName, setSearchName] = useState("");
|
||||||
const [showSubitems, setShowSubitems] = useState<boolean>(false);
|
const [showSubitems, setShowSubitems] = useState<boolean>(false);
|
||||||
const [showPrimaryItems, setShowPrimaryItems] = useState<boolean>(true);
|
const [showPrimaryItems, setShowPrimaryItems] = useState<boolean>(true);
|
||||||
const [showSecondaryItems, setShowSecondaryItems] = useState<boolean>(false);
|
const [showSecondaryItems, setShowSecondaryItems] = useState<boolean>(false);
|
||||||
|
@ -40,10 +41,11 @@ export default function Library(props: Immutable<Props>): JSX.Element {
|
||||||
|
|
||||||
const [filteredItems, setFilteredItems] = useState(
|
const [filteredItems, setFilteredItems] = useState(
|
||||||
filterItems(
|
filterItems(
|
||||||
|
libraryItems,
|
||||||
|
searchName,
|
||||||
showSubitems,
|
showSubitems,
|
||||||
showPrimaryItems,
|
showPrimaryItems,
|
||||||
showSecondaryItems,
|
showSecondaryItems
|
||||||
libraryItems
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -58,13 +60,20 @@ export default function Library(props: Immutable<Props>): JSX.Element {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setFilteredItems(
|
setFilteredItems(
|
||||||
filterItems(
|
filterItems(
|
||||||
|
libraryItems,
|
||||||
|
searchName,
|
||||||
showSubitems,
|
showSubitems,
|
||||||
showPrimaryItems,
|
showPrimaryItems,
|
||||||
showSecondaryItems,
|
showSecondaryItems
|
||||||
libraryItems
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}, [showSubitems, libraryItems, showPrimaryItems, showSecondaryItems]);
|
}, [
|
||||||
|
showSubitems,
|
||||||
|
libraryItems,
|
||||||
|
showPrimaryItems,
|
||||||
|
showSecondaryItems,
|
||||||
|
searchName,
|
||||||
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSortedItem(sortBy(sortingMethod, filteredItems, currencies));
|
setSortedItem(sortBy(sortingMethod, filteredItems, currencies));
|
||||||
|
@ -82,6 +91,18 @@ export default function Library(props: Immutable<Props>): JSX.Element {
|
||||||
description={langui.library_description}
|
description={langui.library_description}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<input
|
||||||
|
className="w-full mb-6"
|
||||||
|
type="text"
|
||||||
|
name="name"
|
||||||
|
id="name"
|
||||||
|
placeholder="Search title..."
|
||||||
|
onChange={(event) => {
|
||||||
|
const input = event.target as HTMLInputElement;
|
||||||
|
setSearchName(input.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<div className="flex flex-row gap-2 place-items-center">
|
<div className="flex flex-row gap-2 place-items-center">
|
||||||
<p className="flex-shrink-0">{langui.group_by}:</p>
|
<p className="flex-shrink-0">{langui.group_by}:</p>
|
||||||
<Select
|
<Select
|
||||||
|
@ -135,12 +156,11 @@ export default function Library(props: Immutable<Props>): JSX.Element {
|
||||||
const contentPanel = (
|
const contentPanel = (
|
||||||
<ContentPanel width={ContentPanelWidthSizes.large}>
|
<ContentPanel width={ContentPanelWidthSizes.large}>
|
||||||
{[...groups].map(([name, items]) => (
|
{[...groups].map(([name, items]) => (
|
||||||
<>
|
<Fragment key={name}>
|
||||||
{items.length > 0 && (
|
{items.length > 0 && (
|
||||||
<>
|
<>
|
||||||
{name && (
|
{name && (
|
||||||
<h2
|
<h2
|
||||||
key={`h2${name}`}
|
|
||||||
className="text-2xl pb-2 pt-10 first-of-type:pt-0
|
className="text-2xl pb-2 pt-10 first-of-type:pt-0
|
||||||
flex flex-row place-items-center gap-2"
|
flex flex-row place-items-center gap-2"
|
||||||
>
|
>
|
||||||
|
@ -153,16 +173,14 @@ export default function Library(props: Immutable<Props>): JSX.Element {
|
||||||
</h2>
|
</h2>
|
||||||
)}
|
)}
|
||||||
<div
|
<div
|
||||||
key={`items${name}`}
|
|
||||||
className="grid gap-8 mobile:gap-4 items-end mobile:grid-cols-2
|
className="grid gap-8 mobile:gap-4 items-end mobile:grid-cols-2
|
||||||
desktop:grid-cols-[repeat(auto-fill,_minmax(13rem,1fr))]
|
desktop:grid-cols-[repeat(auto-fill,_minmax(13rem,1fr))]
|
||||||
pb-12 border-b-[3px] border-dotted last-of-type:border-0"
|
pb-12 border-b-[3px] border-dotted last-of-type:border-0"
|
||||||
>
|
>
|
||||||
{items.map((item) => (
|
{items.map((item) => (
|
||||||
<>
|
<Fragment key={item.id}>
|
||||||
{item.attributes && (
|
{item.attributes && (
|
||||||
<PreviewCard
|
<PreviewCard
|
||||||
key={item.id}
|
|
||||||
href={`/library/${item.attributes.slug}`}
|
href={`/library/${item.attributes.slug}`}
|
||||||
title={item.attributes.title}
|
title={item.attributes.title}
|
||||||
subtitle={item.attributes.subtitle}
|
subtitle={item.attributes.subtitle}
|
||||||
|
@ -187,12 +205,12 @@ export default function Library(props: Immutable<Props>): JSX.Element {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</ContentPanel>
|
</ContentPanel>
|
||||||
);
|
);
|
||||||
|
@ -362,10 +380,11 @@ function getGroups(
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterItems(
|
function filterItems(
|
||||||
|
items: Immutable<Props["items"]>,
|
||||||
|
searchName: string,
|
||||||
showSubitems: boolean,
|
showSubitems: boolean,
|
||||||
showPrimaryItems: boolean,
|
showPrimaryItems: boolean,
|
||||||
showSecondaryItems: boolean,
|
showSecondaryItems: boolean
|
||||||
items: Immutable<Props["items"]>
|
|
||||||
): Immutable<Props["items"]> {
|
): Immutable<Props["items"]> {
|
||||||
return [...items].filter((item) => {
|
return [...items].filter((item) => {
|
||||||
if (!showSubitems && !item.attributes?.root_item) return false;
|
if (!showSubitems && !item.attributes?.root_item) return false;
|
||||||
|
@ -376,10 +395,21 @@ function filterItems(
|
||||||
"variant-set" ||
|
"variant-set" ||
|
||||||
item.attributes.metadata[0].subtype?.data?.attributes?.slug ===
|
item.attributes.metadata[0].subtype?.data?.attributes?.slug ===
|
||||||
"relation-set")
|
"relation-set")
|
||||||
)
|
) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
if (item.attributes?.primary && !showPrimaryItems) return false;
|
if (item.attributes?.primary && !showPrimaryItems) return false;
|
||||||
if (!item.attributes?.primary && !showSecondaryItems) return false;
|
if (!item.attributes?.primary && !showSecondaryItems) return false;
|
||||||
|
if (searchName.length > 1) {
|
||||||
|
if (
|
||||||
|
prettyinlineTitle("", item.attributes?.title, item.attributes?.subtitle)
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(searchName.toLowerCase())
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { getReadySdk } from "graphql/sdk";
|
||||||
import { prettyDate, prettySlug } from "helpers/formatters";
|
import { prettyDate, prettySlug } from "helpers/formatters";
|
||||||
import { Immutable } from "helpers/types";
|
import { Immutable } from "helpers/types";
|
||||||
import { GetStaticPropsContext } from "next";
|
import { GetStaticPropsContext } from "next";
|
||||||
import { useState } from "react";
|
import { Fragment, useState } from "react";
|
||||||
|
|
||||||
interface Props extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
posts: NonNullable<GetPostsPreviewQuery["posts"]>["data"];
|
posts: NonNullable<GetPostsPreviewQuery["posts"]>["data"];
|
||||||
|
@ -47,10 +47,9 @@ export default function News(props: Immutable<Props>): JSX.Element {
|
||||||
desktop:grid-cols-[repeat(auto-fill,_minmax(20rem,1fr))]"
|
desktop:grid-cols-[repeat(auto-fill,_minmax(20rem,1fr))]"
|
||||||
>
|
>
|
||||||
{posts.map((post) => (
|
{posts.map((post) => (
|
||||||
<>
|
<Fragment key={post.id}>
|
||||||
{post.attributes && (
|
{post.attributes && (
|
||||||
<PreviewCard
|
<PreviewCard
|
||||||
key={post.id}
|
|
||||||
href={`/news/${post.attributes.slug}`}
|
href={`/news/${post.attributes.slug}`}
|
||||||
title={
|
title={
|
||||||
post.attributes.translations?.[0]?.title ??
|
post.attributes.translations?.[0]?.title ??
|
||||||
|
@ -69,7 +68,7 @@ export default function News(props: Immutable<Props>): JSX.Element {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</ContentPanel>
|
</ContentPanel>
|
||||||
|
|
|
@ -8,12 +8,12 @@ import {
|
||||||
import { ContentPanel } from "components/Panels/ContentPanel";
|
import { ContentPanel } from "components/Panels/ContentPanel";
|
||||||
import { SubPanel } from "components/Panels/SubPanel";
|
import { SubPanel } from "components/Panels/SubPanel";
|
||||||
import { ChronologyYearComponent } from "components/Wiki/Chronology/ChronologyYearComponent";
|
import { ChronologyYearComponent } from "components/Wiki/Chronology/ChronologyYearComponent";
|
||||||
import { useAppLayout } from "contexts/AppLayoutContext";
|
|
||||||
import { GetChronologyItemsQuery, GetErasQuery } from "graphql/generated";
|
import { GetChronologyItemsQuery, GetErasQuery } from "graphql/generated";
|
||||||
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
|
||||||
import { getReadySdk } from "graphql/sdk";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import { prettySlug } from "helpers/formatters";
|
import { prettySlug } from "helpers/formatters";
|
||||||
import { GetStaticPropsContext } from "next";
|
import { GetStaticPropsContext } from "next";
|
||||||
|
import { Fragment } from "react";
|
||||||
|
|
||||||
interface Props extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
chronologyItems: NonNullable<
|
chronologyItems: NonNullable<
|
||||||
|
@ -24,7 +24,6 @@ interface Props extends AppStaticProps {
|
||||||
|
|
||||||
export default function Chronology(props: Props): JSX.Element {
|
export default function Chronology(props: Props): JSX.Element {
|
||||||
const { chronologyItems, chronologyEras, langui } = props;
|
const { chronologyItems, chronologyEras, langui } = props;
|
||||||
const appLayout = useAppLayout();
|
|
||||||
|
|
||||||
// Group by year the Chronology items
|
// Group by year the Chronology items
|
||||||
const chronologyItemYearGroups: Props["chronologyItems"][number][][][] = [];
|
const chronologyItemYearGroups: Props["chronologyItems"][number][][][] = [];
|
||||||
|
@ -71,10 +70,9 @@ export default function Chronology(props: Props): JSX.Element {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{chronologyEras.map((era) => (
|
{chronologyEras.map((era) => (
|
||||||
<>
|
<Fragment key={era.id}>
|
||||||
{era.attributes && (
|
{era.attributes && (
|
||||||
<NavOption
|
<NavOption
|
||||||
key={era.id}
|
|
||||||
url={`#${era.attributes.slug}`}
|
url={`#${era.attributes.slug}`}
|
||||||
title={
|
title={
|
||||||
era.attributes.title &&
|
era.attributes.title &&
|
||||||
|
@ -87,7 +85,7 @@ export default function Chronology(props: Props): JSX.Element {
|
||||||
border
|
border
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</SubPanel>
|
</SubPanel>
|
||||||
);
|
);
|
||||||
|
@ -103,7 +101,7 @@ export default function Chronology(props: Props): JSX.Element {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{chronologyItemYearGroups.map((era, eraIndex) => (
|
{chronologyItemYearGroups.map((era, eraIndex) => (
|
||||||
<>
|
<Fragment key={eraIndex}>
|
||||||
<InsetBox
|
<InsetBox
|
||||||
id={chronologyEras[eraIndex].attributes?.slug}
|
id={chronologyEras[eraIndex].attributes?.slug}
|
||||||
className="grid text-center my-8 gap-4"
|
className="grid text-center my-8 gap-4"
|
||||||
|
@ -120,18 +118,17 @@ export default function Chronology(props: Props): JSX.Element {
|
||||||
</p>
|
</p>
|
||||||
</InsetBox>
|
</InsetBox>
|
||||||
{era.map((items, index) => (
|
{era.map((items, index) => (
|
||||||
<>
|
<Fragment key={index}>
|
||||||
{items[0].attributes?.year && (
|
{items[0].attributes?.year && (
|
||||||
<ChronologyYearComponent
|
<ChronologyYearComponent
|
||||||
key={`${eraIndex}-${index}`}
|
|
||||||
year={items[0].attributes.year}
|
year={items[0].attributes.year}
|
||||||
items={items}
|
items={items}
|
||||||
langui={langui}
|
langui={langui}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</ContentPanel>
|
</ContentPanel>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue