Fixed bugs + translated components

This commit is contained in:
DrMint 2022-07-14 23:12:22 +02:00
parent 930da37d64
commit 0df66815c8
12 changed files with 301 additions and 337 deletions

View File

@ -51,7 +51,7 @@ interface Props {
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
const ScanSet = ({ export const ScanSet = ({
openLightBox, openLightBox,
scanSet, scanSet,
id, id,
@ -138,7 +138,9 @@ const ScanSet = ({
/> />
)} )}
{languageSwitcherProps.locales.size > 1 && (
<LanguageSwitcher {...languageSwitcherProps} /> <LanguageSwitcher {...languageSwitcherProps} />
)}
<div className="grid place-content-center place-items-center"> <div className="grid place-content-center place-items-center">
<p className="font-headers font-bold">{langui.status}:</p> <p className="font-headers font-bold">{langui.status}:</p>
@ -242,40 +244,3 @@ const ScanSet = ({
</> </>
); );
}; };
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
interface TranslatedProps extends Omit<Props, "title"> {
translations: {
title: string;
language: string;
}[];
fallbackTitle: TranslatedProps["translations"][number]["title"];
languages: AppStaticProps["languages"];
}
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
export const TranslatedScanSet = ({
fallbackTitle,
translations = [{ title: fallbackTitle, language: "default" }],
languages,
...otherProps
}: TranslatedProps): JSX.Element => {
const [selectedTranslation] = useSmartLanguage({
items: translations,
languages: languages,
languageExtractor: useCallback(
(item: TranslatedProps["translations"][number]) => item.language,
[]
),
});
return (
<ScanSet
title={selectedTranslation?.title ?? fallbackTitle}
languages={languages}
{...otherProps}
/>
);
};

View File

@ -1,11 +1,9 @@
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { MouseEventHandler, useCallback, useMemo } from "react"; import { MouseEventHandler, useMemo } from "react";
import { Ico, Icon } from "components/Ico"; import { Ico, Icon } from "components/Ico";
import { ToolTip } from "components/ToolTip"; import { ToolTip } from "components/ToolTip";
import { cJoin, cIf } from "helpers/className"; import { cJoin, cIf } from "helpers/className";
import { isDefinedAndNotEmpty } from "helpers/others"; import { isDefinedAndNotEmpty } from "helpers/others";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { useSmartLanguage } from "hooks/useSmartLanguage";
/* /*
* *
@ -90,45 +88,3 @@ export const NavOption = ({
</ToolTip> </ToolTip>
); );
}; };
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
interface TranslatedProps extends Omit<Props, "subtitle" | "title"> {
translations: {
title: string | null | undefined;
subtitle?: string | null | undefined;
language: string;
}[];
fallbackTitle: TranslatedProps["translations"][number]["title"];
fallbackSubtitle: TranslatedProps["translations"][number]["subtitle"];
languages: AppStaticProps["languages"];
}
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
export const TranslatedNavOption = ({
fallbackTitle,
fallbackSubtitle,
translations = [
{ title: fallbackTitle, subtitle: fallbackSubtitle, language: "default" },
],
languages,
...otherProps
}: TranslatedProps): JSX.Element => {
const [selectedTranslation] = useSmartLanguage({
items: translations,
languages: languages,
languageExtractor: useCallback(
(item: TranslatedProps["translations"][number]) => item.language,
[]
),
});
return (
<NavOption
title={selectedTranslation?.title ?? fallbackTitle}
subtitle={selectedTranslation?.subtitle ?? fallbackSubtitle}
{...otherProps}
/>
);
};

View File

@ -1,5 +1,5 @@
import Link from "next/link"; import Link from "next/link";
import { useCallback, useMemo } from "react"; import { useMemo } from "react";
import { Chip } from "./Chip"; import { Chip } from "./Chip";
import { Ico, Icon } from "./Ico"; import { Ico, Icon } from "./Ico";
import { Img } from "./Img"; import { Img } from "./Img";
@ -16,10 +16,9 @@ import {
prettyDuration, prettyDuration,
prettyPrice, prettyPrice,
prettyShortenNumber, prettyShortenNumber,
prettySlug,
} from "helpers/formatters"; } from "helpers/formatters";
import { ImageQuality } from "helpers/img"; import { ImageQuality } from "helpers/img";
import { useSmartLanguage } from "hooks/useSmartLanguage"; import { useMediaHoverable } from "hooks/useMediaQuery";
/* /*
* *
@ -78,6 +77,7 @@ export const PreviewCard = ({
infoAppend, infoAppend,
}: Props): JSX.Element => { }: Props): JSX.Element => {
const { currency } = useAppLayout(); const { currency } = useAppLayout();
const isHoverable = useMediaHoverable();
const metadataJSX = useMemo( const metadataJSX = useMemo(
() => ( () => (
@ -247,7 +247,7 @@ export const PreviewCard = ({
className={cJoin( className={cJoin(
"z-20 grid gap-2 p-4 transition-opacity linearbg-obi", "z-20 grid gap-2 p-4 transition-opacity linearbg-obi",
cIf( cIf(
!keepInfoVisible, !keepInfoVisible && isHoverable,
`-inset-x-0.5 bottom-2 opacity-0 [border-radius:10%_10%_10%_10%_/_1%_1%_3%_3%] `-inset-x-0.5 bottom-2 opacity-0 [border-radius:10%_10%_10%_10%_/_1%_1%_3%_3%]
group-hover:opacity-100 hoverable:absolute hoverable:drop-shadow-shade-lg group-hover:opacity-100 hoverable:absolute hoverable:drop-shadow-shade-lg
notHoverable:rounded-b-md notHoverable:opacity-100`, notHoverable:rounded-b-md notHoverable:opacity-100`,
@ -291,46 +291,3 @@ export const PreviewCard = ({
</Link> </Link>
); );
}; };
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
interface TranslatedProps
extends Omit<Props, "description" | "pre_title" | "subtitle" | "title"> {
translations: {
pre_title?: string | null | undefined;
title: string | null | undefined;
subtitle?: string | null | undefined;
description?: string | null | undefined;
language: string | undefined;
}[];
slug: string;
languages: AppStaticProps["languages"];
}
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
export const TranslatedPreviewCard = ({
slug,
translations = [{ title: slug, language: "default" }],
languages,
...otherProps
}: TranslatedProps): JSX.Element => {
const [selectedTranslation] = useSmartLanguage({
items: translations,
languages: languages,
languageExtractor: useCallback(
(item: TranslatedProps["translations"][number]) => item.language,
[]
),
});
return (
<PreviewCard
pre_title={selectedTranslation?.pre_title}
title={selectedTranslation?.title ?? prettySlug(slug)}
subtitle={selectedTranslation?.subtitle}
description={selectedTranslation?.description}
{...otherProps}
/>
);
};

View File

@ -1,12 +1,8 @@
import Link from "next/link"; import Link from "next/link";
import { useCallback } from "react";
import { Chip } from "./Chip"; import { Chip } from "./Chip";
import { Img } from "./Img"; import { Img } from "./Img";
import { UploadImageFragment } from "graphql/generated"; import { UploadImageFragment } from "graphql/generated";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { prettySlug } from "helpers/formatters";
import { ImageQuality } from "helpers/img"; import { ImageQuality } from "helpers/img";
import { useSmartLanguage } from "hooks/useSmartLanguage";
/* /*
* *
@ -26,7 +22,7 @@ interface Props {
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
const PreviewLine = ({ export const PreviewLine = ({
href, href,
thumbnail, thumbnail,
pre_title, pre_title,
@ -76,45 +72,3 @@ const PreviewLine = ({
</div> </div>
</Link> </Link>
); );
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
interface TranslatedProps
extends Omit<Props, "pre_title" | "subtitle" | "title"> {
translations: {
pre_title?: string | null | undefined;
title: string | null | undefined;
subtitle?: string | null | undefined;
language: string | undefined;
}[];
slug: string;
languages: AppStaticProps["languages"];
}
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
export const TranslatedPreviewLine = ({
slug,
translations = [{ title: slug, language: "default" }],
languages,
...otherProps
}: TranslatedProps): JSX.Element => {
const [selectedTranslation] = useSmartLanguage({
items: translations,
languages: languages,
languageExtractor: useCallback(
(item: TranslatedProps["translations"][number]) => item.language,
[]
),
});
return (
<PreviewLine
pre_title={selectedTranslation?.pre_title}
title={selectedTranslation?.title ?? prettySlug(slug)}
subtitle={selectedTranslation?.subtitle}
{...otherProps}
/>
);
};

View File

@ -41,7 +41,7 @@ export const RecorderChip = ({ recorder, langui }: Props): JSX.Element => (
{filterHasAttributes(recorder.languages.data, [ {filterHasAttributes(recorder.languages.data, [
"attributes", "attributes",
] as const).map((language) => ( ] as const).map((language) => (
<Fragment key={language.attributes.code}> <Fragment key={language.__typename}>
<Chip text={language.attributes.code.toUpperCase()} /> <Chip text={language.attributes.code.toUpperCase()} />
</Fragment> </Fragment>
))} ))}

View File

@ -0,0 +1,135 @@
import { PreviewCard } from "./PreviewCard";
import { PreviewLine } from "./PreviewLine";
import { ScanSet } from "./Library/ScanSet";
import { NavOption } from "./PanelComponents/NavOption";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { useSmartLanguage } from "hooks/useSmartLanguage";
type TranslatedProps<P, K extends keyof P> = Omit<P, K> & {
translations: (Pick<P, K> & { language: string })[];
fallback: Pick<P, K>;
languages: AppStaticProps["languages"];
};
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
type TranslatedPreviewCardProps = TranslatedProps<
Parameters<typeof PreviewCard>[0],
"description" | "pre_title" | "subtitle" | "title"
>;
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
export const TranslatedPreviewCard = ({
translations,
languages,
fallback,
...otherProps
}: TranslatedPreviewCardProps): JSX.Element => {
const [selectedTranslation] = useSmartLanguage({
items: translations,
languages: languages,
languageExtractor: (item) => item.language,
});
return (
<PreviewCard
pre_title={selectedTranslation?.pre_title ?? fallback.pre_title}
title={selectedTranslation?.title ?? fallback.title}
subtitle={selectedTranslation?.subtitle ?? fallback.subtitle}
description={selectedTranslation?.description ?? fallback.description}
{...otherProps}
/>
);
};
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
type TranslatedPreviewLineProps = TranslatedProps<
Parameters<typeof PreviewLine>[0],
"pre_title" | "subtitle" | "title"
>;
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
export const TranslatedPreviewLine = ({
translations,
languages,
fallback,
...otherProps
}: TranslatedPreviewLineProps): JSX.Element => {
const [selectedTranslation] = useSmartLanguage({
items: translations,
languages: languages,
languageExtractor: (item) => item.language,
});
return (
<PreviewLine
pre_title={selectedTranslation?.pre_title ?? fallback.pre_title}
title={selectedTranslation?.title ?? fallback.title}
subtitle={selectedTranslation?.subtitle ?? fallback.subtitle}
{...otherProps}
/>
);
};
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
type TranslatedScanSetProps = TranslatedProps<
Parameters<typeof ScanSet>[0],
"title"
>;
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
export const TranslatedScanSet = ({
translations,
languages,
fallback,
...otherProps
}: TranslatedScanSetProps): JSX.Element => {
const [selectedTranslation] = useSmartLanguage({
items: translations,
languages: languages,
languageExtractor: (item) => item.language,
});
return (
<ScanSet
title={selectedTranslation?.title ?? fallback.title}
languages={languages}
{...otherProps}
/>
);
};
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
type TranslatedNavOptionProps = TranslatedProps<
Parameters<typeof NavOption>[0],
"subtitle" | "title"
>;
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
export const TranslatedNavOption = ({
translations,
languages,
fallback,
...otherProps
}: TranslatedNavOptionProps): JSX.Element => {
const [selectedTranslation] = useSmartLanguage({
items: translations,
languages: languages,
languageExtractor: (item) => item.language,
});
return (
<NavOption
title={selectedTranslation?.title ?? fallback.title}
subtitle={selectedTranslation?.subtitle ?? fallback.subtitle}
{...otherProps}
/>
);
};

View File

@ -75,22 +75,27 @@ export const filterHasAttributes = <T, P extends PathDot<T>>(
t: T[] | null | undefined, t: T[] | null | undefined,
paths: readonly P[] paths: readonly P[]
): SelectiveNonNullable<T, typeof paths[number]>[] => ): SelectiveNonNullable<T, typeof paths[number]>[] =>
isUndefined(t) isDefined(t)
? [] ? (t.filter((item) =>
: (t.filter((item) =>
hasAttributes(item, paths) hasAttributes(item, paths)
) as unknown as SelectiveNonNullable<T, typeof paths[number]>[]); ) as unknown as SelectiveNonNullable<T, typeof paths[number]>[])
: [];
const hasAttributes = <T>(item: T, paths: readonly PathDot<T>[]): boolean => { const hasAttributes = <T>(item: T, paths: readonly PathDot<T>[]): boolean =>
isDefined(item) && paths.every((path) => hasAttribute(item, path));
const hasAttribute = <T>(item: T, path: string): boolean => {
if (isDefined(item)) { if (isDefined(item)) {
return paths.every((path) => { const [head, ...rest] = path.split(".");
const attributeToCheck = (path as string).split(".")[0]; if (Object.keys(item).includes(head)) {
return ( const attribute = head as keyof T;
isDefined(attributeToCheck) && if (isDefined(item[attribute])) {
Object.keys(item).includes(attributeToCheck) && if (rest.length > 0) {
isDefined(item[attributeToCheck as keyof T]) return hasAttribute(item[attribute], rest.join("."));
); }
}); return true;
}
}
} }
return false; return false;
}; };

View File

@ -12,7 +12,6 @@ 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 { PreviewCard } from "components/PreviewCard"; import { PreviewCard } from "components/PreviewCard";
import { TranslatedPreviewLine } from "components/PreviewLine";
import { RecorderChip } from "components/RecorderChip"; import { RecorderChip } from "components/RecorderChip";
import { ThumbnailHeader } from "components/ThumbnailHeader"; import { ThumbnailHeader } from "components/ThumbnailHeader";
import { ToolTip } from "components/ToolTip"; import { ToolTip } from "components/ToolTip";
@ -27,7 +26,6 @@ import {
} from "helpers/formatters"; } from "helpers/formatters";
import { isUntangibleGroupItem } from "helpers/libraryItem"; import { isUntangibleGroupItem } from "helpers/libraryItem";
import { import {
filterDefined,
filterHasAttributes, filterHasAttributes,
getStatusDescription, getStatusDescription,
isDefinedAndNotEmpty, isDefinedAndNotEmpty,
@ -36,6 +34,7 @@ import { ContentWithTranslations } from "helpers/types";
import { useMediaMobile } from "hooks/useMediaQuery"; import { useMediaMobile } from "hooks/useMediaQuery";
import { AnchorIds, useScrollTopOnChange } from "hooks/useScrollTopOnChange"; import { AnchorIds, useScrollTopOnChange } from "hooks/useScrollTopOnChange";
import { useSmartLanguage } from "hooks/useSmartLanguage"; import { useSmartLanguage } from "hooks/useSmartLanguage";
import { TranslatedPreviewLine } from "components/Translated";
/* /*
* *
@ -344,15 +343,18 @@ const Content = ({
</h2> </h2>
<TranslatedPreviewLine <TranslatedPreviewLine
href={`/contents/${previousContent.attributes.slug}`} href={`/contents/${previousContent.attributes.slug}`}
translations={filterDefined( translations={filterHasAttributes(
previousContent.attributes.translations previousContent.attributes.translations,
["language.data.attributes.code"] as const
).map((translation) => ({ ).map((translation) => ({
pre_title: translation.pre_title, pre_title: translation.pre_title,
title: translation.title, title: translation.title,
subtitle: translation.subtitle, subtitle: translation.subtitle,
language: translation.language?.data?.attributes?.code, language: translation.language.data.attributes.code,
}))} }))}
slug={previousContent.attributes.slug} fallback={{
title: prettySlug(previousContent.attributes.slug),
}}
languages={languages} languages={languages}
thumbnail={ thumbnail={
previousContent.attributes.thumbnail?.data?.attributes previousContent.attributes.thumbnail?.data?.attributes
@ -397,15 +399,16 @@ const Content = ({
</h2> </h2>
<TranslatedPreviewLine <TranslatedPreviewLine
href={`/contents/${nextContent.attributes.slug}`} href={`/contents/${nextContent.attributes.slug}`}
translations={filterDefined( translations={filterHasAttributes(
nextContent.attributes.translations nextContent.attributes.translations,
["language.data.attributes.code"] as const
).map((translation) => ({ ).map((translation) => ({
pre_title: translation.pre_title, pre_title: translation.pre_title,
title: translation.title, title: translation.title,
subtitle: translation.subtitle, subtitle: translation.subtitle,
language: translation.language?.data?.attributes?.code, language: translation.language.data.attributes.code,
}))} }))}
slug={nextContent.attributes.slug} fallback={{ title: nextContent.attributes.slug }}
languages={languages} languages={languages}
thumbnail={nextContent.attributes.thumbnail?.data?.attributes} thumbnail={nextContent.attributes.thumbnail?.data?.attributes}
thumbnailAspectRatio="3/2" thumbnailAspectRatio="3/2"

View File

@ -9,7 +9,6 @@ import {
ContentPanelWidthSizes, ContentPanelWidthSizes,
} from "components/Panels/ContentPanel"; } from "components/Panels/ContentPanel";
import { SubPanel } from "components/Panels/SubPanel"; import { SubPanel } from "components/Panels/SubPanel";
import { TranslatedPreviewCard } from "components/PreviewCard";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps"; import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk"; import { getReadySdk } from "graphql/sdk";
import { prettyinlineTitle, prettySlug } from "helpers/formatters"; import { prettyinlineTitle, prettySlug } from "helpers/formatters";
@ -24,6 +23,7 @@ import { SmartList } from "components/SmartList";
import { ContentPlaceholder } from "components/PanelComponents/ContentPlaceholder"; import { ContentPlaceholder } from "components/PanelComponents/ContentPlaceholder";
import { SelectiveNonNullable } from "helpers/types/SelectiveNonNullable"; import { SelectiveNonNullable } from "helpers/types/SelectiveNonNullable";
import { useBoolean } from "hooks/useBoolean"; import { useBoolean } from "hooks/useBoolean";
import { TranslatedPreviewCard } from "components/Translated";
/* /*
* *
@ -223,19 +223,17 @@ const Contents = ({
items={filterHasAttributes(contents, ["attributes", "id"] as const)} items={filterHasAttributes(contents, ["attributes", "id"] as const)}
getItemId={(item) => item.id} getItemId={(item) => item.id}
renderItem={({ item }) => ( renderItem={({ item }) => (
<>
{item.attributes.translations && (
<TranslatedPreviewCard <TranslatedPreviewCard
href={`/contents/${item.attributes.slug}`} href={`/contents/${item.attributes.slug}`}
translations={item.attributes.translations.map( translations={filterHasAttributes(item.attributes.translations, [
(translation) => ({ "language.data.attributes.code",
pre_title: translation?.pre_title, ] as const).map((translation) => ({
title: translation?.title, pre_title: translation.pre_title,
subtitle: translation?.subtitle, title: translation.title,
language: translation?.language?.data?.attributes?.code, subtitle: translation.subtitle,
}) language: translation.language.data.attributes.code,
)} }))}
slug={item.attributes.slug} fallback={{ title: prettySlug(item.attributes.slug) }}
languages={languages} languages={languages}
thumbnail={item.attributes.thumbnail?.data?.attributes} thumbnail={item.attributes.thumbnail?.data?.attributes}
thumbnailAspectRatio="3/2" thumbnailAspectRatio="3/2"
@ -243,19 +241,15 @@ const Contents = ({
stackNumber={ stackNumber={
effectiveCombineRelatedContent && effectiveCombineRelatedContent &&
item.attributes.group?.data?.attributes?.combine === true item.attributes.group?.data?.attributes?.combine === true
? item.attributes.group.data.attributes.contents?.data ? item.attributes.group.data.attributes.contents?.data.length
.length
: 0 : 0
} }
topChips={ topChips={
item.attributes.type?.data?.attributes item.attributes.type?.data?.attributes
? [ ? [
item.attributes.type.data.attributes.titles?.[0] item.attributes.type.data.attributes.titles?.[0]
? item.attributes.type.data.attributes.titles[0] ? item.attributes.type.data.attributes.titles[0]?.title
?.title : prettySlug(item.attributes.type.data.attributes.slug),
: prettySlug(
item.attributes.type.data.attributes.slug
),
] ]
: undefined : undefined
} }
@ -265,8 +259,6 @@ const Contents = ({
keepInfoVisible={keepInfoVisible} keepInfoVisible={keepInfoVisible}
/> />
)} )}
</>
)}
renderWhenEmpty={() => ( renderWhenEmpty={() => (
<ContentPlaceholder <ContentPlaceholder
message={langui.no_results_message ?? "No results"} message={langui.no_results_message ?? "No results"}

View File

@ -1,9 +1,7 @@
import { GetStaticPaths, GetStaticPathsResult, GetStaticProps } from "next"; import { GetStaticPaths, GetStaticPathsResult, GetStaticProps } from "next";
import { Fragment, useMemo } from "react"; import { Fragment, useMemo } from "react";
import { AppLayout } from "components/AppLayout"; import { AppLayout } from "components/AppLayout";
import { TranslatedScanSet } from "components/Library/ScanSet";
import { ScanSetCover } from "components/Library/ScanSetCover"; import { ScanSetCover } from "components/Library/ScanSetCover";
import { TranslatedNavOption } from "components/PanelComponents/NavOption";
import { import {
ReturnButton, ReturnButton,
ReturnButtonType, ReturnButtonType,
@ -31,6 +29,7 @@ import { isUntangibleGroupItem } from "helpers/libraryItem";
import { PreviewCardCTAs } from "components/Library/PreviewCardCTAs"; import { PreviewCardCTAs } from "components/Library/PreviewCardCTAs";
import { PreviewCard } from "components/PreviewCard"; import { PreviewCard } from "components/PreviewCard";
import { HorizontalLine } from "components/HorizontalLine"; import { HorizontalLine } from "components/HorizontalLine";
import { TranslatedNavOption, TranslatedScanSet } from "components/Translated";
/* /*
* *
@ -69,6 +68,7 @@ const LibrarySlug = ({
displayOn={ReturnButtonType.Desktop} displayOn={ReturnButtonType.Desktop}
/> />
<div className="grid place-items-center">
<div className="mobile:w-[80%]"> <div className="mobile:w-[80%]">
<PreviewCard <PreviewCard
href={`/library/${item.slug}`} href={`/library/${item.slug}`}
@ -98,6 +98,7 @@ const LibrarySlug = ({
} }
/> />
</div> </div>
</div>
<HorizontalLine /> <HorizontalLine />
@ -132,18 +133,16 @@ const LibrarySlug = ({
`${content.attributes.range[0].ending_page}` `${content.attributes.range[0].ending_page}`
: undefined, : undefined,
}))} }))}
fallbackTitle={prettySlug( fallback={{
content.attributes.slug, title: prettySlug(content.attributes.slug, item.slug),
item.slug subtitle:
)}
fallbackSubtitle={
content.attributes.range[0]?.__typename === content.attributes.range[0]?.__typename ===
"ComponentRangePageRange" "ComponentRangePageRange"
? `${content.attributes.range[0].starting_page}` + ? `${content.attributes.range[0].starting_page}` +
`` + `` +
`${content.attributes.range[0].ending_page}` `${content.attributes.range[0].ending_page}`
: undefined : undefined,
} }}
border border
languages={languages} languages={languages}
/> />
@ -210,7 +209,9 @@ const LibrarySlug = ({
translation.subtitle translation.subtitle
), ),
}))} }))}
fallbackTitle={prettySlug(content.attributes.slug, item.slug)} fallback={{
title: prettySlug(content.attributes.slug, item.slug),
}}
languages={languages} languages={languages}
langui={langui} langui={langui}
content={content.attributes.content} content={content.attributes.content}

View File

@ -8,7 +8,6 @@ import {
ContentPanelWidthSizes, ContentPanelWidthSizes,
} from "components/Panels/ContentPanel"; } from "components/Panels/ContentPanel";
import { SubPanel } from "components/Panels/SubPanel"; import { SubPanel } from "components/Panels/SubPanel";
import { TranslatedPreviewCard } from "components/PreviewCard";
import { GetPostsPreviewQuery } from "graphql/generated"; import { GetPostsPreviewQuery } 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";
@ -18,9 +17,10 @@ import { WithLabel } from "components/Inputs/WithLabel";
import { TextInput } from "components/Inputs/TextInput"; import { TextInput } from "components/Inputs/TextInput";
import { Button } from "components/Inputs/Button"; import { Button } from "components/Inputs/Button";
import { useMediaHoverable } from "hooks/useMediaQuery"; import { useMediaHoverable } from "hooks/useMediaQuery";
import { filterDefined, filterHasAttributes } from "helpers/others"; import { filterHasAttributes } from "helpers/others";
import { SmartList } from "components/SmartList"; import { SmartList } from "components/SmartList";
import { useBoolean } from "hooks/useBoolean"; import { useBoolean } from "hooks/useBoolean";
import { TranslatedPreviewCard } from "components/Translated";
/* /*
* *
@ -113,15 +113,15 @@ const News = ({
renderItem={({ item: post }) => ( renderItem={({ item: post }) => (
<TranslatedPreviewCard <TranslatedPreviewCard
href={`/news/${post.attributes.slug}`} href={`/news/${post.attributes.slug}`}
translations={filterDefined(post.attributes.translations).map( translations={filterHasAttributes(post.attributes.translations, [
(translation) => ({ "language.data.attributes.code",
language: translation.language?.data?.attributes?.code, ] as const).map((translation) => ({
language: translation.language.data.attributes.code,
title: translation.title, title: translation.title,
description: translation.excerpt, description: translation.excerpt,
}) }))}
)} fallback={{ title: prettySlug(post.attributes.slug) }}
languages={languages} languages={languages}
slug={post.attributes.slug}
thumbnail={post.attributes.thumbnail?.data?.attributes} thumbnail={post.attributes.thumbnail?.data?.attributes}
thumbnailAspectRatio="3/2" thumbnailAspectRatio="3/2"
thumbnailForceAspectRatio thumbnailForceAspectRatio

View File

@ -12,20 +12,20 @@ import {
ContentPanel, ContentPanel,
ContentPanelWidthSizes, ContentPanelWidthSizes,
} from "components/Panels/ContentPanel"; } from "components/Panels/ContentPanel";
import { TranslatedPreviewCard } from "components/PreviewCard";
import { HorizontalLine } from "components/HorizontalLine"; import { HorizontalLine } from "components/HorizontalLine";
import { Button } from "components/Inputs/Button"; import { Button } from "components/Inputs/Button";
import { Switch } from "components/Inputs/Switch"; import { Switch } from "components/Inputs/Switch";
import { TextInput } from "components/Inputs/TextInput"; import { TextInput } from "components/Inputs/TextInput";
import { WithLabel } from "components/Inputs/WithLabel"; import { WithLabel } from "components/Inputs/WithLabel";
import { useMediaHoverable } from "hooks/useMediaQuery"; import { useMediaHoverable } from "hooks/useMediaQuery";
import { filterDefined, filterHasAttributes, isDefined } from "helpers/others"; import { filterDefined, filterHasAttributes } from "helpers/others";
import { ContentPlaceholder } from "components/PanelComponents/ContentPlaceholder"; import { ContentPlaceholder } from "components/PanelComponents/ContentPlaceholder";
import { SmartList } from "components/SmartList"; import { SmartList } from "components/SmartList";
import { Select } from "components/Inputs/Select"; import { Select } from "components/Inputs/Select";
import { SelectiveNonNullable } from "helpers/types/SelectiveNonNullable"; import { SelectiveNonNullable } from "helpers/types/SelectiveNonNullable";
import { prettySlug } from "helpers/formatters"; import { prettySlug } from "helpers/formatters";
import { useBoolean } from "hooks/useBoolean"; import { useBoolean } from "hooks/useBoolean";
import { TranslatedPreviewCard } from "components/Translated";
/* /*
* *
@ -169,29 +169,27 @@ const Wiki = ({
items={filterHasAttributes(pages, ["id", "attributes"] as const)} items={filterHasAttributes(pages, ["id", "attributes"] as const)}
getItemId={(item) => item.id} getItemId={(item) => item.id}
renderItem={({ item }) => ( renderItem={({ item }) => (
<>
{isDefined(item.attributes.translations) && (
<TranslatedPreviewCard <TranslatedPreviewCard
href={`/wiki/${item.attributes.slug}`} href={`/wiki/${item.attributes.slug}`}
translations={item.attributes.translations.map( translations={filterHasAttributes(item.attributes.translations, [
(translation) => ({ "language.data.attributes.code",
title: translation?.title, ] as const).map((translation) => ({
title: translation.title,
subtitle: subtitle:
translation?.aliases && translation.aliases.length > 0 translation.aliases && translation.aliases.length > 0
? translation.aliases ? translation.aliases
.map((alias) => alias?.alias) .map((alias) => alias?.alias)
.join("・") .join("・")
: undefined, : undefined,
description: translation?.summary, description: translation.summary,
language: translation?.language?.data?.attributes?.code, language: translation.language.data.attributes.code,
}) }))}
)} fallback={{ title: prettySlug(item.attributes.slug) }}
thumbnail={item.attributes.thumbnail?.data?.attributes} thumbnail={item.attributes.thumbnail?.data?.attributes}
thumbnailAspectRatio={"4/3"} thumbnailAspectRatio={"4/3"}
thumbnailRounded thumbnailRounded
thumbnailForceAspectRatio thumbnailForceAspectRatio
languages={languages} languages={languages}
slug={item.attributes.slug}
keepInfoVisible={keepInfoVisible} keepInfoVisible={keepInfoVisible}
topChips={filterHasAttributes(item.attributes.tags?.data, [ topChips={filterHasAttributes(item.attributes.tags?.data, [
"attributes", "attributes",
@ -206,8 +204,6 @@ const Wiki = ({
).map((category) => category.attributes.short)} ).map((category) => category.attributes.short)}
/> />
)} )}
</>
)}
renderWhenEmpty={() => ( renderWhenEmpty={() => (
<ContentPlaceholder <ContentPlaceholder
message={langui.no_results_message ?? "No results"} message={langui.no_results_message ?? "No results"}