Merge pull request #39 from Accords-Library/localdata

Trying to make localdata works
This commit is contained in:
DrMint 2022-08-27 22:43:02 +02:00 committed by GitHub
commit c464cb1402
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
69 changed files with 2053 additions and 1338 deletions

View File

@ -9,7 +9,7 @@ module.exports = {
}, },
}, },
documents: [ documents: [
"src/graphql/operations/*.graphql", "src/graphql/operations/**/*.graphql",
"src/graphql/fragments/*.graphql", "src/graphql/fragments/*.graphql",
], ],
generates: { generates: {

View File

@ -1,19 +0,0 @@
module.exports = {
projects: {
app: {
schema: process.env.URL_GRAPHQL,
documents: [
"src/graphql/operations/*.graphql",
"src/graphql/fragments/*.graphql",
],
extensions: {
endpoints: {
default: {
url: process.env.URL_GRAPHQL,
headers: { Authorization: `Bearer ${process.env.ACCESS_TOKEN}` },
},
},
},
},
},
};

1543
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -3,9 +3,10 @@
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev -p 12499", "dev": "next dev -p 12499",
"precommit": "npm run generate && npm run prettier && npm run unused-exports && npm run eslint && npm run tsc && echo ALL PRECOMMIT CHECKS PASSED SUCCESSFULLY, LET\\'S FUCKING GO!", "precommit": "npm run generate && npm run fetch-local-data && npm run prettier && npm run unused-exports && npm run eslint && npm run tsc && echo ALL PRECOMMIT CHECKS PASSED SUCCESSFULLY, LET\\'S FUCKING GO!",
"unused-exports": "ts-unused-exports ./tsconfig.json --excludePathsFromReport=src/pages --ignoreFiles=generated", "unused-exports": "ts-unused-exports ./tsconfig.json --excludePathsFromReport=src/pages --ignoreFiles=generated",
"prebuild": "npm run generate", "fetch-local-data": "esrun src/graphql/fetchLocalData.ts",
"prebuild": "npm run generate && npm run fetch-local-data",
"build": "next build", "build": "next build",
"postbuild": "next-sitemap --config next-sitemap.config.js", "postbuild": "next-sitemap --config next-sitemap.config.js",
"start": "next start -p 12500", "start": "next start -p 12500",
@ -24,7 +25,7 @@
"@tippyjs/react": "^4.2.6", "@tippyjs/react": "^4.2.6",
"@types/ua-parser-js": "^0.7.36", "@types/ua-parser-js": "^0.7.36",
"autoprefixer": "^10.4.8", "autoprefixer": "^10.4.8",
"graphql-request": "^4.3.0", "graphql-request": "^5.0.0",
"markdown-to-jsx": "^7.1.7", "markdown-to-jsx": "^7.1.7",
"meilisearch": "^0.27.0", "meilisearch": "^0.27.0",
"next": "^12.2.5", "next": "^12.2.5",
@ -40,19 +41,21 @@
"usehooks-ts": "^2.6.0" "usehooks-ts": "^2.6.0"
}, },
"devDependencies": { "devDependencies": {
"@graphql-codegen/cli": "^2.11.6", "@digitak/esrun": "^3.2.10",
"@graphql-codegen/cli": "^2.11.8",
"@graphql-codegen/typescript": "2.7.3", "@graphql-codegen/typescript": "2.7.3",
"@graphql-codegen/typescript-graphql-request": "^4.5.3", "@graphql-codegen/typescript-graphql-request": "^4.5.3",
"@graphql-codegen/typescript-operations": "^2.5.3", "@graphql-codegen/typescript-operations": "^2.5.3",
"@types/node": "18.7.9", "@types/node": "18.7.13",
"@types/nodemailer": "^6.4.5", "@types/nodemailer": "^6.4.5",
"@types/react": "18.0.17", "@types/react": "18.0.17",
"@types/react-dom": "^18.0.6", "@types/react-dom": "^18.0.6",
"@types/throttle-debounce": "^5.0.0", "@types/throttle-debounce": "^5.0.0",
"@types/turndown": "^5.0.1", "@types/turndown": "^5.0.1",
"@typescript-eslint/eslint-plugin": "^5.33.1", "@typescript-eslint/eslint-plugin": "^5.35.1",
"@typescript-eslint/parser": "^5.33.1", "@typescript-eslint/parser": "^5.35.1",
"eslint": "^8.22.0", "dotenv": "^16.0.1",
"eslint": "^8.23.0",
"eslint-config-next": "12.2.5", "eslint-config-next": "12.2.5",
"eslint-plugin-import": "^2.26.0", "eslint-plugin-import": "^2.26.0",
"graphql": "^16.6.0", "graphql": "^16.6.0",
@ -61,6 +64,6 @@
"prettier-plugin-tailwindcss": "^0.1.13", "prettier-plugin-tailwindcss": "^0.1.13",
"tailwindcss": "^3.1.8", "tailwindcss": "^3.1.8",
"ts-unused-exports": "^8.0.0", "ts-unused-exports": "^8.0.0",
"typescript": "^4.7.4" "typescript": "^4.8.2"
} }
} }

View File

@ -0,0 +1 @@
{"currencies":{"data":[{"id":"1","attributes":{"code":"EUR","symbol":"€","rate_to_usd":1.1062771,"display_decimals":true}},{"id":"2","attributes":{"code":"CAD","symbol":"$","rate_to_usd":0.79319156,"display_decimals":true}},{"id":"3","attributes":{"code":"USD","symbol":"$","rate_to_usd":1,"display_decimals":true}},{"id":"4","attributes":{"code":"JPY","symbol":"¥","rate_to_usd":0.0083864261,"display_decimals":false}},{"id":"5","attributes":{"code":"BRL","symbol":"R$","rate_to_usd":0.19904328,"display_decimals":true}},{"id":"6","attributes":{"code":"GBP","symbol":"£","rate_to_usd":1.3181323,"display_decimals":true}},{"id":"7","attributes":{"code":"AUD","symbol":"$","rate_to_usd":0.7422,"display_decimals":true}},{"id":"8","attributes":{"code":"INR","symbol":"₹","rate_to_usd":0.013162881,"display_decimals":false}},{"id":"9","attributes":{"code":"NZD","symbol":"$","rate_to_usd":0.69089984,"display_decimals":true}},{"id":"10","attributes":{"code":"CHF","symbol":"CHF","rate_to_usd":1.0728706,"display_decimals":true}}]}}

View File

@ -0,0 +1 @@
{"languages":{"data":[{"id":"1","attributes":{"name":"French","code":"fr","localized_name":"Français"}},{"id":"2","attributes":{"name":"English","code":"en","localized_name":"English"}},{"id":"3","attributes":{"name":"Japanese","code":"ja","localized_name":"日本語"}},{"id":"4","attributes":{"name":"Spanish","code":"es","localized_name":"Español"}},{"id":"6","attributes":{"name":"Portuguese (Brazil)","code":"pt-br","localized_name":"Português (Brasil)"}},{"id":"8","attributes":{"name":"German","code":"de","localized_name":"Deutsch"}},{"id":"9","attributes":{"name":"Italian","code":"it","localized_name":"Italiano"}},{"id":"10","attributes":{"name":"Russian","code":"ru","localized_name":"русский"}},{"id":"11","attributes":{"name":"Korean","code":"ko","localized_name":"한국어"}},{"id":"12","attributes":{"name":"Chinese (Traditional)","code":"zh-cht","localized_name":"中文(繁體)"}}]}}

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,7 @@
import { Ico, Icon } from "./Ico"; import { Ico, Icon } from "./Ico";
import { ToolTip } from "./ToolTip"; import { ToolTip } from "./ToolTip";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { cJoin } from "helpers/className"; import { cJoin } from "helpers/className";
import { useAppLayout } from "contexts/AppLayoutContext";
/* /*
* *
@ -10,37 +10,39 @@ import { cJoin } from "helpers/className";
interface Props { interface Props {
id: string; id: string;
langui: AppStaticProps["langui"];
className?: string; className?: string;
} }
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
export const AnchorShare = ({ id, langui, className }: Props): JSX.Element => ( export const AnchorShare = ({ id, className }: Props): JSX.Element => {
<ToolTip const { langui } = useAppLayout();
content={langui.copy_anchor_link} return (
trigger="mouseenter"
className="text-sm"
>
<ToolTip <ToolTip
content={langui.anchor_link_copied} content={langui.copy_anchor_link}
trigger="click" trigger="mouseenter"
className="text-sm" className="text-sm"
> >
<Ico <ToolTip
icon={Icon.Link} content={langui.anchor_link_copied}
className={cJoin( trigger="click"
"transition-color cursor-pointer hover:text-dark", className="text-sm"
className >
)} <Ico
onClick={() => { icon={Icon.Link}
navigator.clipboard.writeText( className={cJoin(
`${ "transition-color cursor-pointer hover:text-dark",
process.env.NEXT_PUBLIC_URL_SELF + window.location.pathname className
}#${id}` )}
); onClick={() => {
}} navigator.clipboard.writeText(
/> `${
process.env.NEXT_PUBLIC_URL_SELF + window.location.pathname
}#${id}`
);
}}
/>
</ToolTip>
</ToolTip> </ToolTip>
</ToolTip> );
); };

View File

@ -1,9 +1,10 @@
import Head from "next/head"; import Head from "next/head";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { useEffect, useLayoutEffect, useMemo, useState } from "react"; import { useEffect, useMemo, useState } from "react";
import { useSwipeable } from "react-swipeable"; import { useSwipeable } from "react-swipeable";
import UAParser from "ua-parser-js"; import UAParser from "ua-parser-js";
import { useBoolean, useIsClient } from "usehooks-ts"; import { useBoolean, useIsClient } from "usehooks-ts";
import Script from "next/script";
import { layout } from "../../design.config"; import { layout } from "../../design.config";
import { Ico, Icon } from "./Ico"; import { Ico, Icon } from "./Ico";
import { ButtonGroup } from "./Inputs/ButtonGroup"; import { ButtonGroup } from "./Inputs/ButtonGroup";
@ -13,20 +14,12 @@ import { TextInput } from "./Inputs/TextInput";
import { MainPanel } from "./Panels/MainPanel"; import { MainPanel } from "./Panels/MainPanel";
import { Popup } from "./Popup"; import { Popup } from "./Popup";
import { AnchorIds } from "hooks/useScrollTopOnChange"; import { AnchorIds } from "hooks/useScrollTopOnChange";
import { import { filterHasAttributes, isDefined, isUndefined } from "helpers/others";
filterHasAttributes,
isDefined,
isDefinedAndNotEmpty,
isUndefined,
iterateMap,
} from "helpers/others";
import { prettyLanguage } from "helpers/formatters"; import { prettyLanguage } from "helpers/formatters";
import { cIf, cJoin } from "helpers/className"; import { cIf, cJoin } from "helpers/className";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { useAppLayout } from "contexts/AppLayoutContext"; import { useAppLayout } from "contexts/AppLayoutContext";
import { Button } from "components/Inputs/Button"; import { Button } from "components/Inputs/Button";
import { OpenGraph, TITLE_PREFIX, TITLE_SEPARATOR } from "helpers/openGraph"; import { OpenGraph, TITLE_PREFIX, TITLE_SEPARATOR } from "helpers/openGraph";
import { getDefaultPreferredLanguages } from "helpers/locales";
import { import {
useIs1ColumnLayout, useIs1ColumnLayout,
useIsScreenAtLeast, useIsScreenAtLeast,
@ -49,7 +42,7 @@ export interface AppLayoutRequired {
openGraph: OpenGraph; openGraph: OpenGraph;
} }
interface Props extends AppStaticProps, AppLayoutRequired { interface Props extends AppLayoutRequired {
subPanel?: React.ReactNode; subPanel?: React.ReactNode;
subPanelIcon?: Icon; subPanelIcon?: Icon;
contentPanel?: React.ReactNode; contentPanel?: React.ReactNode;
@ -59,9 +52,6 @@ interface Props extends AppStaticProps, AppLayoutRequired {
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
export const AppLayout = ({ export const AppLayout = ({
langui,
currencies,
languages,
subPanel, subPanel,
contentPanel, contentPanel,
openGraph, openGraph,
@ -96,6 +86,9 @@ export const AppLayout = ({
setScreenWidth, setScreenWidth,
setContentPanelWidth, setContentPanelWidth,
setSubPanelWidth, setSubPanelWidth,
langui,
currencies,
languages,
} = useAppLayout(); } = useAppLayout();
const router = useRouter(); const router = useRouter();
@ -106,18 +99,6 @@ export const AppLayout = ({
useOnResize(AnchorIds.ContentPanel, (width) => setContentPanelWidth(width)); useOnResize(AnchorIds.ContentPanel, (width) => setContentPanelWidth(width));
useOnResize(AnchorIds.SubPanel, (width) => setSubPanelWidth(width)); useOnResize(AnchorIds.SubPanel, (width) => setSubPanelWidth(width));
useEffect(() => {
router.events.on("routeChangeStart", () => {
setConfigPanelOpen(false);
setMainPanelOpen(false);
setSubPanelOpen(false);
});
router.events.on("hashChangeStart", () => {
setSubPanelOpen(false);
});
}, [router.events, setConfigPanelOpen, setMainPanelOpen, setSubPanelOpen]);
const handlers = useSwipeable({ const handlers = useSwipeable({
onSwipedLeft: (SwipeEventData) => { onSwipedLeft: (SwipeEventData) => {
if (menuGestures) { if (menuGestures) {
@ -146,12 +127,6 @@ export const AppLayout = ({
[contentPanel, subPanel] [contentPanel, subPanel]
); );
useLayoutEffect(() => {
document.getElementsByTagName("html")[0].style.fontSize = `${
fontSize * 100
}%`;
}, [fontSize]);
const currencyOptions = useMemo( const currencyOptions = useMemo(
() => () =>
filterHasAttributes(currencies, ["attributes"] as const).map( filterHasAttributes(currencies, ["attributes"] as const).map(
@ -171,26 +146,6 @@ export const AppLayout = ({
if (currencySelect >= 0) setCurrency(currencyOptions[currencySelect]); if (currencySelect >= 0) setCurrency(currencyOptions[currencySelect]);
}, [currencyOptions, currencySelect, setCurrency]); }, [currencyOptions, currencySelect, setCurrency]);
useEffect(() => {
if (preferredLanguages.length === 0) {
if (isDefinedAndNotEmpty(router.locale) && router.locales) {
setPreferredLanguages(
getDefaultPreferredLanguages(router.locale, router.locales)
);
}
} else if (router.locale !== preferredLanguages[0]) {
router.replace(router.asPath, router.asPath, {
locale: preferredLanguages[0],
});
}
}, [
preferredLanguages,
router,
router.locale,
router.locales,
setPreferredLanguages,
]);
const isClient = useIsClient(); const isClient = useIsClient();
const { value: hasDisgardSafariWarning, setTrue: disgardSafariWarning } = const { value: hasDisgardSafariWarning, setTrue: disgardSafariWarning } =
useBoolean(false); useBoolean(false);
@ -256,15 +211,15 @@ export const AppLayout = ({
/> />
<meta property="og:image:alt" content={openGraph.thumbnail.alt} /> <meta property="og:image:alt" content={openGraph.thumbnail.alt} />
<meta property="og:image:type" content="image/jpeg" /> <meta property="og:image:type" content="image/jpeg" />
<script
async
defer
data-website-id={process.env.NEXT_PUBLIC_UMAMI_ID}
src={`${process.env.NEXT_PUBLIC_UMAMI_URL}/umami.js`}
/>
</Head> </Head>
<Script
async
defer
data-website-id={process.env.NEXT_PUBLIC_UMAMI_ID}
src={`${process.env.NEXT_PUBLIC_UMAMI_URL}/umami.js`}
/>
{/* Background when navbar is opened */} {/* Background when navbar is opened */}
<div <div
className={cJoin( className={cJoin(
@ -354,7 +309,7 @@ export const AppLayout = ({
cIf(!mainPanelOpen && is1ColumnLayout, "-translate-x-full") cIf(!mainPanelOpen && is1ColumnLayout, "-translate-x-full")
)} )}
> >
<MainPanel langui={langui} /> <MainPanel />
</div> </div>
{/* Navbar */} {/* Navbar */}
@ -448,24 +403,24 @@ export const AppLayout = ({
<h3 className="text-xl">{langui.languages}</h3> <h3 className="text-xl">{langui.languages}</h3>
{preferredLanguages.length > 0 && ( {preferredLanguages.length > 0 && (
<OrderableList <OrderableList
items={ items={preferredLanguages.map((locale) => ({
new Map( code: locale,
preferredLanguages.map((locale) => [ name: prettyLanguage(locale, languages),
locale, }))}
prettyLanguage(locale, languages), insertLabels={[
]) {
) insertAt: 0,
} name: langui.primary_language ?? "Primary language",
insertLabels={ },
new Map([ {
[0, langui.primary_language], insertAt: 1,
[1, langui.secondary_language], name:
]) langui.secondary_language ?? "Secondary languages",
} },
]}
onChange={(items) => { onChange={(items) => {
const newPreferredLanguages = iterateMap( const newPreferredLanguages = items.map(
items, (item) => item.code
(code) => code
); );
setPreferredLanguages(newPreferredLanguages); setPreferredLanguages(newPreferredLanguages);
}} }}

View File

@ -2,10 +2,10 @@ import { Fragment } from "react";
import { ToolTip } from "../ToolTip"; import { ToolTip } from "../ToolTip";
import { Button } from "./Button"; import { Button } from "./Button";
import { Icon } from "components/Ico"; import { Icon } from "components/Ico";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { cJoin } from "helpers/className"; import { cJoin } from "helpers/className";
import { prettyLanguage } from "helpers/formatters"; import { prettyLanguage } from "helpers/formatters";
import { iterateMap } from "helpers/others"; import { iterateMap } from "helpers/others";
import { useLanguages } from "hooks/useLocalData";
/* /*
* *
@ -14,7 +14,6 @@ import { iterateMap } from "helpers/others";
interface Props { interface Props {
className?: string; className?: string;
languages: AppStaticProps["languages"];
locales: Map<string, number>; locales: Map<string, number>;
localesIndex: number | undefined; localesIndex: number | undefined;
onLanguageChanged: (index: number) => void; onLanguageChanged: (index: number) => void;
@ -28,30 +27,32 @@ export const LanguageSwitcher = ({
className, className,
locales, locales,
localesIndex, localesIndex,
languages,
size, size,
onLanguageChanged, onLanguageChanged,
showBadge = true, showBadge = true,
}: Props): JSX.Element => ( }: Props): JSX.Element => {
<ToolTip const languages = useLanguages();
content={ return (
<div className={cJoin("flex flex-col gap-2", className)}> <ToolTip
{iterateMap(locales, (locale, value, index) => ( content={
<Fragment key={index}> <div className={cJoin("flex flex-col gap-2", className)}>
<Button {iterateMap(locales, (locale, value, index) => (
active={value === localesIndex} <Fragment key={index}>
onClick={() => onLanguageChanged(value)} <Button
text={prettyLanguage(locale, languages)} active={value === localesIndex}
/> onClick={() => onLanguageChanged(value)}
</Fragment> text={prettyLanguage(locale, languages)}
))} />
</div> </Fragment>
} ))}
> </div>
<Button }
badgeNumber={showBadge && locales.size > 1 ? locales.size : undefined} >
icon={Icon.Translate} <Button
size={size} badgeNumber={showBadge && locales.size > 1 ? locales.size : undefined}
/> icon={Icon.Translate}
</ToolTip> size={size}
); />
</ToolTip>
);
};

View File

@ -1,6 +1,6 @@
import { Fragment, useCallback, useState } from "react"; import { Fragment, useCallback } from "react";
import { Ico, Icon } from "components/Ico"; import { Ico, Icon } from "components/Ico";
import { isDefinedAndNotEmpty, iterateMap, mapMoveEntry } from "helpers/others"; import { arrayMove, isDefinedAndNotEmpty } from "helpers/others";
/* /*
* *
@ -9,35 +9,32 @@ import { isDefinedAndNotEmpty, iterateMap, mapMoveEntry } from "helpers/others";
interface Props { interface Props {
className?: string; className?: string;
items: Map<string, string>; items: { code: string; name: string }[];
insertLabels?: Map<number, string | null | undefined>; insertLabels?: { insertAt: number; name: string }[];
onChange?: (items: Map<string, string>) => void; onChange?: (props: Props["items"]) => void;
} }
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
export const OrderableList = ({ export const OrderableList = ({
onChange, onChange,
items: propsItems, items,
insertLabels, insertLabels,
}: Props): JSX.Element => { }: Props): JSX.Element => {
const [items, setItems] = useState<Map<string, string>>(propsItems);
const updateOrder = useCallback( const updateOrder = useCallback(
(sourceIndex: number, targetIndex: number) => { (sourceIndex: number, targetIndex: number) => {
const newItems = mapMoveEntry(items, sourceIndex, targetIndex); console.log("updateOrder");
setItems(newItems); onChange?.(arrayMove(items, sourceIndex, targetIndex));
onChange?.(newItems);
}, },
[items, onChange] [items, onChange]
); );
return ( return (
<div className="grid gap-2"> <div className="grid gap-2">
{iterateMap(items, (key, value, index) => ( {items.map((item, index) => (
<Fragment key={key}> <Fragment key={index}>
{insertLabels && isDefinedAndNotEmpty(insertLabels.get(index)) && ( {insertLabels && isDefinedAndNotEmpty(insertLabels[index]?.name) && (
<p>{insertLabels.get(index)}</p> <p>{insertLabels[index].name}</p>
)} )}
<div <div
onDragStart={(event) => { onDragStart={(event) => {
@ -81,7 +78,7 @@ export const OrderableList = ({
}} }}
/> />
)} )}
{index < items.size - 1 && ( {index < items.length - 1 && (
<Ico <Ico
icon={Icon.ArrowDropDown} icon={Icon.ArrowDropDown}
className="row-start-2 cursor-pointer" className="row-start-2 cursor-pointer"
@ -91,7 +88,7 @@ export const OrderableList = ({
/> />
)} )}
</div> </div>
{value} {item.name}
</div> </div>
</Fragment> </Fragment>
))} ))}

View File

@ -1,9 +1,8 @@
import { Icon } from "components/Ico"; import { Icon } from "components/Ico";
import { Button } from "components/Inputs/Button"; import { Button } from "components/Inputs/Button";
import { ToolTip } from "components/ToolTip"; import { ToolTip } from "components/ToolTip";
import { useAppLayout } from "contexts/AppLayoutContext";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { LibraryItemUserStatus } from "helpers/types"; import { LibraryItemUserStatus } from "helpers/types";
import { useAppLayout } from "contexts/AppLayoutContext";
/* /*
* *
@ -13,17 +12,13 @@ import { LibraryItemUserStatus } from "helpers/types";
interface Props { interface Props {
id: string; id: string;
expand?: boolean; expand?: boolean;
langui: AppStaticProps["langui"];
} }
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
export const PreviewCardCTAs = ({ export const PreviewCardCTAs = ({ id, expand = false }: Props): JSX.Element => {
id, const { libraryItemUserStatus, setLibraryItemUserStatus, langui } =
expand = false, useAppLayout();
langui,
}: Props): JSX.Element => {
const { libraryItemUserStatus, setLibraryItemUserStatus } = useAppLayout();
return ( return (
<> <>
<div <div

View File

@ -6,7 +6,6 @@ import { HorizontalLine } from "components/HorizontalLine";
import { Img } from "components/Img"; import { Img } from "components/Img";
import { InsetBox } from "components/InsetBox"; import { InsetBox } from "components/InsetBox";
import { useAppLayout } from "contexts/AppLayoutContext"; import { useAppLayout } from "contexts/AppLayoutContext";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { cIf, cJoin } from "helpers/className"; import { cIf, cJoin } from "helpers/className";
import { slugify } from "helpers/formatters"; import { slugify } from "helpers/formatters";
import { getAssetURL, ImageQuality } from "helpers/img"; import { getAssetURL, ImageQuality } from "helpers/img";
@ -26,7 +25,6 @@ import { useDeviceSupportsHover } from "hooks/useMediaQuery";
interface MarkdawnProps { interface MarkdawnProps {
className?: string; className?: string;
text: string; text: string;
langui: AppStaticProps["langui"];
} }
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
@ -34,7 +32,6 @@ interface MarkdawnProps {
export const Markdawn = ({ export const Markdawn = ({
className, className,
text: rawText, text: rawText,
langui,
}: MarkdawnProps): JSX.Element => { }: MarkdawnProps): JSX.Element => {
const { playerName } = useAppLayout(); const { playerName } = useAppLayout();
const router = useRouter(); const router = useRouter();
@ -93,7 +90,6 @@ export const Markdawn = ({
}) => ( }) => (
<Header <Header
title={compProps.children} title={compProps.children}
langui={langui}
level={parseInt(compProps.level, 10)} level={parseInt(compProps.level, 10)}
slug={compProps.id} slug={compProps.id}
/> />
@ -102,12 +98,7 @@ export const Markdawn = ({
SceneBreak: { SceneBreak: {
component: (compProps: { id: string }) => ( component: (compProps: { id: string }) => (
<Header <Header title={"* * *"} level={6} slug={compProps.id} />
title={"* * *"}
langui={langui}
level={6}
slug={compProps.id}
/>
), ),
}, },
@ -158,7 +149,7 @@ export const Markdawn = ({
cIf(!isContentPanelAtLeastLg, "!-mb-4") cIf(!isContentPanelAtLeastLg, "!-mb-4")
)} )}
> >
<Markdawn text={compProps.name} langui={langui} /> <Markdawn text={compProps.name} />
</strong> </strong>
<p className="whitespace-pre-line">{compProps.children}</p> <p className="whitespace-pre-line">{compProps.children}</p>
</> </>
@ -266,17 +257,18 @@ export const Markdawn = ({
interface TableOfContentsProps { interface TableOfContentsProps {
text: string; text: string;
title?: string; title?: string;
langui: AppStaticProps["langui"];
horizontalLine?: boolean; horizontalLine?: boolean;
} }
export const TableOfContents = ({ export const TableOfContents = ({
text, text,
title, title,
langui,
horizontalLine = false, horizontalLine = false,
}: TableOfContentsProps): JSX.Element => { }: TableOfContentsProps): JSX.Element => {
const router = useRouter(); const router = useRouter();
const { langui } = useAppLayout();
const toc = useMemo( const toc = useMemo(
() => getTocFromMarkdawn(preprocessMarkDawn(text), title), () => getTocFromMarkdawn(preprocessMarkDawn(text), title),
[text, title] [text, title]
@ -314,10 +306,9 @@ interface HeaderProps {
level: number; level: number;
title: string; title: string;
slug: string; slug: string;
langui: AppStaticProps["langui"];
} }
const Header = ({ level, title, slug, langui }: HeaderProps): JSX.Element => { const Header = ({ level, title, slug }: HeaderProps): JSX.Element => {
const isHoverable = useDeviceSupportsHover(); const isHoverable = useDeviceSupportsHover();
const innerComponent = useMemo( const innerComponent = useMemo(
() => ( () => (
@ -338,12 +329,11 @@ const Header = ({ level, title, slug, langui }: HeaderProps): JSX.Element => {
"opacity-0 transition-opacity group-hover:opacity-100" "opacity-0 transition-opacity group-hover:opacity-100"
)} )}
id={slug} id={slug}
langui={langui}
/> />
</div> </div>
</> </>
), ),
[isHoverable, langui, slug, title] [isHoverable, slug, title]
); );
switch (level) { switch (level) {

View File

@ -2,7 +2,6 @@ import { useCallback } from "react";
import { Icon } from "components/Ico"; import { Icon } from "components/Ico";
import { Button } from "components/Inputs/Button"; import { Button } from "components/Inputs/Button";
import { useAppLayout } from "contexts/AppLayoutContext"; import { useAppLayout } from "contexts/AppLayoutContext";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { TranslatedProps } from "helpers/types/TranslatedProps"; import { TranslatedProps } from "helpers/types/TranslatedProps";
import { useSmartLanguage } from "hooks/useSmartLanguage"; import { useSmartLanguage } from "hooks/useSmartLanguage";
import { useIs3ColumnsLayout } from "hooks/useContainerQuery"; import { useIs3ColumnsLayout } from "hooks/useContainerQuery";
@ -16,7 +15,7 @@ import { isDefined } from "helpers/others";
interface Props { interface Props {
href: string; href: string;
title: string | null | undefined; title: string | null | undefined;
langui: AppStaticProps["langui"];
displayOnlyOn?: "1ColumnLayout" | "3ColumnsLayout"; displayOnlyOn?: "1ColumnLayout" | "3ColumnsLayout";
className?: string; className?: string;
} }
@ -26,11 +25,10 @@ interface Props {
export const ReturnButton = ({ export const ReturnButton = ({
href, href,
title, title,
langui,
displayOnlyOn, displayOnlyOn,
className, className,
}: Props): JSX.Element => { }: Props): JSX.Element => {
const { setSubPanelOpen } = useAppLayout(); const { setSubPanelOpen, langui } = useAppLayout();
const is3ColumnsLayout = useIs3ColumnsLayout(); const is3ColumnsLayout = useIs3ColumnsLayout();
return ( return (

View File

@ -4,7 +4,6 @@ import { Button } from "components/Inputs/Button";
import { NavOption } from "components/PanelComponents/NavOption"; import { NavOption } from "components/PanelComponents/NavOption";
import { ToolTip } from "components/ToolTip"; import { ToolTip } from "components/ToolTip";
import { useAppLayout } from "contexts/AppLayoutContext"; import { useAppLayout } from "contexts/AppLayoutContext";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { Icon } from "components/Ico"; import { Icon } from "components/Ico";
import { cIf, cJoin } from "helpers/className"; import { cIf, cJoin } from "helpers/className";
import { isDefinedAndNotEmpty } from "helpers/others"; import { isDefinedAndNotEmpty } from "helpers/others";
@ -16,18 +15,13 @@ import { useIs3ColumnsLayout } from "hooks/useContainerQuery";
* COMPONENT * COMPONENT
*/ */
interface Props { export const MainPanel = (): JSX.Element => {
langui: AppStaticProps["langui"];
}
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
export const MainPanel = ({ langui }: Props): JSX.Element => {
const is3ColumnsLayout = useIs3ColumnsLayout(); const is3ColumnsLayout = useIs3ColumnsLayout();
const { const {
mainPanelReduced = false, mainPanelReduced = false,
toggleMainPanelReduced, toggleMainPanelReduced,
setConfigPanelOpen, setConfigPanelOpen,
langui,
} = useAppLayout(); } = useAppLayout();
return ( return (

View File

@ -13,7 +13,7 @@ import { useSmartLanguage } from "hooks/useSmartLanguage";
import { PostWithTranslations } from "helpers/types"; import { PostWithTranslations } from "helpers/types";
import { filterHasAttributes, getStatusDescription } from "helpers/others"; import { filterHasAttributes, getStatusDescription } from "helpers/others";
import { prettySlug } from "helpers/formatters"; import { prettySlug } from "helpers/formatters";
import { AppStaticProps } from "graphql/getAppStaticProps"; import { useAppLayout } from "contexts/AppLayoutContext";
/* /*
* *
@ -22,9 +22,6 @@ import { AppStaticProps } from "graphql/getAppStaticProps";
interface Props extends AppLayoutRequired { interface Props extends AppLayoutRequired {
post: PostWithTranslations; post: PostWithTranslations;
langui: AppStaticProps["langui"];
languages: AppStaticProps["languages"];
currencies: AppStaticProps["currencies"];
returnHref?: string; returnHref?: string;
returnTitle?: string | null | undefined; returnTitle?: string | null | undefined;
displayCredits?: boolean; displayCredits?: boolean;
@ -40,8 +37,6 @@ interface Props extends AppLayoutRequired {
export const PostPage = ({ export const PostPage = ({
post, post,
langui,
languages,
returnHref, returnHref,
returnTitle, returnTitle,
displayCredits, displayCredits,
@ -53,10 +48,10 @@ export const PostPage = ({
displayTitle = true, displayTitle = true,
...otherProps ...otherProps
}: Props): JSX.Element => { }: Props): JSX.Element => {
const { langui } = useAppLayout();
const [selectedTranslation, LanguageSwitcher, languageSwitcherProps] = const [selectedTranslation, LanguageSwitcher, languageSwitcherProps] =
useSmartLanguage({ useSmartLanguage({
items: post.translations, items: post.translations,
languages: languages,
languageExtractor: useCallback( languageExtractor: useCallback(
(item: NonNullable<PostWithTranslations["translations"][number]>) => (item: NonNullable<PostWithTranslations["translations"][number]>) =>
item.language?.data?.attributes?.code, item.language?.data?.attributes?.code,
@ -84,7 +79,6 @@ export const PostPage = ({
<ReturnButton <ReturnButton
href={returnHref} href={returnHref}
title={returnTitle} title={returnTitle}
langui={langui}
displayOnlyOn={"3ColumnsLayout"} displayOnlyOn={"3ColumnsLayout"}
/> />
)} )}
@ -118,10 +112,7 @@ export const PostPage = ({
"attributes", "attributes",
] as const).map((author) => ( ] as const).map((author) => (
<Fragment key={author.id}> <Fragment key={author.id}>
<RecorderChip <RecorderChip recorder={author.attributes} />
langui={langui}
recorder={author.attributes}
/>
</Fragment> </Fragment>
))} ))}
</div> </div>
@ -131,12 +122,7 @@ export const PostPage = ({
)} )}
{displayToc && ( {displayToc && (
<TableOfContents <TableOfContents text={body} title={title} horizontalLine />
text={body}
title={title}
langui={langui}
horizontalLine
/>
)} )}
</SubPanel> </SubPanel>
) : undefined, ) : undefined,
@ -160,7 +146,6 @@ export const PostPage = ({
<ReturnButton <ReturnButton
href={returnHref} href={returnHref}
title={returnTitle} title={returnTitle}
langui={langui}
displayOnlyOn={"1ColumnLayout"} displayOnlyOn={"1ColumnLayout"}
className="mb-10" className="mb-10"
/> />
@ -172,7 +157,6 @@ export const PostPage = ({
thumbnail={thumbnail} thumbnail={thumbnail}
title={title} title={title}
description={excerpt} description={excerpt}
langui={langui}
categories={post.categories} categories={post.categories}
languageSwitcher={ languageSwitcher={
languageSwitcherProps.locales.size > 1 ? ( languageSwitcherProps.locales.size > 1 ? (
@ -200,7 +184,7 @@ export const PostPage = ({
{body && ( {body && (
<> <>
{displayThumbnailHeader && <HorizontalLine />} {displayThumbnailHeader && <HorizontalLine />}
<Markdawn text={body} langui={langui} /> <Markdawn text={body} />
</> </>
)} )}
@ -216,7 +200,6 @@ export const PostPage = ({
displayTitle, displayTitle,
excerpt, excerpt,
languageSwitcherProps, languageSwitcherProps,
langui,
post.categories, post.categories,
prependBody, prependBody,
returnHref, returnHref,
@ -231,8 +214,6 @@ export const PostPage = ({
{...otherProps} {...otherProps}
contentPanel={contentPanel} contentPanel={contentPanel}
subPanel={subPanel} subPanel={subPanel}
languages={languages}
langui={langui}
/> />
); );
}; };

View File

@ -10,7 +10,6 @@ import {
PricePickerFragment, PricePickerFragment,
UploadImageFragment, UploadImageFragment,
} from "graphql/generated"; } from "graphql/generated";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { cIf, cJoin } from "helpers/className"; import { cIf, cJoin } from "helpers/className";
import { import {
prettyDate, prettyDate,
@ -22,6 +21,7 @@ import { ImageQuality } from "helpers/img";
import { useDeviceSupportsHover } from "hooks/useMediaQuery"; import { useDeviceSupportsHover } from "hooks/useMediaQuery";
import { useSmartLanguage } from "hooks/useSmartLanguage"; import { useSmartLanguage } from "hooks/useSmartLanguage";
import { TranslatedProps } from "helpers/types/TranslatedProps"; import { TranslatedProps } from "helpers/types/TranslatedProps";
import { useCurrencies } from "hooks/useLocalData";
/* /*
* *
@ -43,7 +43,6 @@ interface Props {
keepInfoVisible?: boolean; keepInfoVisible?: boolean;
stackNumber?: number; stackNumber?: number;
metadata?: { metadata?: {
currencies?: AppStaticProps["currencies"];
releaseDate?: DatePickerFragment | null; releaseDate?: DatePickerFragment | null;
releaseDateFormat?: Intl.DateTimeFormatOptions["dateStyle"]; releaseDateFormat?: Intl.DateTimeFormatOptions["dateStyle"];
price?: PricePickerFragment | null; price?: PricePickerFragment | null;
@ -83,6 +82,7 @@ export const PreviewCard = ({
const { currency } = useAppLayout(); const { currency } = useAppLayout();
const isHoverable = useDeviceSupportsHover(); const isHoverable = useDeviceSupportsHover();
const router = useRouter(); const router = useRouter();
const currencies = useCurrencies();
const metadataJSX = useMemo( const metadataJSX = useMemo(
() => ( () => (
@ -98,13 +98,13 @@ export const PreviewCard = ({
{prettyDate(metadata.releaseDate, router.locale)} {prettyDate(metadata.releaseDate, router.locale)}
</p> </p>
)} )}
{metadata.price && metadata.currencies && ( {metadata.price && (
<p className="justify-self-end text-sm"> <p className="justify-self-end text-sm">
<Ico <Ico
icon={Icon.ShoppingCart} icon={Icon.ShoppingCart}
className="mr-1 translate-y-[.15em] !text-base" className="mr-1 translate-y-[.15em] !text-base"
/> />
{prettyPrice(metadata.price, metadata.currencies, currency)} {prettyPrice(metadata.price, currencies, currency)}
</p> </p>
)} )}
{metadata.views && ( {metadata.views && (
@ -129,7 +129,7 @@ export const PreviewCard = ({
)} )}
</> </>
), ),
[currency, metadata, router.locale] [currencies, currency, metadata, router.locale]
); );
return ( return (

View File

@ -4,9 +4,9 @@ import { Markdawn } from "./Markdown/Markdawn";
import { ToolTip } from "./ToolTip"; import { ToolTip } from "./ToolTip";
import { Chip } from "components/Chip"; import { Chip } from "components/Chip";
import { RecorderChipFragment } from "graphql/generated"; import { RecorderChipFragment } from "graphql/generated";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { ImageQuality } from "helpers/img"; import { ImageQuality } from "helpers/img";
import { filterHasAttributes } from "helpers/others"; import { filterHasAttributes } from "helpers/others";
import { useAppLayout } from "contexts/AppLayoutContext";
/* /*
* *
@ -16,59 +16,60 @@ import { filterHasAttributes } from "helpers/others";
interface Props { interface Props {
className?: string; className?: string;
recorder: RecorderChipFragment; recorder: RecorderChipFragment;
langui: AppStaticProps["langui"];
} }
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
export const RecorderChip = ({ recorder, langui }: Props): JSX.Element => ( export const RecorderChip = ({ recorder }: Props): JSX.Element => {
<ToolTip const { langui } = useAppLayout();
content={
<div className="grid gap-8 p-2 py-5 text-left"> return (
<div className="grid grid-flow-col place-content-start place-items-center gap-6"> <ToolTip
{recorder.avatar?.data?.attributes && ( content={
<Img <div className="grid gap-8 p-2 py-5 text-left">
className="aspect-square w-20 rounded-full border-4 border-mid object-cover" <div className="grid grid-flow-col place-content-start place-items-center gap-6">
src={recorder.avatar.data.attributes} {recorder.avatar?.data?.attributes && (
quality={ImageQuality.Small} <Img
/> className="aspect-square w-20 rounded-full border-4 border-mid object-cover"
)} src={recorder.avatar.data.attributes}
<div className="grid gap-2"> quality={ImageQuality.Small}
<h3 className=" text-2xl">{recorder.username}</h3> />
{recorder.languages?.data && recorder.languages.data.length > 0 && (
<div className="flex flex-row flex-wrap gap-1">
<p>{langui.languages}:</p>
{filterHasAttributes(recorder.languages.data, [
"attributes",
] as const).map((language) => (
<Fragment key={language.__typename}>
<Chip text={language.attributes.code.toUpperCase()} />
</Fragment>
))}
</div>
)}
{recorder.pronouns && (
<div className="flex flex-row flex-wrap gap-1">
<p>{langui.pronouns}:</p>
<Chip text={recorder.pronouns} />
</div>
)} )}
<div className="grid gap-2">
<h3 className=" text-2xl">{recorder.username}</h3>
{recorder.languages?.data && recorder.languages.data.length > 0 && (
<div className="flex flex-row flex-wrap gap-1">
<p>{langui.languages}:</p>
{filterHasAttributes(recorder.languages.data, [
"attributes",
] as const).map((language) => (
<Fragment key={language.__typename}>
<Chip text={language.attributes.code.toUpperCase()} />
</Fragment>
))}
</div>
)}
{recorder.pronouns && (
<div className="flex flex-row flex-wrap gap-1">
<p>{langui.pronouns}:</p>
<Chip text={recorder.pronouns} />
</div>
)}
</div>
</div> </div>
{recorder.bio?.[0] && <Markdawn text={recorder.bio[0].bio ?? ""} />}
</div> </div>
{recorder.bio?.[0] && (
<Markdawn text={recorder.bio[0].bio ?? ""} langui={langui} />
)}
</div>
}
placement="top"
>
<Chip
key={recorder.anonymous_code}
text={
recorder.anonymize
? `Recorder#${recorder.anonymous_code}`
: recorder.username
} }
/> placement="top"
</ToolTip> >
); <Chip
key={recorder.anonymous_code}
text={
recorder.anonymize
? `Recorder#${recorder.anonymous_code}`
: recorder.username
}
/>
</ToolTip>
);
};

View File

@ -2,11 +2,11 @@ import { Fragment, useCallback, useEffect, useMemo, useState } from "react";
import { Chip } from "./Chip"; import { Chip } from "./Chip";
import { PageSelector } from "./Inputs/PageSelector"; import { PageSelector } from "./Inputs/PageSelector";
import { Ico, Icon } from "./Ico"; import { Ico, Icon } from "./Ico";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { cJoin } from "helpers/className"; import { cJoin } from "helpers/className";
import { isDefined, isDefinedAndNotEmpty } from "helpers/others"; import { isDefined, isDefinedAndNotEmpty } from "helpers/others";
import { AnchorIds, useScrollTopOnChange } from "hooks/useScrollTopOnChange"; import { AnchorIds, useScrollTopOnChange } from "hooks/useScrollTopOnChange";
import { useIs3ColumnsLayout } from "hooks/useContainerQuery"; import { useIs3ColumnsLayout } from "hooks/useContainerQuery";
import { useAppLayout } from "contexts/AppLayoutContext";
interface Group<T> { interface Group<T> {
name: string; name: string;
@ -46,7 +46,6 @@ interface Props<T> {
sortingFunction?: (a: T, b: T) => number; sortingFunction?: (a: T, b: T) => number;
// Other // Other
className?: string; className?: string;
langui: AppStaticProps["langui"];
} }
export const SmartList = <T,>({ export const SmartList = <T,>({
@ -67,10 +66,9 @@ export const SmartList = <T,>({
filteringFunction = defaultFilteringFunction, filteringFunction = defaultFilteringFunction,
sortingFunction = defaultSortingFunction, sortingFunction = defaultSortingFunction,
className, className,
langui,
}: Props<T>): JSX.Element => { }: Props<T>): JSX.Element => {
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const { langui } = useAppLayout();
useScrollTopOnChange(AnchorIds.ContentPanel, [page], paginationScroolTop); useScrollTopOnChange(AnchorIds.ContentPanel, [page], paginationScroolTop);
useEffect( useEffect(
() => setPage(0), () => setPage(0),
@ -220,7 +218,7 @@ export const SmartList = <T,>({
) : isDefined(RenderWhenEmpty) ? ( ) : isDefined(RenderWhenEmpty) ? (
<RenderWhenEmpty /> <RenderWhenEmpty />
) : ( ) : (
<DefaultRenderWhenEmpty langui={langui} /> <DefaultRenderWhenEmpty />
)} )}
</div> </div>
@ -241,12 +239,9 @@ export const SmartList = <T,>({
* PRIVATE COMPONENTS * PRIVATE COMPONENTS
*/ */
interface DefaultRenderWhenEmptyProps { const DefaultRenderWhenEmpty = () => {
langui: AppStaticProps["langui"];
}
const DefaultRenderWhenEmpty = ({ langui }: DefaultRenderWhenEmptyProps) => {
const is3ColumnsLayout = useIs3ColumnsLayout(); const is3ColumnsLayout = useIs3ColumnsLayout();
const { langui } = useAppLayout();
return ( return (
<div className="grid h-full place-content-center"> <div className="grid h-full place-content-center">
<div <div

View File

@ -3,11 +3,11 @@ import { Img } from "components/Img";
import { InsetBox } from "components/InsetBox"; import { InsetBox } from "components/InsetBox";
import { Markdawn } from "components/Markdown/Markdawn"; import { Markdawn } from "components/Markdown/Markdawn";
import { GetContentTextQuery, UploadImageFragment } from "graphql/generated"; import { GetContentTextQuery, UploadImageFragment } from "graphql/generated";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { prettyInlineTitle, prettySlug, slugify } from "helpers/formatters"; import { prettyInlineTitle, prettySlug, slugify } from "helpers/formatters";
import { getAssetURL, ImageQuality } from "helpers/img"; import { getAssetURL, ImageQuality } from "helpers/img";
import { filterHasAttributes } from "helpers/others"; import { filterHasAttributes } from "helpers/others";
import { useLightBox } from "hooks/useLightBox"; import { useLightBox } from "hooks/useLightBox";
import { useAppLayout } from "contexts/AppLayoutContext";
/* /*
* *
@ -26,14 +26,13 @@ interface Props {
NonNullable<GetContentTextQuery["contents"]>["data"][number]["attributes"] NonNullable<GetContentTextQuery["contents"]>["data"][number]["attributes"]
>["categories"]; >["categories"];
thumbnail?: UploadImageFragment | null | undefined; thumbnail?: UploadImageFragment | null | undefined;
langui: AppStaticProps["langui"];
languageSwitcher?: JSX.Element; languageSwitcher?: JSX.Element;
} }
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
export const ThumbnailHeader = ({ export const ThumbnailHeader = ({
langui,
pre_title, pre_title,
title, title,
subtitle, subtitle,
@ -44,6 +43,7 @@ export const ThumbnailHeader = ({
languageSwitcher, languageSwitcher,
}: Props): JSX.Element => { }: Props): JSX.Element => {
const [openLightBox, LightBox] = useLightBox(); const [openLightBox, LightBox] = useLightBox();
const { langui } = useAppLayout();
return ( return (
<> <>
@ -106,9 +106,7 @@ export const ThumbnailHeader = ({
{languageSwitcher} {languageSwitcher}
</div> </div>
{description && ( {description && (
<InsetBox className="mt-8"> <InsetBox className="mt-8">{<Markdawn text={description} />}</InsetBox>
{<Markdawn text={description} langui={langui} />}
</InsetBox>
)} )}
</> </>
); );

View File

@ -1,12 +1,12 @@
import { useCallback } from "react"; import { useCallback } from "react";
import { Chip } from "components/Chip"; import { Chip } from "components/Chip";
import { ToolTip } from "components/ToolTip"; import { ToolTip } from "components/ToolTip";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { getStatusDescription } from "helpers/others"; import { getStatusDescription } from "helpers/others";
import { useSmartLanguage } from "hooks/useSmartLanguage"; import { useSmartLanguage } from "hooks/useSmartLanguage";
import { Button } from "components/Inputs/Button"; import { Button } from "components/Inputs/Button";
import { useIsContentPanelNoMoreThan } from "hooks/useContainerQuery"; import { useIsContentPanelNoMoreThan } from "hooks/useContainerQuery";
import { cIf, cJoin } from "helpers/className"; import { cIf, cJoin } from "helpers/className";
import { useAppLayout } from "contexts/AppLayoutContext";
/* /*
* *
@ -23,8 +23,6 @@ interface Props {
definition: string | null | undefined; definition: string | null | undefined;
status: string | undefined; status: string | undefined;
}[]; }[];
languages: AppStaticProps["languages"];
langui: AppStaticProps["langui"];
index: number; index: number;
categories: string[]; categories: string[];
} }
@ -34,16 +32,14 @@ interface Props {
const DefinitionCard = ({ const DefinitionCard = ({
source, source,
translations = [], translations = [],
languages,
langui,
index, index,
categories, categories,
}: Props): JSX.Element => { }: Props): JSX.Element => {
const isContentPanelNoMoreThanMd = useIsContentPanelNoMoreThan("md"); const isContentPanelNoMoreThanMd = useIsContentPanelNoMoreThan("md");
const { langui } = useAppLayout();
const [selectedTranslation, LanguageSwitcher, languageSwitcherProps] = const [selectedTranslation, LanguageSwitcher, languageSwitcherProps] =
useSmartLanguage({ useSmartLanguage({
items: translations, items: translations,
languages: languages,
languageExtractor: useCallback( languageExtractor: useCallback(
(item: Props["translations"][number]) => item.language, (item: Props["translations"][number]) => item.language,
[] []

View File

@ -1,8 +1,19 @@
import React, { ReactNode, useContext, useState } from "react"; import React, {
ReactNode,
useContext,
useEffect,
useLayoutEffect,
useState,
} from "react";
import { useRouter } from "next/router";
import { useLocalStorage } from "usehooks-ts"; import { useLocalStorage } from "usehooks-ts";
import { isDefined } from "helpers/others"; import { isDefined, isDefinedAndNotEmpty } from "helpers/others";
import { LibraryItemUserStatus, RequiredNonNullable } from "helpers/types"; import { LibraryItemUserStatus, RequiredNonNullable } from "helpers/types";
import { useDarkMode } from "hooks/useDarkMode"; import { useDarkMode } from "hooks/useDarkMode";
import { Currencies, Languages, Langui } from "helpers/localData";
import { useCurrencies, useLanguages, useLangui } from "hooks/useLocalData";
import { getDefaultPreferredLanguages } from "helpers/locales";
import { useStateWithLocalStorage } from "hooks/useStateWithLocalStorage";
interface AppLayoutState { interface AppLayoutState {
subPanelOpen: boolean; subPanelOpen: boolean;
@ -17,12 +28,6 @@ interface AppLayoutState {
React.SetStateAction<AppLayoutState["configPanelOpen"]> React.SetStateAction<AppLayoutState["configPanelOpen"]>
>; >;
searchPanelOpen: boolean;
toggleSearchPanelOpen: () => void;
setSearchPanelOpen: React.Dispatch<
React.SetStateAction<AppLayoutState["searchPanelOpen"]>
>;
mainPanelReduced: boolean; mainPanelReduced: boolean;
toggleMainPanelReduced: () => void; toggleMainPanelReduced: () => void;
setMainPanelReduced: React.Dispatch< setMainPanelReduced: React.Dispatch<
@ -90,6 +95,10 @@ interface AppLayoutState {
setSubPanelWidth: React.Dispatch< setSubPanelWidth: React.Dispatch<
React.SetStateAction<AppLayoutState["subPanelWidth"]> React.SetStateAction<AppLayoutState["subPanelWidth"]>
>; >;
langui: Langui;
languages: Languages;
currencies: Currencies;
} }
const initialState: RequiredNonNullable<AppLayoutState> = { const initialState: RequiredNonNullable<AppLayoutState> = {
@ -101,10 +110,6 @@ const initialState: RequiredNonNullable<AppLayoutState> = {
setConfigPanelOpen: () => null, setConfigPanelOpen: () => null,
toggleConfigPanelOpen: () => null, toggleConfigPanelOpen: () => null,
searchPanelOpen: false,
setSearchPanelOpen: () => null,
toggleSearchPanelOpen: () => null,
mainPanelReduced: false, mainPanelReduced: false,
setMainPanelReduced: () => null, setMainPanelReduced: () => null,
toggleMainPanelReduced: () => null, toggleMainPanelReduced: () => null,
@ -152,6 +157,10 @@ const initialState: RequiredNonNullable<AppLayoutState> = {
subPanelWidth: 0, subPanelWidth: 0,
setSubPanelWidth: () => null, setSubPanelWidth: () => null,
currencies: [],
languages: [],
langui: {},
}; };
const AppContext = React.createContext<AppLayoutState>(initialState); const AppContext = React.createContext<AppLayoutState>(initialState);
@ -163,7 +172,9 @@ interface Props {
} }
export const AppContextProvider = (props: Props): JSX.Element => { export const AppContextProvider = (props: Props): JSX.Element => {
const [subPanelOpen, setSubPanelOpen] = useLocalStorage( const router = useRouter();
const [subPanelOpen, setSubPanelOpen] = useStateWithLocalStorage(
"subPanelOpen", "subPanelOpen",
initialState.subPanelOpen initialState.subPanelOpen
); );
@ -178,7 +189,7 @@ export const AppContextProvider = (props: Props): JSX.Element => {
initialState.mainPanelReduced initialState.mainPanelReduced
); );
const [mainPanelOpen, setMainPanelOpen] = useLocalStorage( const [mainPanelOpen, setMainPanelOpen] = useStateWithLocalStorage(
"mainPanelOpen", "mainPanelOpen",
initialState.mainPanelOpen initialState.mainPanelOpen
); );
@ -213,11 +224,6 @@ export const AppContextProvider = (props: Props): JSX.Element => {
const [menuGestures, setMenuGestures] = useState(false); const [menuGestures, setMenuGestures] = useState(false);
const [searchPanelOpen, setSearchPanelOpen] = useLocalStorage(
"searchPanelOpen",
initialState.searchPanelOpen
);
const [libraryItemUserStatus, setLibraryItemUserStatus] = useLocalStorage( const [libraryItemUserStatus, setLibraryItemUserStatus] = useLocalStorage(
"libraryItemUserStatus", "libraryItemUserStatus",
initialState.libraryItemUserStatus initialState.libraryItemUserStatus
@ -231,10 +237,6 @@ export const AppContextProvider = (props: Props): JSX.Element => {
setConfigPanelOpen((current) => (isDefined(current) ? !current : current)); setConfigPanelOpen((current) => (isDefined(current) ? !current : current));
}; };
const toggleSearchPanelOpen = () => {
setSearchPanelOpen((current) => (isDefined(current) ? !current : current));
};
const toggleMainPanelReduced = () => { const toggleMainPanelReduced = () => {
setMainPanelReduced((current) => (isDefined(current) ? !current : current)); setMainPanelReduced((current) => (isDefined(current) ? !current : current));
}; };
@ -265,12 +267,61 @@ export const AppContextProvider = (props: Props): JSX.Element => {
const [contentPanelWidth, setContentPanelWidth] = useState(0); const [contentPanelWidth, setContentPanelWidth] = useState(0);
const [subPanelWidth, setSubPanelWidth] = useState(0); const [subPanelWidth, setSubPanelWidth] = useState(0);
const langui = useLangui();
const languages = useLanguages();
const currencies = useCurrencies();
useEffect(() => {
if (preferredLanguages.length === 0) {
if (isDefinedAndNotEmpty(router.locale) && router.locales) {
setPreferredLanguages(
getDefaultPreferredLanguages(router.locale, router.locales)
);
}
} else if (router.locale !== preferredLanguages[0]) {
/*
* Using a timeout to the code getting stuck into a loop when reaching the website with a
* different preferredLanguages[0] from router.locale
*/
setTimeout(
async () =>
router.replace(router.asPath, router.asPath, {
locale: preferredLanguages[0],
}),
250
);
}
}, [
preferredLanguages,
router,
router.locale,
router.locales,
setPreferredLanguages,
]);
useEffect(() => {
router.events.on("routeChangeStart", () => {
setConfigPanelOpen(false);
setMainPanelOpen(false);
setSubPanelOpen(false);
});
router.events.on("hashChangeStart", () => {
setSubPanelOpen(false);
});
}, [router.events, setConfigPanelOpen, setMainPanelOpen, setSubPanelOpen]);
useLayoutEffect(() => {
document.getElementsByTagName("html")[0].style.fontSize = `${
fontSize * 100
}%`;
}, [fontSize]);
return ( return (
<AppContext.Provider <AppContext.Provider
value={{ value={{
subPanelOpen, subPanelOpen,
configPanelOpen, configPanelOpen,
searchPanelOpen,
mainPanelReduced, mainPanelReduced,
mainPanelOpen, mainPanelOpen,
darkMode, darkMode,
@ -287,7 +338,6 @@ export const AppContextProvider = (props: Props): JSX.Element => {
subPanelWidth, subPanelWidth,
setSubPanelOpen, setSubPanelOpen,
setConfigPanelOpen, setConfigPanelOpen,
setSearchPanelOpen,
setMainPanelReduced, setMainPanelReduced,
setMainPanelOpen, setMainPanelOpen,
setDarkMode, setDarkMode,
@ -301,16 +351,18 @@ export const AppContextProvider = (props: Props): JSX.Element => {
setLibraryItemUserStatus, setLibraryItemUserStatus,
toggleSubPanelOpen, toggleSubPanelOpen,
toggleConfigPanelOpen, toggleConfigPanelOpen,
toggleSearchPanelOpen,
toggleMainPanelReduced, toggleMainPanelReduced,
toggleMainPanelOpen, toggleMainPanelOpen,
toggleDarkMode, toggleDarkMode,
toggleMenuGestures, toggleMenuGestures,
toggleSelectedThemeMode, toggleSelectedThemeMode,
toggleDyslexic, toggleDyslexic,
setContentPanelWidth,
setScreenWidth, setScreenWidth,
setContentPanelWidth,
setSubPanelWidth, setSubPanelWidth,
languages,
langui,
currencies,
}} }}
> >
{props.children} {props.children}

View File

@ -0,0 +1,43 @@
/* eslint-disable import/no-nodejs-modules */
import { resolve } from "path";
import { readFileSync, writeFileSync } from "fs";
import { config } from "dotenv";
import { getReadySdk } from "./sdk";
import { LocalDataGetWebsiteInterfacesQuery } from "./generated";
import { processLangui, Langui } from "helpers/localData";
config({ path: resolve(process.cwd(), ".env.local") });
const LOCAL_DATA_FOLDER = `${process.cwd()}/public/local-data`;
const writeLocalData = (name: LocalDataFile, localData: unknown) => {
const path = `${LOCAL_DATA_FOLDER}/${name}.json`;
writeFileSync(path, JSON.stringify(localData), { encoding: "utf-8" });
console.log(`${path} has been written!`)
};
const readLocalData = <T>(name: LocalDataFile): T => {
const path = `${LOCAL_DATA_FOLDER}/${name}.json`;
return JSON.parse(readFileSync(path, { encoding: "utf8" }));
};
const sdk = getReadySdk();
(async () => {
writeLocalData(
"websiteInterfaces",
await sdk.localDataGetWebsiteInterfaces()
);
writeLocalData("currencies", await sdk.localDataGetCurrencies());
writeLocalData("languages", await sdk.localDataGetLanguages());
})();
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
export type LocalDataFile = "currencies" | "languages" | "websiteInterfaces";
export const getLangui = (locale: string | undefined): Langui => {
const websiteInterfaces =
readLocalData<LocalDataGetWebsiteInterfacesQuery>("websiteInterfaces");
return processLangui(websiteInterfaces, locale);
};

View File

@ -1,55 +0,0 @@
import { GetStaticPropsContext } from "next";
import {
GetCurrenciesQuery,
GetLanguagesQuery,
GetWebsiteInterfaceQuery,
} from "graphql/generated";
import { getReadySdk } from "graphql/sdk";
export type AppStaticProps = {
langui: NonNullable<
NonNullable<
GetWebsiteInterfaceQuery["websiteInterfaces"]
>["data"][number]["attributes"]
>;
currencies: NonNullable<GetCurrenciesQuery["currencies"]>["data"];
languages: NonNullable<GetLanguagesQuery["languages"]>["data"];
};
export const getAppStaticProps = async (
context: GetStaticPropsContext
): Promise<AppStaticProps> => {
const sdk = getReadySdk();
const { languages } = await sdk.getLanguages();
if (languages?.data) {
languages.data.sort((a, b) =>
a.attributes && b.attributes
? a.attributes.localized_name.localeCompare(b.attributes.localized_name)
: 0
);
}
const { currencies } = await sdk.getCurrencies();
if (currencies?.data) {
currencies.data.sort((a, b) =>
a.attributes && b.attributes
? a.attributes.code.localeCompare(b.attributes.code)
: 0
);
}
const langui = (
await sdk.getWebsiteInterface({
language_code: context.locale ?? "en",
})
).websiteInterfaces?.data[0].attributes;
const appStaticProps: AppStaticProps = {
langui: langui ?? {},
currencies: currencies?.data ?? [],
languages: languages?.data ?? [],
};
return appStaticProps;
};

View File

@ -1,8 +1,8 @@
import { GetStaticProps } from "next"; import { GetStaticProps } from "next";
import { AppStaticProps, getAppStaticProps } from "./getAppStaticProps";
import { getReadySdk } from "./sdk"; import { getReadySdk } from "./sdk";
import { getLangui } from "./fetchLocalData";
import { PostWithTranslations } from "helpers/types"; import { PostWithTranslations } from "helpers/types";
import { OpenGraph, getOpenGraph } from "helpers/openGraph"; import { getOpenGraph } from "helpers/openGraph";
import { prettyDate, prettySlug } from "helpers/formatters"; import { prettyDate, prettySlug } from "helpers/formatters";
import { import {
getDefaultPreferredLanguages, getDefaultPreferredLanguages,
@ -10,16 +10,17 @@ import {
} from "helpers/locales"; } from "helpers/locales";
import { filterHasAttributes, isDefined } from "helpers/others"; import { filterHasAttributes, isDefined } from "helpers/others";
import { getDescription } from "helpers/description"; import { getDescription } from "helpers/description";
import { AppLayoutRequired } from "components/AppLayout";
export interface PostStaticProps extends AppStaticProps { export interface PostStaticProps extends AppLayoutRequired {
post: PostWithTranslations; post: PostWithTranslations;
openGraph: OpenGraph;
} }
export const getPostStaticProps = export const getPostStaticProps =
(slug: string): GetStaticProps => (slug: string): GetStaticProps =>
async (context) => { async (context) => {
const sdk = getReadySdk(); const sdk = getReadySdk();
const langui = getLangui(context.locale);
const post = await sdk.getPost({ const post = await sdk.getPost({
slug: slug, slug: slug,
language_code: context.locale ?? "en", language_code: context.locale ?? "en",
@ -31,7 +32,6 @@ export const getPostStaticProps =
isDefined(context.locale) && isDefined(context.locale) &&
isDefined(context.locales) isDefined(context.locales)
) { ) {
const appStaticProps = await getAppStaticProps(context);
const selectedTranslation = staticSmartLanguage({ const selectedTranslation = staticSmartLanguage({
items: post.posts.data[0].attributes.translations, items: post.posts.data[0].attributes.translations,
languageExtractor: (item) => item.language?.data?.attributes?.code, languageExtractor: (item) => item.language?.data?.attributes?.code,
@ -44,10 +44,10 @@ export const getPostStaticProps =
const title = selectedTranslation?.title ?? prettySlug(slug); const title = selectedTranslation?.title ?? prettySlug(slug);
const description = getDescription(selectedTranslation?.excerpt, { const description = getDescription(selectedTranslation?.excerpt, {
[appStaticProps.langui.release_date ?? "Release date"]: [ [langui.release_date ?? "Release date"]: [
prettyDate(post.posts.data[0].attributes.date, context.locale), prettyDate(post.posts.data[0].attributes.date, context.locale),
], ],
[appStaticProps.langui.categories ?? "Categories"]: filterHasAttributes( [langui.categories ?? "Categories"]: filterHasAttributes(
post.posts.data[0].attributes.categories?.data, post.posts.data[0].attributes.categories?.data,
["attributes"] as const ["attributes"] as const
).map((category) => category.attributes.short), ).map((category) => category.attributes.short),
@ -58,14 +58,8 @@ export const getPostStaticProps =
post.posts.data[0].attributes.thumbnail?.data?.attributes; post.posts.data[0].attributes.thumbnail?.data?.attributes;
const props: PostStaticProps = { const props: PostStaticProps = {
...appStaticProps,
post: post.posts.data[0].attributes as PostWithTranslations, post: post.posts.data[0].attributes as PostWithTranslations,
openGraph: getOpenGraph( openGraph: getOpenGraph(langui, title, description, thumbnail),
appStaticProps.langui,
title,
description,
thumbnail
),
}; };
return { return {
props: props, props: props,

View File

@ -1,4 +1,4 @@
query getCurrencies { query localDataGetCurrencies {
currencies(pagination: { limit: -1 }) { currencies(pagination: { limit: -1 }) {
data { data {
id id

View File

@ -1,4 +1,4 @@
query getLanguages { query localDataGetLanguages {
languages(pagination: { limit: -1 }) { languages(pagination: { limit: -1 }) {
data { data {
id id

View File

@ -1,9 +1,14 @@
query getWebsiteInterface($language_code: String) { query localDataGetWebsiteInterfaces {
websiteInterfaces( websiteInterfaces(pagination: { limit: -1 }) {
filters: { ui_language: { code: { eq: $language_code } } }
) {
data { data {
attributes { attributes {
ui_language {
data {
attributes {
code
}
}
}
library library
contents contents
wiki wiki

View File

@ -1,7 +1,7 @@
import { AppStaticProps } from "../graphql/getAppStaticProps";
import { convertPrice } from "./numbers"; import { convertPrice } from "./numbers";
import { isDefinedAndNotEmpty, isUndefined } from "./others"; import { isDefinedAndNotEmpty, isUndefined } from "./others";
import { datePickerToDate } from "./date"; import { datePickerToDate } from "./date";
import { Currencies, Languages, Langui } from "./localData";
import { DatePickerFragment, PricePickerFragment } from "graphql/generated"; import { DatePickerFragment, PricePickerFragment } from "graphql/generated";
export const prettyDate = ( export const prettyDate = (
@ -12,7 +12,7 @@ export const prettyDate = (
export const prettyPrice = ( export const prettyPrice = (
pricePicker: PricePickerFragment, pricePicker: PricePickerFragment,
currencies: AppStaticProps["currencies"], currencies: Currencies,
targetCurrencyCode?: string targetCurrencyCode?: string
): string => { ): string => {
if (!targetCurrencyCode) return ""; if (!targetCurrencyCode) return "";
@ -58,10 +58,7 @@ export const prettyInlineTitle = (
return result; return result;
}; };
export const prettyItemType = ( export const prettyItemType = (metadata: any, langui: Langui): string => {
metadata: any,
langui: AppStaticProps["langui"]
): string => {
switch (metadata.__typename) { switch (metadata.__typename) {
case "ComponentMetadataAudio": case "ComponentMetadataAudio":
return langui.audio ?? "Audio"; return langui.audio ?? "Audio";
@ -242,10 +239,7 @@ export const prettyDuration = (seconds: number): string => {
return result; return result;
}; };
export const prettyLanguage = ( export const prettyLanguage = (code: string, languages: Languages): string => {
code: string,
languages: AppStaticProps["languages"]
): string => {
let result = code; let result = code;
languages.forEach((language) => { languages.forEach((language) => {
if (language.attributes?.code === code) if (language.attributes?.code === code)

58
src/helpers/localData.ts Normal file
View File

@ -0,0 +1,58 @@
import {
LocalDataGetCurrenciesQuery,
LocalDataGetLanguagesQuery,
LocalDataGetWebsiteInterfacesQuery,
} from "graphql/generated";
export type Langui = NonNullable<
NonNullable<
LocalDataGetWebsiteInterfacesQuery["websiteInterfaces"]
>["data"][number]["attributes"]
>;
export const processLangui = (
websiteInterfaces: LocalDataGetWebsiteInterfacesQuery | undefined,
locale: string | undefined
): Langui =>
websiteInterfaces?.websiteInterfaces?.data.find(
(langui) =>
langui.attributes?.ui_language?.data?.attributes?.code === locale
)?.attributes ?? {};
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
export type Currencies = NonNullable<
LocalDataGetCurrenciesQuery["currencies"]
>["data"];
export const processCurrencies = (
currencies: LocalDataGetCurrenciesQuery | undefined
): Currencies => {
if (currencies?.currencies?.data) {
currencies.currencies.data.sort((a, b) =>
a.attributes && b.attributes
? a.attributes.code.localeCompare(b.attributes.code)
: 0
);
}
return currencies?.currencies?.data ?? [];
};
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
export type Languages = NonNullable<
LocalDataGetLanguagesQuery["languages"]
>["data"];
export const processLanguages = (
languages: LocalDataGetLanguagesQuery | undefined
): Languages => {
if (languages?.languages?.data) {
languages.languages.data.sort((a, b) =>
a.attributes && b.attributes
? a.attributes.localized_name.localeCompare(b.attributes.localized_name)
: 0
);
}
return languages?.languages?.data ?? [];
};

View File

@ -1,8 +1,9 @@
import { GetCurrenciesQuery, PricePickerFragment } from "graphql/generated"; import { Currencies } from "./localData";
import { PricePickerFragment } from "graphql/generated";
export const convertPrice = ( export const convertPrice = (
pricePicker: PricePickerFragment, pricePicker: PricePickerFragment,
targetCurrency: NonNullable<GetCurrenciesQuery["currencies"]>["data"][number] targetCurrency: Currencies[number]
): number => { ): number => {
if ( if (
pricePicker.amount && pricePicker.amount &&

View File

@ -5,8 +5,8 @@ import {
getAssetURL, getAssetURL,
} from "./img"; } from "./img";
import { isDefinedAndNotEmpty } from "./others"; import { isDefinedAndNotEmpty } from "./others";
import { Langui } from "./localData";
import { UploadImageFragment } from "graphql/generated"; import { UploadImageFragment } from "graphql/generated";
import { AppStaticProps } from "graphql/getAppStaticProps";
const DEFAULT_OG_THUMBNAIL = { const DEFAULT_OG_THUMBNAIL = {
image: `${process.env.NEXT_PUBLIC_URL_SELF}/default_og.jpg`, image: `${process.env.NEXT_PUBLIC_URL_SELF}/default_og.jpg`,
@ -25,7 +25,7 @@ export interface OpenGraph {
} }
export const getOpenGraph = ( export const getOpenGraph = (
langui: AppStaticProps["langui"], langui: Langui,
title?: string | null | undefined, title?: string | null | undefined,
description?: string | null | undefined, description?: string | null | undefined,
thumbnail?: UploadImageFragment | null | undefined thumbnail?: UploadImageFragment | null | undefined

View File

@ -1,5 +1,5 @@
import { AppStaticProps } from "../graphql/getAppStaticProps";
import { PathDot, SelectiveNonNullable } from "./types/SelectiveNonNullable"; import { PathDot, SelectiveNonNullable } from "./types/SelectiveNonNullable";
import { Langui } from "./localData";
import { import {
Enum_Componentsetstextset_Status, Enum_Componentsetstextset_Status,
GetLibraryItemQuery, GetLibraryItemQuery,
@ -35,7 +35,7 @@ export const sortRangedContent = (contents: SortRangedContentProps): void => {
export const getStatusDescription = ( export const getStatusDescription = (
status: string, status: string,
langui: AppStaticProps["langui"] langui: Langui
): string | null | undefined => { ): string | null | undefined => {
switch (status) { switch (status) {
case Enum_Componentsetstextset_Status.Incomplete: case Enum_Componentsetstextset_Status.Incomplete:
@ -112,13 +112,11 @@ export const iterateMap = <K, V, U>(
return toList.map(([key, value], index) => callbackfn(key, value, index)); return toList.map(([key, value], index) => callbackfn(key, value, index));
}; };
export const mapMoveEntry = <K, V>( export const arrayMove = <T>(
map: Map<K, V>, arr: T[],
sourceIndex: number, sourceIndex: number,
targetIndex: number targetIndex: number
): Map<K, V> => new Map(arrayMove([...map], sourceIndex, targetIndex)); ): T[] => {
const arrayMove = <T>(arr: T[], sourceIndex: number, targetIndex: number) => {
arr.splice(targetIndex, 0, arr.splice(sourceIndex, 1)[0]); arr.splice(targetIndex, 0, arr.splice(sourceIndex, 1)[0]);
return arr; return arr;
}; };

View File

@ -1,6 +1,6 @@
import { useEffect } from "react"; import { useEffect } from "react";
import { useLocalStorage } from "usehooks-ts";
import { usePrefersDarkMode } from "./useMediaQuery"; import { usePrefersDarkMode } from "./useMediaQuery";
import { useStateWithLocalStorage } from "./useStateWithLocalStorage";
export const useDarkMode = ( export const useDarkMode = (
key: string, key: string,
@ -11,9 +11,9 @@ export const useDarkMode = (
React.Dispatch<React.SetStateAction<boolean>>, React.Dispatch<React.SetStateAction<boolean>>,
React.Dispatch<React.SetStateAction<boolean>> React.Dispatch<React.SetStateAction<boolean>>
] => { ] => {
const [darkMode, setDarkMode] = useLocalStorage(key, initialValue); const [darkMode, setDarkMode] = useStateWithLocalStorage(key, initialValue);
const prefersDarkMode = usePrefersDarkMode(); const prefersDarkMode = usePrefersDarkMode();
const [selectedThemeMode, setSelectedThemeMode] = useLocalStorage( const [selectedThemeMode, setSelectedThemeMode] = useStateWithLocalStorage(
"selectedThemeMode", "selectedThemeMode",
false false
); );

35
src/hooks/useLocalData.ts Normal file
View File

@ -0,0 +1,35 @@
import { useFetch } from "usehooks-ts";
import { useRouter } from "next/router";
import { useMemo } from "react";
import { LocalDataGetWebsiteInterfacesQuery } from "graphql/generated";
import {
Currencies,
Languages,
Langui,
processCurrencies,
processLanguages,
processLangui,
} from "helpers/localData";
import { LocalDataFile } from "graphql/fetchLocalData";
const useFetchLocalData = (name: LocalDataFile) =>
useFetch<LocalDataGetWebsiteInterfacesQuery>(`/local-data/${name}.json`);
export const useLangui = (): Langui => {
const { locale } = useRouter();
const { data: websiteInterfaces } = useFetchLocalData("websiteInterfaces");
return useMemo(
() => processLangui(websiteInterfaces, locale),
[websiteInterfaces, locale]
);
};
export const useCurrencies = (): Currencies => {
const { data: currencies } = useFetchLocalData("currencies");
return useMemo(() => processCurrencies(currencies), [currencies]);
};
export const useLanguages = (): Languages => {
const { data: languages } = useFetchLocalData("languages");
return useMemo(() => processLanguages(languages), [languages]);
};

View File

@ -1,14 +1,13 @@
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { useEffect, useMemo, useState } from "react"; import { useEffect, useMemo, useState } from "react";
import { useLanguages } from "./useLocalData";
import { LanguageSwitcher } from "components/Inputs/LanguageSwitcher"; import { LanguageSwitcher } from "components/Inputs/LanguageSwitcher";
import { useAppLayout } from "contexts/AppLayoutContext"; import { useAppLayout } from "contexts/AppLayoutContext";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { filterDefined, isDefined } from "helpers/others"; import { filterDefined, isDefined } from "helpers/others";
import { getPreferredLanguage } from "helpers/locales"; import { getPreferredLanguage } from "helpers/locales";
interface Props<T> { interface Props<T> {
items: T[]; items: T[];
languages?: AppStaticProps["languages"];
languageExtractor: (item: NonNullable<T>) => string | undefined; languageExtractor: (item: NonNullable<T>) => string | undefined;
transform?: (item: NonNullable<T>) => NonNullable<T>; transform?: (item: NonNullable<T>) => NonNullable<T>;
} }
@ -16,7 +15,6 @@ interface Props<T> {
export const useSmartLanguage = <T>({ export const useSmartLanguage = <T>({
items, items,
languageExtractor, languageExtractor,
languages = [],
transform = (item) => item, transform = (item) => item,
}: Props<T>): [ }: Props<T>): [
T | undefined, T | undefined,
@ -24,6 +22,7 @@ export const useSmartLanguage = <T>({
Parameters<typeof LanguageSwitcher>[0] Parameters<typeof LanguageSwitcher>[0]
] => { ] => {
const { preferredLanguages } = useAppLayout(); const { preferredLanguages } = useAppLayout();
const languages = useLanguages();
const router = useRouter(); const router = useRouter();
const availableLocales = useMemo(() => { const availableLocales = useMemo(() => {

View File

@ -0,0 +1,31 @@
import { useEffect, useState } from "react";
import { isDefined } from "helpers/others";
export const useStateWithLocalStorage = <T>(
key: string,
initialValue: T
): [T, React.Dispatch<React.SetStateAction<T>>] => {
const [value, setValue] = useState<T>(initialValue);
const [isFromLocaleStorage, setFromLocaleStorage] = useState<boolean>(false);
useEffect(() => {
try {
const item = localStorage.getItem(key);
if (isDefined(item)) {
setValue(JSON.parse(item) as T);
} else {
setValue(initialValue);
}
setFromLocaleStorage(true);
} catch (error) {
console.warn(`Error reading localStorage key “${key}”:`, error);
setValue(initialValue);
}
}, [initialValue, key]);
useEffect(() => {
if (isFromLocaleStorage) localStorage.setItem(key, JSON.stringify(value));
}, [value, key, isFromLocaleStorage]);
return [value, setValue];
};

View File

@ -2,30 +2,25 @@ import { GetStaticProps } from "next";
import { AppLayout, AppLayoutRequired } from "components/AppLayout"; import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { ReturnButton } from "components/PanelComponents/ReturnButton"; import { ReturnButton } from "components/PanelComponents/ReturnButton";
import { ContentPanel } from "components/Panels/ContentPanel"; import { ContentPanel } from "components/Panels/ContentPanel";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getOpenGraph } from "helpers/openGraph"; import { getOpenGraph } from "helpers/openGraph";
import { getLangui } from "graphql/fetchLocalData";
/* /*
* *
* PAGE * PAGE
*/ */
interface Props extends AppStaticProps, AppLayoutRequired {} interface Props extends AppLayoutRequired {}
const FourOhFour = ({ const FourOhFour = ({ openGraph, ...otherProps }: Props): JSX.Element => (
langui,
openGraph,
...otherProps
}: Props): JSX.Element => (
<AppLayout <AppLayout
contentPanel={ contentPanel={
<ContentPanel> <ContentPanel>
<h1>{openGraph.title}</h1> <h1>{openGraph.title}</h1>
<ReturnButton href="/" title="Home" langui={langui} /> <ReturnButton href="/" title="Home" />
</ContentPanel> </ContentPanel>
} }
openGraph={openGraph} openGraph={openGraph}
langui={langui}
{...otherProps} {...otherProps}
/> />
); );
@ -36,14 +31,10 @@ export default FourOhFour;
* NEXT DATA FETCHING * NEXT DATA FETCHING
*/ */
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = (context) => {
const appStaticProps = await getAppStaticProps(context); const langui = getLangui(context.locale);
const props: Props = { const props: Props = {
...appStaticProps, openGraph: getOpenGraph(langui, `404 - ${langui.page_not_found}`),
openGraph: getOpenGraph(
appStaticProps.langui,
`404 - ${appStaticProps.langui.page_not_found}`
),
}; };
return { return {
props: props, props: props,

View File

@ -2,30 +2,25 @@ import { GetStaticProps } from "next";
import { AppLayout, AppLayoutRequired } from "components/AppLayout"; import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { ReturnButton } from "components/PanelComponents/ReturnButton"; import { ReturnButton } from "components/PanelComponents/ReturnButton";
import { ContentPanel } from "components/Panels/ContentPanel"; import { ContentPanel } from "components/Panels/ContentPanel";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getOpenGraph } from "helpers/openGraph"; import { getOpenGraph } from "helpers/openGraph";
import { getLangui } from "graphql/fetchLocalData";
/* /*
* *
* PAGE * PAGE
*/ */
interface Props extends AppStaticProps, AppLayoutRequired {} interface Props extends AppLayoutRequired {}
const FiveHundred = ({ const FiveHundred = ({ openGraph, ...otherProps }: Props): JSX.Element => (
langui,
openGraph,
...otherProps
}: Props): JSX.Element => (
<AppLayout <AppLayout
contentPanel={ contentPanel={
<ContentPanel> <ContentPanel>
<h1>{openGraph.title}</h1> <h1>{openGraph.title}</h1>
<ReturnButton href="/" title="Home" langui={langui} /> <ReturnButton href="/" title="Home" />
</ContentPanel> </ContentPanel>
} }
openGraph={openGraph} openGraph={openGraph}
langui={langui}
{...otherProps} {...otherProps}
/> />
); );
@ -36,14 +31,10 @@ export default FiveHundred;
* NEXT DATA FETCHING * NEXT DATA FETCHING
*/ */
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = (context) => {
const appStaticProps = await getAppStaticProps(context); const langui = getLangui(context.locale);
const props: Props = { const props: Props = {
...appStaticProps, openGraph: getOpenGraph(langui, "500 - Internal Server Error"),
openGraph: getOpenGraph(
appStaticProps.langui,
"500 - Internal Server Error"
),
}; };
return { return {
props: props, props: props,

View File

@ -3,21 +3,25 @@ import {
getPostStaticProps, getPostStaticProps,
PostStaticProps, PostStaticProps,
} from "graphql/getPostStaticProps"; } from "graphql/getPostStaticProps";
import { useAppLayout } from "contexts/AppLayoutContext";
/* /*
* *
* PAGE * PAGE
*/ */
const AccordsHandbook = (props: PostStaticProps): JSX.Element => ( const AccordsHandbook = (props: PostStaticProps): JSX.Element => {
<PostPage const { langui } = useAppLayout();
{...props} return (
returnHref="/about-us/" <PostPage
returnTitle={props.langui.about_us} {...props}
displayToc returnHref="/about-us/"
displayLanguageSwitcher returnTitle={langui.about_us}
/> displayToc
); displayLanguageSwitcher
/>
);
};
export default AccordsHandbook; export default AccordsHandbook;
/* /*

View File

@ -10,14 +10,16 @@ import { cIf, cJoin } from "helpers/className";
import { randomInt } from "helpers/numbers"; import { randomInt } from "helpers/numbers";
import { RequestMailProps, ResponseMailProps } from "pages/api/mail"; import { RequestMailProps, ResponseMailProps } from "pages/api/mail";
import { useIs1ColumnLayout } from "hooks/useContainerQuery"; import { useIs1ColumnLayout } from "hooks/useContainerQuery";
import { useAppLayout } from "contexts/AppLayoutContext";
/* /*
* *
* PAGE * PAGE
*/ */
const AboutUs = ({ langui, ...otherProps }: PostStaticProps): JSX.Element => { const AboutUs = (props: PostStaticProps): JSX.Element => {
const router = useRouter(); const router = useRouter();
const { langui } = useAppLayout();
const is1ColumnLayout = useIs1ColumnLayout(); const is1ColumnLayout = useIs1ColumnLayout();
const [formResponse, setFormResponse] = useState(""); const [formResponse, setFormResponse] = useState("");
const [formState, setFormState] = useState<"completed" | "ongoing" | "stale">( const [formState, setFormState] = useState<"completed" | "ongoing" | "stale">(
@ -174,8 +176,7 @@ const AboutUs = ({ langui, ...otherProps }: PostStaticProps): JSX.Element => {
return ( return (
<PostPage <PostPage
{...otherProps} {...props}
langui={langui}
returnHref="/about-us/" returnHref="/about-us/"
returnTitle={langui.about_us} returnTitle={langui.about_us}
displayToc displayToc

View File

@ -4,47 +4,50 @@ import { Icon } from "components/Ico";
import { NavOption } from "components/PanelComponents/NavOption"; import { NavOption } from "components/PanelComponents/NavOption";
import { PanelHeader } from "components/PanelComponents/PanelHeader"; import { PanelHeader } from "components/PanelComponents/PanelHeader";
import { SubPanel } from "components/Panels/SubPanel"; import { SubPanel } from "components/Panels/SubPanel";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getOpenGraph } from "helpers/openGraph"; import { getOpenGraph } from "helpers/openGraph";
import { HorizontalLine } from "components/HorizontalLine"; import { HorizontalLine } from "components/HorizontalLine";
import { useAppLayout } from "contexts/AppLayoutContext";
import { getLangui } from "graphql/fetchLocalData";
/* /*
* *
* PAGE * PAGE
*/ */
interface Props extends AppStaticProps, AppLayoutRequired {} interface Props extends AppLayoutRequired {}
const AboutUs = ({ langui, ...otherProps }: Props): JSX.Element => ( const AboutUs = (props: Props): JSX.Element => {
<AppLayout const { langui } = useAppLayout();
subPanel={ return (
<SubPanel> <AppLayout
<PanelHeader subPanel={
icon={Icon.Info} <SubPanel>
title={langui.about_us} <PanelHeader
description={langui.about_us_description} icon={Icon.Info}
/> title={langui.about_us}
description={langui.about_us_description}
/>
<HorizontalLine /> <HorizontalLine />
<NavOption <NavOption
title={langui.accords_handbook} title={langui.accords_handbook}
url="/about-us/accords-handbook" url="/about-us/accords-handbook"
border border
/> />
<NavOption title={langui.legality} url="/about-us/legality" border /> <NavOption title={langui.legality} url="/about-us/legality" border />
<NavOption <NavOption
title={langui.sharing_policy} title={langui.sharing_policy}
url="/about-us/sharing-policy" url="/about-us/sharing-policy"
border border
/> />
<NavOption title={langui.contact_us} url="/about-us/contact" border /> <NavOption title={langui.contact_us} url="/about-us/contact" border />
</SubPanel> </SubPanel>
} }
langui={langui} {...props}
{...otherProps} />
/> );
); };
export default AboutUs; export default AboutUs;
/* /*
@ -52,14 +55,10 @@ export default AboutUs;
* NEXT DATA FETCHING * NEXT DATA FETCHING
*/ */
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = (context) => {
const appStaticProps = await getAppStaticProps(context); const langui = getLangui(context.locale);
const props: Props = { const props: Props = {
...appStaticProps, openGraph: getOpenGraph(langui, langui.about_us ?? "About us"),
openGraph: getOpenGraph(
appStaticProps.langui,
appStaticProps.langui.about_us ?? "About us"
),
}; };
return { return {
props: props, props: props,

View File

@ -3,21 +3,25 @@ import {
getPostStaticProps, getPostStaticProps,
PostStaticProps, PostStaticProps,
} from "graphql/getPostStaticProps"; } from "graphql/getPostStaticProps";
import { useAppLayout } from "contexts/AppLayoutContext";
/* /*
* *
* PAGE * PAGE
*/ */
const Legality = (props: PostStaticProps): JSX.Element => ( const Legality = (props: PostStaticProps): JSX.Element => {
<PostPage const { langui } = useAppLayout();
{...props} return (
returnHref="/about-us/" <PostPage
returnTitle={props.langui.about_us} {...props}
displayToc returnHref="/about-us/"
displayLanguageSwitcher returnTitle={langui.about_us}
/> displayToc
); displayLanguageSwitcher
/>
);
};
export default Legality; export default Legality;
/* /*

View File

@ -3,21 +3,25 @@ import {
getPostStaticProps, getPostStaticProps,
PostStaticProps, PostStaticProps,
} from "graphql/getPostStaticProps"; } from "graphql/getPostStaticProps";
import { useAppLayout } from "contexts/AppLayoutContext";
/* /*
* *
* PAGE * PAGE
*/ */
const SharingPolicy = (props: PostStaticProps): JSX.Element => ( const SharingPolicy = (props: PostStaticProps): JSX.Element => {
<PostPage const { langui } = useAppLayout();
{...props} return (
returnHref="/about-us/" <PostPage
returnTitle={props.langui.about_us} {...props}
displayToc returnHref="/about-us/"
displayLanguageSwitcher returnTitle={langui.about_us}
/> displayToc
); displayLanguageSwitcher
/>
);
};
export default SharingPolicy; export default SharingPolicy;
/* /*

View File

@ -4,19 +4,21 @@ import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { NavOption } from "components/PanelComponents/NavOption"; import { NavOption } from "components/PanelComponents/NavOption";
import { PanelHeader } from "components/PanelComponents/PanelHeader"; import { PanelHeader } from "components/PanelComponents/PanelHeader";
import { SubPanel } from "components/Panels/SubPanel"; import { SubPanel } from "components/Panels/SubPanel";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Icon } from "components/Ico"; import { Icon } from "components/Ico";
import { getOpenGraph } from "helpers/openGraph"; import { getOpenGraph } from "helpers/openGraph";
import { HorizontalLine } from "components/HorizontalLine"; import { HorizontalLine } from "components/HorizontalLine";
import { useAppLayout } from "contexts/AppLayoutContext";
import { getLangui } from "graphql/fetchLocalData";
/* /*
* *
* PAGE * PAGE
*/ */
interface Props extends AppStaticProps, AppLayoutRequired {} interface Props extends AppLayoutRequired {}
const Archives = ({ langui, ...otherProps }: Props): JSX.Element => { const Archives = (props: Props): JSX.Element => {
const { langui } = useAppLayout();
const subPanel = useMemo( const subPanel = useMemo(
() => ( () => (
<SubPanel> <SubPanel>
@ -31,7 +33,7 @@ const Archives = ({ langui, ...otherProps }: Props): JSX.Element => {
), ),
[langui] [langui]
); );
return <AppLayout subPanel={subPanel} langui={langui} {...otherProps} />; return <AppLayout subPanel={subPanel} {...props} />;
}; };
export default Archives; export default Archives;
@ -40,14 +42,10 @@ export default Archives;
* NEXT DATA FETCHING * NEXT DATA FETCHING
*/ */
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = (context) => {
const appStaticProps = await getAppStaticProps(context); const langui = getLangui(context.locale);
const props: Props = { const props: Props = {
...appStaticProps, openGraph: getOpenGraph(langui, langui.archives ?? "Archives"),
openGraph: getOpenGraph(
appStaticProps.langui,
appStaticProps.langui.archives ?? "Archives"
),
}; };
return { return {
props: props, props: props,

View File

@ -12,7 +12,6 @@ import {
import { SubPanel } from "components/Panels/SubPanel"; import { SubPanel } from "components/Panels/SubPanel";
import { PreviewCard } from "components/PreviewCard"; import { PreviewCard } from "components/PreviewCard";
import { GetVideoChannelQuery } from "graphql/generated"; import { GetVideoChannelQuery } from "graphql/generated";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk"; import { getReadySdk } from "graphql/sdk";
import { getVideoThumbnailURL } from "helpers/videos"; import { getVideoThumbnailURL } from "helpers/videos";
import { Icon } from "components/Ico"; import { Icon } from "components/Ico";
@ -26,6 +25,8 @@ import { SmartList } from "components/SmartList";
import { cIf } from "helpers/className"; import { cIf } from "helpers/className";
import { useIsContentPanelAtLeast } from "hooks/useContainerQuery"; import { useIsContentPanelAtLeast } from "hooks/useContainerQuery";
import { TextInput } from "components/Inputs/TextInput"; import { TextInput } from "components/Inputs/TextInput";
import { useAppLayout } from "contexts/AppLayoutContext";
import { getLangui } from "graphql/fetchLocalData";
/* /*
* *
@ -41,15 +42,16 @@ const DEFAULT_FILTERS_STATE = {
* PAGE * PAGE
*/ */
interface Props extends AppStaticProps, AppLayoutRequired { interface Props extends AppLayoutRequired {
channel: NonNullable< channel: NonNullable<
GetVideoChannelQuery["videoChannels"] GetVideoChannelQuery["videoChannels"]
>["data"][number]["attributes"]; >["data"][number]["attributes"];
} }
const Channel = ({ langui, channel, ...otherProps }: Props): JSX.Element => { const Channel = ({ channel, ...otherProps }: Props): JSX.Element => {
const { value: keepInfoVisible, toggle: toggleKeepInfoVisible } = const { value: keepInfoVisible, toggle: toggleKeepInfoVisible } =
useBoolean(true); useBoolean(true);
const { langui } = useAppLayout();
const hoverable = useDeviceSupportsHover(); const hoverable = useDeviceSupportsHover();
const isContentPanelAtLeast4xl = useIsContentPanelAtLeast("4xl"); const isContentPanelAtLeast4xl = useIsContentPanelAtLeast("4xl");
@ -63,7 +65,6 @@ const Channel = ({ langui, channel, ...otherProps }: Props): JSX.Element => {
<ReturnButton <ReturnButton
href="/archives/videos/" href="/archives/videos/"
title={langui.videos} title={langui.videos}
langui={langui}
displayOnlyOn={"3ColumnsLayout"} displayOnlyOn={"3ColumnsLayout"}
className="mb-10" className="mb-10"
/> />
@ -122,7 +123,6 @@ const Channel = ({ langui, channel, ...otherProps }: Props): JSX.Element => {
}} }}
/> />
)} )}
langui={langui}
className={cIf( className={cIf(
isContentPanelAtLeast4xl, isContentPanelAtLeast4xl,
"grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))] gap-x-6 gap-y-8", "grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))] gap-x-6 gap-y-8",
@ -140,7 +140,6 @@ const Channel = ({ langui, channel, ...otherProps }: Props): JSX.Element => {
channel?.videos?.data, channel?.videos?.data,
isContentPanelAtLeast4xl, isContentPanelAtLeast4xl,
keepInfoVisible, keepInfoVisible,
langui,
searchName, searchName,
] ]
); );
@ -149,7 +148,6 @@ const Channel = ({ langui, channel, ...otherProps }: Props): JSX.Element => {
<AppLayout <AppLayout
subPanel={subPanel} subPanel={subPanel}
contentPanel={contentPanel} contentPanel={contentPanel}
langui={langui}
{...otherProps} {...otherProps}
/> />
); );
@ -163,6 +161,7 @@ export default Channel;
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = async (context) => {
const sdk = getReadySdk(); const sdk = getReadySdk();
const langui = getLangui(context.locale);
const channel = await sdk.getVideoChannel({ const channel = await sdk.getVideoChannel({
channel: channel:
context.params && isDefined(context.params.uid) context.params && isDefined(context.params.uid)
@ -177,12 +176,10 @@ export const getStaticProps: GetStaticProps = async (context) => {
) )
.reverse(); .reverse();
const appStaticProps = await getAppStaticProps(context);
const props: Props = { const props: Props = {
...appStaticProps,
channel: channel.videoChannels.data[0].attributes, channel: channel.videoChannels.data[0].attributes,
openGraph: getOpenGraph( openGraph: getOpenGraph(
appStaticProps.langui, langui,
channel.videoChannels.data[0].attributes.title channel.videoChannels.data[0].attributes.title
), ),
}; };

View File

@ -16,7 +16,6 @@ import {
import { SubPanel } from "components/Panels/SubPanel"; import { SubPanel } from "components/Panels/SubPanel";
import { PreviewCard } from "components/PreviewCard"; import { PreviewCard } from "components/PreviewCard";
import { GetVideosPreviewQuery } from "graphql/generated"; import { GetVideosPreviewQuery } from "graphql/generated";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk"; import { getReadySdk } from "graphql/sdk";
import { filterHasAttributes } from "helpers/others"; import { filterHasAttributes } from "helpers/others";
import { getVideoThumbnailURL } from "helpers/videos"; import { getVideoThumbnailURL } from "helpers/videos";
@ -26,6 +25,8 @@ import { compareDate } from "helpers/date";
import { HorizontalLine } from "components/HorizontalLine"; import { HorizontalLine } from "components/HorizontalLine";
import { cIf } from "helpers/className"; import { cIf } from "helpers/className";
import { useIsContentPanelAtLeast } from "hooks/useContainerQuery"; import { useIsContentPanelAtLeast } from "hooks/useContainerQuery";
import { useAppLayout } from "contexts/AppLayoutContext";
import { getLangui } from "graphql/fetchLocalData";
/* /*
* *
@ -41,11 +42,12 @@ const DEFAULT_FILTERS_STATE = {
* PAGE * PAGE
*/ */
interface Props extends AppStaticProps, AppLayoutRequired { interface Props extends AppLayoutRequired {
videos: NonNullable<GetVideosPreviewQuery["videos"]>["data"]; videos: NonNullable<GetVideosPreviewQuery["videos"]>["data"];
} }
const Videos = ({ langui, videos, ...otherProps }: Props): JSX.Element => { const Videos = ({ videos, ...otherProps }: Props): JSX.Element => {
const { langui } = useAppLayout();
const hoverable = useDeviceSupportsHover(); const hoverable = useDeviceSupportsHover();
const isContentPanelAtLeast4xl = useIsContentPanelAtLeast("4xl"); const isContentPanelAtLeast4xl = useIsContentPanelAtLeast("4xl");
@ -62,7 +64,6 @@ const Videos = ({ langui, videos, ...otherProps }: Props): JSX.Element => {
<ReturnButton <ReturnButton
href="/archives/" href="/archives/"
title={"Archives"} title={"Archives"}
langui={langui}
displayOnlyOn={"3ColumnsLayout"} displayOnlyOn={"3ColumnsLayout"}
className="mb-10" className="mb-10"
/> />
@ -118,7 +119,6 @@ const Videos = ({ langui, videos, ...otherProps }: Props): JSX.Element => {
}} }}
/> />
)} )}
langui={langui}
className={cIf( className={cIf(
isContentPanelAtLeast4xl, isContentPanelAtLeast4xl,
"grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))] gap-x-6 gap-y-8", "grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))] gap-x-6 gap-y-8",
@ -130,13 +130,12 @@ const Videos = ({ langui, videos, ...otherProps }: Props): JSX.Element => {
/> />
</ContentPanel> </ContentPanel>
), ),
[isContentPanelAtLeast4xl, keepInfoVisible, langui, searchName, videos] [isContentPanelAtLeast4xl, keepInfoVisible, searchName, videos]
); );
return ( return (
<AppLayout <AppLayout
subPanel={subPanel} subPanel={subPanel}
contentPanel={contentPanel} contentPanel={contentPanel}
langui={langui}
{...otherProps} {...otherProps}
/> />
); );
@ -150,6 +149,7 @@ export default Videos;
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = async (context) => {
const sdk = getReadySdk(); const sdk = getReadySdk();
const langui = getLangui(context.locale);
const videos = await sdk.getVideosPreview(); const videos = await sdk.getVideosPreview();
if (!videos.videos) return { notFound: true }; if (!videos.videos) return { notFound: true };
videos.videos.data videos.videos.data
@ -157,14 +157,10 @@ export const getStaticProps: GetStaticProps = async (context) => {
compareDate(a.attributes?.published_date, b.attributes?.published_date) compareDate(a.attributes?.published_date, b.attributes?.published_date)
) )
.reverse(); .reverse();
const appStaticProps = await getAppStaticProps(context);
const props: Props = { const props: Props = {
...appStaticProps,
videos: videos.videos.data, videos: videos.videos.data,
openGraph: getOpenGraph( openGraph: getOpenGraph(langui, langui.videos ?? "Videos"),
appStaticProps.langui,
appStaticProps.langui.videos ?? "Videos"
),
}; };
return { return {
props: props, props: props,

View File

@ -15,28 +15,28 @@ import {
import { SubPanel } from "components/Panels/SubPanel"; import { SubPanel } from "components/Panels/SubPanel";
import { useAppLayout } from "contexts/AppLayoutContext"; import { useAppLayout } from "contexts/AppLayoutContext";
import { GetVideoQuery } from "graphql/generated"; import { GetVideoQuery } from "graphql/generated";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk"; import { getReadySdk } from "graphql/sdk";
import { prettyDate, prettyShortenNumber } from "helpers/formatters"; import { prettyDate, prettyShortenNumber } from "helpers/formatters";
import { filterHasAttributes, isDefined } from "helpers/others"; import { filterHasAttributes, isDefined } from "helpers/others";
import { getVideoFile } from "helpers/videos"; import { getVideoFile } from "helpers/videos";
import { getOpenGraph } from "helpers/openGraph"; import { getOpenGraph } from "helpers/openGraph";
import { useIsContentPanelAtLeast } from "hooks/useContainerQuery"; import { useIsContentPanelAtLeast } from "hooks/useContainerQuery";
import { getLangui } from "graphql/fetchLocalData";
/* /*
* *
* PAGE * PAGE
*/ */
interface Props extends AppStaticProps, AppLayoutRequired { interface Props extends AppLayoutRequired {
video: NonNullable< video: NonNullable<
NonNullable<GetVideoQuery["videos"]>["data"][number]["attributes"] NonNullable<GetVideoQuery["videos"]>["data"][number]["attributes"]
>; >;
} }
const Video = ({ langui, video, ...otherProps }: Props): JSX.Element => { const Video = ({ video, ...otherProps }: Props): JSX.Element => {
const isContentPanelAtLeast4xl = useIsContentPanelAtLeast("4xl"); const isContentPanelAtLeast4xl = useIsContentPanelAtLeast("4xl");
const { setSubPanelOpen } = useAppLayout(); const { setSubPanelOpen, langui } = useAppLayout();
const router = useRouter(); const router = useRouter();
const subPanel = useMemo( const subPanel = useMemo(
@ -45,7 +45,6 @@ const Video = ({ langui, video, ...otherProps }: Props): JSX.Element => {
<ReturnButton <ReturnButton
href="/archives/videos/" href="/archives/videos/"
title={langui.videos} title={langui.videos}
langui={langui}
displayOnlyOn={"3ColumnsLayout"} displayOnlyOn={"3ColumnsLayout"}
/> />
@ -82,7 +81,6 @@ const Video = ({ langui, video, ...otherProps }: Props): JSX.Element => {
<ReturnButton <ReturnButton
href="/library/" href="/library/"
title={langui.library} title={langui.library}
langui={langui}
displayOnlyOn={"1ColumnLayout"} displayOnlyOn={"1ColumnLayout"}
className="mb-10" className="mb-10"
/> />
@ -201,7 +199,6 @@ const Video = ({ langui, video, ...otherProps }: Props): JSX.Element => {
<AppLayout <AppLayout
subPanel={subPanel} subPanel={subPanel}
contentPanel={contentPanel} contentPanel={contentPanel}
langui={langui}
{...otherProps} {...otherProps}
/> />
); );
@ -215,6 +212,7 @@ export default Video;
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = async (context) => {
const sdk = getReadySdk(); const sdk = getReadySdk();
const langui = getLangui(context.locale);
const videos = await sdk.getVideo({ const videos = await sdk.getVideo({
uid: uid:
context.params && isDefined(context.params.uid) context.params && isDefined(context.params.uid)
@ -222,14 +220,10 @@ export const getStaticProps: GetStaticProps = async (context) => {
: "", : "",
}); });
if (!videos.videos?.data[0]?.attributes) return { notFound: true }; if (!videos.videos?.data[0]?.attributes) return { notFound: true };
const appStaticProps = await getAppStaticProps(context);
const props: Props = { const props: Props = {
...appStaticProps,
video: videos.videos.data[0].attributes, video: videos.videos.data[0].attributes,
openGraph: getOpenGraph( openGraph: getOpenGraph(langui, videos.videos.data[0].attributes.title),
appStaticProps.langui,
videos.videos.data[0].attributes.title
),
}; };
return { return {
props: props, props: props,

View File

@ -1,6 +1,5 @@
import { GetStaticProps, GetStaticPaths, GetStaticPathsResult } from "next"; import { GetStaticProps, GetStaticPaths, GetStaticPathsResult } from "next";
import { useCallback, useMemo } from "react"; import { useCallback, useMemo } from "react";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk"; import { getReadySdk } from "graphql/sdk";
import { isDefined, filterHasAttributes } from "helpers/others"; import { isDefined, filterHasAttributes } from "helpers/others";
import { ChronicleWithTranslations } from "helpers/types"; import { ChronicleWithTranslations } from "helpers/types";
@ -22,13 +21,15 @@ import {
} from "helpers/locales"; } from "helpers/locales";
import { getDescription } from "helpers/description"; import { getDescription } from "helpers/description";
import { TranslatedChroniclesList } from "components/Chronicles/ChroniclesList"; import { TranslatedChroniclesList } from "components/Chronicles/ChroniclesList";
import { useAppLayout } from "contexts/AppLayoutContext";
import { getLangui } from "graphql/fetchLocalData";
/* /*
* *
* PAGE * PAGE
*/ */
interface Props extends AppStaticProps, AppLayoutRequired { interface Props extends AppLayoutRequired {
chronicle: ChronicleWithTranslations; chronicle: ChronicleWithTranslations;
chapters: NonNullable< chapters: NonNullable<
GetChroniclesChaptersQuery["chroniclesChapters"] GetChroniclesChaptersQuery["chroniclesChapters"]
@ -38,14 +39,12 @@ interface Props extends AppStaticProps, AppLayoutRequired {
const Chronicle = ({ const Chronicle = ({
chronicle, chronicle,
chapters, chapters,
langui,
languages,
...otherProps ...otherProps
}: Props): JSX.Element => { }: Props): JSX.Element => {
const { langui } = useAppLayout();
const [selectedTranslation, LanguageSwitcher, languageSwitcherProps] = const [selectedTranslation, LanguageSwitcher, languageSwitcherProps] =
useSmartLanguage({ useSmartLanguage({
items: chronicle.translations, items: chronicle.translations,
languages: languages,
languageExtractor: useCallback( languageExtractor: useCallback(
(item: ChronicleWithTranslations["translations"][number]) => (item: ChronicleWithTranslations["translations"][number]) =>
item?.language?.data?.attributes?.code, item?.language?.data?.attributes?.code,
@ -71,7 +70,6 @@ const Chronicle = ({
ContentLanguageSwitcherProps, ContentLanguageSwitcherProps,
] = useSmartLanguage({ ] = useSmartLanguage({
items: primaryContent?.translations ?? [], items: primaryContent?.translations ?? [],
languages: languages,
languageExtractor: useCallback( languageExtractor: useCallback(
( (
item: NonNullable< item: NonNullable<
@ -93,7 +91,6 @@ const Chronicle = ({
displayOnlyOn={"1ColumnLayout"} displayOnlyOn={"1ColumnLayout"}
href="/chronicles" href="/chronicles"
title={langui.chronicles} title={langui.chronicles}
langui={langui}
className="mb-10" className="mb-10"
/> />
@ -108,7 +105,7 @@ const Chronicle = ({
)} )}
{isDefined(selectedTranslation.body) && ( {isDefined(selectedTranslation.body) && (
<Markdawn text={selectedTranslation.body.body} langui={langui} /> <Markdawn text={selectedTranslation.body.body} />
)} )}
</> </>
) : ( ) : (
@ -130,16 +127,12 @@ const Chronicle = ({
type={primaryContent?.type} type={primaryContent?.type}
description={selectedContentTranslation.description} description={selectedContentTranslation.description}
thumbnail={primaryContent?.thumbnail?.data?.attributes} thumbnail={primaryContent?.thumbnail?.data?.attributes}
langui={langui}
/> />
{selectedContentTranslation.text_set?.text && ( {selectedContentTranslation.text_set?.text && (
<> <>
<HorizontalLine /> <HorizontalLine />
<Markdawn <Markdawn text={selectedContentTranslation.text_set.text} />
text={selectedContentTranslation.text_set.text}
langui={langui}
/>
</> </>
)} )}
</> </>
@ -169,7 +162,6 @@ const Chronicle = ({
displayOnlyOn={"3ColumnsLayout"} displayOnlyOn={"3ColumnsLayout"}
href="/chronicles" href="/chronicles"
title={langui.chronicles} title={langui.chronicles}
langui={langui}
/> />
<HorizontalLine /> <HorizontalLine />
@ -202,8 +194,6 @@ const Chronicle = ({
<AppLayout <AppLayout
contentPanel={contentPanel} contentPanel={contentPanel}
subPanel={subPanel} subPanel={subPanel}
langui={langui}
languages={languages}
subPanelIcon={Icon.FormatListNumbered} subPanelIcon={Icon.FormatListNumbered}
{...otherProps} {...otherProps}
/> />
@ -218,6 +208,7 @@ export default Chronicle;
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = async (context) => {
const sdk = getReadySdk(); const sdk = getReadySdk();
const langui = getLangui(context.locale);
const slug = const slug =
context.params && isDefined(context.params.slug) context.params && isDefined(context.params.slug)
? context.params.slug.toString() ? context.params.slug.toString()
@ -232,7 +223,6 @@ export const getStaticProps: GetStaticProps = async (context) => {
!chronicles.chroniclesChapters?.data !chronicles.chroniclesChapters?.data
) )
return { notFound: true }; return { notFound: true };
const appStaticProps = await getAppStaticProps(context);
const { title, description } = (() => { const { title, description } = (() => {
if (context.locale && context.locales) { if (context.locale && context.locales) {
@ -260,16 +250,15 @@ export const getStaticProps: GetStaticProps = async (context) => {
description: getDescription( description: getDescription(
selectedContentTranslation.description, selectedContentTranslation.description,
{ {
[appStaticProps.langui.type ?? "Type"]: [ [langui.type ?? "Type"]: [
chronicle.chronicles.data[0].attributes.contents.data[0] chronicle.chronicles.data[0].attributes.contents.data[0]
.attributes.type?.data?.attributes?.titles?.[0]?.title, .attributes.type?.data?.attributes?.titles?.[0]?.title,
], ],
[appStaticProps.langui.categories ?? "Categories"]: [langui.categories ?? "Categories"]: filterHasAttributes(
filterHasAttributes( chronicle.chronicles.data[0].attributes.contents.data[0]
chronicle.chronicles.data[0].attributes.contents.data[0] .attributes.categories?.data,
.attributes.categories?.data, ["attributes"] as const
["attributes"] as const ).map((category) => category.attributes.short),
).map((category) => category.attributes.short),
} }
), ),
}; };
@ -304,16 +293,10 @@ export const getStaticProps: GetStaticProps = async (context) => {
: undefined; : undefined;
const props: Props = { const props: Props = {
...appStaticProps,
chronicle: chronicle.chronicles.data[0] chronicle: chronicle.chronicles.data[0]
.attributes as ChronicleWithTranslations, .attributes as ChronicleWithTranslations,
chapters: chronicles.chroniclesChapters.data, chapters: chronicles.chroniclesChapters.data,
openGraph: getOpenGraph( openGraph: getOpenGraph(langui, title, description, thumbnail),
appStaticProps.langui,
title,
description,
thumbnail
),
}; };
return { return {
props: props, props: props,

View File

@ -3,7 +3,6 @@ import { useMemo } from "react";
import { AppLayout, AppLayoutRequired } from "components/AppLayout"; import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { PanelHeader } from "components/PanelComponents/PanelHeader"; import { PanelHeader } from "components/PanelComponents/PanelHeader";
import { SubPanel } from "components/Panels/SubPanel"; import { SubPanel } from "components/Panels/SubPanel";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Icon } from "components/Ico"; import { Icon } from "components/Ico";
import { getReadySdk } from "graphql/sdk"; import { getReadySdk } from "graphql/sdk";
import { GetChroniclesChaptersQuery } from "graphql/generated"; import { GetChroniclesChaptersQuery } from "graphql/generated";
@ -12,23 +11,22 @@ import { prettySlug } from "helpers/formatters";
import { getOpenGraph } from "helpers/openGraph"; import { getOpenGraph } from "helpers/openGraph";
import { TranslatedChroniclesList } from "components/Chronicles/ChroniclesList"; import { TranslatedChroniclesList } from "components/Chronicles/ChroniclesList";
import { HorizontalLine } from "components/HorizontalLine"; import { HorizontalLine } from "components/HorizontalLine";
import { useAppLayout } from "contexts/AppLayoutContext";
import { getLangui } from "graphql/fetchLocalData";
/* /*
* *
* PAGE * PAGE
*/ */
interface Props extends AppStaticProps, AppLayoutRequired { interface Props extends AppLayoutRequired {
chapters: NonNullable< chapters: NonNullable<
GetChroniclesChaptersQuery["chroniclesChapters"] GetChroniclesChaptersQuery["chroniclesChapters"]
>["data"]; >["data"];
} }
const Chronicles = ({ const Chronicles = ({ chapters, ...otherProps }: Props): JSX.Element => {
langui, const { langui } = useAppLayout();
chapters,
...otherProps
}: Props): JSX.Element => {
const subPanel = useMemo( const subPanel = useMemo(
() => ( () => (
<SubPanel> <SubPanel>
@ -63,7 +61,7 @@ const Chronicles = ({
[chapters, langui] [chapters, langui]
); );
return <AppLayout subPanel={subPanel} langui={langui} {...otherProps} />; return <AppLayout subPanel={subPanel} {...otherProps} />;
}; };
export default Chronicles; export default Chronicles;
@ -74,16 +72,13 @@ export default Chronicles;
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = async (context) => {
const sdk = getReadySdk(); const sdk = getReadySdk();
const langui = getLangui(context.locale);
const chronicles = await sdk.getChroniclesChapters(); const chronicles = await sdk.getChroniclesChapters();
if (!chronicles.chroniclesChapters?.data) return { notFound: true }; if (!chronicles.chroniclesChapters?.data) return { notFound: true };
const appStaticProps = await getAppStaticProps(context);
const props: Props = { const props: Props = {
...appStaticProps,
chapters: chronicles.chroniclesChapters.data, chapters: chronicles.chroniclesChapters.data,
openGraph: getOpenGraph( openGraph: getOpenGraph(langui, langui.chronicles ?? "Chronicles"),
appStaticProps.langui,
appStaticProps.langui.chronicles ?? "Chronicles"
),
}; };
return { return {
props: props, props: props,

View File

@ -12,7 +12,6 @@ import { PreviewCard } from "components/PreviewCard";
import { RecorderChip } from "components/RecorderChip"; import { RecorderChip } from "components/RecorderChip";
import { ThumbnailHeader } from "components/ThumbnailHeader"; import { ThumbnailHeader } from "components/ThumbnailHeader";
import { ToolTip } from "components/ToolTip"; import { ToolTip } from "components/ToolTip";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk"; import { getReadySdk } from "graphql/sdk";
import { import {
prettyInlineTitle, prettyInlineTitle,
@ -41,30 +40,26 @@ import {
useIsContentPanelAtLeast, useIsContentPanelAtLeast,
} from "hooks/useContainerQuery"; } from "hooks/useContainerQuery";
import { cIf } from "helpers/className"; import { cIf } from "helpers/className";
import { getLangui } from "graphql/fetchLocalData";
import { useAppLayout } from "contexts/AppLayoutContext";
/* /*
* *
* PAGE * PAGE
*/ */
interface Props extends AppStaticProps, AppLayoutRequired { interface Props extends AppLayoutRequired {
content: ContentWithTranslations; content: ContentWithTranslations;
} }
const Content = ({ const Content = ({ content, ...otherProps }: Props): JSX.Element => {
langui,
content,
languages,
currencies,
...otherProps
}: Props): JSX.Element => {
const isContentPanelAtLeast2xl = useIsContentPanelAtLeast("2xl"); const isContentPanelAtLeast2xl = useIsContentPanelAtLeast("2xl");
const is1ColumnLayout = useIs1ColumnLayout(); const is1ColumnLayout = useIs1ColumnLayout();
const { langui, languages } = useAppLayout();
const [selectedTranslation, LanguageSwitcher, languageSwitcherProps] = const [selectedTranslation, LanguageSwitcher, languageSwitcherProps] =
useSmartLanguage({ useSmartLanguage({
items: content.translations, items: content.translations,
languages: languages,
languageExtractor: useCallback( languageExtractor: useCallback(
(item: NonNullable<Props["content"]["translations"][number]>) => (item: NonNullable<Props["content"]["translations"][number]>) =>
item.language?.data?.attributes?.code, item.language?.data?.attributes?.code,
@ -182,10 +177,7 @@ const Content = ({
["attributes", "id"] as const ["attributes", "id"] as const
).map((recorder) => ( ).map((recorder) => (
<Fragment key={recorder.id}> <Fragment key={recorder.id}>
<RecorderChip <RecorderChip recorder={recorder.attributes} />
langui={langui}
recorder={recorder.attributes}
/>
</Fragment> </Fragment>
))} ))}
</div> </div>
@ -204,10 +196,7 @@ const Content = ({
["attributes", "id"] as const ["attributes", "id"] as const
).map((recorder) => ( ).map((recorder) => (
<Fragment key={recorder.id}> <Fragment key={recorder.id}>
<RecorderChip <RecorderChip recorder={recorder.attributes} />
langui={langui}
recorder={recorder.attributes}
/>
</Fragment> </Fragment>
))} ))}
</div> </div>
@ -226,10 +215,7 @@ const Content = ({
["attributes", "id"] as const ["attributes", "id"] as const
).map((recorder) => ( ).map((recorder) => (
<Fragment key={recorder.id}> <Fragment key={recorder.id}>
<RecorderChip <RecorderChip recorder={recorder.attributes} />
langui={langui}
recorder={recorder.attributes}
/>
</Fragment> </Fragment>
))} ))}
</div> </div>
@ -240,10 +226,7 @@ const Content = ({
<div> <div>
<p className="font-headers font-bold">{langui.notes}:</p> <p className="font-headers font-bold">{langui.notes}:</p>
<div className="grid place-content-center place-items-center gap-2"> <div className="grid place-content-center place-items-center gap-2">
<Markdawn <Markdawn text={selectedTranslation.text_set.notes} />
text={selectedTranslation.text_set.notes}
langui={langui}
/>
</div> </div>
</div> </div>
)} )}
@ -260,7 +243,6 @@ const Content = ({
selectedTranslation.title, selectedTranslation.title,
selectedTranslation.subtitle selectedTranslation.subtitle
)} )}
langui={langui}
horizontalLine horizontalLine
/> />
</> </>
@ -311,7 +293,6 @@ const Content = ({
["attributes"] as const ["attributes"] as const
).map((category) => category.attributes.short)} ).map((category) => category.attributes.short)}
metadata={{ metadata={{
currencies: currencies,
releaseDate: libraryItem.attributes.release_date, releaseDate: libraryItem.attributes.release_date,
price: libraryItem.attributes.price, price: libraryItem.attributes.price,
position: "Bottom", position: "Bottom",
@ -319,12 +300,7 @@ const Content = ({
infoAppend={ infoAppend={
!isUntangibleGroupItem( !isUntangibleGroupItem(
libraryItem.attributes.metadata?.[0] libraryItem.attributes.metadata?.[0]
) && ( ) && <PreviewCardCTAs id={libraryItem.id} />
<PreviewCardCTAs
id={libraryItem.id}
langui={langui}
/>
)
} }
/> />
</div> </div>
@ -338,7 +314,6 @@ const Content = ({
), ),
[ [
content.ranged_contents?.data, content.ranged_contents?.data,
currencies,
languages, languages,
langui, langui,
returnButtonProps, returnButtonProps,
@ -365,7 +340,6 @@ const Content = ({
description={selectedTranslation?.description} description={selectedTranslation?.description}
type={content.type} type={content.type}
categories={content.categories} categories={content.categories}
langui={langui}
languageSwitcher={ languageSwitcher={
languageSwitcherProps.locales.size > 1 ? ( languageSwitcherProps.locales.size > 1 ? (
<LanguageSwitcher {...languageSwitcherProps} /> <LanguageSwitcher {...languageSwitcherProps} />
@ -425,10 +399,7 @@ const Content = ({
{selectedTranslation?.text_set?.text && ( {selectedTranslation?.text_set?.text && (
<> <>
<HorizontalLine /> <HorizontalLine />
<Markdawn <Markdawn text={selectedTranslation.text_set.text} />
text={selectedTranslation.text_set.text}
langui={langui}
/>
</> </>
)} )}
@ -501,9 +472,6 @@ const Content = ({
<AppLayout <AppLayout
contentPanel={contentPanel} contentPanel={contentPanel}
subPanel={subPanel} subPanel={subPanel}
currencies={currencies}
languages={languages}
langui={langui}
{...otherProps} {...otherProps}
/> />
); );
@ -517,6 +485,7 @@ export default Content;
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = async (context) => {
const sdk = getReadySdk(); const sdk = getReadySdk();
const langui = getLangui(context.locale);
const slug = context.params?.slug ? context.params.slug.toString() : ""; const slug = context.params?.slug ? context.params.slug.toString() : "";
const content = await sdk.getContentText({ const content = await sdk.getContentText({
slug: slug, slug: slug,
@ -526,7 +495,6 @@ export const getStaticProps: GetStaticProps = async (context) => {
if (!content.contents?.data[0]?.attributes?.translations) { if (!content.contents?.data[0]?.attributes?.translations) {
return { notFound: true }; return { notFound: true };
} }
const appStaticProps = await getAppStaticProps(context);
const { title, description } = (() => { const { title, description } = (() => {
if (context.locale && context.locales) { if (context.locale && context.locales) {
@ -546,15 +514,14 @@ export const getStaticProps: GetStaticProps = async (context) => {
selectedTranslation.subtitle selectedTranslation.subtitle
), ),
description: getDescription(selectedTranslation.description, { description: getDescription(selectedTranslation.description, {
[appStaticProps.langui.type ?? "Type"]: [ [langui.type ?? "Type"]: [
content.contents.data[0].attributes.type?.data?.attributes content.contents.data[0].attributes.type?.data?.attributes
?.titles?.[0]?.title, ?.titles?.[0]?.title,
], ],
[appStaticProps.langui.categories ?? "Categories"]: [langui.categories ?? "Categories"]: filterHasAttributes(
filterHasAttributes( content.contents.data[0].attributes.categories?.data,
content.contents.data[0].attributes.categories?.data, ["attributes"] as const
["attributes"] as const ).map((category) => category.attributes.short),
).map((category) => category.attributes.short),
}), }),
}; };
} }
@ -569,14 +536,8 @@ export const getStaticProps: GetStaticProps = async (context) => {
content.contents.data[0].attributes.thumbnail?.data?.attributes; content.contents.data[0].attributes.thumbnail?.data?.attributes;
const props: Props = { const props: Props = {
...appStaticProps,
content: content.contents.data[0].attributes as ContentWithTranslations, content: content.contents.data[0].attributes as ContentWithTranslations,
openGraph: getOpenGraph( openGraph: getOpenGraph(langui, title, description, thumbnail),
appStaticProps.langui,
title,
description,
thumbnail
),
}; };
return { return {
props: props, props: props,

View File

@ -10,7 +10,6 @@ import {
ContentPanelWidthSizes, ContentPanelWidthSizes,
} from "components/Panels/ContentPanel"; } from "components/Panels/ContentPanel";
import { SubPanel } from "components/Panels/SubPanel"; import { SubPanel } from "components/Panels/SubPanel";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk"; import { getReadySdk } from "graphql/sdk";
import { prettyInlineTitle, prettySlug } from "helpers/formatters"; import { prettyInlineTitle, prettySlug } from "helpers/formatters";
import { TextInput } from "components/Inputs/TextInput"; import { TextInput } from "components/Inputs/TextInput";
@ -27,6 +26,8 @@ import { HorizontalLine } from "components/HorizontalLine";
import { TranslatedPreviewCard } from "components/PreviewCard"; import { TranslatedPreviewCard } from "components/PreviewCard";
import { useIsContentPanelAtLeast } from "hooks/useContainerQuery"; import { useIsContentPanelAtLeast } from "hooks/useContainerQuery";
import { cJoin, cIf } from "helpers/className"; import { cJoin, cIf } from "helpers/className";
import { useAppLayout } from "contexts/AppLayoutContext";
import { getLangui } from "graphql/fetchLocalData";
/* /*
* *
@ -44,17 +45,13 @@ const DEFAULT_FILTERS_STATE = {
* PAGE * PAGE
*/ */
interface Props extends AppStaticProps, AppLayoutRequired { interface Props extends AppLayoutRequired {
contents: NonNullable<GetContentsQuery["contents"]>["data"]; contents: NonNullable<GetContentsQuery["contents"]>["data"];
} }
const Contents = ({ const Contents = ({ contents, ...otherProps }: Props): JSX.Element => {
langui,
contents,
languages,
...otherProps
}: Props): JSX.Element => {
const hoverable = useDeviceSupportsHover(); const hoverable = useDeviceSupportsHover();
const { langui } = useAppLayout();
const isContentPanelAtLeast4xl = useIsContentPanelAtLeast("4xl"); const isContentPanelAtLeast4xl = useIsContentPanelAtLeast("4xl");
const [groupingMethod, setGroupingMethod] = useState<number>( const [groupingMethod, setGroupingMethod] = useState<number>(
@ -142,6 +139,7 @@ const Contents = ({
<Button <Button
href="/contents" href="/contents"
/* TODO: Langui */
text={"Switch to folder view"} text={"Switch to folder view"}
icon={Icon.Folder} icon={Icon.Folder}
/> />
@ -262,7 +260,6 @@ const Contents = ({
.join(" ")}` .join(" ")}`
} }
paginationItemPerPage={50} paginationItemPerPage={50}
langui={langui}
/> />
</ContentPanel> </ContentPanel>
), ),
@ -272,7 +269,6 @@ const Contents = ({
filteringFunction, filteringFunction,
groupingFunction, groupingFunction,
keepInfoVisible, keepInfoVisible,
langui,
searchName, searchName,
] ]
); );
@ -282,8 +278,6 @@ const Contents = ({
subPanel={subPanel} subPanel={subPanel}
contentPanel={contentPanel} contentPanel={contentPanel}
subPanelIcon={Icon.Search} subPanelIcon={Icon.Search}
languages={languages}
langui={langui}
{...otherProps} {...otherProps}
/> />
); );
@ -297,6 +291,7 @@ export default Contents;
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = async (context) => {
const sdk = getReadySdk(); const sdk = getReadySdk();
const langui = getLangui(context.locale);
const contents = await sdk.getContents({ const contents = await sdk.getContents({
language_code: context.locale ?? "en", language_code: context.locale ?? "en",
}); });
@ -307,14 +302,9 @@ export const getStaticProps: GetStaticProps = async (context) => {
return titleA.localeCompare(titleB); return titleA.localeCompare(titleB);
}); });
const appStaticProps = await getAppStaticProps(context);
const props: Props = { const props: Props = {
...appStaticProps,
contents: contents.contents.data, contents: contents.contents.data,
openGraph: getOpenGraph( openGraph: getOpenGraph(langui, langui.contents ?? "Contents"),
appStaticProps.langui,
appStaticProps.langui.contents ?? "Contents"
),
}; };
return { return {
props: props, props: props,

View File

@ -5,7 +5,6 @@ import {
ContentPanel, ContentPanel,
ContentPanelWidthSizes, ContentPanelWidthSizes,
} from "components/Panels/ContentPanel"; } from "components/Panels/ContentPanel";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getOpenGraph } from "helpers/openGraph"; import { getOpenGraph } from "helpers/openGraph";
import { getReadySdk } from "graphql/sdk"; import { getReadySdk } from "graphql/sdk";
import { filterHasAttributes } from "helpers/others"; import { filterHasAttributes } from "helpers/others";
@ -27,13 +26,15 @@ import { TranslatedPreviewCard } from "components/PreviewCard";
import { HorizontalLine } from "components/HorizontalLine"; import { HorizontalLine } from "components/HorizontalLine";
import { useIsContentPanelAtLeast } from "hooks/useContainerQuery"; import { useIsContentPanelAtLeast } from "hooks/useContainerQuery";
import { cJoin, cIf } from "helpers/className"; import { cJoin, cIf } from "helpers/className";
import { useAppLayout } from "contexts/AppLayoutContext";
import { getLangui } from "graphql/fetchLocalData";
/* /*
* *
* PAGE * PAGE
*/ */
interface Props extends AppStaticProps, AppLayoutRequired { interface Props extends AppLayoutRequired {
folder: NonNullable< folder: NonNullable<
NonNullable< NonNullable<
GetContentsFolderQuery["contentsFolders"] GetContentsFolderQuery["contentsFolders"]
@ -42,11 +43,11 @@ interface Props extends AppStaticProps, AppLayoutRequired {
} }
const ContentsFolder = ({ const ContentsFolder = ({
langui,
openGraph, openGraph,
folder, folder,
...otherProps ...otherProps
}: Props): JSX.Element => { }: Props): JSX.Element => {
const { langui } = useAppLayout();
const isContentPanelAtLeast4xl = useIsContentPanelAtLeast("4xl"); const isContentPanelAtLeast4xl = useIsContentPanelAtLeast("4xl");
const subPanel = useMemo( const subPanel = useMemo(
@ -62,6 +63,7 @@ const ContentsFolder = ({
<Button <Button
href="/contents/all" href="/contents/all"
/* TODO: Langui */
text={"Switch to grid view"} text={"Switch to grid view"}
icon={Icon.Apps} icon={Icon.Apps}
/> />
@ -142,7 +144,6 @@ const ContentsFolder = ({
) )
)} )}
renderWhenEmpty={() => <></>} renderWhenEmpty={() => <></>}
langui={langui}
groupingFunction={() => [langui.folders ?? "Folders"]} groupingFunction={() => [langui.folders ?? "Folders"]}
/> />
@ -188,14 +189,11 @@ const ContentsFolder = ({
"grid-cols-2 gap-x-3 gap-y-5" "grid-cols-2 gap-x-3 gap-y-5"
)} )}
renderWhenEmpty={() => <></>} renderWhenEmpty={() => <></>}
langui={langui}
groupingFunction={() => [langui.contents ?? "Contents"]} groupingFunction={() => [langui.contents ?? "Contents"]}
/> />
{folder.contents?.data.length === 0 && {folder.contents?.data.length === 0 &&
folder.subfolders?.data.length === 0 && ( folder.subfolders?.data.length === 0 && <NoContentNorFolderMessage />}
<NoContentNorFolderMessage langui={langui} />
)}
</ContentPanel> </ContentPanel>
), ),
[ [
@ -214,7 +212,6 @@ const ContentsFolder = ({
subPanel={subPanel} subPanel={subPanel}
contentPanel={contentPanel} contentPanel={contentPanel}
openGraph={openGraph} openGraph={openGraph}
langui={langui}
{...otherProps} {...otherProps}
/> />
); );
@ -228,6 +225,7 @@ export default ContentsFolder;
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = async (context) => {
const sdk = getReadySdk(); const sdk = getReadySdk();
const langui = getLangui(context.locale);
const slug = context.params?.slug ? context.params.slug.toString() : ""; const slug = context.params?.slug ? context.params.slug.toString() : "";
const contentsFolder = await sdk.getContentsFolder({ const contentsFolder = await sdk.getContentsFolder({
slug: slug, slug: slug,
@ -238,11 +236,10 @@ export const getStaticProps: GetStaticProps = async (context) => {
} }
const folder = contentsFolder.contentsFolders.data[0].attributes; const folder = contentsFolder.contentsFolders.data[0].attributes;
const appStaticProps = await getAppStaticProps(context);
const title = (() => { const title = (() => {
if (slug === "root") { if (slug === "root") {
return appStaticProps.langui.contents ?? "Contents"; return langui.contents ?? "Contents";
} }
if (context.locale && context.locales) { if (context.locale && context.locales) {
const selectedTranslation = staticSmartLanguage({ const selectedTranslation = staticSmartLanguage({
@ -261,8 +258,7 @@ export const getStaticProps: GetStaticProps = async (context) => {
})(); })();
const props: Props = { const props: Props = {
...appStaticProps, openGraph: getOpenGraph(langui, title),
openGraph: getOpenGraph(appStaticProps.langui, title),
folder, folder,
}; };
return { return {
@ -340,19 +336,16 @@ const TranslatedPreviewFolder = ({
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
interface NoContentNorFolderMessageProps { const NoContentNorFolderMessage = () => {
langui: AppStaticProps["langui"]; const { langui } = useAppLayout();
} return (
<div className="grid place-content-center">
const NoContentNorFolderMessage = ({ <div
langui, className="grid grid-flow-col place-items-center gap-9 rounded-2xl border-2 border-dotted
}: NoContentNorFolderMessageProps) => (
<div className="grid place-content-center">
<div
className="grid grid-flow-col place-items-center gap-9 rounded-2xl border-2 border-dotted
border-dark p-8 text-dark opacity-40" border-dark p-8 text-dark opacity-40"
> >
<p className="max-w-xs text-2xl">{langui.empty_folder_message}</p> <p className="max-w-xs text-2xl">{langui.empty_folder_message}</p>
</div>
</div> </div>
</div> );
); };

View File

@ -9,18 +9,18 @@ import {
} from "components/Panels/ContentPanel"; } from "components/Panels/ContentPanel";
import { ToolTip } from "components/ToolTip"; import { ToolTip } from "components/ToolTip";
import { DevGetContentsQuery } from "graphql/generated"; import { DevGetContentsQuery } from "graphql/generated";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk"; import { getReadySdk } from "graphql/sdk";
import { filterDefined, filterHasAttributes } from "helpers/others"; import { filterDefined, filterHasAttributes } from "helpers/others";
import { Report, Severity } from "helpers/types/Report"; import { Report, Severity } from "helpers/types/Report";
import { getOpenGraph } from "helpers/openGraph"; import { getOpenGraph } from "helpers/openGraph";
import { getLangui } from "graphql/fetchLocalData";
/* /*
* *
* PAGE * PAGE
*/ */
interface Props extends AppStaticProps, AppLayoutRequired { interface Props extends AppLayoutRequired {
contents: DevGetContentsQuery; contents: DevGetContentsQuery;
} }
@ -99,12 +99,11 @@ export default CheckupContents;
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = async (context) => {
const sdk = getReadySdk(); const sdk = getReadySdk();
const langui = getLangui(context.locale);
const contents = await sdk.devGetContents(); const contents = await sdk.devGetContents();
const appStaticProps = await getAppStaticProps(context);
const props: Props = { const props: Props = {
...appStaticProps,
contents: contents, contents: contents,
openGraph: getOpenGraph(appStaticProps.langui, "Checkup Contents"), openGraph: getOpenGraph(langui, "Checkup Contents"),
}; };
return { return {
props: props, props: props,

View File

@ -12,17 +12,17 @@ import {
DevGetLibraryItemsQuery, DevGetLibraryItemsQuery,
Enum_Componentcollectionscomponentlibraryimages_Status, Enum_Componentcollectionscomponentlibraryimages_Status,
} from "graphql/generated"; } from "graphql/generated";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk"; import { getReadySdk } from "graphql/sdk";
import { Report, Severity } from "helpers/types/Report"; import { Report, Severity } from "helpers/types/Report";
import { getOpenGraph } from "helpers/openGraph"; import { getOpenGraph } from "helpers/openGraph";
import { getLangui } from "graphql/fetchLocalData";
/* /*
* *
* PAGE * PAGE
*/ */
interface Props extends AppStaticProps, AppLayoutRequired { interface Props extends AppLayoutRequired {
libraryItems: DevGetLibraryItemsQuery; libraryItems: DevGetLibraryItemsQuery;
} }
@ -104,12 +104,12 @@ export default CheckupLibraryItems;
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = async (context) => {
const sdk = getReadySdk(); const sdk = getReadySdk();
const langui = getLangui(context.locale);
const libraryItems = await sdk.devGetLibraryItems(); const libraryItems = await sdk.devGetLibraryItems();
const appStaticProps = await getAppStaticProps(context);
const props: Props = { const props: Props = {
...appStaticProps,
libraryItems: libraryItems, libraryItems: libraryItems,
openGraph: getOpenGraph(appStaticProps.langui, "Checkup Library Items"), openGraph: getOpenGraph(langui, "Checkup Library Items"),
}; };
return { return {
props: props, props: props,

View File

@ -10,18 +10,18 @@ import {
} from "components/Panels/ContentPanel"; } from "components/Panels/ContentPanel";
import { Popup } from "components/Popup"; import { Popup } from "components/Popup";
import { ToolTip } from "components/ToolTip"; import { ToolTip } from "components/ToolTip";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Icon } from "components/Ico"; import { Icon } from "components/Ico";
import { getOpenGraph } from "helpers/openGraph"; import { getOpenGraph } from "helpers/openGraph";
import { getLangui } from "graphql/fetchLocalData";
/* /*
* *
* PAGE * PAGE
*/ */
interface Props extends AppStaticProps, AppLayoutRequired {} interface Props extends AppLayoutRequired {}
const Editor = ({ langui, ...otherProps }: Props): JSX.Element => { const Editor = (props: Props): JSX.Element => {
const handleInput = useCallback((text: string) => { const handleInput = useCallback((text: string) => {
setMarkdown(text); setMarkdown(text);
}, []); }, []);
@ -445,13 +445,13 @@ const Editor = ({ langui, ...otherProps }: Props): JSX.Element => {
<div> <div>
<h2>Preview</h2> <h2>Preview</h2>
<div className="h-[70vh] overflow-scroll rounded-xl bg-mid bg-opacity-40 p-8"> <div className="h-[70vh] overflow-scroll rounded-xl bg-mid bg-opacity-40 p-8">
<Markdawn className="w-full" text={markdown} langui={langui} /> <Markdawn className="w-full" text={markdown} />
</div> </div>
</div> </div>
</div> </div>
<div className="mt-8"> <div className="mt-8">
<TableOfContents text={markdown} langui={langui} /> <TableOfContents text={markdown} />
</div> </div>
</ContentPanel> </ContentPanel>
), ),
@ -460,7 +460,6 @@ const Editor = ({ langui, ...otherProps }: Props): JSX.Element => {
converterOpened, converterOpened,
handleInput, handleInput,
insert, insert,
langui,
markdown, markdown,
preline, preline,
toggleWrap, toggleWrap,
@ -468,9 +467,7 @@ const Editor = ({ langui, ...otherProps }: Props): JSX.Element => {
] ]
); );
return ( return <AppLayout contentPanel={contentPanel} {...props} />;
<AppLayout contentPanel={contentPanel} langui={langui} {...otherProps} />
);
}; };
export default Editor; export default Editor;
@ -479,11 +476,10 @@ export default Editor;
* NEXT DATA FETCHING * NEXT DATA FETCHING
*/ */
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = (context) => {
const appStaticProps = await getAppStaticProps(context); const langui = getLangui(context.locale);
const props: Props = { const props: Props = {
...appStaticProps, openGraph: getOpenGraph(langui, "Markdawn Editor"),
openGraph: getOpenGraph(appStaticProps.langui, "Markdawn Editor"),
}; };
return { return {
props: props, props: props,

View File

@ -8,8 +8,8 @@ import {
ContentPanelWidthSizes, ContentPanelWidthSizes,
} from "components/Panels/ContentPanel"; } from "components/Panels/ContentPanel";
import { ToolTip } from "components/ToolTip"; import { ToolTip } from "components/ToolTip";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getOpenGraph } from "helpers/openGraph"; import { getOpenGraph } from "helpers/openGraph";
import { getLangui } from "graphql/fetchLocalData";
/* /*
* *
@ -23,7 +23,7 @@ const SIZE_MULTIPLIER = 1000;
* PAGE * PAGE
*/ */
interface Props extends AppStaticProps, AppLayoutRequired {} interface Props extends AppLayoutRequired {}
const replaceSelection = ( const replaceSelection = (
text: string, text: string,
@ -580,14 +580,10 @@ export default Transcript;
* NEXT DATA FETCHING * NEXT DATA FETCHING
*/ */
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = (context) => {
const appStaticProps = await getAppStaticProps(context); const langui = getLangui(context.locale);
const props: Props = { const props: Props = {
...appStaticProps, openGraph: getOpenGraph(langui, "Japanese Transcription Tool"),
openGraph: getOpenGraph(
appStaticProps.langui,
"Japanese Transcription Tool"
),
}; };
return { return {
props: props, props: props,

View File

@ -3,18 +3,15 @@ import {
getPostStaticProps, getPostStaticProps,
PostStaticProps, PostStaticProps,
} from "graphql/getPostStaticProps"; } from "graphql/getPostStaticProps";
import { getOpenGraph } from "helpers/openGraph";
/* /*
* *
* PAGE * PAGE
*/ */
const Home = ({ langui, ...otherProps }: PostStaticProps): JSX.Element => ( const Home = ({ ...otherProps }: PostStaticProps): JSX.Element => (
<PostPage <PostPage
{...otherProps} {...otherProps}
openGraph={getOpenGraph(langui)}
langui={langui}
prependBody={ prependBody={
<div className="grid w-full place-content-center place-items-center gap-5 text-center"> <div className="grid w-full place-content-center place-items-center gap-5 text-center">
<div <div

View File

@ -23,7 +23,6 @@ import {
Enum_Componentmetadatabooks_Page_Order, Enum_Componentmetadatabooks_Page_Order,
GetLibraryItemQuery, GetLibraryItemQuery,
} from "graphql/generated"; } from "graphql/generated";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk"; import { getReadySdk } from "graphql/sdk";
import { import {
prettyDate, prettyDate,
@ -56,6 +55,8 @@ import { getDescription } from "helpers/description";
import { useIntersectionList } from "hooks/useIntersectionList"; import { useIntersectionList } from "hooks/useIntersectionList";
import { HorizontalLine } from "components/HorizontalLine"; import { HorizontalLine } from "components/HorizontalLine";
import { useIsContentPanelNoMoreThan } from "hooks/useContainerQuery"; import { useIsContentPanelNoMoreThan } from "hooks/useContainerQuery";
import { useCurrencies } from "hooks/useLocalData";
import { getLangui } from "graphql/fetchLocalData";
/* /*
* *
@ -75,7 +76,7 @@ const intersectionIds = [
* PAGE * PAGE
*/ */
interface Props extends AppStaticProps, AppLayoutRequired { interface Props extends AppLayoutRequired {
item: NonNullable< item: NonNullable<
NonNullable< NonNullable<
GetLibraryItemQuery["libraryItems"] GetLibraryItemQuery["libraryItems"]
@ -86,15 +87,10 @@ interface Props extends AppStaticProps, AppLayoutRequired {
>["data"][number]["id"]; >["data"][number]["id"];
} }
const LibrarySlug = ({ const LibrarySlug = ({ item, itemId, ...otherProps }: Props): JSX.Element => {
item,
itemId,
langui,
currencies,
languages,
...otherProps
}: Props): JSX.Element => {
const { currency } = useAppLayout(); const { currency } = useAppLayout();
const { langui } = useAppLayout();
const currencies = useCurrencies();
const isContentPanelNoMoreThan3xl = useIsContentPanelNoMoreThan("3xl"); const isContentPanelNoMoreThan3xl = useIsContentPanelNoMoreThan("3xl");
const isContentPanelNoMoreThanSm = useIsContentPanelNoMoreThan("sm"); const isContentPanelNoMoreThanSm = useIsContentPanelNoMoreThan("sm");
const hoverable = useDeviceSupportsHover(); const hoverable = useDeviceSupportsHover();
@ -128,7 +124,6 @@ const LibrarySlug = ({
<ReturnButton <ReturnButton
href="/library/" href="/library/"
title={langui.library} title={langui.library}
langui={langui}
displayOnlyOn="3ColumnsLayout" displayOnlyOn="3ColumnsLayout"
/> />
@ -196,7 +191,6 @@ const LibrarySlug = ({
<ReturnButton <ReturnButton
href="/library/" href="/library/"
title={langui.library} title={langui.library}
langui={langui}
displayOnlyOn="1ColumnLayout" displayOnlyOn="1ColumnLayout"
className="mb-10" className="mb-10"
/> />
@ -252,7 +246,7 @@ const LibrarySlug = ({
{!isUntangibleGroupItem(item.metadata?.[0]) && {!isUntangibleGroupItem(item.metadata?.[0]) &&
isDefinedAndNotEmpty(itemId) && ( isDefinedAndNotEmpty(itemId) && (
<PreviewCardCTAs id={itemId} langui={langui} expand /> <PreviewCardCTAs id={itemId} expand />
)} )}
{item.descriptions?.[0] && ( {item.descriptions?.[0] && (
@ -571,7 +565,6 @@ const LibrarySlug = ({
(category) => category.attributes?.short ?? "" (category) => category.attributes?.short ?? ""
)} )}
metadata={{ metadata={{
currencies: currencies,
releaseDate: subitem.attributes.release_date, releaseDate: subitem.attributes.release_date,
price: subitem.attributes.price, price: subitem.attributes.price,
position: "Bottom", position: "Bottom",
@ -579,7 +572,7 @@ const LibrarySlug = ({
infoAppend={ infoAppend={
!isUntangibleGroupItem( !isUntangibleGroupItem(
subitem.attributes.metadata?.[0] subitem.attributes.metadata?.[0]
) && <PreviewCardCTAs id={subitem.id} langui={langui} /> ) && <PreviewCardCTAs id={subitem.id} />
} }
/> />
</Fragment> </Fragment>
@ -635,7 +628,6 @@ const LibrarySlug = ({
} }
: undefined : undefined
} }
langui={langui}
rangeStart={ rangeStart={
rangedContent.attributes.range[0]?.__typename === rangedContent.attributes.range[0]?.__typename ===
"ComponentRangePageRange" "ComponentRangePageRange"
@ -645,7 +637,6 @@ const LibrarySlug = ({
slug={rangedContent.attributes.slug} slug={rangedContent.attributes.slug}
parentSlug={item.slug} parentSlug={item.slug}
key={rangedContent.id} key={rangedContent.id}
languages={languages}
hasScanSet={ hasScanSet={
isDefined(rangedContent.attributes.scan_set) && isDefined(rangedContent.attributes.scan_set) &&
rangedContent.attributes.scan_set.length > 0 rangedContent.attributes.scan_set.length > 0
@ -689,7 +680,6 @@ const LibrarySlug = ({
keepInfoVisible, keepInfoVisible,
displayOpenScans, displayOpenScans,
openLightBox, openLightBox,
languages,
] ]
); );
@ -697,9 +687,6 @@ const LibrarySlug = ({
<AppLayout <AppLayout
contentPanel={contentPanel} contentPanel={contentPanel}
subPanel={subPanel} subPanel={subPanel}
currencies={currencies}
languages={languages}
langui={langui}
{...otherProps} {...otherProps}
/> />
); );
@ -713,6 +700,7 @@ export default LibrarySlug;
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = async (context) => {
const sdk = getReadySdk(); const sdk = getReadySdk();
const langui = getLangui(context.locale);
const item = await sdk.getLibraryItem({ const item = await sdk.getLibraryItem({
slug: slug:
context.params && isDefined(context.params.slug) context.params && isDefined(context.params.slug)
@ -722,22 +710,21 @@ export const getStaticProps: GetStaticProps = async (context) => {
}); });
if (!item.libraryItems?.data[0]?.attributes) return { notFound: true }; if (!item.libraryItems?.data[0]?.attributes) return { notFound: true };
sortRangedContent(item.libraryItems.data[0].attributes.contents); sortRangedContent(item.libraryItems.data[0].attributes.contents);
const appStaticProps = await getAppStaticProps(context);
const { title, thumbnail } = item.libraryItems.data[0].attributes; const { title, thumbnail } = item.libraryItems.data[0].attributes;
const description = getDescription( const description = getDescription(
item.libraryItems.data[0].attributes.descriptions?.[0]?.description, item.libraryItems.data[0].attributes.descriptions?.[0]?.description,
{ {
[appStaticProps.langui.categories ?? "Categories"]: filterHasAttributes( [langui.categories ?? "Categories"]: filterHasAttributes(
item.libraryItems.data[0].attributes.categories?.data, item.libraryItems.data[0].attributes.categories?.data,
["attributes.short"] ["attributes.short"]
).map((category) => category.attributes.short), ).map((category) => category.attributes.short),
[appStaticProps.langui.type ?? "Type"]: item.libraryItems.data[0] [langui.type ?? "Type"]: item.libraryItems.data[0].attributes
.attributes.metadata?.[0] .metadata?.[0]
? [prettyItemSubType(item.libraryItems.data[0].attributes.metadata[0])] ? [prettyItemSubType(item.libraryItems.data[0].attributes.metadata[0])]
: [], : [],
[appStaticProps.langui.release_date ?? "Release date"]: [ [langui.release_date ?? "Release date"]: [
item.libraryItems.data[0].attributes.release_date item.libraryItems.data[0].attributes.release_date
? prettyDate( ? prettyDate(
item.libraryItems.data[0].attributes.release_date, item.libraryItems.data[0].attributes.release_date,
@ -749,11 +736,10 @@ export const getStaticProps: GetStaticProps = async (context) => {
); );
const props: Props = { const props: Props = {
...appStaticProps,
item: item.libraryItems.data[0].attributes, item: item.libraryItems.data[0].attributes,
itemId: item.libraryItems.data[0].id, itemId: item.libraryItems.data[0].id,
openGraph: getOpenGraph( openGraph: getOpenGraph(
appStaticProps.langui, langui,
title, title,
description, description,
thumbnail?.data?.attributes thumbnail?.data?.attributes
@ -803,8 +789,7 @@ interface ContentLineProps {
rangeStart: string; rangeStart: string;
parentSlug: string; parentSlug: string;
slug: string; slug: string;
langui: AppStaticProps["langui"];
languages: AppStaticProps["languages"];
hasScanSet: boolean; hasScanSet: boolean;
condensed: boolean; condensed: boolean;
} }
@ -812,17 +797,15 @@ interface ContentLineProps {
const ContentLine = ({ const ContentLine = ({
rangeStart, rangeStart,
content, content,
langui,
languages,
hasScanSet, hasScanSet,
slug, slug,
parentSlug, parentSlug,
condensed, condensed,
}: ContentLineProps): JSX.Element => { }: ContentLineProps): JSX.Element => {
const { langui } = useAppLayout();
const { value: isOpened, toggle: toggleOpened } = useBoolean(false); const { value: isOpened, toggle: toggleOpened } = useBoolean(false);
const [selectedTranslation] = useSmartLanguage({ const [selectedTranslation] = useSmartLanguage({
items: content?.translations ?? [], items: content?.translations ?? [],
languages: languages,
languageExtractor: useCallback( languageExtractor: useCallback(
( (
item: NonNullable<ContentLineProps["content"]>["translations"][number] item: NonNullable<ContentLineProps["content"]>["translations"][number]

View File

@ -11,7 +11,6 @@ import {
GetLibraryItemScansQuery, GetLibraryItemScansQuery,
UploadImageFragment, UploadImageFragment,
} from "graphql/generated"; } from "graphql/generated";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk"; import { getReadySdk } from "graphql/sdk";
import { import {
prettyInlineTitle, prettyInlineTitle,
@ -47,13 +46,15 @@ import {
useIsContentPanelNoMoreThan, useIsContentPanelNoMoreThan,
} from "hooks/useContainerQuery"; } from "hooks/useContainerQuery";
import { cIf, cJoin } from "helpers/className"; import { cIf, cJoin } from "helpers/className";
import { useAppLayout } from "contexts/AppLayoutContext";
import { getLangui } from "graphql/fetchLocalData";
/* /*
* *
* PAGE * PAGE
*/ */
interface Props extends AppStaticProps, AppLayoutRequired { interface Props extends AppLayoutRequired {
item: NonNullable< item: NonNullable<
NonNullable< NonNullable<
GetLibraryItemScansQuery["libraryItems"] GetLibraryItemScansQuery["libraryItems"]
@ -64,16 +65,10 @@ interface Props extends AppStaticProps, AppLayoutRequired {
>; >;
} }
const LibrarySlug = ({ const LibrarySlug = ({ item, itemId, ...otherProps }: Props): JSX.Element => {
item,
itemId,
langui,
languages,
currencies,
...otherProps
}: Props): JSX.Element => {
const [openLightBox, LightBox] = useLightBox(); const [openLightBox, LightBox] = useLightBox();
const is1ColumnLayout = useIs1ColumnLayout(); const is1ColumnLayout = useIs1ColumnLayout();
const { langui } = useAppLayout();
const ids = useMemo( const ids = useMemo(
() => () =>
@ -90,7 +85,6 @@ const LibrarySlug = ({
<ReturnButton <ReturnButton
href={`/library/${item.slug}`} href={`/library/${item.slug}`}
title={langui.item} title={langui.item}
langui={langui}
className="mb-4" className="mb-4"
displayOnlyOn="3ColumnsLayout" displayOnlyOn="3ColumnsLayout"
/> />
@ -113,14 +107,13 @@ const LibrarySlug = ({
"attributes", "attributes",
] as const).map((category) => category.attributes.short)} ] as const).map((category) => category.attributes.short)}
metadata={{ metadata={{
currencies: currencies,
releaseDate: item.release_date, releaseDate: item.release_date,
price: item.price, price: item.price,
position: "Bottom", position: "Bottom",
}} }}
infoAppend={ infoAppend={
!isUntangibleGroupItem(item.metadata?.[0]) && ( !isUntangibleGroupItem(item.metadata?.[0]) && (
<PreviewCardCTAs id={itemId} langui={langui} /> <PreviewCardCTAs id={itemId} />
) )
} }
/> />
@ -180,7 +173,6 @@ const LibrarySlug = ({
</SubPanel> </SubPanel>
), ),
[ [
currencies,
currentIntersection, currentIntersection,
item.categories?.data, item.categories?.data,
item.contents?.data, item.contents?.data,
@ -205,18 +197,12 @@ const LibrarySlug = ({
<ReturnButton <ReturnButton
href={`/library/${item.slug}`} href={`/library/${item.slug}`}
title={langui.item} title={langui.item}
langui={langui}
displayOnlyOn="1ColumnLayout" displayOnlyOn="1ColumnLayout"
className="mb-10" className="mb-10"
/> />
{item.images && ( {item.images && (
<ScanSetCover <ScanSetCover images={item.images} openLightBox={openLightBox} />
images={item.images}
openLightBox={openLightBox}
languages={languages}
langui={langui}
/>
)} )}
{item.contents?.data.map((content) => ( {item.contents?.data.map((content) => (
@ -240,8 +226,6 @@ const LibrarySlug = ({
fallback={{ fallback={{
title: prettySlug(content.attributes.slug, item.slug), title: prettySlug(content.attributes.slug, item.slug),
}} }}
languages={languages}
langui={langui}
content={content.attributes.content} content={content.attributes.content}
/> />
)} )}
@ -255,7 +239,6 @@ const LibrarySlug = ({
item.contents?.data, item.contents?.data,
item.images, item.images,
item.slug, item.slug,
languages,
langui, langui,
] ]
); );
@ -264,9 +247,6 @@ const LibrarySlug = ({
<AppLayout <AppLayout
contentPanel={contentPanel} contentPanel={contentPanel}
subPanel={subPanel} subPanel={subPanel}
languages={languages}
langui={langui}
currencies={currencies}
{...otherProps} {...otherProps}
/> />
); );
@ -280,6 +260,7 @@ export default LibrarySlug;
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = async (context) => {
const sdk = getReadySdk(); const sdk = getReadySdk();
const langui = getLangui(context.locale);
const item = await sdk.getLibraryItemScans({ const item = await sdk.getLibraryItemScans({
slug: slug:
context.params && isDefined(context.params.slug) context.params && isDefined(context.params.slug)
@ -290,13 +271,12 @@ export const getStaticProps: GetStaticProps = async (context) => {
if (!item.libraryItems?.data[0]?.attributes || !item.libraryItems.data[0]?.id) if (!item.libraryItems?.data[0]?.attributes || !item.libraryItems.data[0]?.id)
return { notFound: true }; return { notFound: true };
sortRangedContent(item.libraryItems.data[0].attributes.contents); sortRangedContent(item.libraryItems.data[0].attributes.contents);
const appStaticProps = await getAppStaticProps(context);
const props: Props = { const props: Props = {
...appStaticProps,
item: item.libraryItems.data[0].attributes, item: item.libraryItems.data[0].attributes,
itemId: item.libraryItems.data[0].id, itemId: item.libraryItems.data[0].id,
openGraph: getOpenGraph( openGraph: getOpenGraph(
appStaticProps.langui, langui,
item.libraryItems.data[0].attributes.title, item.libraryItems.data[0].attributes.title,
undefined, undefined,
item.libraryItems.data[0].attributes.thumbnail?.data?.attributes item.libraryItems.data[0].attributes.thumbnail?.data?.attributes
@ -352,8 +332,7 @@ interface ScanSetProps {
>; >;
id: string; id: string;
title: string; title: string;
languages: AppStaticProps["languages"];
langui: AppStaticProps["langui"];
content: NonNullable< content: NonNullable<
NonNullable< NonNullable<
NonNullable< NonNullable<
@ -370,15 +349,13 @@ const ScanSet = ({
scanSet, scanSet,
id, id,
title, title,
languages,
langui,
content, content,
}: ScanSetProps): JSX.Element => { }: ScanSetProps): JSX.Element => {
const is1ColumnLayout = useIsContentPanelNoMoreThan("2xl"); const is1ColumnLayout = useIsContentPanelNoMoreThan("2xl");
const { langui } = useAppLayout();
const [selectedScan, LanguageSwitcher, languageSwitcherProps] = const [selectedScan, LanguageSwitcher, languageSwitcherProps] =
useSmartLanguage({ useSmartLanguage({
items: scanSet, items: scanSet,
languages: languages,
languageExtractor: useCallback( languageExtractor: useCallback(
(item: NonNullable<ScanSetProps["scanSet"][number]>) => (item: NonNullable<ScanSetProps["scanSet"][number]>) =>
item.language?.data?.attributes?.code, item.language?.data?.attributes?.code,
@ -479,10 +456,7 @@ const ScanSet = ({
"attributes", "attributes",
] as const).map((scanner) => ( ] as const).map((scanner) => (
<Fragment key={scanner.id}> <Fragment key={scanner.id}>
<RecorderChip <RecorderChip recorder={scanner.attributes} />
langui={langui}
recorder={scanner.attributes}
/>
</Fragment> </Fragment>
))} ))}
</div> </div>
@ -498,10 +472,7 @@ const ScanSet = ({
"attributes", "attributes",
] as const).map((cleaner) => ( ] as const).map((cleaner) => (
<Fragment key={cleaner.id}> <Fragment key={cleaner.id}>
<RecorderChip <RecorderChip recorder={cleaner.attributes} />
langui={langui}
recorder={cleaner.attributes}
/>
</Fragment> </Fragment>
))} ))}
</div> </div>
@ -520,10 +491,7 @@ const ScanSet = ({
"attributes", "attributes",
] as const).map((typesetter) => ( ] as const).map((typesetter) => (
<Fragment key={typesetter.id}> <Fragment key={typesetter.id}>
<RecorderChip <RecorderChip recorder={typesetter.attributes} />
langui={langui}
recorder={typesetter.attributes}
/>
</Fragment> </Fragment>
))} ))}
</div> </div>
@ -604,21 +572,17 @@ interface ScanSetCoverProps {
>["data"][number]["attributes"] >["data"][number]["attributes"]
>["images"] >["images"]
>; >;
languages: AppStaticProps["languages"];
langui: AppStaticProps["langui"];
} }
const ScanSetCover = ({ const ScanSetCover = ({
openLightBox, openLightBox,
images, images,
languages,
langui,
}: ScanSetCoverProps): JSX.Element => { }: ScanSetCoverProps): JSX.Element => {
const is1ColumnLayout = useIsContentPanelNoMoreThan("4xl"); const is1ColumnLayout = useIsContentPanelNoMoreThan("4xl");
const { langui } = useAppLayout();
const [selectedScan, LanguageSwitcher, languageSwitcherProps] = const [selectedScan, LanguageSwitcher, languageSwitcherProps] =
useSmartLanguage({ useSmartLanguage({
items: images, items: images,
languages: languages,
languageExtractor: useCallback( languageExtractor: useCallback(
(item: NonNullable<ScanSetCoverProps["images"][number]>) => (item: NonNullable<ScanSetCoverProps["images"][number]>) =>
item.language?.data?.attributes?.code, item.language?.data?.attributes?.code,
@ -687,10 +651,7 @@ const ScanSetCover = ({
"attributes", "attributes",
] as const).map((scanner) => ( ] as const).map((scanner) => (
<Fragment key={scanner.id}> <Fragment key={scanner.id}>
<RecorderChip <RecorderChip recorder={scanner.attributes} />
langui={langui}
recorder={scanner.attributes}
/>
</Fragment> </Fragment>
))} ))}
</div> </div>
@ -706,10 +667,7 @@ const ScanSetCover = ({
"attributes", "attributes",
] as const).map((cleaner) => ( ] as const).map((cleaner) => (
<Fragment key={cleaner.id}> <Fragment key={cleaner.id}>
<RecorderChip <RecorderChip recorder={cleaner.attributes} />
langui={langui}
recorder={cleaner.attributes}
/>
</Fragment> </Fragment>
))} ))}
</div> </div>
@ -728,10 +686,7 @@ const ScanSetCover = ({
"attributes", "attributes",
] as const).map((typesetter) => ( ] as const).map((typesetter) => (
<Fragment key={typesetter.id}> <Fragment key={typesetter.id}>
<RecorderChip <RecorderChip recorder={typesetter.attributes} />
langui={langui}
recorder={typesetter.attributes}
/>
</Fragment> </Fragment>
))} ))}
</div> </div>

View File

@ -11,7 +11,6 @@ import {
} from "components/Panels/ContentPanel"; } from "components/Panels/ContentPanel";
import { SubPanel } from "components/Panels/SubPanel"; import { SubPanel } from "components/Panels/SubPanel";
import { GetLibraryItemsPreviewQuery } from "graphql/generated"; import { GetLibraryItemsPreviewQuery } from "graphql/generated";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk"; import { getReadySdk } from "graphql/sdk";
import { prettyInlineTitle, prettyItemSubType } from "helpers/formatters"; import { prettyInlineTitle, prettyItemSubType } from "helpers/formatters";
import { LibraryItemUserStatus } from "helpers/types"; import { LibraryItemUserStatus } from "helpers/types";
@ -34,6 +33,8 @@ import { compareDate } from "helpers/date";
import { HorizontalLine } from "components/HorizontalLine"; import { HorizontalLine } from "components/HorizontalLine";
import { useIsContentPanelAtLeast } from "hooks/useContainerQuery"; import { useIsContentPanelAtLeast } from "hooks/useContainerQuery";
import { cIf, cJoin } from "helpers/className"; import { cIf, cJoin } from "helpers/className";
import { useCurrencies } from "hooks/useLocalData";
import { getLangui } from "graphql/fetchLocalData";
/* /*
* *
@ -56,17 +57,14 @@ const DEFAULT_FILTERS_STATE = {
* PAGE * PAGE
*/ */
interface Props extends AppStaticProps, AppLayoutRequired { interface Props extends AppLayoutRequired {
items: NonNullable<GetLibraryItemsPreviewQuery["libraryItems"]>["data"]; items: NonNullable<GetLibraryItemsPreviewQuery["libraryItems"]>["data"];
} }
const Library = ({ const Library = ({ items, ...otherProps }: Props): JSX.Element => {
langui,
items,
currencies,
...otherProps
}: Props): JSX.Element => {
const hoverable = useDeviceSupportsHover(); const hoverable = useDeviceSupportsHover();
const currencies = useCurrencies();
const { langui } = useAppLayout();
const { libraryItemUserStatus } = useAppLayout(); const { libraryItemUserStatus } = useAppLayout();
const isContentPanelAtLeast4xl = useIsContentPanelAtLeast("4xl"); const isContentPanelAtLeast4xl = useIsContentPanelAtLeast("4xl");
@ -417,14 +415,13 @@ const Library = ({
(category) => category.attributes?.short ?? "" (category) => category.attributes?.short ?? ""
)} )}
metadata={{ metadata={{
currencies: currencies,
releaseDate: item.attributes.release_date, releaseDate: item.attributes.release_date,
price: item.attributes.price, price: item.attributes.price,
position: "Bottom", position: "Bottom",
}} }}
infoAppend={ infoAppend={
!isUntangibleGroupItem(item.attributes.metadata?.[0]) && ( !isUntangibleGroupItem(item.attributes.metadata?.[0]) && (
<PreviewCardCTAs id={item.id} langui={langui} /> <PreviewCardCTAs id={item.id} />
) )
} }
/> />
@ -448,18 +445,15 @@ const Library = ({
} }
filteringFunction={filteringFunction} filteringFunction={filteringFunction}
paginationItemPerPage={25} paginationItemPerPage={25}
langui={langui}
/> />
</ContentPanel> </ContentPanel>
), ),
[ [
currencies,
filteringFunction, filteringFunction,
groupingFunction, groupingFunction,
isContentPanelAtLeast4xl, isContentPanelAtLeast4xl,
items, items,
keepInfoVisible, keepInfoVisible,
langui,
searchName, searchName,
sortingFunction, sortingFunction,
] ]
@ -470,8 +464,6 @@ const Library = ({
subPanel={subPanel} subPanel={subPanel}
contentPanel={contentPanel} contentPanel={contentPanel}
subPanelIcon={Icon.Search} subPanelIcon={Icon.Search}
currencies={currencies}
langui={langui}
{...otherProps} {...otherProps}
/> />
); );
@ -485,18 +477,15 @@ export default Library;
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = async (context) => {
const sdk = getReadySdk(); const sdk = getReadySdk();
const langui = getLangui(context.locale);
const items = await sdk.getLibraryItemsPreview({ const items = await sdk.getLibraryItemsPreview({
language_code: context.locale ?? "en", language_code: context.locale ?? "en",
}); });
if (!items.libraryItems?.data) return { notFound: true }; if (!items.libraryItems?.data) return { notFound: true };
const appStaticProps = await getAppStaticProps(context);
const props: Props = { const props: Props = {
...appStaticProps,
items: items.libraryItems.data, items: items.libraryItems.data,
openGraph: getOpenGraph( openGraph: getOpenGraph(langui, langui.library ?? "Library"),
appStaticProps.langui,
appStaticProps.langui.library ?? "Library"
),
}; };
return { return {
props: props, props: props,

View File

@ -2,31 +2,34 @@ import { GetStaticProps } from "next";
import { AppLayout, AppLayoutRequired } from "components/AppLayout"; import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { PanelHeader } from "components/PanelComponents/PanelHeader"; import { PanelHeader } from "components/PanelComponents/PanelHeader";
import { SubPanel } from "components/Panels/SubPanel"; import { SubPanel } from "components/Panels/SubPanel";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Icon } from "components/Ico"; import { Icon } from "components/Ico";
import { getOpenGraph } from "helpers/openGraph"; import { getOpenGraph } from "helpers/openGraph";
import { useAppLayout } from "contexts/AppLayoutContext";
import { getLangui } from "graphql/fetchLocalData";
/* /*
* *
* PAGE * PAGE
*/ */
interface Props extends AppStaticProps, AppLayoutRequired {} interface Props extends AppLayoutRequired {}
const Merch = ({ langui, ...otherProps }: Props): JSX.Element => ( const Merch = (props: Props): JSX.Element => {
<AppLayout const { langui } = useAppLayout();
subPanel={ return (
<SubPanel> <AppLayout
<PanelHeader subPanel={
icon={Icon.Store} <SubPanel>
title={langui.merch} <PanelHeader
description={langui.merch_description} icon={Icon.Store}
/> title={langui.merch}
</SubPanel> description={langui.merch_description}
} />
langui={langui} </SubPanel>
{...otherProps} }
/> {...props}
); />
);
};
export default Merch; export default Merch;
/* /*
@ -34,14 +37,10 @@ export default Merch;
* NEXT DATA FETCHING * NEXT DATA FETCHING
*/ */
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = (context) => {
const appStaticProps = await getAppStaticProps(context); const langui = getLangui(context.locale);
const props: Props = { const props: Props = {
...appStaticProps, openGraph: getOpenGraph(langui, langui.merch ?? "Merch"),
openGraph: getOpenGraph(
appStaticProps.langui,
appStaticProps.langui.merch ?? "Merch"
),
}; };
return { return {
props: props, props: props,

View File

@ -1,30 +1,33 @@
import { GetStaticPaths, GetStaticPathsResult, GetStaticProps } from "next"; import { GetStaticPaths, GetStaticPathsResult, GetStaticProps } from "next";
import { PostPage } from "components/PostPage"; import { PostPage } from "components/PostPage";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { import {
getPostStaticProps, getPostStaticProps,
PostStaticProps, PostStaticProps,
} from "graphql/getPostStaticProps"; } from "graphql/getPostStaticProps";
import { getReadySdk } from "graphql/sdk"; import { getReadySdk } from "graphql/sdk";
import { filterHasAttributes, isDefined } from "helpers/others"; import { filterHasAttributes, isDefined } from "helpers/others";
import { useAppLayout } from "contexts/AppLayoutContext";
/* /*
* *
* PAGE * PAGE
*/ */
interface Props extends AppStaticProps, PostStaticProps {} interface Props extends PostStaticProps {}
const LibrarySlug = (props: Props): JSX.Element => ( const LibrarySlug = (props: Props): JSX.Element => {
<PostPage const { langui } = useAppLayout();
returnHref="/news" return (
returnTitle={props.langui.news} <PostPage
displayCredits returnHref="/news"
displayThumbnailHeader returnTitle={langui.news}
displayToc displayCredits
{...props} displayThumbnailHeader
/> displayToc
); {...props}
/>
);
};
export default LibrarySlug; export default LibrarySlug;
/* /*

View File

@ -10,7 +10,6 @@ import {
} from "components/Panels/ContentPanel"; } from "components/Panels/ContentPanel";
import { SubPanel } from "components/Panels/SubPanel"; import { SubPanel } from "components/Panels/SubPanel";
import { GetPostsPreviewQuery } from "graphql/generated"; import { GetPostsPreviewQuery } from "graphql/generated";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk"; import { getReadySdk } from "graphql/sdk";
import { prettySlug } from "helpers/formatters"; import { prettySlug } from "helpers/formatters";
import { Icon } from "components/Ico"; import { Icon } from "components/Ico";
@ -26,6 +25,8 @@ import { TranslatedPreviewCard } from "components/PreviewCard";
import { HorizontalLine } from "components/HorizontalLine"; import { HorizontalLine } from "components/HorizontalLine";
import { cIf } from "helpers/className"; import { cIf } from "helpers/className";
import { useIsContentPanelAtLeast } from "hooks/useContainerQuery"; import { useIsContentPanelAtLeast } from "hooks/useContainerQuery";
import { useAppLayout } from "contexts/AppLayoutContext";
import { getLangui } from "graphql/fetchLocalData";
/* /*
* *
@ -42,12 +43,13 @@ const DEFAULT_FILTERS_STATE = {
* PAGE * PAGE
*/ */
interface Props extends AppStaticProps, AppLayoutRequired { interface Props extends AppLayoutRequired {
posts: NonNullable<GetPostsPreviewQuery["posts"]>["data"]; posts: NonNullable<GetPostsPreviewQuery["posts"]>["data"];
} }
const News = ({ langui, posts, ...otherProps }: Props): JSX.Element => { const News = ({ posts, ...otherProps }: Props): JSX.Element => {
const isContentPanelAtLeast4xl = useIsContentPanelAtLeast("4xl"); const isContentPanelAtLeast4xl = useIsContentPanelAtLeast("4xl");
const { langui } = useAppLayout();
const hoverable = useDeviceSupportsHover(); const hoverable = useDeviceSupportsHover();
const [searchName, setSearchName] = useState( const [searchName, setSearchName] = useState(
DEFAULT_FILTERS_STATE.searchName DEFAULT_FILTERS_STATE.searchName
@ -109,7 +111,6 @@ const News = ({ langui, posts, ...otherProps }: Props): JSX.Element => {
<SmartList <SmartList
items={filterHasAttributes(posts, ["attributes", "id"] as const)} items={filterHasAttributes(posts, ["attributes", "id"] as const)}
getItemId={(post) => post.id} getItemId={(post) => post.id}
langui={langui}
renderItem={({ item: post }) => ( renderItem={({ item: post }) => (
<TranslatedPreviewCard <TranslatedPreviewCard
href={`/news/${post.attributes.slug}`} href={`/news/${post.attributes.slug}`}
@ -150,7 +151,7 @@ const News = ({ langui, posts, ...otherProps }: Props): JSX.Element => {
/> />
</ContentPanel> </ContentPanel>
), ),
[keepInfoVisible, langui, posts, searchName, isContentPanelAtLeast4xl] [keepInfoVisible, posts, searchName, isContentPanelAtLeast4xl]
); );
return ( return (
@ -158,7 +159,6 @@ const News = ({ langui, posts, ...otherProps }: Props): JSX.Element => {
subPanel={subPanel} subPanel={subPanel}
contentPanel={contentPanel} contentPanel={contentPanel}
subPanelIcon={Icon.Search} subPanelIcon={Icon.Search}
langui={langui}
{...otherProps} {...otherProps}
/> />
); );
@ -172,16 +172,13 @@ export default News;
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = async (context) => {
const sdk = getReadySdk(); const sdk = getReadySdk();
const langui = getLangui(context.locale);
const posts = await sdk.getPostsPreview(); const posts = await sdk.getPostsPreview();
if (!posts.posts) return { notFound: true }; if (!posts.posts) return { notFound: true };
const appStaticProps = await getAppStaticProps(context);
const props: Props = { const props: Props = {
...appStaticProps,
posts: sortPosts(posts.posts.data), posts: sortPosts(posts.posts.data),
openGraph: getOpenGraph( openGraph: getOpenGraph(langui, langui.news ?? "News"),
appStaticProps.langui,
appStaticProps.langui.news ?? "News"
),
}; };
return { return {
props: props, props: props,

View File

@ -11,7 +11,6 @@ import {
} from "components/Panels/ContentPanel"; } from "components/Panels/ContentPanel";
import { SubPanel } from "components/Panels/SubPanel"; import { SubPanel } from "components/Panels/SubPanel";
import DefinitionCard from "components/Wiki/DefinitionCard"; import DefinitionCard from "components/Wiki/DefinitionCard";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk"; import { getReadySdk } from "graphql/sdk";
import { import {
filterHasAttributes, filterHasAttributes,
@ -31,26 +30,23 @@ import {
import { getDescription } from "helpers/description"; import { getDescription } from "helpers/description";
import { cIf, cJoin } from "helpers/className"; import { cIf, cJoin } from "helpers/className";
import { useIs3ColumnsLayout } from "hooks/useContainerQuery"; import { useIs3ColumnsLayout } from "hooks/useContainerQuery";
import { useAppLayout } from "contexts/AppLayoutContext";
import { getLangui } from "graphql/fetchLocalData";
/* /*
* *
* PAGE * PAGE
*/ */
interface Props extends AppStaticProps, AppLayoutRequired { interface Props extends AppLayoutRequired {
page: WikiPageWithTranslations; page: WikiPageWithTranslations;
} }
const WikiPage = ({ const WikiPage = ({ page, ...otherProps }: Props): JSX.Element => {
page, const { langui } = useAppLayout();
langui,
languages,
...otherProps
}: Props): JSX.Element => {
const [selectedTranslation, LanguageSwitcher, languageSwitcherProps] = const [selectedTranslation, LanguageSwitcher, languageSwitcherProps] =
useSmartLanguage({ useSmartLanguage({
items: page.translations, items: page.translations,
languages: languages,
languageExtractor: useCallback( languageExtractor: useCallback(
(item: NonNullable<Props["page"]["translations"][number]>) => (item: NonNullable<Props["page"]["translations"][number]>) =>
item.language?.data?.attributes?.code, item.language?.data?.attributes?.code,
@ -67,7 +63,6 @@ const WikiPage = ({
<ReturnButton <ReturnButton
href={`/wiki`} href={`/wiki`}
title={langui.wiki} title={langui.wiki}
langui={langui}
displayOnlyOn={"3ColumnsLayout"} displayOnlyOn={"3ColumnsLayout"}
/> />
</SubPanel> </SubPanel>
@ -83,7 +78,6 @@ const WikiPage = ({
<ReturnButton <ReturnButton
href={`/wiki`} href={`/wiki`}
title={langui.wiki} title={langui.wiki}
langui={langui}
displayOnlyOn={"1ColumnLayout"} displayOnlyOn={"1ColumnLayout"}
className="mb-10" className="mb-10"
/> />
@ -200,8 +194,6 @@ const WikiPage = ({
}) })
)} )}
index={index + 1} index={index + 1}
languages={languages}
langui={langui}
categories={filterHasAttributes( categories={filterHasAttributes(
definition.categories?.data, definition.categories?.data,
["attributes"] as const ["attributes"] as const
@ -219,7 +211,6 @@ const WikiPage = ({
LightBox, LightBox,
is3ColumnsLayout, is3ColumnsLayout,
languageSwitcherProps, languageSwitcherProps,
languages,
langui, langui,
openLightBox, openLightBox,
page.categories?.data, page.categories?.data,
@ -234,8 +225,6 @@ const WikiPage = ({
<AppLayout <AppLayout
subPanel={subPanel} subPanel={subPanel}
contentPanel={contentPanel} contentPanel={contentPanel}
languages={languages}
langui={langui}
{...otherProps} {...otherProps}
/> />
); );
@ -249,6 +238,7 @@ export default WikiPage;
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = async (context) => {
const sdk = getReadySdk(); const sdk = getReadySdk();
const langui = getLangui(context.locale);
const slug = const slug =
context.params && isDefined(context.params.slug) context.params && isDefined(context.params.slug)
? context.params.slug.toString() ? context.params.slug.toString()
@ -259,18 +249,17 @@ export const getStaticProps: GetStaticProps = async (context) => {
}); });
if (!page.wikiPages?.data[0].attributes?.translations) if (!page.wikiPages?.data[0].attributes?.translations)
return { notFound: true }; return { notFound: true };
const appStaticProps = await getAppStaticProps(context);
const { title, description } = (() => { const { title, description } = (() => {
const chipsGroups = { const chipsGroups = {
[appStaticProps.langui.tags ?? "Tags"]: filterHasAttributes( [langui.tags ?? "Tags"]: filterHasAttributes(
page.wikiPages.data[0].attributes.tags?.data, page.wikiPages.data[0].attributes.tags?.data,
["attributes"] as const ["attributes"] as const
).map( ).map(
(tag) => (tag) =>
tag.attributes.titles?.[0]?.title ?? prettySlug(tag.attributes.slug) tag.attributes.titles?.[0]?.title ?? prettySlug(tag.attributes.slug)
), ),
[appStaticProps.langui.categories ?? "Categories"]: filterHasAttributes( [langui.categories ?? "Categories"]: filterHasAttributes(
page.wikiPages.data[0].attributes.categories?.data, page.wikiPages.data[0].attributes.categories?.data,
["attributes"] as const ["attributes"] as const
).map((category) => category.attributes.short), ).map((category) => category.attributes.short),
@ -303,14 +292,8 @@ export const getStaticProps: GetStaticProps = async (context) => {
page.wikiPages.data[0].attributes.thumbnail?.data?.attributes; page.wikiPages.data[0].attributes.thumbnail?.data?.attributes;
const props: Props = { const props: Props = {
...appStaticProps,
page: page.wikiPages.data[0].attributes as WikiPageWithTranslations, page: page.wikiPages.data[0].attributes as WikiPageWithTranslations,
openGraph: getOpenGraph( openGraph: getOpenGraph(langui, title, description, thumbnail),
appStaticProps.langui,
title,
description,
thumbnail
),
}; };
return { return {
props: props, props: props,

View File

@ -11,7 +11,6 @@ import {
GetChronologyItemsQuery, GetChronologyItemsQuery,
GetErasQuery, GetErasQuery,
} from "graphql/generated"; } from "graphql/generated";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk"; import { getReadySdk } from "graphql/sdk";
import { prettySlug } from "helpers/formatters"; import { prettySlug } from "helpers/formatters";
import { import {
@ -31,13 +30,15 @@ import { TranslatedProps } from "helpers/types/TranslatedProps";
import { TranslatedNavOption } from "components/PanelComponents/NavOption"; import { TranslatedNavOption } from "components/PanelComponents/NavOption";
import { useIntersectionList } from "hooks/useIntersectionList"; import { useIntersectionList } from "hooks/useIntersectionList";
import { HorizontalLine } from "components/HorizontalLine"; import { HorizontalLine } from "components/HorizontalLine";
import { useAppLayout } from "contexts/AppLayoutContext";
import { getLangui } from "graphql/fetchLocalData";
/* /*
* *
* PAGE * PAGE
*/ */
interface Props extends AppStaticProps, AppLayoutRequired { interface Props extends AppLayoutRequired {
chronologyItems: NonNullable< chronologyItems: NonNullable<
GetChronologyItemsQuery["chronologyItems"] GetChronologyItemsQuery["chronologyItems"]
>["data"]; >["data"];
@ -47,10 +48,9 @@ interface Props extends AppStaticProps, AppLayoutRequired {
const Chronology = ({ const Chronology = ({
chronologyItems, chronologyItems,
chronologyEras, chronologyEras,
langui,
languages,
...otherProps ...otherProps
}: Props): JSX.Element => { }: Props): JSX.Element => {
const { langui } = useAppLayout();
const ids = useMemo( const ids = useMemo(
() => () =>
filterHasAttributes(chronologyEras, ["attributes"] as const).map( filterHasAttributes(chronologyEras, ["attributes"] as const).map(
@ -67,7 +67,6 @@ const Chronology = ({
<ReturnButton <ReturnButton
href="/wiki" href="/wiki"
title={langui.wiki} title={langui.wiki}
langui={langui}
displayOnlyOn="3ColumnsLayout" displayOnlyOn="3ColumnsLayout"
/> />
@ -106,7 +105,6 @@ const Chronology = ({
<ReturnButton <ReturnButton
href="/wiki" href="/wiki"
title={langui.wiki} title={langui.wiki}
langui={langui}
displayOnlyOn="1ColumnLayout" displayOnlyOn="1ColumnLayout"
className="mb-10" className="mb-10"
/> />
@ -131,22 +129,18 @@ const Chronology = ({
item.attributes.year >= era.attributes.starting_year && item.attributes.year >= era.attributes.starting_year &&
item.attributes.year < era.attributes.ending_year item.attributes.year < era.attributes.ending_year
)} )}
langui={langui}
languages={languages}
/> />
) )
)} )}
</ContentPanel> </ContentPanel>
), ),
[chronologyEras, chronologyItems, languages, langui] [chronologyEras, chronologyItems, langui]
); );
return ( return (
<AppLayout <AppLayout
contentPanel={contentPanel} contentPanel={contentPanel}
subPanel={subPanel} subPanel={subPanel}
langui={langui}
languages={languages}
{...otherProps} {...otherProps}
/> />
); );
@ -160,19 +154,16 @@ export default Chronology;
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = async (context) => {
const sdk = getReadySdk(); const sdk = getReadySdk();
const langui = getLangui(context.locale);
const chronologyItems = await sdk.getChronologyItems(); const chronologyItems = await sdk.getChronologyItems();
const chronologyEras = await sdk.getEras(); const chronologyEras = await sdk.getEras();
if (!chronologyItems.chronologyItems || !chronologyEras.chronologyEras) if (!chronologyItems.chronologyItems || !chronologyEras.chronologyEras)
return { notFound: true }; return { notFound: true };
const appStaticProps = await getAppStaticProps(context);
const props: Props = { const props: Props = {
...appStaticProps,
chronologyItems: chronologyItems.chronologyItems.data, chronologyItems: chronologyItems.chronologyItems.data,
chronologyEras: chronologyEras.chronologyEras.data, chronologyEras: chronologyEras.chronologyEras.data,
openGraph: getOpenGraph( openGraph: getOpenGraph(langui, langui.chronology ?? "Chronology"),
appStaticProps.langui,
appStaticProps.langui.chronology ?? "Chronology"
),
}; };
return { return {
props: props, props: props,
@ -189,8 +180,6 @@ interface ChronologyEraProps {
title: string; title: string;
description?: string | null | undefined; description?: string | null | undefined;
chronologyItems: Props["chronologyItems"]; chronologyItems: Props["chronologyItems"];
langui: AppStaticProps["langui"];
languages: AppStaticProps["languages"];
} }
const ChronologyEra = ({ const ChronologyEra = ({
@ -198,8 +187,6 @@ const ChronologyEra = ({
title, title,
description, description,
chronologyItems, chronologyItems,
langui,
languages,
}: ChronologyEraProps) => { }: ChronologyEraProps) => {
const yearGroups = useMemo(() => { const yearGroups = useMemo(() => {
const memo: Props["chronologyItems"][] = []; const memo: Props["chronologyItems"][] = [];
@ -222,7 +209,7 @@ const ChronologyEra = ({
<InsetBox className="my-8 grid gap-4 text-center"> <InsetBox className="my-8 grid gap-4 text-center">
<h2 className="flex place-content-center gap-3 text-2xl"> <h2 className="flex place-content-center gap-3 text-2xl">
{title} {title}
<AnchorShare id={id} langui={langui} /> <AnchorShare id={id} />
</h2> </h2>
{isDefinedAndNotEmpty(description) && ( {isDefinedAndNotEmpty(description) && (
@ -231,12 +218,7 @@ const ChronologyEra = ({
</InsetBox> </InsetBox>
<div> <div>
{yearGroups.map((item, index) => ( {yearGroups.map((item, index) => (
<ChronologyYear <ChronologyYear key={index} items={item} />
key={index}
items={item}
langui={langui}
languages={languages}
/>
))} ))}
</div> </div>
</div> </div>
@ -271,11 +253,9 @@ const TranslatedChronologyEra = ({
interface ChronologyYearProps { interface ChronologyYearProps {
items: NonNullable<Props["chronologyItems"]>; items: NonNullable<Props["chronologyItems"]>;
langui: AppStaticProps["langui"];
languages: AppStaticProps["languages"];
} }
const ChronologyYear = ({ items, langui, languages }: ChronologyYearProps) => ( const ChronologyYear = ({ items }: ChronologyYearProps) => (
<div <div
className="rounded-2xl target:my-4 target:bg-mid target:py-4" className="rounded-2xl target:my-4 target:bg-mid target:py-4"
id={generateAnchor(items[0].attributes?.year)} id={generateAnchor(items[0].attributes?.year)}
@ -284,8 +264,6 @@ const ChronologyYear = ({ items, langui, languages }: ChronologyYearProps) => (
(item, index) => ( (item, index) => (
<ChronologyDate <ChronologyDate
key={index} key={index}
langui={langui}
languages={languages}
date={{ date={{
year: item.attributes.year, year: item.attributes.year,
month: item.attributes.month, month: item.attributes.month,
@ -315,15 +293,11 @@ interface ChronologyDateProps {
NonNullable<Props["chronologyItems"]>[number]["attributes"] NonNullable<Props["chronologyItems"]>[number]["attributes"]
>["events"] >["events"]
>; >;
langui: AppStaticProps["langui"];
languages: AppStaticProps["languages"];
} }
export const ChronologyDate = ({ export const ChronologyDate = ({
date, date,
events, events,
langui,
languages,
}: ChronologyDateProps): JSX.Element => { }: ChronologyDateProps): JSX.Element => {
const router = useRouter(); const router = useRouter();
return ( return (
@ -368,8 +342,6 @@ export const ChronologyDate = ({
id={generateAnchor(date.year, date.month, date.day)} id={generateAnchor(date.year, date.month, date.day)}
key={event.id} key={event.id}
event={event} event={event}
langui={langui}
languages={languages}
/> />
) )
)} )}
@ -388,17 +360,15 @@ interface ChronologyEventProps {
>["events"] >["events"]
>[number] >[number]
>; >;
langui: AppStaticProps["langui"];
languages: AppStaticProps["languages"];
id: string; id: string;
} }
export const ChronologyEvent = ({ export const ChronologyEvent = ({
event, event,
langui,
languages,
id, id,
}: ChronologyEventProps): JSX.Element => { }: ChronologyEventProps): JSX.Element => {
const { langui } = useAppLayout();
const [selectedTranslation, LanguageSwitcher, languageSwitcherProps] = const [selectedTranslation, LanguageSwitcher, languageSwitcherProps] =
useSmartLanguage({ useSmartLanguage({
items: event.translations ?? [], items: event.translations ?? [],
@ -410,7 +380,6 @@ export const ChronologyEvent = ({
) => item?.language?.data?.attributes?.code, ) => item?.language?.data?.attributes?.code,
[] []
), ),
languages: languages,
}); });
return ( return (
@ -449,7 +418,7 @@ export const ChronologyEvent = ({
</p> </p>
<span className="flex-shrink"> <span className="flex-shrink">
<AnchorShare id={id} langui={langui} /> <AnchorShare id={id} />
</span> </span>
</div> </div>

View File

@ -5,7 +5,6 @@ import { AppLayout, AppLayoutRequired } from "components/AppLayout";
import { NavOption } from "components/PanelComponents/NavOption"; import { NavOption } from "components/PanelComponents/NavOption";
import { PanelHeader } from "components/PanelComponents/PanelHeader"; import { PanelHeader } from "components/PanelComponents/PanelHeader";
import { SubPanel } from "components/Panels/SubPanel"; import { SubPanel } from "components/Panels/SubPanel";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Icon } from "components/Ico"; import { Icon } from "components/Ico";
import { getReadySdk } from "graphql/sdk"; import { getReadySdk } from "graphql/sdk";
import { GetWikiPageQuery, GetWikiPagesPreviewsQuery } from "graphql/generated"; import { GetWikiPageQuery, GetWikiPagesPreviewsQuery } from "graphql/generated";
@ -28,6 +27,8 @@ import { getOpenGraph } from "helpers/openGraph";
import { TranslatedPreviewCard } from "components/PreviewCard"; import { TranslatedPreviewCard } from "components/PreviewCard";
import { useIsContentPanelAtLeast } from "hooks/useContainerQuery"; import { useIsContentPanelAtLeast } from "hooks/useContainerQuery";
import { cIf } from "helpers/className"; import { cIf } from "helpers/className";
import { useAppLayout } from "contexts/AppLayoutContext";
import { getLangui } from "graphql/fetchLocalData";
/* /*
* *
@ -45,12 +46,13 @@ const DEFAULT_FILTERS_STATE = {
* PAGE * PAGE
*/ */
interface Props extends AppStaticProps, AppLayoutRequired { interface Props extends AppLayoutRequired {
pages: NonNullable<GetWikiPagesPreviewsQuery["wikiPages"]>["data"]; pages: NonNullable<GetWikiPagesPreviewsQuery["wikiPages"]>["data"];
} }
const Wiki = ({ langui, pages, ...otherProps }: Props): JSX.Element => { const Wiki = ({ pages, ...otherProps }: Props): JSX.Element => {
const hoverable = useDeviceSupportsHover(); const hoverable = useDeviceSupportsHover();
const { langui } = useAppLayout();
const isContentPanelAtLeast4xl = useIsContentPanelAtLeast("4xl"); const isContentPanelAtLeast4xl = useIsContentPanelAtLeast("4xl");
const [searchName, setSearchName] = useState( const [searchName, setSearchName] = useState(
@ -198,7 +200,6 @@ const Wiki = ({ langui, pages, ...otherProps }: Props): JSX.Element => {
).map((category) => category.attributes.short)} ).map((category) => category.attributes.short)}
/> />
)} )}
langui={langui}
className={cIf( className={cIf(
isContentPanelAtLeast4xl, isContentPanelAtLeast4xl,
"grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))] gap-x-6 gap-y-8", "grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))] gap-x-6 gap-y-8",
@ -223,7 +224,6 @@ const Wiki = ({ langui, pages, ...otherProps }: Props): JSX.Element => {
[ [
groupingFunction, groupingFunction,
keepInfoVisible, keepInfoVisible,
langui,
pages, pages,
searchName, searchName,
isContentPanelAtLeast4xl, isContentPanelAtLeast4xl,
@ -235,7 +235,6 @@ const Wiki = ({ langui, pages, ...otherProps }: Props): JSX.Element => {
subPanel={subPanel} subPanel={subPanel}
contentPanel={contentPanel} contentPanel={contentPanel}
subPanelIcon={Icon.Search} subPanelIcon={Icon.Search}
langui={langui}
{...otherProps} {...otherProps}
/> />
); );
@ -249,18 +248,15 @@ export default Wiki;
export const getStaticProps: GetStaticProps = async (context) => { export const getStaticProps: GetStaticProps = async (context) => {
const sdk = getReadySdk(); const sdk = getReadySdk();
const langui = getLangui(context.locale);
const pages = await sdk.getWikiPagesPreviews({ const pages = await sdk.getWikiPagesPreviews({
language_code: context.locale ?? "en", language_code: context.locale ?? "en",
}); });
if (!pages.wikiPages?.data) return { notFound: true }; if (!pages.wikiPages?.data) return { notFound: true };
const appStaticProps = await getAppStaticProps(context);
const props: Props = { const props: Props = {
...appStaticProps,
pages: sortPages(pages.wikiPages.data), pages: sortPages(pages.wikiPages.data),
openGraph: getOpenGraph( openGraph: getOpenGraph(langui, langui.wiki ?? "Wiki"),
appStaticProps.langui,
appStaticProps.langui.wiki ?? "Wiki"
),
}; };
return { return {
props: props, props: props,