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,
scanSet,
id,
@ -138,7 +138,9 @@ const ScanSet = ({
/>
)}
<LanguageSwitcher {...languageSwitcherProps} />
{languageSwitcherProps.locales.size > 1 && (
<LanguageSwitcher {...languageSwitcherProps} />
)}
<div className="grid place-content-center place-items-center">
<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 { MouseEventHandler, useCallback, useMemo } from "react";
import { MouseEventHandler, useMemo } from "react";
import { Ico, Icon } from "components/Ico";
import { ToolTip } from "components/ToolTip";
import { cJoin, cIf } from "helpers/className";
import { isDefinedAndNotEmpty } from "helpers/others";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { useSmartLanguage } from "hooks/useSmartLanguage";
/*
*
@ -90,45 +88,3 @@ export const NavOption = ({
</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 { useCallback, useMemo } from "react";
import { useMemo } from "react";
import { Chip } from "./Chip";
import { Ico, Icon } from "./Ico";
import { Img } from "./Img";
@ -16,10 +16,9 @@ import {
prettyDuration,
prettyPrice,
prettyShortenNumber,
prettySlug,
} from "helpers/formatters";
import { ImageQuality } from "helpers/img";
import { useSmartLanguage } from "hooks/useSmartLanguage";
import { useMediaHoverable } from "hooks/useMediaQuery";
/*
*
@ -78,6 +77,7 @@ export const PreviewCard = ({
infoAppend,
}: Props): JSX.Element => {
const { currency } = useAppLayout();
const isHoverable = useMediaHoverable();
const metadataJSX = useMemo(
() => (
@ -247,7 +247,7 @@ export const PreviewCard = ({
className={cJoin(
"z-20 grid gap-2 p-4 transition-opacity linearbg-obi",
cIf(
!keepInfoVisible,
!keepInfoVisible && isHoverable,
`-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
notHoverable:rounded-b-md notHoverable:opacity-100`,
@ -291,46 +291,3 @@ export const PreviewCard = ({
</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 { useCallback } from "react";
import { Chip } from "./Chip";
import { Img } from "./Img";
import { UploadImageFragment } from "graphql/generated";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { prettySlug } from "helpers/formatters";
import { ImageQuality } from "helpers/img";
import { useSmartLanguage } from "hooks/useSmartLanguage";
/*
*
@ -26,7 +22,7 @@ interface Props {
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
const PreviewLine = ({
export const PreviewLine = ({
href,
thumbnail,
pre_title,
@ -76,45 +72,3 @@ const PreviewLine = ({
</div>
</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, [
"attributes",
] as const).map((language) => (
<Fragment key={language.attributes.code}>
<Fragment key={language.__typename}>
<Chip text={language.attributes.code.toUpperCase()} />
</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,
paths: readonly P[]
): SelectiveNonNullable<T, typeof paths[number]>[] =>
isUndefined(t)
? []
: (t.filter((item) =>
isDefined(t)
? (t.filter((item) =>
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)) {
return paths.every((path) => {
const attributeToCheck = (path as string).split(".")[0];
return (
isDefined(attributeToCheck) &&
Object.keys(item).includes(attributeToCheck) &&
isDefined(item[attributeToCheck as keyof T])
);
});
const [head, ...rest] = path.split(".");
if (Object.keys(item).includes(head)) {
const attribute = head as keyof T;
if (isDefined(item[attribute])) {
if (rest.length > 0) {
return hasAttribute(item[attribute], rest.join("."));
}
return true;
}
}
}
return false;
};

View File

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

View File

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

View File

@ -1,9 +1,7 @@
import { GetStaticPaths, GetStaticPathsResult, GetStaticProps } from "next";
import { Fragment, useMemo } from "react";
import { AppLayout } from "components/AppLayout";
import { TranslatedScanSet } from "components/Library/ScanSet";
import { ScanSetCover } from "components/Library/ScanSetCover";
import { TranslatedNavOption } from "components/PanelComponents/NavOption";
import {
ReturnButton,
ReturnButtonType,
@ -31,6 +29,7 @@ import { isUntangibleGroupItem } from "helpers/libraryItem";
import { PreviewCardCTAs } from "components/Library/PreviewCardCTAs";
import { PreviewCard } from "components/PreviewCard";
import { HorizontalLine } from "components/HorizontalLine";
import { TranslatedNavOption, TranslatedScanSet } from "components/Translated";
/*
*
@ -69,34 +68,36 @@ const LibrarySlug = ({
displayOn={ReturnButtonType.Desktop}
/>
<div className="mobile:w-[80%]">
<PreviewCard
href={`/library/${item.slug}`}
title={item.title}
subtitle={item.subtitle}
thumbnail={item.thumbnail?.data?.attributes}
thumbnailAspectRatio="21/29.7"
thumbnailRounded={false}
topChips={
item.metadata && item.metadata.length > 0 && item.metadata[0]
? [prettyItemSubType(item.metadata[0])]
: []
}
bottomChips={filterHasAttributes(item.categories?.data, [
"attributes",
] as const).map((category) => category.attributes.short)}
metadata={{
currencies: currencies,
release_date: item.release_date,
price: item.price,
position: "Bottom",
}}
infoAppend={
!isUntangibleGroupItem(item.metadata?.[0]) && (
<PreviewCardCTAs id={itemId} langui={langui} />
)
}
/>
<div className="grid place-items-center">
<div className="mobile:w-[80%]">
<PreviewCard
href={`/library/${item.slug}`}
title={item.title}
subtitle={item.subtitle}
thumbnail={item.thumbnail?.data?.attributes}
thumbnailAspectRatio="21/29.7"
thumbnailRounded={false}
topChips={
item.metadata && item.metadata.length > 0 && item.metadata[0]
? [prettyItemSubType(item.metadata[0])]
: []
}
bottomChips={filterHasAttributes(item.categories?.data, [
"attributes",
] as const).map((category) => category.attributes.short)}
metadata={{
currencies: currencies,
release_date: item.release_date,
price: item.price,
position: "Bottom",
}}
infoAppend={
!isUntangibleGroupItem(item.metadata?.[0]) && (
<PreviewCardCTAs id={itemId} langui={langui} />
)
}
/>
</div>
</div>
<HorizontalLine />
@ -132,18 +133,16 @@ const LibrarySlug = ({
`${content.attributes.range[0].ending_page}`
: undefined,
}))}
fallbackTitle={prettySlug(
content.attributes.slug,
item.slug
)}
fallbackSubtitle={
content.attributes.range[0]?.__typename ===
"ComponentRangePageRange"
? `${content.attributes.range[0].starting_page}` +
`` +
`${content.attributes.range[0].ending_page}`
: undefined
}
fallback={{
title: prettySlug(content.attributes.slug, item.slug),
subtitle:
content.attributes.range[0]?.__typename ===
"ComponentRangePageRange"
? `${content.attributes.range[0].starting_page}` +
`` +
`${content.attributes.range[0].ending_page}`
: undefined,
}}
border
languages={languages}
/>
@ -210,7 +209,9 @@ const LibrarySlug = ({
translation.subtitle
),
}))}
fallbackTitle={prettySlug(content.attributes.slug, item.slug)}
fallback={{
title: prettySlug(content.attributes.slug, item.slug),
}}
languages={languages}
langui={langui}
content={content.attributes.content}

View File

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

View File

@ -12,20 +12,20 @@ import {
ContentPanel,
ContentPanelWidthSizes,
} from "components/Panels/ContentPanel";
import { TranslatedPreviewCard } from "components/PreviewCard";
import { HorizontalLine } from "components/HorizontalLine";
import { Button } from "components/Inputs/Button";
import { Switch } from "components/Inputs/Switch";
import { TextInput } from "components/Inputs/TextInput";
import { WithLabel } from "components/Inputs/WithLabel";
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 { SmartList } from "components/SmartList";
import { Select } from "components/Inputs/Select";
import { SelectiveNonNullable } from "helpers/types/SelectiveNonNullable";
import { prettySlug } from "helpers/formatters";
import { useBoolean } from "hooks/useBoolean";
import { TranslatedPreviewCard } from "components/Translated";
/*
*
@ -169,44 +169,40 @@ const Wiki = ({
items={filterHasAttributes(pages, ["id", "attributes"] as const)}
getItemId={(item) => item.id}
renderItem={({ item }) => (
<>
{isDefined(item.attributes.translations) && (
<TranslatedPreviewCard
href={`/wiki/${item.attributes.slug}`}
translations={item.attributes.translations.map(
(translation) => ({
title: translation?.title,
subtitle:
translation?.aliases && translation.aliases.length > 0
? translation.aliases
.map((alias) => alias?.alias)
.join("・")
: undefined,
description: translation?.summary,
language: translation?.language?.data?.attributes?.code,
})
)}
thumbnail={item.attributes.thumbnail?.data?.attributes}
thumbnailAspectRatio={"4/3"}
thumbnailRounded
thumbnailForceAspectRatio
languages={languages}
slug={item.attributes.slug}
keepInfoVisible={keepInfoVisible}
topChips={filterHasAttributes(item.attributes.tags?.data, [
"attributes",
] as const).map(
(tag) =>
tag.attributes.titles?.[0]?.title ??
prettySlug(tag.attributes.slug)
)}
bottomChips={filterHasAttributes(
item.attributes.categories?.data,
["attributes"] as const
).map((category) => category.attributes.short)}
/>
<TranslatedPreviewCard
href={`/wiki/${item.attributes.slug}`}
translations={filterHasAttributes(item.attributes.translations, [
"language.data.attributes.code",
] as const).map((translation) => ({
title: translation.title,
subtitle:
translation.aliases && translation.aliases.length > 0
? translation.aliases
.map((alias) => alias?.alias)
.join("・")
: undefined,
description: translation.summary,
language: translation.language.data.attributes.code,
}))}
fallback={{ title: prettySlug(item.attributes.slug) }}
thumbnail={item.attributes.thumbnail?.data?.attributes}
thumbnailAspectRatio={"4/3"}
thumbnailRounded
thumbnailForceAspectRatio
languages={languages}
keepInfoVisible={keepInfoVisible}
topChips={filterHasAttributes(item.attributes.tags?.data, [
"attributes",
] as const).map(
(tag) =>
tag.attributes.titles?.[0]?.title ??
prettySlug(tag.attributes.slug)
)}
</>
bottomChips={filterHasAttributes(
item.attributes.categories?.data,
["attributes"] as const
).map((category) => category.attributes.short)}
/>
)}
renderWhenEmpty={() => (
<ContentPlaceholder