OpenGraph support

This commit is contained in:
DrMint 2022-07-23 10:24:13 +02:00
parent 74b77431a9
commit 7832b71f5c
41 changed files with 747 additions and 447 deletions

View File

@ -19,13 +19,13 @@ import {
isUndefined,
iterateMap,
} from "helpers/others";
import { getOgImage, ImageQuality } from "helpers/img";
import { prettyLanguage, prettySlug } from "helpers/formatters";
import { prettyLanguage } from "helpers/formatters";
import { cIf, cJoin } from "helpers/className";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { UploadImageFragment } from "graphql/generated";
import { useAppLayout } from "contexts/AppLayoutContext";
import { Button } from "components/Inputs/Button";
import { OpenGraph } from "helpers/openGraph";
import { getDefaultPreferredLanguages } from "helpers/locales";
/*
*
@ -33,21 +33,20 @@ import { Button } from "components/Inputs/Button";
*/
const SENSIBILITY_SWIPE = 1.1;
const TITLE_PREFIX = "Accords Library";
/*
*
* COMPONENT
*/
interface Props extends AppStaticProps {
export interface AppLayoutRequired {
openGraph: OpenGraph;
}
interface Props extends AppStaticProps, AppLayoutRequired {
subPanel?: React.ReactNode;
subPanelIcon?: Icon;
contentPanel?: React.ReactNode;
title?: string;
navTitle: string | null | undefined;
thumbnail?: UploadImageFragment;
description?: string;
contentPanelScroolbar?: boolean;
}
@ -59,10 +58,7 @@ export const AppLayout = ({
languages,
subPanel,
contentPanel,
thumbnail,
title,
navTitle,
description,
openGraph,
subPanelIcon = Icon.Tune,
contentPanelScroolbar = true,
}: Props): JSX.Element => {
@ -136,33 +132,6 @@ export const AppLayout = ({
[contentPanel, subPanel]
);
const metaImage = useMemo(
() =>
thumbnail
? getOgImage(ImageQuality.Og, thumbnail)
: {
image: "/default_og.jpg",
width: 1200,
height: 630,
alt: "Accord's Library Logo",
},
[thumbnail]
);
const { ogTitle, metaTitle } = useMemo(() => {
const resultTitle =
title ?? navTitle ?? prettySlug(router.asPath.split("/").pop());
return {
ogTitle: resultTitle,
metaTitle: `${TITLE_PREFIX} - ${resultTitle}`,
};
}, [navTitle, router.asPath, title]);
const metaDescription = useMemo(
() => description ?? langui.default_description ?? "",
[description, langui.default_description]
);
useLayoutEffect(() => {
document.getElementsByTagName("html")[0].style.fontSize = `${
(fontSize ?? 1) * 100
@ -191,25 +160,13 @@ export const AppLayout = ({
useEffect(() => {
if (preferredLanguages) {
if (preferredLanguages.length === 0) {
let defaultPreferredLanguages: string[] = [];
if (isDefinedAndNotEmpty(router.locale) && router.locales) {
if (router.locale === "en") {
defaultPreferredLanguages = [router.locale];
router.locales.map((locale) => {
if (locale !== router.locale)
defaultPreferredLanguages.push(locale);
});
} else {
defaultPreferredLanguages = [router.locale, "en"];
router.locales.map((locale) => {
if (locale !== router.locale && locale !== "en")
defaultPreferredLanguages.push(locale);
});
}
setPreferredLanguages(
getDefaultPreferredLanguages(router.locale, router.locales)
);
}
setPreferredLanguages(defaultPreferredLanguages);
} else if (router.locale !== preferredLanguages[0]) {
router.push(router.asPath, router.asPath, {
router.replace(router.asPath, router.asPath, {
locale: preferredLanguages[0],
});
}
@ -251,27 +208,36 @@ export const AppLayout = ({
)}
>
<Head>
<title>{metaTitle}</title>
<meta name="description" content={metaDescription} />
<title>{openGraph.title}</title>
<meta name="description" content={openGraph.description} />
<meta name="twitter:title" content={metaTitle}></meta>
<meta name="twitter:description" content={metaDescription}></meta>
<meta name="twitter:title" content={openGraph.title}></meta>
<meta
name="twitter:description"
content={openGraph.description}
></meta>
<meta name="twitter:card" content="summary_large_image"></meta>
<meta name="twitter:image" content={metaImage.image}></meta>
<meta name="twitter:image" content={openGraph.thumbnail.image}></meta>
<meta property="og:title" content={metaTitle} />
<meta property="og:description" content={metaDescription} />
<meta property="og:image" content={metaImage.image}></meta>
<meta property="og:image:secure_url" content={metaImage.image}></meta>
<meta property="og:title" content={openGraph.title} />
<meta property="og:description" content={openGraph.description} />
<meta property="og:image" content={openGraph.thumbnail.image}></meta>
<meta
property="og:image:secure_url"
content={openGraph.thumbnail.image}
></meta>
<meta
property="og:image:width"
content={metaImage.width.toString()}
content={openGraph.thumbnail.width.toString()}
></meta>
<meta
property="og:image:height"
content={metaImage.height.toString()}
content={openGraph.thumbnail.height.toString()}
></meta>
<meta
property="og:image:alt"
content={openGraph.thumbnail.alt}
></meta>
<meta property="og:image:alt" content={metaImage.alt}></meta>
<meta property="og:image:type" content="image/jpeg"></meta>
</Head>
@ -370,13 +336,13 @@ export const AppLayout = ({
className={cJoin(
"overflow-hidden text-center font-headers font-black",
cIf(
ogTitle && ogTitle.length > 30,
openGraph.title.length > 30,
"max-h-14 text-xl",
"max-h-16 text-2xl"
)
)}
>
{ogTitle}
{openGraph.title}
</p>
{isDefined(subPanel) && !turnSubIntoContent && (
<Ico

View File

@ -1,5 +1,5 @@
import { Fragment, useCallback, useMemo } from "react";
import { AppLayout } from "./AppLayout";
import { AppLayout, AppLayoutRequired } from "./AppLayout";
import { Chip } from "./Chip";
import { HorizontalLine } from "./HorizontalLine";
import { Markdawn, TableOfContents } from "./Markdown/Markdawn";
@ -13,7 +13,6 @@ import { useSmartLanguage } from "hooks/useSmartLanguage";
import { PostWithTranslations } from "helpers/types";
import { filterHasAttributes, getStatusDescription } from "helpers/others";
import { prettySlug } from "helpers/formatters";
import { getDescription } from "helpers/description";
import { AppStaticProps } from "graphql/getAppStaticProps";
/*
@ -21,7 +20,7 @@ import { AppStaticProps } from "graphql/getAppStaticProps";
* COMPONENT
*/
interface Props {
interface Props extends AppLayoutRequired {
post: PostWithTranslations;
langui: AppStaticProps["langui"];
languages: AppStaticProps["languages"];
@ -52,7 +51,7 @@ export const PostPage = ({
appendBody,
prependBody,
displayTitle = true,
currencies,
...otherProps
}: Props): JSX.Element => {
const [selectedTranslation, LanguageSwitcher, languageSwitcherProps] =
useSmartLanguage({
@ -221,16 +220,9 @@ export const PostPage = ({
return (
<AppLayout
navTitle={title}
description={getDescription({
langui: langui,
description: selectedTranslation?.excerpt,
categories: post.categories,
})}
{...otherProps}
contentPanel={contentPanel}
subPanel={subPanel}
thumbnail={thumbnail ?? undefined}
currencies={currencies}
languages={languages}
langui={langui}
/>

View File

@ -1,5 +1,6 @@
import Link from "next/link";
import { useMemo } from "react";
import { useRouter } from "next/router";
import { Chip } from "./Chip";
import { Ico, Icon } from "./Ico";
import { Img } from "./Img";
@ -41,7 +42,8 @@ interface Props {
stackNumber?: number;
metadata?: {
currencies?: AppStaticProps["currencies"];
release_date?: DatePickerFragment | null;
releaseDate?: DatePickerFragment | null;
releaseDateFormat?: Intl.DateTimeFormatOptions["dateStyle"];
price?: PricePickerFragment | null;
views?: number;
author?: string;
@ -78,19 +80,20 @@ export const PreviewCard = ({
}: Props): JSX.Element => {
const { currency } = useAppLayout();
const isHoverable = useMediaHoverable();
const router = useRouter();
const metadataJSX = useMemo(
() => (
<>
{metadata && (metadata.release_date || metadata.price) && (
{metadata && (metadata.releaseDate || metadata.price) && (
<div className="flex w-full flex-row flex-wrap gap-x-3">
{metadata.release_date && (
{metadata.releaseDate && (
<p className="text-sm mobile:text-xs">
<Ico
icon={Icon.Event}
className="mr-1 translate-y-[.15em] !text-base"
/>
{prettyDate(metadata.release_date)}
{prettyDate(metadata.releaseDate, router.locale)}
</p>
)}
{metadata.price && metadata.currencies && (
@ -124,7 +127,7 @@ export const PreviewCard = ({
)}
</>
),
[currency, metadata]
[currency, metadata, router.locale]
);
return (
@ -278,7 +281,7 @@ export const PreviewCard = ({
{bottomChips && bottomChips.length > 0 && (
<div
className="grid grid-flow-col place-content-start gap-1 overflow-x-scroll
[scrollbar-width:none] webkit-scrollbar:w-0"
[scrollbar-width:none] webkit-scrollbar:h-0"
>
{bottomChips.map((text, index) => (
<Chip key={index} className="text-sm" text={text} />

View File

@ -2,9 +2,18 @@ import { GetStaticProps } from "next";
import { AppStaticProps, getAppStaticProps } from "./getAppStaticProps";
import { getReadySdk } from "./sdk";
import { PostWithTranslations } from "helpers/types";
import { OpenGraph, getOpenGraph } from "helpers/openGraph";
import { prettyDate, prettySlug } from "helpers/formatters";
import {
getDefaultPreferredLanguages,
staticSmartLanguage,
} from "helpers/locales";
import { filterHasAttributes, isDefined } from "helpers/others";
import { getDescription } from "helpers/description";
export interface PostStaticProps extends AppStaticProps {
post: PostWithTranslations;
openGraph: OpenGraph;
}
export const getPostStaticProps =
@ -15,10 +24,48 @@ export const getPostStaticProps =
slug: slug,
language_code: context.locale ?? "en",
});
if (post.posts?.data[0]?.attributes?.translations) {
if (
post.posts?.data &&
post.posts.data.length > 0 &&
post.posts.data[0].attributes?.translations &&
isDefined(context.locale) &&
isDefined(context.locales)
) {
const appStaticProps = await getAppStaticProps(context);
const selectedTranslation = staticSmartLanguage({
items: post.posts.data[0].attributes.translations,
languageExtractor: (item) => item.language?.data?.attributes?.code,
preferredLanguages: getDefaultPreferredLanguages(
context.locale,
context.locales
),
});
const title = selectedTranslation?.title ?? prettySlug(slug);
const description = getDescription(selectedTranslation?.excerpt, {
[appStaticProps.langui.release_date ?? "Release date"]: [
prettyDate(post.posts.data[0].attributes.date, context.locale),
],
[appStaticProps.langui.categories ?? "Categories"]: filterHasAttributes(
post.posts.data[0].attributes.categories?.data,
["attributes"] as const
).map((category) => category.attributes.short),
});
const thumbnail =
selectedTranslation?.thumbnail?.data?.attributes ??
post.posts.data[0].attributes.thumbnail?.data?.attributes;
const props: PostStaticProps = {
...(await getAppStaticProps(context)),
...appStaticProps,
post: post.posts.data[0].attributes as PostWithTranslations,
openGraph: getOpenGraph(
appStaticProps.langui,
title,
description,
thumbnail
),
};
return {
props: props,

View File

@ -20,19 +20,12 @@ query getWikiPage($slug: String, $language_code: String) {
}
}
}
tags(pagination: { limit: -1 }) {
tags {
data {
id
attributes {
slug
titles(filters: { language: { code: { eq: $language_code } } }) {
language {
data {
attributes {
code
}
}
}
title
}
}

View File

@ -1,9 +1,13 @@
import { isUndefined } from "./others";
import { DatePickerFragment } from "graphql/generated";
export const compareDate = (
a: DatePickerFragment,
b: DatePickerFragment
a: DatePickerFragment | null | undefined,
b: DatePickerFragment | null | undefined
): number => {
if (isUndefined(a) || isUndefined(b)) {
return 0;
}
const dateA = (a.year ?? 99999) * 365 + (a.month ?? 12) * 31 + (a.day ?? 31);
const dateB = (b.year ?? 99999) * 365 + (b.month ?? 12) * 31 + (b.day ?? 31);
return dateA - dateB;

View File

@ -1,52 +1,28 @@
import { prettySlug } from "./formatters";
import { isDefined } from "./others";
import { Content } from "./types";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { isDefined, isDefinedAndNotEmpty } from "./others";
interface Description {
langui: AppStaticProps["langui"];
description?: string | null | undefined;
type?: Content["type"];
categories?: Content["categories"];
}
export const getDescription = (
description: string | null | undefined,
chipsGroups?: Record<string, (string | undefined)[]>
): string => {
let result = "";
export const getDescription = ({
langui,
description: text,
type,
categories,
}: Description): string => {
let description = "";
// TEXT
if (text) {
description += prettyMarkdown(text);
description += "\n\n";
if (isDefinedAndNotEmpty(description)) {
result += prettyMarkdown(description);
if (isDefined(chipsGroups)) {
result += "\n\n";
}
}
// TYPE
if (type?.data) {
description += `${langui.type}: `;
description += `(${
type.data.attributes?.titles?.[0]?.title ??
prettySlug(type.data.attributes?.slug)
})`;
description += "\n";
for (const key in chipsGroups) {
if (Object.hasOwn(chipsGroups, key)) {
const chipsGroup = chipsGroups[key];
if (chipsGroup.length > 0) {
result += `${key}: ${prettyChip(chipsGroup)}\n`;
}
}
}
// CATEGORIES
if (categories?.data && categories.data.length > 0) {
description += `${langui.categories}: `;
description += prettyChip(
categories.data.map((category) => category.attributes?.short)
);
description += "\n";
}
return description;
return result;
};
const prettyMarkdown = (markdown: string): string =>

View File

@ -1,17 +1,18 @@
import { AppStaticProps } from "../graphql/getAppStaticProps";
import { convertPrice } from "./numbers";
import { isDefinedAndNotEmpty } from "./others";
import { isDefinedAndNotEmpty, isUndefined } from "./others";
import { DatePickerFragment, PricePickerFragment } from "graphql/generated";
export const prettyDate = (datePicker: DatePickerFragment): string => {
let result = "";
if (datePicker.year) result += datePicker.year.toString();
if (datePicker.month)
result += `/${datePicker.month.toString().padStart(2, "0")}`;
if (datePicker.day)
result += `/${datePicker.day.toString().padStart(2, "0")}`;
return result;
};
export const prettyDate = (
datePicker: DatePickerFragment,
locale = "en",
dateStyle: Intl.DateTimeFormatOptions["dateStyle"] = "medium"
): string =>
new Date(
datePicker.year ?? 0,
datePicker.month ?? 0,
datePicker.day ?? 1
).toLocaleString(locale, { dateStyle });
export const prettyPrice = (
pricePicker: PricePickerFragment,
@ -19,19 +20,23 @@ export const prettyPrice = (
targetCurrencyCode?: string
): string => {
if (!targetCurrencyCode) return "";
let result = "";
currencies.map((currency) => {
if (currency.attributes?.code === targetCurrencyCode) {
const amountInTargetCurrency = convertPrice(pricePicker, currency);
result =
currency.attributes.symbol +
amountInTargetCurrency.toLocaleString(undefined, {
minimumFractionDigits: currency.attributes.display_decimals ? 2 : 0,
maximumFractionDigits: currency.attributes.display_decimals ? 2 : 0,
});
}
if (isUndefined(pricePicker.amount)) return "";
const targetCurrency = currencies.find(
(currency) => currency.attributes?.code === targetCurrencyCode
);
if (targetCurrency?.attributes) {
const amountInTargetCurrency = convertPrice(pricePicker, targetCurrency);
return amountInTargetCurrency.toLocaleString("en", {
style: "currency",
currency: targetCurrency.attributes.code,
});
}
return pricePicker.amount.toLocaleString("en", {
style: "currency",
currency: pricePicker.currency?.data?.attributes?.code,
});
return result;
};
export const prettySlug = (slug?: string, parentSlug?: string): string => {

View File

@ -1,5 +1,3 @@
import { UploadImageFragment } from "graphql/generated";
export enum ImageQuality {
Small = "small",
Medium = "medium",
@ -7,7 +5,7 @@ export enum ImageQuality {
Og = "og",
}
interface OgImage {
export interface OgImage {
image: string;
width: number;
height: number;
@ -65,20 +63,3 @@ export const getImgSizesByQuality = (
return { width: 0, height: 0 };
}
};
export const getOgImage = (
quality: ImageQuality,
image: UploadImageFragment
): OgImage => {
const imgSize = getImgSizesByQuality(
image.width ?? 0,
image.height ?? 0,
quality
);
return {
image: getAssetURL(image.url, quality),
width: imgSize.width,
height: imgSize.height,
alt: image.alternativeText ?? "",
};
};

54
src/helpers/locales.ts Normal file
View File

@ -0,0 +1,54 @@
import { isDefined } from "./others";
export const getDefaultPreferredLanguages = (
routerLocal: string,
locales: string[]
): string[] => {
let defaultPreferredLanguages: string[] = [];
if (routerLocal === "en") {
defaultPreferredLanguages = [routerLocal];
locales.map((locale) => {
if (locale !== routerLocal) defaultPreferredLanguages.push(locale);
});
} else {
defaultPreferredLanguages = [routerLocal, "en"];
locales.map((locale) => {
if (locale !== routerLocal && locale !== "en")
defaultPreferredLanguages.push(locale);
});
}
return defaultPreferredLanguages;
};
export const getPreferredLanguage = (
preferredLanguages: (string | undefined)[],
availableLanguages: Map<string, number>
): number | undefined => {
for (const locale of preferredLanguages) {
if (isDefined(locale) && availableLanguages.has(locale)) {
return availableLanguages.get(locale);
}
}
return undefined;
};
interface StaticSmartLanguageProps<T> {
items: T[];
preferredLanguages: string[];
languageExtractor: (item: NonNullable<T>) => string | undefined;
}
export const staticSmartLanguage = <T>({
languageExtractor,
preferredLanguages,
items,
}: StaticSmartLanguageProps<T>): T | undefined => {
for (const language of preferredLanguages) {
for (const item of items) {
if (isDefined(item) && languageExtractor(item) === language) {
return item;
}
}
}
return undefined;
};

51
src/helpers/openGraph.ts Normal file
View File

@ -0,0 +1,51 @@
import {
OgImage,
getImgSizesByQuality,
ImageQuality,
getAssetURL,
} from "./img";
import { isDefinedAndNotEmpty } from "./others";
import { UploadImageFragment } from "graphql/generated";
import { AppStaticProps } from "graphql/getAppStaticProps";
const DEFAULT_OG_THUMBNAIL = {
image: `${process.env.NEXT_PUBLIC_URL_SELF}/default_og.jpg`,
width: 1200,
height: 630,
alt: "Accord's Library Logo",
};
const TITLE_PREFIX = "Accords Library";
export interface OpenGraph {
title: string;
description: string;
thumbnail: OgImage;
}
export const getOpenGraph = (
langui: AppStaticProps["langui"],
title: string,
description?: string | null | undefined,
thumbnail?: UploadImageFragment | null | undefined
): OpenGraph => ({
title: `${TITLE_PREFIX}${isDefinedAndNotEmpty(title) && ` - ${title}`}`,
description: isDefinedAndNotEmpty(description)
? description
: langui.default_description ?? "",
thumbnail: thumbnail ? getOgImage(thumbnail) : DEFAULT_OG_THUMBNAIL,
});
const getOgImage = (image: UploadImageFragment): OgImage => {
const imgSize = getImgSizesByQuality(
image.width ?? 0,
image.height ?? 0,
ImageQuality.Og
);
return {
image: getAssetURL(image.url, ImageQuality.Og),
width: imgSize.width,
height: imgSize.height,
alt: image.alternativeText ?? "",
};
};

View File

@ -17,7 +17,7 @@ export interface PostWithTranslations extends Omit<Post, "translations"> {
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
export type Content = NonNullable<
type Content = NonNullable<
NonNullable<GetContentTextQuery["contents"]>["data"][number]["attributes"]
>;

View File

@ -4,6 +4,7 @@ import { LanguageSwitcher } from "components/Inputs/LanguageSwitcher";
import { useAppLayout } from "contexts/AppLayoutContext";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { filterDefined, isDefined } from "helpers/others";
import { getPreferredLanguage } from "helpers/locales";
interface Props<T> {
items: T[];
@ -12,18 +13,6 @@ interface Props<T> {
transform?: (item: NonNullable<T>) => NonNullable<T>;
}
const getPreferredLanguage = (
preferredLanguages: (string | undefined)[],
availableLanguages: Map<string, number>
): number | undefined => {
for (const locale of preferredLanguages) {
if (isDefined(locale) && availableLanguages.has(locale)) {
return availableLanguages.get(locale);
}
}
return undefined;
};
export const useSmartLanguage = <T>({
items,
languageExtractor,

View File

@ -1,25 +1,29 @@
import { GetStaticProps } from "next";
import { AppLayout } from "components/AppLayout";
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import {
ReturnButton,
ReturnButtonType,
} from "components/PanelComponents/ReturnButton";
import { ContentPanel } from "components/Panels/ContentPanel";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getOpenGraph } from "helpers/openGraph";
/*
*
* PAGE
*/
interface Props extends AppStaticProps {}
interface Props extends AppStaticProps, AppLayoutRequired {}
const FourOhFour = ({ langui, ...otherProps }: Props): JSX.Element => (
const FourOhFour = ({
langui,
openGraph,
...otherProps
}: Props): JSX.Element => (
<AppLayout
navTitle="404"
contentPanel={
<ContentPanel>
<h1>404 - {langui.page_not_found}</h1>
<h1>{openGraph.title}</h1>
<ReturnButton
href="/"
title="Home"
@ -28,6 +32,7 @@ const FourOhFour = ({ langui, ...otherProps }: Props): JSX.Element => (
/>
</ContentPanel>
}
openGraph={openGraph}
langui={langui}
{...otherProps}
/>
@ -40,8 +45,13 @@ export default FourOhFour;
*/
export const getStaticProps: GetStaticProps = async (context) => {
const appStaticProps = await getAppStaticProps(context);
const props: Props = {
...(await getAppStaticProps(context)),
...appStaticProps,
openGraph: getOpenGraph(
appStaticProps.langui,
`404 - ${appStaticProps.langui.page_not_found}`
),
};
return {
props: props,

View File

@ -1,25 +1,29 @@
import { GetStaticProps } from "next";
import { AppLayout } from "components/AppLayout";
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import {
ReturnButton,
ReturnButtonType,
} from "components/PanelComponents/ReturnButton";
import { ContentPanel } from "components/Panels/ContentPanel";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getOpenGraph } from "helpers/openGraph";
/*
*
* PAGE
*/
interface Props extends AppStaticProps {}
interface Props extends AppStaticProps, AppLayoutRequired {}
const FiveHundred = ({ langui, ...otherProps }: Props): JSX.Element => (
const FiveHundred = ({
langui,
openGraph,
...otherProps
}: Props): JSX.Element => (
<AppLayout
navTitle="500"
contentPanel={
<ContentPanel>
<h1>500 - Internal Server Error</h1>
<h1>{openGraph.title}</h1>
<ReturnButton
href="/"
title="Home"
@ -28,6 +32,7 @@ const FiveHundred = ({ langui, ...otherProps }: Props): JSX.Element => (
/>
</ContentPanel>
}
openGraph={openGraph}
langui={langui}
{...otherProps}
/>
@ -40,8 +45,13 @@ export default FiveHundred;
*/
export const getStaticProps: GetStaticProps = async (context) => {
const appStaticProps = await getAppStaticProps(context);
const props: Props = {
...(await getAppStaticProps(context)),
...appStaticProps,
openGraph: getOpenGraph(
appStaticProps.langui,
"500 - Internal Server Error"
),
};
return {
props: props,

View File

@ -9,19 +9,11 @@ import {
* PAGE
*/
const AccordsHandbook = ({
post,
langui,
languages,
currencies,
}: PostStaticProps): JSX.Element => (
const AccordsHandbook = (props: PostStaticProps): JSX.Element => (
<PostPage
currencies={currencies}
languages={languages}
langui={langui}
post={post}
{...props}
returnHref="/about-us/"
returnTitle={langui.about_us}
returnTitle={props.langui.about_us}
displayToc
displayLanguageSwitcher
/>

View File

@ -15,12 +15,7 @@ import { RequestMailProps, ResponseMailProps } from "pages/api/mail";
* PAGE
*/
const AboutUs = ({
post,
langui,
languages,
currencies,
}: PostStaticProps): JSX.Element => {
const AboutUs = ({ langui, ...otherProps }: PostStaticProps): JSX.Element => {
const router = useRouter();
const [formResponse, setFormResponse] = useState("");
const [formState, setFormState] = useState<"completed" | "ongoing" | "stale">(
@ -177,10 +172,8 @@ const AboutUs = ({
return (
<PostPage
currencies={currencies}
languages={languages}
{...otherProps}
langui={langui}
post={post}
returnHref="/about-us/"
returnTitle={langui.about_us}
displayToc

View File

@ -1,21 +1,21 @@
import { GetStaticProps } from "next";
import { AppLayout } from "components/AppLayout";
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { Icon } from "components/Ico";
import { NavOption } from "components/PanelComponents/NavOption";
import { PanelHeader } from "components/PanelComponents/PanelHeader";
import { SubPanel } from "components/Panels/SubPanel";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getOpenGraph } from "helpers/openGraph";
/*
*
* PAGE
*/
interface Props extends AppStaticProps {}
interface Props extends AppStaticProps, AppLayoutRequired {}
const AboutUs = ({ langui, ...otherProps }: Props): JSX.Element => (
<AppLayout
navTitle={langui.about_us}
subPanel={
<SubPanel>
<PanelHeader
@ -49,8 +49,13 @@ export default AboutUs;
*/
export const getStaticProps: GetStaticProps = async (context) => {
const appStaticProps = await getAppStaticProps(context);
const props: Props = {
...(await getAppStaticProps(context)),
...appStaticProps,
openGraph: getOpenGraph(
appStaticProps.langui,
appStaticProps.langui.about_us ?? "About us"
),
};
return {
props: props,

View File

@ -9,19 +9,11 @@ import {
* PAGE
*/
const Legality = ({
post,
langui,
languages,
currencies,
}: PostStaticProps): JSX.Element => (
const Legality = (props: PostStaticProps): JSX.Element => (
<PostPage
currencies={currencies}
languages={languages}
langui={langui}
post={post}
{...props}
returnHref="/about-us/"
returnTitle={langui.about_us}
returnTitle={props.langui.about_us}
displayToc
displayLanguageSwitcher
/>

View File

@ -9,19 +9,11 @@ import {
* PAGE
*/
const SharingPolicy = ({
post,
langui,
languages,
currencies,
}: PostStaticProps): JSX.Element => (
const SharingPolicy = (props: PostStaticProps): JSX.Element => (
<PostPage
currencies={currencies}
languages={languages}
langui={langui}
post={post}
{...props}
returnHref="/about-us/"
returnTitle={langui.about_us}
returnTitle={props.langui.about_us}
displayToc
displayLanguageSwitcher
/>

View File

@ -1,18 +1,19 @@
import { GetStaticProps } from "next";
import { useMemo } from "react";
import { AppLayout } from "components/AppLayout";
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { NavOption } from "components/PanelComponents/NavOption";
import { PanelHeader } from "components/PanelComponents/PanelHeader";
import { SubPanel } from "components/Panels/SubPanel";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Icon } from "components/Ico";
import { getOpenGraph } from "helpers/openGraph";
/*
*
* PAGE
*/
interface Props extends AppStaticProps {}
interface Props extends AppStaticProps, AppLayoutRequired {}
const Archives = ({ langui, ...otherProps }: Props): JSX.Element => {
const subPanel = useMemo(
@ -28,14 +29,7 @@ const Archives = ({ langui, ...otherProps }: Props): JSX.Element => {
),
[langui]
);
return (
<AppLayout
navTitle={langui.archives}
subPanel={subPanel}
langui={langui}
{...otherProps}
/>
);
return <AppLayout subPanel={subPanel} langui={langui} {...otherProps} />;
};
export default Archives;
@ -45,8 +39,13 @@ export default Archives;
*/
export const getStaticProps: GetStaticProps = async (context) => {
const appStaticProps = await getAppStaticProps(context);
const props: Props = {
...(await getAppStaticProps(context)),
...appStaticProps,
openGraph: getOpenGraph(
appStaticProps.langui,
appStaticProps.langui.archives ?? "Archives"
),
};
return {
props: props,

View File

@ -1,6 +1,6 @@
import { GetStaticPaths, GetStaticPathsResult, GetStaticProps } from "next";
import { Fragment, useMemo } from "react";
import { AppLayout } from "components/AppLayout";
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { Switch } from "components/Inputs/Switch";
import { PanelHeader } from "components/PanelComponents/PanelHeader";
import {
@ -22,13 +22,14 @@ import { useMediaHoverable } from "hooks/useMediaQuery";
import { WithLabel } from "components/Inputs/WithLabel";
import { filterHasAttributes, isDefined } from "helpers/others";
import { useBoolean } from "hooks/useBoolean";
import { getOpenGraph } from "helpers/openGraph";
/*
*
* PAGE
*/
interface Props extends AppStaticProps {
interface Props extends AppStaticProps, AppLayoutRequired {
channel: NonNullable<
GetVideoChannelQuery["videoChannels"]
>["data"][number]["attributes"];
@ -91,7 +92,7 @@ const Channel = ({ langui, channel, ...otherProps }: Props): JSX.Element => {
thumbnailAspectRatio="16/9"
keepInfoVisible={keepInfoVisible}
metadata={{
release_date: video.attributes.published_date,
releaseDate: video.attributes.published_date,
views: video.attributes.views,
author: channel?.title,
position: "Top",
@ -116,7 +117,6 @@ const Channel = ({ langui, channel, ...otherProps }: Props): JSX.Element => {
return (
<AppLayout
navTitle={langui.archives}
subPanel={subPanel}
contentPanel={contentPanel}
langui={langui}
@ -140,9 +140,14 @@ export const getStaticProps: GetStaticProps = async (context) => {
: "",
});
if (!channel.videoChannels?.data[0].attributes) return { notFound: true };
const appStaticProps = await getAppStaticProps(context);
const props: Props = {
...(await getAppStaticProps(context)),
...appStaticProps,
channel: channel.videoChannels.data[0].attributes,
openGraph: getOpenGraph(
appStaticProps.langui,
channel.videoChannels.data[0].attributes.title
),
};
return {
props: props,

View File

@ -1,6 +1,6 @@
import { GetStaticProps } from "next";
import { useMemo, useState } from "react";
import { AppLayout } from "components/AppLayout";
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { SmartList } from "components/SmartList";
import { Icon } from "components/Ico";
import { Switch } from "components/Inputs/Switch";
@ -20,11 +20,12 @@ import { PreviewCard } from "components/PreviewCard";
import { GetVideosPreviewQuery } from "graphql/generated";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk";
import { prettyDate } from "helpers/formatters";
import { filterHasAttributes } from "helpers/others";
import { getVideoThumbnailURL } from "helpers/videos";
import { useMediaHoverable } from "hooks/useMediaQuery";
import { useBoolean } from "hooks/useBoolean";
import { getOpenGraph } from "helpers/openGraph";
import { compareDate } from "helpers/date";
/*
*
@ -40,7 +41,7 @@ const DEFAULT_FILTERS_STATE = {
* PAGE
*/
interface Props extends AppStaticProps {
interface Props extends AppStaticProps, AppLayoutRequired {
videos: NonNullable<GetVideosPreviewQuery["videos"]>["data"];
}
@ -73,7 +74,7 @@ const Videos = ({ langui, videos, ...otherProps }: Props): JSX.Element => {
<TextInput
className="mb-6 w-full"
placeholder={langui.search_title ?? undefined}
placeholder={langui.search_title ?? "Search title..."}
value={searchName}
onChange={setSearchName}
/>
@ -107,7 +108,7 @@ const Videos = ({ langui, videos, ...otherProps }: Props): JSX.Element => {
thumbnailForceAspectRatio
keepInfoVisible={keepInfoVisible}
metadata={{
release_date: item.attributes.published_date,
releaseDate: item.attributes.published_date,
views: item.attributes.views,
author: item.attributes.channel?.data?.attributes?.title,
position: "Top",
@ -132,7 +133,6 @@ const Videos = ({ langui, videos, ...otherProps }: Props): JSX.Element => {
);
return (
<AppLayout
navTitle={langui.archives}
subPanel={subPanel}
contentPanel={contentPanel}
langui={langui}
@ -152,19 +152,18 @@ export const getStaticProps: GetStaticProps = async (context) => {
const videos = await sdk.getVideosPreview();
if (!videos.videos) return { notFound: true };
videos.videos.data
.sort((a, b) => {
const dateA = a.attributes?.published_date
? prettyDate(a.attributes.published_date)
: "9999";
const dateB = b.attributes?.published_date
? prettyDate(b.attributes.published_date)
: "9999";
return dateA.localeCompare(dateB);
})
.sort((a, b) =>
compareDate(a.attributes?.published_date, b.attributes?.published_date)
)
.reverse();
const appStaticProps = await getAppStaticProps(context);
const props: Props = {
...(await getAppStaticProps(context)),
...appStaticProps,
videos: videos.videos.data,
openGraph: getOpenGraph(
appStaticProps.langui,
appStaticProps.langui.videos ?? "Videos"
),
};
return {
props: props,

View File

@ -1,6 +1,7 @@
import { GetStaticPaths, GetStaticPathsResult, GetStaticProps } from "next";
import { useMemo } from "react";
import { AppLayout } from "components/AppLayout";
import { useRouter } from "next/router";
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { HorizontalLine } from "components/HorizontalLine";
import { Ico, Icon } from "components/Ico";
import { Button } from "components/Inputs/Button";
@ -23,13 +24,14 @@ import { prettyDate, prettyShortenNumber } from "helpers/formatters";
import { filterHasAttributes, isDefined } from "helpers/others";
import { getVideoFile } from "helpers/videos";
import { useMediaMobile } from "hooks/useMediaQuery";
import { getOpenGraph } from "helpers/openGraph";
/*
*
* PAGE
*/
interface Props extends AppStaticProps {
interface Props extends AppStaticProps, AppLayoutRequired {
video: NonNullable<
NonNullable<GetVideoQuery["videos"]>["data"][number]["attributes"]
>;
@ -38,6 +40,8 @@ interface Props extends AppStaticProps {
const Video = ({ langui, video, ...otherProps }: Props): JSX.Element => {
const isMobile = useMediaMobile();
const { setSubPanelOpen } = useAppLayout();
const router = useRouter();
const subPanel = useMemo(
() => (
<SubPanel>
@ -118,7 +122,7 @@ const Video = ({ langui, video, ...otherProps }: Props): JSX.Element => {
icon={Icon.Event}
className="mr-1 translate-y-[.15em] !text-base"
/>
{prettyDate(video.published_date)}
{prettyDate(video.published_date, router.locale)}
</p>
<p>
<Ico
@ -184,6 +188,7 @@ const Video = ({ langui, video, ...otherProps }: Props): JSX.Element => {
[
isMobile,
langui,
router.locale,
video.channel?.data?.attributes,
video.description,
video.gone,
@ -198,7 +203,6 @@ const Video = ({ langui, video, ...otherProps }: Props): JSX.Element => {
return (
<AppLayout
navTitle={langui.archives}
subPanel={subPanel}
contentPanel={contentPanel}
langui={langui}
@ -222,9 +226,14 @@ export const getStaticProps: GetStaticProps = async (context) => {
: "",
});
if (!videos.videos?.data[0]?.attributes) return { notFound: true };
const appStaticProps = await getAppStaticProps(context);
const props: Props = {
...(await getAppStaticProps(context)),
...appStaticProps,
video: videos.videos.data[0].attributes,
openGraph: getOpenGraph(
appStaticProps.langui,
videos.videos.data[0].attributes.title
),
};
return {
props: props,

View File

@ -4,7 +4,7 @@ import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk";
import { isDefined, filterHasAttributes } from "helpers/others";
import { ChronicleWithTranslations } from "helpers/types";
import { AppLayout } from "components/AppLayout";
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { useSmartLanguage } from "hooks/useSmartLanguage";
import { ContentPanel } from "components/Panels/ContentPanel";
import { Markdawn } from "components/Markdown/Markdawn";
@ -12,20 +12,26 @@ import { SubPanel } from "components/Panels/SubPanel";
import { ThumbnailHeader } from "components/ThumbnailHeader";
import { HorizontalLine } from "components/HorizontalLine";
import { GetChroniclesChaptersQuery } from "graphql/generated";
import { prettySlug } from "helpers/formatters";
import { prettyInlineTitle, prettySlug } from "helpers/formatters";
import {
ReturnButton,
ReturnButtonType,
} from "components/PanelComponents/ReturnButton";
import { TranslatedChroniclesList } from "components/Translated";
import { Icon } from "components/Ico";
import { getOpenGraph } from "helpers/openGraph";
import {
getDefaultPreferredLanguages,
staticSmartLanguage,
} from "helpers/locales";
import { getDescription } from "helpers/description";
/*
*
* PAGE
*/
interface Props extends AppStaticProps {
interface Props extends AppStaticProps, AppLayoutRequired {
chronicle: ChronicleWithTranslations;
chapters: NonNullable<
GetChroniclesChaptersQuery["chroniclesChapters"]
@ -191,7 +197,6 @@ const Chronicle = ({
return (
<AppLayout
navTitle={langui.chronicles}
contentPanel={contentPanel}
subPanel={subPanel}
langui={langui}
@ -220,15 +225,92 @@ export const getStaticProps: GetStaticProps = async (context) => {
});
const chronicles = await sdk.getChroniclesChapters();
if (
!chronicle.chronicles?.data[0].attributes?.translations ||
!chronicle.chronicles?.data[0]?.attributes?.translations ||
!chronicles.chroniclesChapters?.data
)
return { notFound: true };
const appStaticProps = await getAppStaticProps(context);
const { title, description } = (() => {
if (context.locale && context.locales) {
if (
chronicle.chronicles.data[0].attributes.contents?.data[0]?.attributes
?.translations
) {
const selectedContentTranslation = staticSmartLanguage({
items:
chronicle.chronicles.data[0].attributes.contents.data[0].attributes
.translations,
languageExtractor: (item) => item.language?.data?.attributes?.code,
preferredLanguages: getDefaultPreferredLanguages(
context.locale,
context.locales
),
});
if (selectedContentTranslation) {
return {
title: prettyInlineTitle(
selectedContentTranslation.pre_title,
selectedContentTranslation.title,
selectedContentTranslation.subtitle
),
description: getDescription(
selectedContentTranslation.description,
{
[appStaticProps.langui.type ?? "Type"]: [
chronicle.chronicles.data[0].attributes.contents.data[0]
.attributes.type?.data?.attributes?.titles?.[0]?.title,
],
[appStaticProps.langui.categories ?? "Categories"]:
filterHasAttributes(
chronicle.chronicles.data[0].attributes.contents.data[0]
.attributes.categories?.data,
["attributes"] as const
).map((category) => category.attributes.short),
}
),
};
}
} else {
const selectedTranslation = staticSmartLanguage({
items: chronicle.chronicles.data[0].attributes.translations,
languageExtractor: (item) => item.language?.data?.attributes?.code,
preferredLanguages: getDefaultPreferredLanguages(
context.locale,
context.locales
),
});
if (selectedTranslation) {
return {
title: selectedTranslation.title,
description: selectedTranslation.summary,
};
}
}
}
return {
title: prettySlug(chronicle.chronicles.data[0].attributes.slug),
description: undefined,
};
})();
const thumbnail =
chronicle.chronicles.data[0].attributes.translations.length === 0
? chronicle.chronicles.data[0].attributes.contents?.data[0]?.attributes
?.thumbnail?.data?.attributes
: undefined;
const props: Props = {
...(await getAppStaticProps(context)),
...appStaticProps,
chronicle: chronicle.chronicles.data[0]
.attributes as ChronicleWithTranslations,
chapters: chronicles.chroniclesChapters.data,
openGraph: getOpenGraph(
appStaticProps.langui,
title,
description,
thumbnail
),
};
return {
props: props,

View File

@ -1,6 +1,6 @@
import { GetStaticProps } from "next";
import { useMemo } from "react";
import { AppLayout } from "components/AppLayout";
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { PanelHeader } from "components/PanelComponents/PanelHeader";
import { SubPanel } from "components/Panels/SubPanel";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
@ -10,13 +10,14 @@ import { GetChroniclesChaptersQuery } from "graphql/generated";
import { filterHasAttributes } from "helpers/others";
import { prettySlug } from "helpers/formatters";
import { TranslatedChroniclesList } from "components/Translated";
import { getOpenGraph } from "helpers/openGraph";
/*
*
* PAGE
*/
interface Props extends AppStaticProps {
interface Props extends AppStaticProps, AppLayoutRequired {
chapters: NonNullable<
GetChroniclesChaptersQuery["chroniclesChapters"]
>["data"];
@ -58,14 +59,7 @@ const Chronicles = ({
[chapters, langui]
);
return (
<AppLayout
navTitle={langui.chronicles}
subPanel={subPanel}
langui={langui}
{...otherProps}
/>
);
return <AppLayout subPanel={subPanel} langui={langui} {...otherProps} />;
};
export default Chronicles;
@ -78,9 +72,14 @@ export const getStaticProps: GetStaticProps = async (context) => {
const sdk = getReadySdk();
const chronicles = await sdk.getChroniclesChapters();
if (!chronicles.chroniclesChapters?.data) return { notFound: true };
const appStaticProps = await getAppStaticProps(context);
const props: Props = {
...(await getAppStaticProps(context)),
...appStaticProps,
chapters: chronicles.chroniclesChapters.data,
openGraph: getOpenGraph(
appStaticProps.langui,
appStaticProps.langui.chronicles ?? "Chronicles"
),
};
return {
props: props,

View File

@ -1,6 +1,6 @@
import { GetStaticPaths, GetStaticPathsResult, GetStaticProps } from "next";
import { Fragment, useCallback, useMemo } from "react";
import { AppLayout } from "components/AppLayout";
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { Chip } from "components/Chip";
import { HorizontalLine } from "components/HorizontalLine";
import { PreviewCardCTAs } from "components/Library/PreviewCardCTAs";
@ -17,7 +17,6 @@ import { ThumbnailHeader } from "components/ThumbnailHeader";
import { ToolTip } from "components/ToolTip";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk";
import { getDescription } from "helpers/description";
import {
prettyInlineTitle,
prettyLanguage,
@ -35,13 +34,19 @@ import { useMediaMobile } from "hooks/useMediaQuery";
import { AnchorIds, useScrollTopOnChange } from "hooks/useScrollTopOnChange";
import { useSmartLanguage } from "hooks/useSmartLanguage";
import { TranslatedPreviewLine } from "components/Translated";
import { getOpenGraph } from "helpers/openGraph";
import {
getDefaultPreferredLanguages,
staticSmartLanguage,
} from "helpers/locales";
import { getDescription } from "helpers/description";
/*
*
* PAGE
*/
interface Props extends AppStaticProps {
interface Props extends AppStaticProps, AppLayoutRequired {
content: ContentWithTranslations;
}
@ -260,7 +265,7 @@ const Content = ({
).map((category) => category.attributes.short)}
metadata={{
currencies: currencies,
release_date: libraryItem.attributes.release_date,
releaseDate: libraryItem.attributes.release_date,
price: libraryItem.attributes.price,
position: "Bottom",
}}
@ -457,22 +462,6 @@ const Content = ({
return (
<AppLayout
navTitle={
selectedTranslation
? prettyInlineTitle(
selectedTranslation.pre_title,
selectedTranslation.title,
selectedTranslation.subtitle
)
: prettySlug(content.slug)
}
description={getDescription({
langui: langui,
description: selectedTranslation?.description,
type: content.type,
categories: content.categories,
})}
thumbnail={content.thumbnail?.data?.attributes ?? undefined}
contentPanel={contentPanel}
subPanel={subPanel}
currencies={currencies}
@ -500,9 +489,57 @@ export const getStaticProps: GetStaticProps = async (context) => {
if (!content.contents?.data[0]?.attributes?.translations) {
return { notFound: true };
}
const appStaticProps = await getAppStaticProps(context);
const { title, description } = (() => {
if (context.locale && context.locales) {
const selectedTranslation = staticSmartLanguage({
items: content.contents.data[0].attributes.translations,
languageExtractor: (item) => item.language?.data?.attributes?.code,
preferredLanguages: getDefaultPreferredLanguages(
context.locale,
context.locales
),
});
if (selectedTranslation) {
return {
title: prettyInlineTitle(
selectedTranslation.pre_title,
selectedTranslation.title,
selectedTranslation.subtitle
),
description: getDescription(selectedTranslation.description, {
[appStaticProps.langui.type ?? "Type"]: [
content.contents.data[0].attributes.type?.data?.attributes
?.titles?.[0]?.title,
],
[appStaticProps.langui.categories ?? "Categories"]:
filterHasAttributes(
content.contents.data[0].attributes.categories?.data,
["attributes"] as const
).map((category) => category.attributes.short),
}),
};
}
}
return {
title: prettySlug(content.contents.data[0].attributes.slug),
description: undefined,
};
})();
const thumbnail =
content.contents.data[0].attributes.thumbnail?.data?.attributes;
const props: Props = {
...(await getAppStaticProps(context)),
...appStaticProps,
content: content.contents.data[0].attributes as ContentWithTranslations,
openGraph: getOpenGraph(
appStaticProps.langui,
title,
description,
thumbnail
),
};
return {
props: props,

View File

@ -1,6 +1,6 @@
import { GetStaticProps } from "next";
import { useState, useMemo, useCallback } from "react";
import { AppLayout } from "components/AppLayout";
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { Select } from "components/Inputs/Select";
import { Switch } from "components/Inputs/Switch";
import { PanelHeader } from "components/PanelComponents/PanelHeader";
@ -23,6 +23,7 @@ import { SmartList } from "components/SmartList";
import { SelectiveNonNullable } from "helpers/types/SelectiveNonNullable";
import { useBoolean } from "hooks/useBoolean";
import { TranslatedPreviewCard } from "components/Translated";
import { getOpenGraph } from "helpers/openGraph";
/*
*
@ -41,7 +42,7 @@ const DEFAULT_FILTERS_STATE = {
* PAGE
*/
interface Props extends AppStaticProps {
interface Props extends AppStaticProps, AppLayoutRequired {
contents: NonNullable<GetContentsQuery["contents"]>["data"];
}
@ -164,7 +165,7 @@ const Contents = ({
<TextInput
className="mb-6 w-full"
placeholder={langui.search_title ?? undefined}
placeholder={langui.search_title ?? "Search..."}
value={searchName}
onChange={setSearchName}
/>
@ -174,7 +175,7 @@ const Contents = ({
input={
<Select
className="w-full"
options={[langui.category ?? "", langui.type ?? ""]}
options={[langui.category ?? "Category", langui.type ?? "Type"]}
value={groupingMethod}
onChange={setGroupingMethod}
allowEmpty
@ -317,7 +318,6 @@ const Contents = ({
return (
<AppLayout
navTitle={langui.contents}
subPanel={subPanel}
contentPanel={contentPanel}
subPanelIcon={Icon.Search}
@ -346,9 +346,14 @@ export const getStaticProps: GetStaticProps = async (context) => {
return titleA.localeCompare(titleB);
});
const appStaticProps = await getAppStaticProps(context);
const props: Props = {
...(await getAppStaticProps(context)),
...appStaticProps,
contents: contents.contents.data,
openGraph: getOpenGraph(
appStaticProps.langui,
appStaticProps.langui.contents ?? "Contents"
),
};
return {
props: props,

View File

@ -1,6 +1,6 @@
import { GetStaticProps } from "next";
import { useMemo } from "react";
import { AppLayout } from "components/AppLayout";
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { Chip } from "components/Chip";
import { Button } from "components/Inputs/Button";
import {
@ -13,13 +13,14 @@ import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk";
import { filterDefined, filterHasAttributes } from "helpers/others";
import { Report, Severity } from "helpers/types/Report";
import { getOpenGraph } from "helpers/openGraph";
/*
*
* PAGE
*/
interface Props extends AppStaticProps {
interface Props extends AppStaticProps, AppLayoutRequired {
contents: DevGetContentsQuery;
}
@ -87,13 +88,7 @@ const CheckupContents = ({ contents, ...otherProps }: Props): JSX.Element => {
[testReport.lines, testReport.title]
);
return (
<AppLayout
navTitle={"Checkup"}
contentPanel={contentPanel}
{...otherProps}
/>
);
return <AppLayout contentPanel={contentPanel} {...otherProps} />;
};
export default CheckupContents;
@ -105,9 +100,11 @@ export default CheckupContents;
export const getStaticProps: GetStaticProps = async (context) => {
const sdk = getReadySdk();
const contents = await sdk.devGetContents();
const appStaticProps = await getAppStaticProps(context);
const props: Props = {
...(await getAppStaticProps(context)),
...appStaticProps,
contents: contents,
openGraph: getOpenGraph(appStaticProps.langui, "Checkup Contents"),
};
return {
props: props,

View File

@ -1,6 +1,6 @@
import { GetStaticProps } from "next";
import { useMemo } from "react";
import { AppLayout } from "components/AppLayout";
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { Chip } from "components/Chip";
import { Button } from "components/Inputs/Button";
import {
@ -15,13 +15,14 @@ import {
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk";
import { Report, Severity } from "helpers/types/Report";
import { getOpenGraph } from "helpers/openGraph";
/*
*
* PAGE
*/
interface Props extends AppStaticProps {
interface Props extends AppStaticProps, AppLayoutRequired {
libraryItems: DevGetLibraryItemsQuery;
}
@ -92,13 +93,7 @@ const CheckupLibraryItems = ({
[testReport.lines, testReport.title]
);
return (
<AppLayout
navTitle={"Checkup"}
contentPanel={contentPanel}
{...otherProps}
/>
);
return <AppLayout contentPanel={contentPanel} {...otherProps} />;
};
export default CheckupLibraryItems;
@ -110,9 +105,11 @@ export default CheckupLibraryItems;
export const getStaticProps: GetStaticProps = async (context) => {
const sdk = getReadySdk();
const libraryItems = await sdk.devGetLibraryItems();
const appStaticProps = await getAppStaticProps(context);
const props: Props = {
...(await getAppStaticProps(context)),
...appStaticProps,
libraryItems: libraryItems,
openGraph: getOpenGraph(appStaticProps.langui, "Checkup Library Items"),
};
return {
props: props,

View File

@ -1,7 +1,7 @@
import { GetStaticProps } from "next";
import { useCallback, useMemo, useRef, useState } from "react";
import TurndownService from "turndown";
import { AppLayout } from "components/AppLayout";
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { Button } from "components/Inputs/Button";
import { Markdawn, TableOfContents } from "components/Markdown/Markdawn";
import {
@ -12,13 +12,14 @@ import { Popup } from "components/Popup";
import { ToolTip } from "components/ToolTip";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Icon } from "components/Ico";
import { getOpenGraph } from "helpers/openGraph";
/*
*
* PAGE
*/
interface Props extends AppStaticProps {}
interface Props extends AppStaticProps, AppLayoutRequired {}
const Editor = ({ langui, ...otherProps }: Props): JSX.Element => {
const handleInput = useCallback((text: string) => {
@ -465,12 +466,7 @@ const Editor = ({ langui, ...otherProps }: Props): JSX.Element => {
);
return (
<AppLayout
navTitle="Markdawn Editor"
contentPanel={contentPanel}
langui={langui}
{...otherProps}
/>
<AppLayout contentPanel={contentPanel} langui={langui} {...otherProps} />
);
};
export default Editor;
@ -481,8 +477,10 @@ export default Editor;
*/
export const getStaticProps: GetStaticProps = async (context) => {
const appStaticProps = await getAppStaticProps(context);
const props: Props = {
...(await getAppStaticProps(context)),
...appStaticProps,
openGraph: getOpenGraph(appStaticProps.langui, "Markdawn Editor"),
};
return {
props: props,

View File

@ -1,6 +1,6 @@
import { GetStaticProps } from "next";
import { useCallback, useMemo, useRef, useState } from "react";
import { AppLayout } from "components/AppLayout";
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { Button } from "components/Inputs/Button";
import { ButtonGroup } from "components/Inputs/ButtonGroup";
import {
@ -9,6 +9,7 @@ import {
} from "components/Panels/ContentPanel";
import { ToolTip } from "components/ToolTip";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getOpenGraph } from "helpers/openGraph";
/*
*
@ -22,7 +23,7 @@ const SIZE_MULTIPLIER = 1000;
* PAGE
*/
interface Props extends AppStaticProps {}
interface Props extends AppStaticProps, AppLayoutRequired {}
const replaceSelection = (
text: string,
@ -566,7 +567,6 @@ const Transcript = (props: Props): JSX.Element => {
return (
<AppLayout
navTitle="Transcript"
contentPanel={contentPanel}
{...props}
contentPanelScroolbar={false}
@ -581,8 +581,13 @@ export default Transcript;
*/
export const getStaticProps: GetStaticProps = async (context) => {
const appStaticProps = await getAppStaticProps(context);
const props: Props = {
...(await getAppStaticProps(context)),
...appStaticProps,
openGraph: getOpenGraph(
appStaticProps.langui,
"Japanese Transcription Tool"
),
};
return {
props: props,

View File

@ -9,17 +9,9 @@ import {
* PAGE
*/
const Home = ({
post,
langui,
languages,
currencies,
}: PostStaticProps): JSX.Element => (
const Home = (props: PostStaticProps): JSX.Element => (
<PostPage
currencies={currencies}
languages={languages}
langui={langui}
post={post}
{...props}
prependBody={
<div className="grid w-full place-content-center place-items-center gap-5 text-center">
<div

View File

@ -1,6 +1,7 @@
import { Fragment, useCallback, useMemo } from "react";
import { GetStaticPaths, GetStaticPathsResult, GetStaticProps } from "next";
import { AppLayout } from "components/AppLayout";
import { useRouter } from "next/router";
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { Chip } from "components/Chip";
import { Img } from "components/Img";
import { Button } from "components/Inputs/Button";
@ -52,15 +53,16 @@ import { WithLabel } from "components/Inputs/WithLabel";
import { Ico, Icon } from "components/Ico";
import { cJoin, cIf } from "helpers/className";
import { useSmartLanguage } from "hooks/useSmartLanguage";
import { getDescription } from "helpers/description";
import { useBoolean } from "hooks/useBoolean";
import { getOpenGraph } from "helpers/openGraph";
import { getDescription } from "helpers/description";
/*
*
* PAGE
*/
interface Props extends AppStaticProps {
interface Props extends AppStaticProps, AppLayoutRequired {
item: NonNullable<
NonNullable<
GetLibraryItemQuery["libraryItems"]
@ -81,6 +83,7 @@ const LibrarySlug = ({
}: Props): JSX.Element => {
const { currency } = useAppLayout();
const hoverable = useMediaHoverable();
const router = useRouter();
const [openLightBox, LightBox] = useLightBox();
const { state: keepInfoVisible, toggleState: toggleKeepInfoVisible } =
useBoolean(false);
@ -300,7 +303,7 @@ const LibrarySlug = ({
{item.release_date && (
<div className="grid place-content-start place-items-center">
<h3 className="text-xl">{langui.release_date}</h3>
<p>{prettyDate(item.release_date)}</p>
<p>{prettyDate(item.release_date, router.locale)}</p>
</div>
)}
@ -483,7 +486,7 @@ const LibrarySlug = ({
)}
metadata={{
currencies: currencies,
release_date: subitem.attributes.release_date,
releaseDate: subitem.attributes.release_date,
price: subitem.attributes.price,
position: "Bottom",
}}
@ -569,8 +572,23 @@ const LibrarySlug = ({
[
LightBox,
langui,
item,
item.thumbnail?.data?.attributes,
item.subitem_of?.data,
item.title,
item.subtitle,
item.metadata,
item.descriptions,
item.urls,
item.gallery,
item.release_date,
item.price,
item.categories,
item.size,
item.subitems,
item.contents,
item.slug,
itemId,
router.locale,
currencies,
currency,
isVariantSet,
@ -585,14 +603,8 @@ const LibrarySlug = ({
return (
<AppLayout
navTitle={prettyInlineTitle("", item.title, item.subtitle)}
contentPanel={contentPanel}
subPanel={subPanel}
thumbnail={item.thumbnail?.data?.attributes ?? undefined}
description={getDescription({
langui,
description: item.descriptions?.[0]?.description,
})}
currencies={currencies}
languages={languages}
langui={langui}
@ -618,10 +630,42 @@ export const getStaticProps: GetStaticProps = async (context) => {
});
if (!item.libraryItems?.data[0]?.attributes) return { notFound: true };
sortRangedContent(item.libraryItems.data[0].attributes.contents);
const appStaticProps = await getAppStaticProps(context);
const { title, thumbnail } = item.libraryItems.data[0].attributes;
const description = getDescription(
item.libraryItems.data[0].attributes.descriptions?.[0]?.description,
{
[appStaticProps.langui.categories ?? "Categories"]: filterHasAttributes(
item.libraryItems.data[0].attributes.categories?.data,
["attributes.short"]
).map((category) => category.attributes.short),
[appStaticProps.langui.type ?? "Type"]: item.libraryItems.data[0]
.attributes.metadata?.[0]
? [prettyItemSubType(item.libraryItems.data[0].attributes.metadata[0])]
: [],
[appStaticProps.langui.release_date ?? "Release date"]: [
item.libraryItems.data[0].attributes.release_date
? prettyDate(
item.libraryItems.data[0].attributes.release_date,
context.locale
)
: undefined,
],
}
);
const props: Props = {
...(await getAppStaticProps(context)),
...appStaticProps,
item: item.libraryItems.data[0].attributes,
itemId: item.libraryItems.data[0].id,
openGraph: getOpenGraph(
appStaticProps.langui,
title,
description,
thumbnail?.data?.attributes
),
};
return {
props: props,

View File

@ -1,6 +1,6 @@
import { GetStaticPaths, GetStaticPathsResult, GetStaticProps } from "next";
import { Fragment, useMemo } from "react";
import { AppLayout } from "components/AppLayout";
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { ScanSetCover } from "components/Library/ScanSetCover";
import {
ReturnButton,
@ -30,13 +30,14 @@ import { PreviewCardCTAs } from "components/Library/PreviewCardCTAs";
import { PreviewCard } from "components/PreviewCard";
import { HorizontalLine } from "components/HorizontalLine";
import { TranslatedNavOption, TranslatedScanSet } from "components/Translated";
import { getOpenGraph } from "helpers/openGraph";
/*
*
* PAGE
*/
interface Props extends AppStaticProps {
interface Props extends AppStaticProps, AppLayoutRequired {
item: NonNullable<
NonNullable<
GetLibraryItemScansQuery["libraryItems"]
@ -87,7 +88,7 @@ const LibrarySlug = ({
] as const).map((category) => category.attributes.short)}
metadata={{
currencies: currencies,
release_date: item.release_date,
releaseDate: item.release_date,
price: item.price,
position: "Bottom",
}}
@ -232,10 +233,8 @@ const LibrarySlug = ({
return (
<AppLayout
navTitle={prettyInlineTitle("", item.title, item.subtitle)}
contentPanel={contentPanel}
subPanel={subPanel}
thumbnail={item.thumbnail?.data?.attributes ?? undefined}
languages={languages}
langui={langui}
currencies={currencies}
@ -262,10 +261,17 @@ export const getStaticProps: GetStaticProps = async (context) => {
if (!item.libraryItems?.data[0]?.attributes || !item.libraryItems.data[0]?.id)
return { notFound: true };
sortRangedContent(item.libraryItems.data[0].attributes.contents);
const appStaticProps = await getAppStaticProps(context);
const props: Props = {
...(await getAppStaticProps(context)),
...appStaticProps,
item: item.libraryItems.data[0].attributes,
itemId: item.libraryItems.data[0].id,
openGraph: getOpenGraph(
appStaticProps.langui,
item.libraryItems.data[0].attributes.title,
undefined,
item.libraryItems.data[0].attributes.thumbnail?.data?.attributes
),
};
return {
props: props,

View File

@ -1,6 +1,6 @@
import { GetStaticProps } from "next";
import { useState, useMemo, useCallback } from "react";
import { AppLayout } from "components/AppLayout";
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { Select } from "components/Inputs/Select";
import { Switch } from "components/Inputs/Switch";
import { PanelHeader } from "components/PanelComponents/PanelHeader";
@ -12,11 +12,7 @@ import { SubPanel } from "components/Panels/SubPanel";
import { GetLibraryItemsPreviewQuery } from "graphql/generated";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk";
import {
prettyDate,
prettyInlineTitle,
prettyItemSubType,
} from "helpers/formatters";
import { prettyInlineTitle, prettyItemSubType } from "helpers/formatters";
import { LibraryItemUserStatus } from "helpers/types";
import { Icon } from "components/Ico";
import { WithLabel } from "components/Inputs/WithLabel";
@ -33,6 +29,8 @@ import { convertPrice } from "helpers/numbers";
import { SmartList } from "components/SmartList";
import { SelectiveNonNullable } from "helpers/types/SelectiveNonNullable";
import { useBoolean } from "hooks/useBoolean";
import { getOpenGraph } from "helpers/openGraph";
import { compareDate } from "helpers/date";
/*
*
@ -55,7 +53,7 @@ const DEFAULT_FILTERS_STATE = {
* PAGE
*/
interface Props extends AppStaticProps {
interface Props extends AppStaticProps, AppLayoutRequired {
items: NonNullable<GetLibraryItemsPreviewQuery["libraryItems"]>["data"];
}
@ -174,13 +172,10 @@ const Library = ({
return priceA - priceB;
}
case 2: {
const dateA = a.attributes.release_date
? prettyDate(a.attributes.release_date)
: "9999";
const dateB = b.attributes.release_date
? prettyDate(b.attributes.release_date)
: "9999";
return dateA.localeCompare(dateB);
return compareDate(
a.attributes.release_date,
b.attributes.release_date
);
}
default:
return 0;
@ -268,7 +263,7 @@ const Library = ({
<TextInput
className="mb-6 w-full"
placeholder={langui.search_title ?? undefined}
placeholder={langui.search_title ?? "Search..."}
value={searchName}
onChange={setSearchName}
/>
@ -433,7 +428,7 @@ const Library = ({
)}
metadata={{
currencies: currencies,
release_date: item.attributes.release_date,
releaseDate: item.attributes.release_date,
price: item.attributes.price,
position: "Bottom",
}}
@ -474,7 +469,6 @@ const Library = ({
return (
<AppLayout
navTitle={langui.library}
subPanel={subPanel}
contentPanel={contentPanel}
subPanelIcon={Icon.Search}
@ -497,9 +491,14 @@ export const getStaticProps: GetStaticProps = async (context) => {
language_code: context.locale ?? "en",
});
if (!items.libraryItems?.data) return { notFound: true };
const appStaticProps = await getAppStaticProps(context);
const props: Props = {
...(await getAppStaticProps(context)),
...appStaticProps,
items: items.libraryItems.data,
openGraph: getOpenGraph(
appStaticProps.langui,
appStaticProps.langui.library ?? "Library"
),
};
return {
props: props,

View File

@ -1,19 +1,19 @@
import { GetStaticProps } from "next";
import { AppLayout } from "components/AppLayout";
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { PanelHeader } from "components/PanelComponents/PanelHeader";
import { SubPanel } from "components/Panels/SubPanel";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Icon } from "components/Ico";
import { getOpenGraph } from "helpers/openGraph";
/*
*
* PAGE
*/
interface Props extends AppStaticProps {}
interface Props extends AppStaticProps, AppLayoutRequired {}
const Merch = ({ langui, ...otherProps }: Props): JSX.Element => (
<AppLayout
navTitle={langui.merch}
subPanel={
<SubPanel>
<PanelHeader
@ -35,8 +35,13 @@ export default Merch;
*/
export const getStaticProps: GetStaticProps = async (context) => {
const appStaticProps = await getAppStaticProps(context);
const props: Props = {
...(await getAppStaticProps(context)),
...appStaticProps,
openGraph: getOpenGraph(
appStaticProps.langui,
appStaticProps.langui.merch ?? "Merch"
),
};
return {
props: props,

View File

@ -1,6 +1,6 @@
import { GetStaticProps } from "next";
import { useMemo, useState } from "react";
import { AppLayout } from "components/AppLayout";
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { Switch } from "components/Inputs/Switch";
import { PanelHeader } from "components/PanelComponents/PanelHeader";
import {
@ -11,7 +11,7 @@ import { SubPanel } from "components/Panels/SubPanel";
import { GetPostsPreviewQuery } from "graphql/generated";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk";
import { prettyDate, prettySlug } from "helpers/formatters";
import { prettySlug } from "helpers/formatters";
import { Icon } from "components/Ico";
import { WithLabel } from "components/Inputs/WithLabel";
import { TextInput } from "components/Inputs/TextInput";
@ -21,6 +21,8 @@ import { filterHasAttributes } from "helpers/others";
import { SmartList } from "components/SmartList";
import { useBoolean } from "hooks/useBoolean";
import { TranslatedPreviewCard } from "components/Translated";
import { getOpenGraph } from "helpers/openGraph";
import { compareDate } from "helpers/date";
/*
*
@ -37,7 +39,7 @@ const DEFAULT_FILTERS_STATE = {
* PAGE
*/
interface Props extends AppStaticProps {
interface Props extends AppStaticProps, AppLayoutRequired {
posts: NonNullable<GetPostsPreviewQuery["posts"]>["data"];
}
@ -63,7 +65,7 @@ const News = ({ langui, posts, ...otherProps }: Props): JSX.Element => {
<TextInput
className="mb-6 w-full"
placeholder={langui.search_title ?? undefined}
placeholder={langui.search_title ?? "Search..."}
value={searchName}
onChange={setSearchName}
/>
@ -124,7 +126,8 @@ const News = ({ langui, posts, ...otherProps }: Props): JSX.Element => {
)}
keepInfoVisible={keepInfoVisible}
metadata={{
release_date: post.attributes.date,
releaseDate: post.attributes.date,
releaseDateFormat: "long",
position: "Top",
}}
/>
@ -144,7 +147,6 @@ const News = ({ langui, posts, ...otherProps }: Props): JSX.Element => {
return (
<AppLayout
navTitle={langui.news}
subPanel={subPanel}
contentPanel={contentPanel}
subPanelIcon={Icon.Search}
@ -164,9 +166,14 @@ export const getStaticProps: GetStaticProps = async (context) => {
const sdk = getReadySdk();
const posts = await sdk.getPostsPreview();
if (!posts.posts) return { notFound: true };
const appStaticProps = await getAppStaticProps(context);
const props: Props = {
...(await getAppStaticProps(context)),
...appStaticProps,
posts: sortPosts(posts.posts.data),
openGraph: getOpenGraph(
appStaticProps.langui,
appStaticProps.langui.news ?? "News"
),
};
return {
props: props,
@ -180,9 +187,5 @@ export const getStaticProps: GetStaticProps = async (context) => {
const sortPosts = (posts: Props["posts"]): Props["posts"] =>
posts
.sort((a, b) => {
const dateA = a.attributes?.date ? prettyDate(a.attributes.date) : "9999";
const dateB = b.attributes?.date ? prettyDate(b.attributes.date) : "9999";
return dateA.localeCompare(dateB);
})
.sort((a, b) => compareDate(a.attributes?.date, b.attributes?.date))
.reverse();

View File

@ -1,6 +1,6 @@
import { useCallback, useMemo } from "react";
import { GetStaticPaths, GetStaticPathsResult, GetStaticProps } from "next";
import { AppLayout } from "components/AppLayout";
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { Chip } from "components/Chip";
import { HorizontalLine } from "components/HorizontalLine";
import { Img } from "components/Img";
@ -26,13 +26,19 @@ import { useSmartLanguage } from "hooks/useSmartLanguage";
import { prettySlug } from "helpers/formatters";
import { useLightBox } from "hooks/useLightBox";
import { getAssetURL, ImageQuality } from "helpers/img";
import { getOpenGraph } from "helpers/openGraph";
import {
getDefaultPreferredLanguages,
staticSmartLanguage,
} from "helpers/locales";
import { getDescription } from "helpers/description";
/*
*
* PAGE
*/
interface Props extends AppStaticProps {
interface Props extends AppStaticProps, AppLayoutRequired {
page: WikiPageWithTranslations;
}
@ -217,7 +223,6 @@ const WikiPage = ({
return (
<AppLayout
navTitle={langui.news}
subPanel={subPanel}
contentPanel={contentPanel}
languages={languages}
@ -245,9 +250,58 @@ export const getStaticProps: GetStaticProps = async (context) => {
});
if (!page.wikiPages?.data[0].attributes?.translations)
return { notFound: true };
const appStaticProps = await getAppStaticProps(context);
const { title, description } = (() => {
const chipsGroups = {
[appStaticProps.langui.tags ?? "Tags"]: filterHasAttributes(
page.wikiPages.data[0].attributes.tags?.data,
["attributes"] as const
).map(
(tag) =>
tag.attributes.titles?.[0]?.title ?? prettySlug(tag.attributes.slug)
),
[appStaticProps.langui.categories ?? "Categories"]: filterHasAttributes(
page.wikiPages.data[0].attributes.categories?.data,
["attributes"] as const
).map((category) => category.attributes.short),
};
if (context.locale && context.locales) {
const selectedTranslation = staticSmartLanguage({
items: page.wikiPages.data[0].attributes.translations,
languageExtractor: (item) => item.language?.data?.attributes?.code,
preferredLanguages: getDefaultPreferredLanguages(
context.locale,
context.locales
),
});
if (selectedTranslation) {
return {
title: selectedTranslation.title,
description: getDescription(selectedTranslation.summary, chipsGroups),
};
}
}
return {
title: prettySlug(page.wikiPages.data[0].attributes.slug),
description: getDescription(undefined, chipsGroups),
};
})();
const thumbnail =
page.wikiPages.data[0].attributes.thumbnail?.data?.attributes;
const props: Props = {
...(await getAppStaticProps(context)),
...appStaticProps,
page: page.wikiPages.data[0].attributes as WikiPageWithTranslations,
openGraph: getOpenGraph(
appStaticProps.langui,
title,
description,
thumbnail
),
};
return {
props: props,

View File

@ -1,6 +1,6 @@
import { GetStaticProps } from "next";
import { Fragment, useMemo } from "react";
import { AppLayout } from "components/AppLayout";
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { InsetBox } from "components/InsetBox";
import { NavOption } from "components/PanelComponents/NavOption";
import {
@ -15,13 +15,14 @@ import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk";
import { prettySlug } from "helpers/formatters";
import { filterHasAttributes, isDefined } from "helpers/others";
import { getOpenGraph } from "helpers/openGraph";
/*
*
* PAGE
*/
interface Props extends AppStaticProps {
interface Props extends AppStaticProps, AppLayoutRequired {
chronologyItems: NonNullable<
GetChronologyItemsQuery["chronologyItems"]
>["data"];
@ -145,7 +146,6 @@ const Chronology = ({
return (
<AppLayout
navTitle={langui.chronology}
contentPanel={contentPanel}
subPanel={subPanel}
langui={langui}
@ -166,10 +166,15 @@ export const getStaticProps: GetStaticProps = async (context) => {
const chronologyEras = await sdk.getEras();
if (!chronologyItems.chronologyItems || !chronologyEras.chronologyEras)
return { notFound: true };
const appStaticProps = await getAppStaticProps(context);
const props: Props = {
...(await getAppStaticProps(context)),
...appStaticProps,
chronologyItems: chronologyItems.chronologyItems.data,
chronologyEras: chronologyEras.chronologyEras.data,
openGraph: getOpenGraph(
appStaticProps.langui,
appStaticProps.langui.chronology ?? "Chronology"
),
};
return {
props: props,

View File

@ -1,6 +1,6 @@
import { GetStaticProps } from "next";
import { useCallback, useMemo, useState } from "react";
import { AppLayout } from "components/AppLayout";
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { NavOption } from "components/PanelComponents/NavOption";
import { PanelHeader } from "components/PanelComponents/PanelHeader";
import { SubPanel } from "components/Panels/SubPanel";
@ -25,6 +25,7 @@ import { SelectiveNonNullable } from "helpers/types/SelectiveNonNullable";
import { prettySlug } from "helpers/formatters";
import { useBoolean } from "hooks/useBoolean";
import { TranslatedPreviewCard } from "components/Translated";
import { getOpenGraph } from "helpers/openGraph";
/*
*
@ -42,7 +43,7 @@ const DEFAULT_FILTERS_STATE = {
* PAGE
*/
interface Props extends AppStaticProps {
interface Props extends AppStaticProps, AppLayoutRequired {
pages: NonNullable<GetWikiPagesPreviewsQuery["wikiPages"]>["data"];
}
@ -74,7 +75,7 @@ const Wiki = ({ langui, pages, ...otherProps }: Props): JSX.Element => {
<TextInput
className="mb-6 w-full"
placeholder={langui.search_title ?? undefined}
placeholder={langui.search_title ?? "Search..."}
value={searchName}
onChange={setSearchName}
/>
@ -84,7 +85,7 @@ const Wiki = ({ langui, pages, ...otherProps }: Props): JSX.Element => {
input={
<Select
className="w-full"
options={[langui.category ?? ""]}
options={[langui.category ?? "Category"]}
value={groupingMethod}
onChange={setGroupingMethod}
allowEmpty
@ -219,7 +220,6 @@ const Wiki = ({ langui, pages, ...otherProps }: Props): JSX.Element => {
return (
<AppLayout
navTitle={langui.wiki}
subPanel={subPanel}
contentPanel={contentPanel}
subPanelIcon={Icon.Search}
@ -241,9 +241,14 @@ export const getStaticProps: GetStaticProps = async (context) => {
language_code: context.locale ?? "en",
});
if (!pages.wikiPages?.data) return { notFound: true };
const appStaticProps = await getAppStaticProps(context);
const props: Props = {
...(await getAppStaticProps(context)),
...appStaticProps,
pages: sortPages(pages.wikiPages.data),
openGraph: getOpenGraph(
appStaticProps.langui,
appStaticProps.langui.wiki ?? "Wiki"
),
};
return {
props: props,