Added more grouping options for Library and Contents #9

Merged
DrMint merged 6 commits from develop into main 2022-03-11 00:43:42 +00:00
18 changed files with 393 additions and 241 deletions

100
package-lock.json generated
View File

@ -11,7 +11,7 @@
"@fontsource/opendyslexic": "^4.5.2",
"@fontsource/vollkorn": "^4.5.4",
"@fontsource/zen-maru-gothic": "^4.5.5",
"markdown-to-jsx": "^7.1.6",
"markdown-to-jsx": "^7.1.7",
"next": "^12.1.0",
"react": "17.0.2",
"react-dom": "17.0.2",
@ -21,13 +21,13 @@
},
"devDependencies": {
"@tailwindcss/typography": "^0.5.2",
"@types/node": "17.0.18",
"@types/react": "17.0.39",
"@types/react-dom": "^17.0.11",
"eslint": "8.9.0",
"@types/node": "17.0.21",
"@types/react": "17.0.40",
"@types/react-dom": "^17.0.13",
"eslint": "8.10.0",
"eslint-config-next": "12.1.0",
"tailwindcss": "^3.0.23",
"typescript": "4.5.5"
"typescript": "4.6.2"
}
},
"node_modules/@babel/code-frame": {
@ -162,9 +162,9 @@
}
},
"node_modules/@eslint/eslintrc": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.1.0.tgz",
"integrity": "sha512-C1DfL7XX4nPqGd6jcP01W9pVM1HYCuUkFk1432D7F0v3JSlUIeOYn9oCoi3eoLZ+iwBSb29BMFxxny0YrrEZqg==",
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.0.tgz",
"integrity": "sha512-igm9SjJHNEJRiUnecP/1R5T3wKLEJ7pL6e2P+GUSfCd0dGjPYYZve08uzw8L2J8foVHFz+NGu12JxRcU2gGo6w==",
"dev": true,
"dependencies": {
"ajv": "^6.12.4",
@ -476,9 +476,9 @@
"dev": true
},
"node_modules/@types/node": {
"version": "17.0.18",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.18.tgz",
"integrity": "sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA==",
"version": "17.0.21",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz",
"integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==",
"dev": true
},
"node_modules/@types/parse-json": {
@ -494,9 +494,9 @@
"dev": true
},
"node_modules/@types/react": {
"version": "17.0.39",
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.39.tgz",
"integrity": "sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug==",
"version": "17.0.40",
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.40.tgz",
"integrity": "sha512-UrXhD/JyLH+W70nNSufXqMZNuUD2cXHu6UjCllC6pmOQgBX4SGXOH8fjRka0O0Ee0HrFxapDD8Bwn81Kmiz6jQ==",
"dev": true,
"dependencies": {
"@types/prop-types": "*",
@ -505,9 +505,9 @@
}
},
"node_modules/@types/react-dom": {
"version": "17.0.11",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.11.tgz",
"integrity": "sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==",
"version": "17.0.13",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.13.tgz",
"integrity": "sha512-wEP+B8hzvy6ORDv1QBhcQia4j6ea4SFIBttHYpXKPFZRviBvknq0FRh3VrIxeXUmsPkwuXVZrVGG7KUVONmXCQ==",
"dev": true,
"dependencies": {
"@types/react": "*"
@ -1302,12 +1302,12 @@
}
},
"node_modules/eslint": {
"version": "8.9.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.9.0.tgz",
"integrity": "sha512-PB09IGwv4F4b0/atrbcMFboF/giawbBLVC7fyDamk5Wtey4Jh2K+rYaBhCAbUyEI4QzB1ly09Uglc9iCtFaG2Q==",
"version": "8.10.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.10.0.tgz",
"integrity": "sha512-tcI1D9lfVec+R4LE1mNDnzoJ/f71Kl/9Cv4nG47jOueCMBrCCKYXr4AUVS7go6mWYGFD4+EoN6+eXSrEbRzXVw==",
"dev": true,
"dependencies": {
"@eslint/eslintrc": "^1.1.0",
"@eslint/eslintrc": "^1.2.0",
"@humanwhocodes/config-array": "^0.9.2",
"ajv": "^6.10.0",
"chalk": "^4.0.0",
@ -2447,9 +2447,9 @@
}
},
"node_modules/markdown-to-jsx": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.1.6.tgz",
"integrity": "sha512-1wrIGZYwIG2gR3yfRmbr4FlQmhaAKoKTpRo4wur4fp9p0njU1Hi7vR8fj0AUKKIcPduiJmPprzmCB5B/GvlC7g==",
"version": "7.1.7",
"resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.1.7.tgz",
"integrity": "sha512-VI3TyyHlGkO8uFle0IOibzpO1c1iJDcXcS/zBrQrXQQvJ2tpdwVzVZ7XdKsyRz1NdRmre4dqQkMZzUHaKIG/1w==",
"engines": {
"node": ">= 10"
},
@ -3529,9 +3529,9 @@
}
},
"node_modules/typescript": {
"version": "4.5.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz",
"integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==",
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz",
"integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
@ -3772,9 +3772,9 @@
}
},
"@eslint/eslintrc": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.1.0.tgz",
"integrity": "sha512-C1DfL7XX4nPqGd6jcP01W9pVM1HYCuUkFk1432D7F0v3JSlUIeOYn9oCoi3eoLZ+iwBSb29BMFxxny0YrrEZqg==",
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.0.tgz",
"integrity": "sha512-igm9SjJHNEJRiUnecP/1R5T3wKLEJ7pL6e2P+GUSfCd0dGjPYYZve08uzw8L2J8foVHFz+NGu12JxRcU2gGo6w==",
"dev": true,
"requires": {
"ajv": "^6.12.4",
@ -3968,9 +3968,9 @@
"dev": true
},
"@types/node": {
"version": "17.0.18",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.18.tgz",
"integrity": "sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA==",
"version": "17.0.21",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz",
"integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==",
"dev": true
},
"@types/parse-json": {
@ -3986,9 +3986,9 @@
"dev": true
},
"@types/react": {
"version": "17.0.39",
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.39.tgz",
"integrity": "sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug==",
"version": "17.0.40",
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.40.tgz",
"integrity": "sha512-UrXhD/JyLH+W70nNSufXqMZNuUD2cXHu6UjCllC6pmOQgBX4SGXOH8fjRka0O0Ee0HrFxapDD8Bwn81Kmiz6jQ==",
"dev": true,
"requires": {
"@types/prop-types": "*",
@ -3997,9 +3997,9 @@
}
},
"@types/react-dom": {
"version": "17.0.11",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.11.tgz",
"integrity": "sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==",
"version": "17.0.13",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.13.tgz",
"integrity": "sha512-wEP+B8hzvy6ORDv1QBhcQia4j6ea4SFIBttHYpXKPFZRviBvknq0FRh3VrIxeXUmsPkwuXVZrVGG7KUVONmXCQ==",
"dev": true,
"requires": {
"@types/react": "*"
@ -4564,12 +4564,12 @@
"dev": true
},
"eslint": {
"version": "8.9.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.9.0.tgz",
"integrity": "sha512-PB09IGwv4F4b0/atrbcMFboF/giawbBLVC7fyDamk5Wtey4Jh2K+rYaBhCAbUyEI4QzB1ly09Uglc9iCtFaG2Q==",
"version": "8.10.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.10.0.tgz",
"integrity": "sha512-tcI1D9lfVec+R4LE1mNDnzoJ/f71Kl/9Cv4nG47jOueCMBrCCKYXr4AUVS7go6mWYGFD4+EoN6+eXSrEbRzXVw==",
"dev": true,
"requires": {
"@eslint/eslintrc": "^1.1.0",
"@eslint/eslintrc": "^1.2.0",
"@humanwhocodes/config-array": "^0.9.2",
"ajv": "^6.10.0",
"chalk": "^4.0.0",
@ -5430,9 +5430,9 @@
}
},
"markdown-to-jsx": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.1.6.tgz",
"integrity": "sha512-1wrIGZYwIG2gR3yfRmbr4FlQmhaAKoKTpRo4wur4fp9p0njU1Hi7vR8fj0AUKKIcPduiJmPprzmCB5B/GvlC7g==",
"version": "7.1.7",
"resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.1.7.tgz",
"integrity": "sha512-VI3TyyHlGkO8uFle0IOibzpO1c1iJDcXcS/zBrQrXQQvJ2tpdwVzVZ7XdKsyRz1NdRmre4dqQkMZzUHaKIG/1w==",
"requires": {}
},
"merge2": {
@ -6153,9 +6153,9 @@
"dev": true
},
"typescript": {
"version": "4.5.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz",
"integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==",
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz",
"integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==",
"dev": true
},
"unbox-primitive": {

View File

@ -13,7 +13,7 @@
"@fontsource/opendyslexic": "^4.5.2",
"@fontsource/vollkorn": "^4.5.4",
"@fontsource/zen-maru-gothic": "^4.5.5",
"markdown-to-jsx": "^7.1.6",
"markdown-to-jsx": "^7.1.7",
"next": "^12.1.0",
"react": "17.0.2",
"react-dom": "17.0.2",
@ -23,12 +23,12 @@
},
"devDependencies": {
"@tailwindcss/typography": "^0.5.2",
"@types/node": "17.0.18",
"@types/react": "17.0.39",
"@types/react-dom": "^17.0.11",
"eslint": "8.9.0",
"@types/node": "17.0.21",
"@types/react": "17.0.40",
"@types/react-dom": "^17.0.13",
"eslint": "8.10.0",
"eslint-config-next": "12.1.0",
"tailwindcss": "^3.0.23",
"typescript": "4.5.5"
"typescript": "4.6.2"
}
}

View File

@ -199,7 +199,7 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
</div>
{/* Sub panel */}
{subPanel ? (
{subPanel && (
<div
className={`${subPanelClass} border-r-[1px] mobile:bottom-20 mobile:border-r-0 mobile:border-l-[1px] border-black border-dotted top-0 bottom-0 right-0 left-12 overflow-y-scroll webkit-scrollbar:w-0 [scrollbar-width:none] transition-transform duration-300 bg-light texture-paper-dots
${
@ -212,8 +212,6 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
>
{subPanel}
</div>
) : (
""
)}
{/* Main panel */}

View File

@ -64,15 +64,13 @@ export default function ChronologyItemComponent(
props.item.attributes.day
)}
>
{props.displayYear ? (
{props.displayYear && (
<p className="text-lg mt-[-.2em] font-bold">
{generateYear(
props.item.attributes.displayed_date,
props.item.attributes.year
)}
</p>
) : (
""
)}
<p className="col-start-1 text-dark text-sm">
@ -108,7 +106,7 @@ export default function ChronologyItemComponent(
{translation.title ? <h3>{translation.title}</h3> : ""}
</div>
{translation.description ? (
{translation.description && (
<p
className={
event.translations.length > 1
@ -118,8 +116,6 @@ export default function ChronologyItemComponent(
>
{translation.description}
</p>
) : (
""
)}
{translation.note ? (
<em>{"Notes: " + translation.note}</em>

View File

@ -53,7 +53,7 @@ export default function ThumbnailHeader(
</div>
<div className="grid grid-flow-col gap-8">
{content.type ? (
{content.type && (
<div className="grid place-items-center place-content-start gap-2">
<h3 className="text-xl">{langui.type}</h3>
<Button>
@ -62,19 +62,15 @@ export default function ThumbnailHeader(
: prettySlug(content.type.data.attributes.slug)}
</Button>
</div>
) : (
""
)}
{content.categories.data.length > 0 ? (
{content.categories.data.length > 0 && (
<div className="grid place-items-center place-content-start gap-2">
<h3 className="text-xl">{langui.categories}</h3>
{content.categories.data.map((category) => (
<Button key={category.id}>{category.attributes.name}</Button>
))}
</div>
) : (
""
)}
</div>
{content.titles.length > 0 && content.titles[0].description && (

View File

@ -54,7 +54,7 @@ export default function ContentTOCLine(
? content.attributes.range[0].starting_page
: ""}
</p>
{content.attributes.content.data ? (
{content.attributes.content.data && (
<Chip className="justify-self-end thin:hidden">
{content.attributes.content.data.attributes.type.data.attributes
.titles.length > 0
@ -65,8 +65,6 @@ export default function ContentTOCLine(
.attributes.slug
)}
</Chip>
) : (
""
)}
</div>
<div
@ -78,24 +76,20 @@ export default function ContentTOCLine(
subdirectory_arrow_right
</span>
{content.attributes.scan_set.length > 0 ? (
{content.attributes.scan_set.length > 0 && (
<Button
href={`/contents/${content.attributes.content.data.attributes.slug}/scans/`}
>
{langui.view_scans}
</Button>
) : (
""
)}
{content.attributes.content.data ? (
{content.attributes.content.data && (
<Button
href={`/contents/${content.attributes.content.data.attributes.slug}`}
>
{langui.open_content}
</Button>
) : (
""
)}
{content.attributes.scan_set.length === 0 &&

View File

@ -33,14 +33,12 @@ export default function LibraryContentPreview(
)}
<div className="linearbg-obi fine:drop-shadow-shade-lg fine:absolute coarse:rounded-b-md bottom-2 -inset-x-0.5 opacity-[var(--cover-opacity)] transition-opacity z-20 grid p-4 gap-2">
<div className="grid grid-flow-col gap-1 overflow-hidden place-content-start">
{item.type.data ? (
{item.type.data && (
<Chip>
{item.type.data.attributes.titles.length > 0
? item.type.data.attributes.titles[0].title
: prettySlug(item.type.data.attributes.slug)}
</Chip>
) : (
""
)}
</div>
<div>

View File

@ -16,6 +16,7 @@ export type LibraryItemsPreviewProps = {
title: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["title"];
subtitle: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["subtitle"];
price?: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["price"];
categories: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["categories"];
release_date?: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["release_date"];
metadata?: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["metadata"];
};
@ -43,31 +44,36 @@ export default function LibraryItemsPreview(
)}
<div className="linearbg-obi fine:drop-shadow-shade-lg fine:absolute place-items-start bottom-2 -inset-x-0.5 opacity-[var(--cover-opacity)] transition-opacity z-20 grid p-4 gap-2">
{item.metadata && item.metadata.length > 0 ? (
{item.metadata && item.metadata.length > 0 && (
<div className="flex flex-row gap-1">
<Chip>{prettyItemSubType(item.metadata[0])}</Chip>
</div>
) : (
""
)}
<div>
<h2 className="mobile:text-sm text-lg leading-5">{item.title}</h2>
<h3 className="mobile:text-xs leading-3">{item.subtitle}</h3>
</div>
{item.release_date || item.price ? (
<div className="w-full grid grid-flow-col gap-1 overflow-x-scroll webkit-scrollbar:w-0 [scrollbar-width:none] place-content-start">
{item.categories.data.map((category) => (
<Chip key={category.id} className="text-sm">
{category.attributes.short}
</Chip>
))}
</div>
{(item.release_date || item.price) && (
<div className="grid grid-flow-col w-full">
{item.release_date ? (
{item.release_date && (
<p className="mobile:text-xs text-sm">
<span className="material-icons !text-base translate-y-[.15em] mr-1">
event
</span>
{prettyDate(item.release_date)}
</p>
) : (
""
)}
{item.price && props.currencies ? (
{item.price && props.currencies && (
<p className="mobile:text-xs text-sm justify-self-end">
<span className="material-icons !text-base translate-y-[.15em] mr-1">
shopping_cart
@ -78,12 +84,8 @@ export default function LibraryItemsPreview(
appLayout.currency
)}
</p>
) : (
""
)}
</div>
) : (
""
)}
</div>
</div>

View File

@ -10,10 +10,8 @@ export default function PanelHeader(props: PanelHeaderProps): JSX.Element {
return (
<>
<div className="w-full grid place-items-center">
{props.icon ? (
{props.icon && (
<span className="material-icons !text-4xl mb-3">{props.icon}</span>
) : (
""
)}
<h2 className="text-2xl">{props.title}</h2>
{props.description ? <p>{props.description}</p> : ""}

View File

@ -34,8 +34,10 @@ export default function ReturnButton(props: ReturnButtonProps): JSX.Element {
<Button
onClick={() => appLayout.setSubPanelOpen(false)}
href={props.href}
className="grid grid-flow-col gap-2"
>
&emsp;{props.langui.return_to} {props.title}
<span className="material-icons">navigate_before</span>
{props.langui.return_to} {props.title}
</Button>
{props.horizontalLine && <HorizontalLine />}
</div>

View File

@ -192,10 +192,8 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
}`}
>
<p>
{langui.licensing_notice ? (
{langui.licensing_notice && (
<Markdown>{langui.licensing_notice}</Markdown>
) : (
""
)}
</p>
<a
@ -210,10 +208,8 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
</div>
</a>
<p>
{langui.copyright_notice ? (
{langui.copyright_notice && (
<Markdown>{langui.copyright_notice}</Markdown>
) : (
""
)}
</p>
<div className="mt-12 mb-4 grid h-4 grid-flow-col place-content-center gap-8">

View File

@ -205,6 +205,15 @@ query getLibraryItemsPreview($language_code: String) {
}
}
}
categories {
data {
id
attributes {
name
short
}
}
}
metadata {
__typename
... on ComponentMetadataBooks {
@ -354,6 +363,15 @@ query getLibraryItem($slug: String, $language_code: String) {
}
}
}
categories {
data {
id
attributes {
name
short
}
}
}
size {
width
height
@ -523,6 +541,15 @@ query getLibraryItem($slug: String, $language_code: String) {
}
}
}
categories {
data {
id
attributes {
name
short
}
}
}
metadata {
__typename
... on ComponentMetadataBooks {
@ -666,6 +693,7 @@ query getLibraryItem($slug: String, $language_code: String) {
data {
id
attributes {
name
short
}
}
@ -736,6 +764,7 @@ query getContents($language_code: String) {
data {
id
attributes {
name
short
}
}

View File

@ -317,6 +317,18 @@ export type GetLibraryItemsPreviewQuery = {
};
};
};
categories: {
__typename: "CategoryRelationResponseCollection";
data: Array<{
__typename: "CategoryEntity";
id: string;
attributes: {
__typename: "Category";
name: string;
short: string;
};
}>;
};
metadata: Array<
| {
__typename: "ComponentMetadataAudio";
@ -510,6 +522,18 @@ export type GetLibraryItemQuery = {
};
};
};
categories: {
__typename: "CategoryRelationResponseCollection";
data: Array<{
__typename: "CategoryEntity";
id: string;
attributes: {
__typename: "Category";
name: string;
short: string;
};
}>;
};
size: {
__typename: "ComponentBasicsSize";
width: number;
@ -726,6 +750,18 @@ export type GetLibraryItemQuery = {
};
};
};
categories: {
__typename: "CategoryRelationResponseCollection";
data: Array<{
__typename: "CategoryEntity";
id: string;
attributes: {
__typename: "Category";
name: string;
short: string;
};
}>;
};
metadata: Array<
| {
__typename: "ComponentMetadataAudio";
@ -897,6 +933,7 @@ export type GetLibraryItemQuery = {
id: string;
attributes: {
__typename: "Category";
name: string;
short: string;
};
}>;
@ -982,7 +1019,11 @@ export type GetContentsQuery = {
data: Array<{
__typename: "CategoryEntity";
id: string;
attributes: { __typename: "Category"; short: string };
attributes: {
__typename: "Category";
name: string;
short: string;
};
}>;
};
type: {

View File

@ -44,28 +44,22 @@ export default function ContentIndex(props: ContentIndexProps): JSX.Element {
<HorizontalLine />
{content.text_set.length > 0 ? (
{content.text_set.length > 0 && (
<Button href={`/contents/${content.slug}/read/`}>
{langui.read_content}
</Button>
) : (
""
)}
{content.audio_set.length > 0 ? (
{content.audio_set.length > 0 && (
<Button href={`/contents/${content.slug}/listen/`}>
{langui.listen_content}
</Button>
) : (
""
)}
{content.video_set.length > 0 ? (
{content.video_set.length > 0 && (
<Button href={`/contents/${content.slug}/watch/`}>
{langui.watch_content}
</Button>
) : (
""
)}
</div>
</ContentPanel>

View File

@ -47,7 +47,7 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
horizontalLine
/>
{content.text_set.length > 0 ? (
{content.text_set.length > 0 && (
<div className="grid gap-5">
<h2 className="text-xl">
{content.text_set[0].source_language.data.attributes.code ===
@ -140,8 +140,6 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
</div>
)}
</div>
) : (
""
)}
</SubPanel>
);
@ -159,10 +157,8 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
<HorizontalLine />
{content.text_set.length > 0 ? (
{content.text_set.length > 0 && (
<Markdawn text={content.text_set[0].text} />
) : (
""
)}
</div>
</ContentPanel>

View File

@ -8,15 +8,30 @@ import { getContents } from "graphql/operations";
import PanelHeader from "components/PanelComponents/PanelHeader";
import AppLayout from "components/AppLayout";
import LibraryContentPreview from "components/Library/LibraryContentPreview";
import { prettyinlineTitle } from "queries/helpers";
import { prettyinlineTitle, prettySlug } from "queries/helpers";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import Select from "components/Select";
import { useEffect, useState } from "react";
interface LibraryProps extends AppStaticProps {
interface ContentsProps extends AppStaticProps {
contents: GetContentsQuery["contents"]["data"];
}
export default function Library(props: LibraryProps): JSX.Element {
const { langui } = props;
type GroupContentItems = Map<string, GetContentsQuery["contents"]["data"]>;
export default function Contents(props: ContentsProps): JSX.Element {
const { langui, contents } = props;
const [groupingMethod, setGroupingMethod] = useState<number>(-1);
const [groups, setGroups] = useState<GroupContentItems>(
getGroups(groupingMethod, contents)
);
useEffect(() => {
setGroups(getGroups(groupingMethod, contents));
}, [langui, groupingMethod, contents]);
const subPanel = (
<SubPanel>
<PanelHeader
@ -24,15 +39,45 @@ export default function Library(props: LibraryProps): JSX.Element {
title={langui.contents}
description={langui.contents_description}
/>
<div className="flex flex-row gap-2 place-items-center">
<p className="flex-shrink-0">{langui.group_by}:</p>
<Select
className="w-full"
options={[langui.category, langui.type]}
state={groupingMethod}
setState={setGroupingMethod}
allowEmpty
/>
</div>
</SubPanel>
);
const contentPanel = (
<ContentPanel width={ContentPanelWidthSizes.large}>
<div className="grid gap-8 items-end grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))]">
{props.contents.map((item) => (
<LibraryContentPreview key={item.id} item={item.attributes} />
))}
</div>
{[...groups].map(([name, items]) => (
<>
{items.length > 0 && (
<>
{name && (
<h2
key={"h2" + name}
className="text-2xl pb-2 pt-10 first-of-type:pt-0"
>
{name}
</h2>
)}
<div
key={"items" + name}
className="grid gap-8 items-end grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))]"
>
{items.map((item) => (
<LibraryContentPreview key={item.id} item={item.attributes} />
))}
</div>
</>
)}
</>
))}
</ContentPanel>
);
return (
@ -72,7 +117,7 @@ export const getStaticProps: GetStaticProps = async (context) => {
return titleA.localeCompare(titleB);
});
const props: LibraryProps = {
const props: ContentsProps = {
...(await getAppStaticProps(context)),
contents: contents,
};
@ -80,3 +125,61 @@ export const getStaticProps: GetStaticProps = async (context) => {
props: props,
};
};
function getGroups(
groupByType: number,
items: ContentsProps["contents"]
): GroupContentItems {
switch (groupByType) {
case 0:
const typeGroup = new Map();
typeGroup.set("Drakengard 1", []);
typeGroup.set("Drakengard 1.3", []);
typeGroup.set("Drakengard 2", []);
typeGroup.set("Drakengard 3", []);
typeGroup.set("Drakengard 4", []);
typeGroup.set("NieR Gestalt", []);
typeGroup.set("NieR Replicant", []);
typeGroup.set("NieR Replicant ver.1.22474487139...", []);
typeGroup.set("NieR:Automata", []);
typeGroup.set("NieR Re[in]carnation", []);
typeGroup.set("SINoALICE", []);
typeGroup.set("Voice of Cards", []);
typeGroup.set("Final Fantasy XIV", []);
typeGroup.set("Thou Shalt Not Die", []);
typeGroup.set("Bakuken", []);
typeGroup.set("YoRHa", []);
typeGroup.set("YoRHa Boys", []);
typeGroup.set("No category", []);
items.map((item) => {
if (item.attributes.categories.data.length === 0) {
typeGroup.get("No category")?.push(item);
} else {
item.attributes.categories.data.map((category) => {
typeGroup.get(category.attributes.name)?.push(item);
});
}
});
return typeGroup;
case 1:
const groupType: GroupContentItems = new Map();
items.map((item) => {
const type =
item.attributes.type.data.attributes.titles.length > 0
? item.attributes.type.data.attributes.titles[0].title
: prettySlug(item.attributes.type.data.attributes.slug);
if (!groupType.has(type)) groupType.set(type, []);
groupType.get(type)?.push(item);
});
return groupType;
default:
const groupDefault: GroupContentItems = new Map();
groupDefault.set("", items);
return groupDefault;
}
}

View File

@ -70,15 +70,13 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
onClick={() => appLayout.setSubPanelOpen(false)}
/>
{item.gallery.data.length > 0 ? (
{item.gallery.data.length > 0 && (
<NavOption
title={langui.gallery}
url="#gallery"
border
onClick={() => appLayout.setSubPanelOpen(false)}
/>
) : (
""
)}
<NavOption
@ -88,21 +86,17 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
onClick={() => appLayout.setSubPanelOpen(false)}
/>
{item.subitems.data.length > 0 ? (
{item.subitems.data.length > 0 && (
<NavOption
title={isVariantSet ? langui.variants : langui.subitems}
url={isVariantSet ? "#variants" : "#subitems"}
border
onClick={() => appLayout.setSubPanelOpen(false)}
/>
) : (
""
)}
{item.contents.data.length > 0 ? (
{item.contents.data.length > 0 && (
<NavOption title={langui.contents} url="#contents" border />
) : (
""
)}
</div>
</SubPanel>
@ -134,7 +128,7 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
<InsetBox id="summary" className="grid place-items-center">
<div className="w-[clamp(0px,100%,42rem)] grid place-items-center gap-8">
{item.subitem_of.data.length > 0 ? (
{item.subitem_of.data.length > 0 && (
<div className="grid place-items-center">
<p>{langui.subitem_of}</p>
<Button
@ -147,26 +141,18 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
)}
</Button>
</div>
) : (
""
)}
<div className="grid place-items-center">
<h1 className="text-3xl">{item.title}</h1>
{item.subtitle ? (
<h2 className="text-2xl">{item.subtitle}</h2>
) : (
""
)}
{item.subtitle && <h2 className="text-2xl">{item.subtitle}</h2>}
</div>
{item.descriptions.length > 0 ? (
{item.descriptions.length > 0 && (
<p className="text-justify">{item.descriptions[0].description}</p>
) : (
""
)}
</div>
</InsetBox>
{item.gallery.data.length > 0 ? (
{item.gallery.data.length > 0 && (
<div id="gallery" className="grid place-items-center gap-8 w-full">
<h2 className="text-2xl">{langui.gallery}</h2>
<div className="grid w-full gap-8 items-end grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))]">
@ -186,15 +172,13 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
))}
</div>
</div>
) : (
""
)}
<InsetBox id="details" className="grid place-items-center">
<div className="w-[clamp(0px,100%,42rem)] grid place-items gap-8">
<h2 className="text-2xl text-center">{langui.details}</h2>
<div className="grid grid-flow-col w-full place-content-between">
{item.metadata.length > 0 ? (
{item.metadata.length > 0 && (
<div className="grid place-items-center place-content-start">
<h3 className="text-xl">{langui.type}</h3>
<div className="grid grid-flow-col gap-1">
@ -203,20 +187,16 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
<Chip>{prettyItemSubType(item.metadata[0])}</Chip>
</div>
</div>
) : (
""
)}
{item.release_date ? (
{item.release_date && (
<div className="grid place-items-center place-content-start">
<h3 className="text-xl">{langui.release_date}</h3>
<p>{prettyDate(item.release_date)}</p>
</div>
) : (
""
)}
{item.price ? (
{item.price && (
<div className="grid place-items-center text-center place-content-start">
<h3 className="text-xl">{langui.price}</h3>
<p>
@ -234,11 +214,23 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
</p>
)}
</div>
) : (
""
)}
</div>
{item.size ? (
{item.categories.data.length > 0 && (
<div>
<h3 className="text-xl">{langui.categories}</h3>
<div className="flex flex-row flex-wrap place-items-center place-content-start gap-2">
{item.categories.data.map((category) => (
<Chip key={category.id}>
{category.attributes.short}
</Chip>
))}
</div>
</div>
)}
{item.size && (
<>
<h3 className="text-xl">{langui.size}</h3>
<div className="grid grid-flow-col w-full place-content-between">
@ -256,7 +248,7 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
<p>{convertMmToInch(item.size.height)} in</p>
</div>
</div>
{item.size.thickness ? (
{item.size.thickness && (
<div className="flex flex-row flex-wrap place-items-start gap-4">
<p className="font-bold">{langui.thickness}:</p>
<div>
@ -264,84 +256,68 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
<p>{convertMmToInch(item.size.thickness)} in</p>
</div>
</div>
) : (
""
)}
</div>
</>
) : (
""
)}
{item.metadata.length > 0 &&
item.metadata[0].__typename !== "ComponentMetadataGroup" &&
item.metadata[0].__typename !== "ComponentMetadataOther" ? (
<>
<h3 className="text-xl">{langui.type_information}</h3>
<div className="grid grid-cols-2 w-full place-content-between">
{item.metadata[0].__typename === "ComponentMetadataBooks" ? (
<>
<div className="flex flex-row place-content-start gap-4">
<p className="font-bold">{langui.pages}:</p>
<p>{item.metadata[0].page_count}</p>
</div>
item.metadata[0].__typename !== "ComponentMetadataGroup" &&
item.metadata[0].__typename !== "ComponentMetadataOther" && (
<>
<h3 className="text-xl">{langui.type_information}</h3>
<div className="grid grid-cols-2 w-full place-content-between">
{item.metadata[0].__typename ===
"ComponentMetadataBooks" && (
<>
<div className="flex flex-row place-content-start gap-4">
<p className="font-bold">{langui.pages}:</p>
<p>{item.metadata[0].page_count}</p>
</div>
<div className="flex flex-row place-content-start gap-4">
<p className="font-bold">{langui.binding}:</p>
<p>
{item.metadata[0].binding_type ===
Enum_Componentmetadatabooks_Binding_Type.Paperback
? langui.paperback
: item.metadata[0].binding_type ===
Enum_Componentmetadatabooks_Binding_Type.Hardcover
? langui.hardcover
: ""}
</p>
</div>
<div className="flex flex-row place-content-start gap-4">
<p className="font-bold">{langui.page_order}:</p>
<p>
{item.metadata[0].page_order ===
Enum_Componentmetadatabooks_Page_Order.LeftToRight
? langui.left_to_right
: item.metadata[0].page_order ===
Enum_Componentmetadatabooks_Page_Order.RightToLeft
? langui.right_to_left
: ""}
</p>
</div>
<div className="flex flex-row place-content-start gap-4">
<p className="font-bold">{langui.languages}:</p>
{item.metadata[0].languages.data.map((lang) => (
<p key={lang.attributes.code}>
{lang.attributes.name}
<div className="flex flex-row place-content-start gap-4">
<p className="font-bold">{langui.binding}:</p>
<p>
{item.metadata[0].binding_type ===
Enum_Componentmetadatabooks_Binding_Type.Paperback
? langui.paperback
: item.metadata[0].binding_type ===
Enum_Componentmetadatabooks_Binding_Type.Hardcover
? langui.hardcover
: ""}
</p>
))}
</div>
</>
) : item.metadata[0].__typename ===
"ComponentMetadataAudio" ? (
<></>
) : item.metadata[0].__typename ===
"ComponentMetadataVideo" ? (
<></>
) : item.metadata[0].__typename ===
"ComponentMetadataGame" ? (
<></>
) : (
""
)}
</div>
</>
) : (
""
)}
</div>
<div className="flex flex-row place-content-start gap-4">
<p className="font-bold">{langui.page_order}:</p>
<p>
{item.metadata[0].page_order ===
Enum_Componentmetadatabooks_Page_Order.LeftToRight
? langui.left_to_right
: item.metadata[0].page_order ===
Enum_Componentmetadatabooks_Page_Order.RightToLeft
? langui.right_to_left
: ""}
</p>
</div>
<div className="flex flex-row place-content-start gap-4">
<p className="font-bold">{langui.languages}:</p>
{item.metadata[0].languages.data.map((lang) => (
<p key={lang.attributes.code}>
{lang.attributes.name}
</p>
))}
</div>
</>
)}
</div>
</>
)}
</div>
</InsetBox>
{item.subitems.data.length > 0 ? (
{item.subitems.data.length > 0 && (
<div
id={isVariantSet ? "variants" : "subitems"}
className="grid place-items-center gap-8 w-full"
@ -358,11 +334,9 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
))}
</div>
</div>
) : (
""
)}
{item.contents.data.length > 0 ? (
{item.contents.data.length > 0 && (
<div id="contents" className="w-full grid place-items-center gap-8">
<h2 className="text-2xl">{langui.contents}</h2>
<div className="grid gap-4 w-full">
@ -376,8 +350,6 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
))}
</div>
</div>
) : (
""
)}
</div>
</ContentPanel>

View File

@ -56,7 +56,7 @@ export default function Library(props: LibraryProps): JSX.Element {
useEffect(() => {
setSortedItem(sortBy(sortingMethod, filteredItems, currencies));
}, [filteredItems, sortingMethod]);
}, [currencies, filteredItems, sortingMethod]);
useEffect(() => {
setGroups(getGroups(langui, groupingMethod, sortedItems));
@ -113,9 +113,16 @@ export default function Library(props: LibraryProps): JSX.Element {
<>
{items.length > 0 && (
<>
<h2 className="text-2xl pb-2 pt-10 first-of-type:pt-0">{name}</h2>
{name && (
<h2
key={"h2" + name}
className="text-2xl pb-2 pt-10 first-of-type:pt-0"
>
{name}
</h2>
)}
<div
key={name}
key={"items" + name}
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) => (
@ -163,7 +170,37 @@ function getGroups(
): GroupLibraryItems {
switch (groupByType) {
case 0:
return new Map();
const typeGroup = new Map();
typeGroup.set("Drakengard 1", []);
typeGroup.set("Drakengard 1.3", []);
typeGroup.set("Drakengard 2", []);
typeGroup.set("Drakengard 3", []);
typeGroup.set("Drakengard 4", []);
typeGroup.set("NieR Gestalt", []);
typeGroup.set("NieR Replicant", []);
typeGroup.set("NieR Replicant ver.1.22474487139...", []);
typeGroup.set("NieR:Automata", []);
typeGroup.set("NieR Re[in]carnation", []);
typeGroup.set("SINoALICE", []);
typeGroup.set("Voice of Cards", []);
typeGroup.set("Final Fantasy XIV", []);
typeGroup.set("Thou Shalt Not Die", []);
typeGroup.set("Bakuken", []);
typeGroup.set("YoRHa", []);
typeGroup.set("YoRHa Boys", []);
typeGroup.set("No category", []);
items.map((item) => {
if (item.attributes.categories.data.length === 0) {
typeGroup.get("No category")?.push(item);
} else {
item.attributes.categories.data.map((category) => {
typeGroup.get(category.attributes.name)?.push(item);
});
}
});
return typeGroup;
case 1:
const groupType: GroupLibraryItems = new Map();