Added covers in the scanset

This commit is contained in:
DrMint 2022-04-12 18:10:26 +02:00
parent b3f3ddf60e
commit 822adbec48
4 changed files with 358 additions and 39 deletions

View File

@ -1,10 +1,14 @@
import Button from "components/Button";
import Chip from "components/Chip";
import Img, { getAssetURL, ImageQuality } from "components/Img"; import Img, { getAssetURL, ImageQuality } from "components/Img";
import LanguageSwitcher from "components/LanguageSwitcher"; import LanguageSwitcher from "components/LanguageSwitcher";
import RecorderChip from "components/RecorderChip";
import ToolTip from "components/ToolTip";
import { useAppLayout } from "contexts/AppLayoutContext"; import { useAppLayout } from "contexts/AppLayoutContext";
import { GetLibraryItemScansQuery } from "graphql/generated"; import { GetLibraryItemScansQuery } from "graphql/generated";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { AppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps } from "queries/getAppStaticProps";
import { getPreferredLanguage } from "queries/helpers"; import { getPreferredLanguage, getStatusDescription } from "queries/helpers";
import { Dispatch, SetStateAction, useEffect, useMemo, useState } from "react"; import { Dispatch, SetStateAction, useEffect, useMemo, useState } from "react";
interface Props { interface Props {
@ -30,6 +34,20 @@ interface Props {
slug: string; slug: string;
title: string; title: string;
languages: AppStaticProps["languages"]; languages: AppStaticProps["languages"];
langui: AppStaticProps["langui"];
content: Exclude<
Exclude<
Exclude<
Exclude<
GetLibraryItemScansQuery["libraryItems"],
null | undefined
>["data"][number]["attributes"],
null | undefined
>["contents"],
null | undefined
>["data"][number]["attributes"],
null | undefined
>["content"];
} }
export default function ScanSet(props: Props): JSX.Element { export default function ScanSet(props: Props): JSX.Element {
@ -41,6 +59,8 @@ export default function ScanSet(props: Props): JSX.Element {
slug, slug,
title, title,
languages, languages,
langui,
content,
} = props; } = props;
const appLayout = useAppLayout(); const appLayout = useAppLayout();
const router = useRouter(); const router = useRouter();
@ -73,46 +93,137 @@ export default function ScanSet(props: Props): JSX.Element {
}, [selectedScanIndex]); }, [selectedScanIndex]);
return ( return (
<div> <>
<div className="flex flex-row place-items-center gap-4 text-base pb-6 pt-10 first-of-type:pt-0"> {selectedScan && (
<h2 <div>
id={slug} <div className="flex flex-row flex-wrap place-items-center gap-6 text-base pt-10 first-of-type:pt-0">
className="text-2xl" <h2 id={slug} className="text-2xl">
> {title}
{title} </h2>
</h2>
<LanguageSwitcher
languages={languages}
locales={scanLocales}
localesIndex={selectedScanIndex}
setLocalesIndex={setSelectedScanIndex}
/>
</div>
<div className="grid gap-8 items-end mobile:grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(10rem,1fr))] pb-12 border-b-[3px] border-dotted last-of-type:border-0"> <Chip>
{selectedScan?.pages?.data.map((page, index) => ( {selectedScan.language?.data?.attributes?.code ===
<div selectedScan.source_language?.data?.attributes?.code
key={page.id} ? "Scan"
className="drop-shadow-shade-lg hover:scale-[1.02] cursor-pointer transition-transform" : "Scanlation"}
onClick={() => { </Chip>
const images: string[] = []; </div>
selectedScan.pages?.data.map((image) => {
if (image.attributes?.url) <div className="flex flex-row flex-wrap gap-4 pb-6 place-items-center">
images.push( {content?.data?.attributes?.slug && (
getAssetURL(image.attributes.url, ImageQuality.Large) <Button href={`/contents/${content?.data?.attributes?.slug}`}>
); {langui.open_content}
}); </Button>
setLightboxOpen(true); )}
setLightboxImages(images);
setLightboxIndex(index); <LanguageSwitcher
}} languages={languages}
> locales={scanLocales}
{page.attributes && ( localesIndex={selectedScanIndex}
<Img image={page.attributes} quality={ImageQuality.Small} /> setLocalesIndex={setSelectedScanIndex}
/>
<div className="grid place-items-center place-content-center">
<p className="font-headers">{langui.status}:</p>
<ToolTip
content={getStatusDescription(selectedScan.status, langui)}
maxWidth={"20rem"}
>
<Chip>{selectedScan.status}</Chip>
</ToolTip>
</div>
{selectedScan.scanners && selectedScan.scanners.data.length > 0 && (
<div>
<p className="font-headers">{"Scanners"}:</p>
<div className="grid place-items-center place-content-center gap-2">
{selectedScan.scanners.data.map((scanner) => (
<>
{scanner.attributes && (
<RecorderChip
key={scanner.id}
langui={langui}
recorder={scanner.attributes}
/>
)}
</>
))}
</div>
</div>
)}
{selectedScan.cleaners && selectedScan.cleaners.data.length > 0 && (
<div>
<p className="font-headers">{"Cleaners"}:</p>
<div className="grid place-items-center place-content-center gap-2">
{selectedScan.cleaners.data.map((cleaner) => (
<>
{cleaner.attributes && (
<RecorderChip
key={cleaner.id}
langui={langui}
recorder={cleaner.attributes}
/>
)}
</>
))}
</div>
</div>
)}
{selectedScan.typesetters &&
selectedScan.typesetters.data.length > 0 && (
<div>
<p className="font-headers">{"Typesetters"}:</p>
<div className="grid place-items-center place-content-center gap-2">
{selectedScan.typesetters.data.map((typesetter) => (
<>
{typesetter.attributes && (
<RecorderChip
key={typesetter.id}
langui={langui}
recorder={typesetter.attributes}
/>
)}
</>
))}
</div>
</div>
)}
{selectedScan.notes && (
<ToolTip content={selectedScan.notes}>
<Chip>{"Notes"}</Chip>
</ToolTip>
)} )}
</div> </div>
))}
</div> <div className="grid gap-8 items-end mobile:grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(10rem,1fr))] pb-12 border-b-[3px] border-dotted last-of-type:border-0">
</div> {selectedScan.pages?.data.map((page, index) => (
<div
key={page.id}
className="drop-shadow-shade-lg hover:scale-[1.02] cursor-pointer transition-transform"
onClick={() => {
const images: string[] = [];
selectedScan.pages?.data.map((image) => {
if (image.attributes?.url)
images.push(
getAssetURL(image.attributes.url, ImageQuality.Large)
);
});
setLightboxOpen(true);
setLightboxImages(images);
setLightboxIndex(index);
}}
>
{page.attributes && (
<Img image={page.attributes} quality={ImageQuality.Small} />
)}
</div>
))}
</div>
</div>
)}
</>
); );
} }

View File

@ -0,0 +1,128 @@
import Img, { getAssetURL, ImageQuality } from "components/Img";
import LanguageSwitcher from "components/LanguageSwitcher";
import { useAppLayout } from "contexts/AppLayoutContext";
import {
GetLibraryItemScansQuery,
UploadImageFragment,
} from "graphql/generated";
import { useRouter } from "next/router";
import { AppStaticProps } from "queries/getAppStaticProps";
import { getPreferredLanguage } from "queries/helpers";
import { Dispatch, SetStateAction, useEffect, useMemo, useState } from "react";
interface Props {
setLightboxOpen: Dispatch<SetStateAction<boolean>>;
setLightboxImages: Dispatch<SetStateAction<string[]>>;
setLightboxIndex: Dispatch<SetStateAction<number>>;
images: Exclude<
Exclude<
Exclude<
GetLibraryItemScansQuery["libraryItems"],
null | undefined
>["data"][number]["attributes"],
null | undefined
>["images"],
null | undefined
>;
languages: AppStaticProps["languages"];
langui: AppStaticProps["langui"];
}
export default function ScanSetCover(props: Props): JSX.Element {
const {
setLightboxOpen,
setLightboxImages,
setLightboxIndex,
images,
languages,
langui,
} = props;
const appLayout = useAppLayout();
const router = useRouter();
const [selectedScan, setSelectedScan] = useState<Props["images"][number]>();
const scanLocales: Map<string, number> = new Map();
const [selectedScanIndex, setSelectedScanIndex] = useState<
number | undefined
>();
images.map((scan, index) => {
if (scan?.language?.data?.attributes?.code) {
scanLocales.set(scan.language.data.attributes.code, index);
}
});
useMemo(() => {
setSelectedScanIndex(
getPreferredLanguage(
appLayout.preferredLanguages ?? [router.locale],
scanLocales
)
);
}, [appLayout.preferredLanguages]);
useEffect(() => {
if (selectedScanIndex !== undefined)
setSelectedScan(images[selectedScanIndex]);
}, [selectedScanIndex]);
const coverImages: UploadImageFragment[] = [];
if (selectedScan?.obi_belt?.full?.data?.attributes)
coverImages.push(selectedScan.obi_belt?.full?.data?.attributes);
if (selectedScan?.obi_belt?.inside_full?.data?.attributes)
coverImages.push(selectedScan.obi_belt?.inside_full?.data?.attributes);
if (selectedScan?.dust_jacket?.full?.data?.attributes)
coverImages.push(selectedScan.dust_jacket?.full?.data?.attributes);
if (selectedScan?.dust_jacket?.inside_full?.data?.attributes)
coverImages.push(selectedScan.dust_jacket?.inside_full?.data?.attributes);
if (selectedScan?.cover?.full?.data?.attributes)
coverImages.push(selectedScan.cover?.full?.data?.attributes);
if (selectedScan?.cover?.inside_full?.data?.attributes)
coverImages.push(selectedScan.cover?.inside_full?.data?.attributes);
if (coverImages.length > 0) {
return (
<>
{selectedScan && (
<div>
<div className="flex flex-row flex-wrap place-items-center gap-6 text-base pt-10 first-of-type:pt-0">
<h2 className="text-2xl">{"Cover"}</h2>
</div>
<div className="flex flex-row flex-wrap gap-4 pb-6 place-items-center">
<LanguageSwitcher
languages={languages}
locales={scanLocales}
localesIndex={selectedScanIndex}
setLocalesIndex={setSelectedScanIndex}
/>
</div>
<div className="grid gap-8 items-end mobile:grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(10rem,1fr))] pb-12 border-b-[3px] border-dotted last-of-type:border-0">
{coverImages.map((image, index) => (
<div
key={image.url}
className="drop-shadow-shade-lg hover:scale-[1.02] cursor-pointer transition-transform"
onClick={() => {
const imgs: string[] = [];
coverImages.map((img) => {
if (img.url)
imgs.push(getAssetURL(img.url, ImageQuality.Large));
});
setLightboxOpen(true);
setLightboxImages(imgs);
setLightboxIndex(index);
}}
>
<Img image={image} quality={ImageQuality.Small} />
</div>
))}
</div>
</div>
)}
</>
);
}
return <></>;
}

View File

@ -6,6 +6,63 @@ query getLibraryItemScans($slug: String, $language_code: String) {
slug slug
title title
subtitle subtitle
images {
cover {
full {
data {
attributes {
...uploadImage
}
}
}
inside_full {
data {
attributes {
...uploadImage
}
}
}
}
dust_jacket {
full {
data {
attributes {
...uploadImage
}
}
}
inside_full {
data {
attributes {
...uploadImage
}
}
}
}
obi_belt {
full {
data {
attributes {
...uploadImage
}
}
}
inside_full {
data {
attributes {
...uploadImage
}
}
}
}
language {
data {
attributes {
code
}
}
}
}
thumbnail { thumbnail {
data { data {
attributes { attributes {
@ -29,6 +86,13 @@ query getLibraryItemScans($slug: String, $language_code: String) {
ending_time ending_time
} }
} }
content {
data {
attributes {
slug
}
}
}
scan_set { scan_set {
status status
language { language {

View File

@ -1,5 +1,6 @@
import AppLayout from "components/AppLayout"; import AppLayout from "components/AppLayout";
import ScanSet from "components/Library/ScanSet"; import ScanSet from "components/Library/ScanSet";
import ScanSetCover from "components/Library/ScanSetCover";
import LightBox from "components/LightBox"; import LightBox from "components/LightBox";
import NavOption from "components/PanelComponents/NavOption"; import NavOption from "components/PanelComponents/NavOption";
import ReturnButton, { import ReturnButton, {
@ -87,10 +88,23 @@ export default function LibrarySlug(props: Props): JSX.Element {
displayOn={ReturnButtonType.mobile} displayOn={ReturnButtonType.mobile}
className="mb-10" className="mb-10"
/> />
{item?.images && (
<ScanSetCover
images={item.images}
setLightboxImages={setLightboxImages}
setLightboxIndex={setLightboxIndex}
setLightboxOpen={setLightboxOpen}
languages={languages}
langui={langui}
/>
)}
{item?.contents?.data.map((content) => ( {item?.contents?.data.map((content) => (
<> <>
{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}
setLightboxImages={setLightboxImages} setLightboxImages={setLightboxImages}
setLightboxIndex={setLightboxIndex} setLightboxIndex={setLightboxIndex}
@ -98,6 +112,8 @@ export default function LibrarySlug(props: Props): JSX.Element {
slug={content.attributes.slug} slug={content.attributes.slug}
title={prettySlug(content.attributes.slug, item.slug)} title={prettySlug(content.attributes.slug, item.slug)}
languages={languages} languages={languages}
langui={langui}
content={content.attributes.content}
/> />
)} )}
</> </>