Added smart language switch for posts ad hoc page and content
This commit is contained in:
parent
049a2e2044
commit
a84560d86e
|
@ -171,7 +171,7 @@ module.exports = {
|
||||||
"@typescript-eslint/no-require-imports": "error",
|
"@typescript-eslint/no-require-imports": "error",
|
||||||
// "@typescript-eslint/no-type-alias": "warn",
|
// "@typescript-eslint/no-type-alias": "warn",
|
||||||
"@typescript-eslint/no-unnecessary-boolean-literal-compare": "warn",
|
"@typescript-eslint/no-unnecessary-boolean-literal-compare": "warn",
|
||||||
// "@typescript-eslint/no-unnecessary-condition": "warn",
|
"@typescript-eslint/no-unnecessary-condition": "warn",
|
||||||
"@typescript-eslint/no-unnecessary-qualifier": "warn",
|
"@typescript-eslint/no-unnecessary-qualifier": "warn",
|
||||||
"@typescript-eslint/no-unnecessary-type-arguments": "warn",
|
"@typescript-eslint/no-unnecessary-type-arguments": "warn",
|
||||||
"@typescript-eslint/prefer-enum-initializers": "error",
|
"@typescript-eslint/prefer-enum-initializers": "error",
|
||||||
|
|
|
@ -11,42 +11,61 @@ interface Props {
|
||||||
target?: "_blank";
|
target?: "_blank";
|
||||||
onClick?: MouseEventHandler<HTMLDivElement>;
|
onClick?: MouseEventHandler<HTMLDivElement>;
|
||||||
draggable?: boolean;
|
draggable?: boolean;
|
||||||
|
badgeNumber?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Button(props: Props): JSX.Element {
|
export default function Button(props: Props): JSX.Element {
|
||||||
|
const {
|
||||||
|
draggable,
|
||||||
|
id,
|
||||||
|
onClick,
|
||||||
|
active,
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
target,
|
||||||
|
href,
|
||||||
|
locale,
|
||||||
|
badgeNumber,
|
||||||
|
} = props;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const button = (
|
const button = (
|
||||||
<div
|
<div
|
||||||
draggable={props.draggable}
|
draggable={draggable}
|
||||||
id={props.id}
|
id={id}
|
||||||
onClick={props.onClick}
|
onClick={onClick}
|
||||||
className={`grid place-content-center place-items-center border-[1px] border-dark text-dark rounded-full px-4 pt-[0.4rem] pb-[0.5rem] transition-all select-none ${
|
className={`grid place-content-center place-items-center border-[1px]
|
||||||
props.className
|
border-dark text-dark rounded-full px-4 pt-[0.4rem] pb-[0.5rem]
|
||||||
} ${
|
transition-all select-none hover:[--opacityBadge:0] --opacityBadge:100 ${className} ${
|
||||||
props.active
|
active
|
||||||
? "text-light bg-black drop-shadow-black-lg !border-black cursor-not-allowed"
|
? "text-light bg-black drop-shadow-black-lg !border-black cursor-not-allowed"
|
||||||
: "cursor-pointer hover:text-light hover:bg-dark hover:drop-shadow-shade-lg active:bg-black active:text-light active:drop-shadow-black-lg active:border-black"
|
: "cursor-pointer hover:text-light hover:bg-dark hover:drop-shadow-shade-lg active:bg-black active:text-light active:drop-shadow-black-lg active:border-black"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{props.children}
|
{badgeNumber && (
|
||||||
|
<div className="opacity-[var(--opacityBadge)] transition-opacity grid place-items-center absolute -top-3 -right-2 bg-dark w-8 h-8 text-light font-bold rounded-full">
|
||||||
|
{badgeNumber}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
if (props.target) {
|
if (target) {
|
||||||
return (
|
return (
|
||||||
<a href={props.href} target={props.target} rel="noreferrer">
|
<a href={href} target={target} rel="noreferrer">
|
||||||
<div>{button}</div>
|
<div className="relative">{button}</div>
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
className="relative"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (props.href || props.locale)
|
if (href || locale)
|
||||||
router.push(props.href ?? router.asPath, props.href, {
|
router.push(href ?? router.asPath, href, {
|
||||||
locale: props.locale,
|
locale: locale,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
@ -26,6 +26,7 @@ interface Props {
|
||||||
>["categories"];
|
>["categories"];
|
||||||
thumbnail?: UploadImageFragment | null | undefined;
|
thumbnail?: UploadImageFragment | null | undefined;
|
||||||
langui: AppStaticProps["langui"];
|
langui: AppStaticProps["langui"];
|
||||||
|
languageSwitcher?: JSX.Element;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ThumbnailHeader(props: Props): JSX.Element {
|
export default function ThumbnailHeader(props: Props): JSX.Element {
|
||||||
|
@ -38,6 +39,7 @@ export default function ThumbnailHeader(props: Props): JSX.Element {
|
||||||
type,
|
type,
|
||||||
categories,
|
categories,
|
||||||
description,
|
description,
|
||||||
|
languageSwitcher,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -67,7 +69,7 @@ export default function ThumbnailHeader(props: Props): JSX.Element {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-flow-col gap-8">
|
<div className="flex place-content-center flex-row flew-wrap gap-8">
|
||||||
{type?.data?.attributes && (
|
{type?.data?.attributes && (
|
||||||
<div className="flex flex-col place-items-center gap-2">
|
<div className="flex flex-col place-items-center gap-2">
|
||||||
<h3 className="text-xl">{langui.type}</h3>
|
<h3 className="text-xl">{langui.type}</h3>
|
||||||
|
@ -92,6 +94,7 @@ export default function ThumbnailHeader(props: Props): JSX.Element {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{languageSwitcher}
|
||||||
</div>
|
</div>
|
||||||
{description && <InsetBox className="mt-8">{description}</InsetBox>}
|
{description && <InsetBox className="mt-8">{description}</InsetBox>}
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -1,33 +1,31 @@
|
||||||
import { useRouter } from "next/router";
|
|
||||||
import { AppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps } from "queries/getAppStaticProps";
|
||||||
import { prettyLanguage } from "queries/helpers";
|
import { prettyLanguage } from "queries/helpers";
|
||||||
|
import { Dispatch, SetStateAction } from "react";
|
||||||
import Button from "./Button";
|
import Button from "./Button";
|
||||||
|
import ToolTip from "./ToolTip";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
className?: string;
|
className?: string;
|
||||||
locales: (string | undefined)[];
|
|
||||||
languages: AppStaticProps["languages"];
|
languages: AppStaticProps["languages"];
|
||||||
langui: AppStaticProps["langui"];
|
locales: Map<string, number>;
|
||||||
href?: string;
|
localesIndex: number | undefined;
|
||||||
|
setLocalesIndex: Dispatch<SetStateAction<number | undefined>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function LanguageSwitcher(props: Props): JSX.Element {
|
export default function LanguageSwitcher(props: Props): JSX.Element {
|
||||||
const { locales, langui, href } = props;
|
const { locales, localesIndex, setLocalesIndex } = props;
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full grid place-content-center">
|
<ToolTip
|
||||||
<div className="flex flex-col place-items-center text-center gap-4 my-12 border-2 border-mid rounded-xl p-8 max-w-lg">
|
content={
|
||||||
<p>{langui.language_switch_message}</p>
|
<div className="flex flex-col gap-2">
|
||||||
<div className="flex flex-wrap flex-row gap-2">
|
{[...locales].map(([locale, value], index) => (
|
||||||
{locales.map((locale, index) => (
|
|
||||||
<>
|
<>
|
||||||
{locale && (
|
{locale && (
|
||||||
<Button
|
<Button
|
||||||
key={index}
|
key={index}
|
||||||
active={locale === router.locale}
|
active={value === localesIndex}
|
||||||
href={href}
|
onClick={() => setLocalesIndex(value)}
|
||||||
locale={locale}
|
|
||||||
>
|
>
|
||||||
{prettyLanguage(locale, props.languages)}
|
{prettyLanguage(locale, props.languages)}
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -35,7 +33,11 @@ export default function LanguageSwitcher(props: Props): JSX.Element {
|
||||||
</>
|
</>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
}
|
||||||
</div>
|
>
|
||||||
|
<Button badgeNumber={locales.size}>
|
||||||
|
<span className="material-icons">translate</span>
|
||||||
|
</Button>
|
||||||
|
</ToolTip>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,230 @@
|
||||||
|
import { useAppLayout } from "contexts/AppLayoutContext";
|
||||||
|
import { GetPostQuery } from "graphql/generated";
|
||||||
|
import { useRouter } from "next/router";
|
||||||
|
import { AppStaticProps } from "queries/getAppStaticProps";
|
||||||
|
import {
|
||||||
|
getPreferredLanguage,
|
||||||
|
getStatusDescription,
|
||||||
|
prettySlug,
|
||||||
|
} from "queries/helpers";
|
||||||
|
import { useEffect, useMemo, useState } from "react";
|
||||||
|
import AppLayout from "./AppLayout";
|
||||||
|
import Chip from "./Chip";
|
||||||
|
import ThumbnailHeader from "./Content/ThumbnailHeader";
|
||||||
|
import HorizontalLine from "./HorizontalLine";
|
||||||
|
import LanguageSwitcher from "./LanguageSwitcher";
|
||||||
|
import Markdawn from "./Markdown/Markdawn";
|
||||||
|
import TOC from "./Markdown/TOC";
|
||||||
|
import ReturnButton, { ReturnButtonType } from "./PanelComponents/ReturnButton";
|
||||||
|
import ContentPanel from "./Panels/ContentPanel";
|
||||||
|
import SubPanel from "./Panels/SubPanel";
|
||||||
|
import RecorderChip from "./RecorderChip";
|
||||||
|
import ToolTip from "./ToolTip";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
post: Exclude<
|
||||||
|
GetPostQuery["posts"],
|
||||||
|
null | undefined
|
||||||
|
>["data"][number]["attributes"];
|
||||||
|
langui: AppStaticProps["langui"];
|
||||||
|
languages: AppStaticProps["languages"];
|
||||||
|
currencies: AppStaticProps["currencies"];
|
||||||
|
returnHref?: string;
|
||||||
|
returnTitle?: string | null | undefined;
|
||||||
|
displayCredits?: boolean;
|
||||||
|
displayToc?: boolean;
|
||||||
|
displayThumbnailHeader?: boolean;
|
||||||
|
displayTitle?: boolean;
|
||||||
|
displayLanguageSwitcher?: boolean;
|
||||||
|
prependBody?: JSX.Element;
|
||||||
|
appendBody?: JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Post(props: Props): JSX.Element {
|
||||||
|
const {
|
||||||
|
post,
|
||||||
|
langui,
|
||||||
|
languages,
|
||||||
|
returnHref,
|
||||||
|
returnTitle,
|
||||||
|
displayCredits,
|
||||||
|
displayToc,
|
||||||
|
displayThumbnailHeader,
|
||||||
|
displayLanguageSwitcher,
|
||||||
|
appendBody,
|
||||||
|
prependBody,
|
||||||
|
} = props;
|
||||||
|
const displayTitle = props.displayTitle ?? true;
|
||||||
|
|
||||||
|
const appLayout = useAppLayout();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const [selectedTranslation, setSelectedTranslation] = useState<
|
||||||
|
| Exclude<
|
||||||
|
Exclude<Props["post"], null | undefined>["translations"],
|
||||||
|
null | undefined
|
||||||
|
>[number]
|
||||||
|
>();
|
||||||
|
const translationLocales: Map<string, number> = new Map();
|
||||||
|
|
||||||
|
const [selectedTranslationIndex, setSelectedTranslationIndex] = useState<
|
||||||
|
number | undefined
|
||||||
|
>();
|
||||||
|
|
||||||
|
if (post?.translations) {
|
||||||
|
post.translations.map((translation, index) => {
|
||||||
|
if (translation?.language?.data?.attributes?.code) {
|
||||||
|
translationLocales.set(
|
||||||
|
translation.language.data.attributes.code,
|
||||||
|
index
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
useMemo(() => {
|
||||||
|
setSelectedTranslationIndex(
|
||||||
|
getPreferredLanguage(
|
||||||
|
appLayout.preferredLanguages ?? [router.locale],
|
||||||
|
translationLocales
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}, [appLayout.preferredLanguages]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedTranslationIndex !== undefined)
|
||||||
|
setSelectedTranslation(post?.translations?.[selectedTranslationIndex]);
|
||||||
|
}, [selectedTranslationIndex]);
|
||||||
|
|
||||||
|
const thumbnail =
|
||||||
|
selectedTranslation?.thumbnail?.data?.attributes ??
|
||||||
|
post?.thumbnail?.data?.attributes;
|
||||||
|
|
||||||
|
const body = selectedTranslation?.body ?? "";
|
||||||
|
const title = selectedTranslation?.title ?? prettySlug(post?.slug);
|
||||||
|
const except = selectedTranslation?.excerpt ?? "";
|
||||||
|
|
||||||
|
const subPanel =
|
||||||
|
returnHref || returnTitle || displayCredits || displayToc ? (
|
||||||
|
<SubPanel>
|
||||||
|
{returnHref && returnTitle && (
|
||||||
|
<ReturnButton
|
||||||
|
href={returnHref}
|
||||||
|
title={returnTitle}
|
||||||
|
langui={langui}
|
||||||
|
displayOn={ReturnButtonType.desktop}
|
||||||
|
horizontalLine
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{displayCredits && (
|
||||||
|
<>
|
||||||
|
{selectedTranslation && (
|
||||||
|
<div className="grid grid-flow-col place-items-center place-content-center gap-2">
|
||||||
|
<p className="font-headers">{langui.status}:</p>
|
||||||
|
|
||||||
|
<ToolTip
|
||||||
|
content={getStatusDescription(
|
||||||
|
selectedTranslation.status,
|
||||||
|
langui
|
||||||
|
)}
|
||||||
|
maxWidth={"20rem"}
|
||||||
|
>
|
||||||
|
<Chip>{selectedTranslation.status}</Chip>
|
||||||
|
</ToolTip>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{post?.authors && post.authors.data.length > 0 && (
|
||||||
|
<div>
|
||||||
|
<p className="font-headers">{"Authors"}:</p>
|
||||||
|
<div className="grid place-items-center place-content-center gap-2">
|
||||||
|
{post.authors.data.map((author) => (
|
||||||
|
<>
|
||||||
|
{author.attributes && (
|
||||||
|
<RecorderChip
|
||||||
|
key={author.id}
|
||||||
|
langui={langui}
|
||||||
|
recorder={author.attributes}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<HorizontalLine />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{displayToc && <TOC text={body} title={title} />}
|
||||||
|
</SubPanel>
|
||||||
|
) : undefined;
|
||||||
|
|
||||||
|
const contentPanel = (
|
||||||
|
<ContentPanel>
|
||||||
|
<ReturnButton
|
||||||
|
href="/news"
|
||||||
|
title={langui.news}
|
||||||
|
langui={langui}
|
||||||
|
displayOn={ReturnButtonType.mobile}
|
||||||
|
className="mb-10"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{displayThumbnailHeader ? (
|
||||||
|
<>
|
||||||
|
<ThumbnailHeader
|
||||||
|
thumbnail={thumbnail}
|
||||||
|
title={title}
|
||||||
|
description={except}
|
||||||
|
langui={langui}
|
||||||
|
categories={post?.categories}
|
||||||
|
languageSwitcher={
|
||||||
|
<LanguageSwitcher
|
||||||
|
languages={languages}
|
||||||
|
locales={translationLocales}
|
||||||
|
localesIndex={selectedTranslationIndex}
|
||||||
|
setLocalesIndex={setSelectedTranslationIndex}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<HorizontalLine />
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{displayLanguageSwitcher && (
|
||||||
|
<div className="grid place-content-end place-items-start">
|
||||||
|
<LanguageSwitcher
|
||||||
|
languages={languages}
|
||||||
|
locales={translationLocales}
|
||||||
|
localesIndex={selectedTranslationIndex}
|
||||||
|
setLocalesIndex={setSelectedTranslationIndex}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{displayTitle && (
|
||||||
|
<h1 className="text-center flex gap-3 justify-center text-4xl my-16">
|
||||||
|
{title}
|
||||||
|
</h1>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{prependBody}
|
||||||
|
<Markdawn text={body} />
|
||||||
|
{appendBody}
|
||||||
|
</ContentPanel>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AppLayout
|
||||||
|
navTitle={title}
|
||||||
|
contentPanel={contentPanel}
|
||||||
|
subPanel={subPanel}
|
||||||
|
thumbnail={thumbnail ?? undefined}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ query getContentText($slug: String, $language_code: String) {
|
||||||
id
|
id
|
||||||
attributes {
|
attributes {
|
||||||
slug
|
slug
|
||||||
titles(filters: { language: { code: { eq: $language_code } } }) {
|
titles {
|
||||||
pre_title
|
pre_title
|
||||||
title
|
title
|
||||||
subtitle
|
subtitle
|
||||||
|
@ -56,7 +56,9 @@ query getContentText($slug: String, $language_code: String) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
text_set_languages: text_set {
|
text_set {
|
||||||
|
status
|
||||||
|
text
|
||||||
language {
|
language {
|
||||||
data {
|
data {
|
||||||
attributes {
|
attributes {
|
||||||
|
@ -64,10 +66,6 @@ query getContentText($slug: String, $language_code: String) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
text_set(filters: { language: { code: { eq: $language_code } } }) {
|
|
||||||
status
|
|
||||||
text
|
|
||||||
source_language {
|
source_language {
|
||||||
data {
|
data {
|
||||||
attributes {
|
attributes {
|
||||||
|
|
|
@ -29,7 +29,8 @@ query getLibraryItemScans($slug: String, $language_code: String) {
|
||||||
ending_time
|
ending_time
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scan_set_languages: scan_set {
|
scan_set {
|
||||||
|
status
|
||||||
language {
|
language {
|
||||||
data {
|
data {
|
||||||
attributes {
|
attributes {
|
||||||
|
@ -37,16 +38,6 @@ query getLibraryItemScans($slug: String, $language_code: String) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
scan_set(
|
|
||||||
filters: {
|
|
||||||
or: [
|
|
||||||
{ language: { code: { eq: "xx" } } }
|
|
||||||
{ language: { code: { eq: $language_code } } }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
status
|
|
||||||
source_language {
|
source_language {
|
||||||
data {
|
data {
|
||||||
attributes {
|
attributes {
|
||||||
|
|
|
@ -33,7 +33,7 @@ query getPost($slug: String, $language_code: String) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
translations_languages: translations {
|
translations {
|
||||||
language {
|
language {
|
||||||
data {
|
data {
|
||||||
attributes {
|
attributes {
|
||||||
|
@ -41,8 +41,6 @@ query getPost($slug: String, $language_code: String) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
translations(filters: { language: { code: { eq: $language_code } } }) {
|
|
||||||
status
|
status
|
||||||
title
|
title
|
||||||
excerpt
|
excerpt
|
||||||
|
|
|
@ -1,18 +1,8 @@
|
||||||
import AppLayout from "components/AppLayout";
|
import Post from "components/Post";
|
||||||
import LanguageSwitcher from "components/LanguageSwitcher";
|
|
||||||
import Markdawn from "components/Markdown/Markdawn";
|
|
||||||
import TOC from "components/Markdown/TOC";
|
|
||||||
import ReturnButton, {
|
|
||||||
ReturnButtonType,
|
|
||||||
} from "components/PanelComponents/ReturnButton";
|
|
||||||
import ContentPanel from "components/Panels/ContentPanel";
|
|
||||||
import SubPanel from "components/Panels/SubPanel";
|
|
||||||
import { GetPostQuery } from "graphql/generated";
|
import { GetPostQuery } from "graphql/generated";
|
||||||
import { getReadySdk } from "graphql/sdk";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import { GetStaticPropsContext } from "next";
|
import { GetStaticPropsContext } from "next";
|
||||||
import { useRouter } from "next/router";
|
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
import { getLocalesFromLanguages, prettySlug } from "queries/helpers";
|
|
||||||
|
|
||||||
interface Props extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
post: Exclude<
|
post: Exclude<
|
||||||
|
@ -22,53 +12,17 @@ interface Props extends AppStaticProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function AccordsHandbook(props: Props): JSX.Element {
|
export default function AccordsHandbook(props: Props): JSX.Element {
|
||||||
const { langui, post } = props;
|
const { post, langui, languages, currencies } = props;
|
||||||
const router = useRouter();
|
|
||||||
const locales = getLocalesFromLanguages(post?.translations_languages);
|
|
||||||
|
|
||||||
const body = post?.translations?.[0]?.body ?? "";
|
|
||||||
const title = post?.translations?.[0]?.title ?? prettySlug(post?.slug);
|
|
||||||
|
|
||||||
const subPanel = (
|
|
||||||
<SubPanel>
|
|
||||||
<ReturnButton
|
|
||||||
href="/about-us"
|
|
||||||
displayOn={ReturnButtonType.desktop}
|
|
||||||
langui={langui}
|
|
||||||
title={langui.about_us}
|
|
||||||
horizontalLine
|
|
||||||
/>
|
|
||||||
<TOC text={body} title={title} />
|
|
||||||
</SubPanel>
|
|
||||||
);
|
|
||||||
|
|
||||||
const contentPanel = (
|
|
||||||
<ContentPanel>
|
|
||||||
<ReturnButton
|
|
||||||
href="/about-us"
|
|
||||||
displayOn={ReturnButtonType.mobile}
|
|
||||||
langui={langui}
|
|
||||||
title={langui.about_us}
|
|
||||||
className="mb-10"
|
|
||||||
/>
|
|
||||||
{locales.includes(router.locale ?? "en") ? (
|
|
||||||
<Markdawn text={body} />
|
|
||||||
) : (
|
|
||||||
<LanguageSwitcher
|
|
||||||
locales={locales}
|
|
||||||
languages={props.languages}
|
|
||||||
langui={props.langui}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</ContentPanel>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppLayout
|
<Post
|
||||||
navTitle={title}
|
currencies={currencies}
|
||||||
subPanel={subPanel}
|
languages={languages}
|
||||||
contentPanel={contentPanel}
|
langui={langui}
|
||||||
{...props}
|
post={post}
|
||||||
|
returnHref="/about-us/"
|
||||||
|
returnTitle={langui.about_us}
|
||||||
|
displayToc
|
||||||
|
displayLanguageSwitcher
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,12 @@
|
||||||
import AppLayout from "components/AppLayout";
|
|
||||||
import InsetBox from "components/InsetBox";
|
import InsetBox from "components/InsetBox";
|
||||||
import LanguageSwitcher from "components/LanguageSwitcher";
|
import Post from "components/Post";
|
||||||
import Markdawn from "components/Markdown/Markdawn";
|
|
||||||
import TOC from "components/Markdown/TOC";
|
|
||||||
import ReturnButton, {
|
|
||||||
ReturnButtonType,
|
|
||||||
} from "components/PanelComponents/ReturnButton";
|
|
||||||
import ContentPanel from "components/Panels/ContentPanel";
|
|
||||||
import SubPanel from "components/Panels/SubPanel";
|
|
||||||
import { GetPostQuery } from "graphql/generated";
|
import { GetPostQuery } from "graphql/generated";
|
||||||
import { getReadySdk } from "graphql/sdk";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import { GetStaticPropsContext } from "next";
|
import { GetStaticPropsContext } from "next";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { RequestMailProps, ResponseMailProps } from "pages/api/mail";
|
import { RequestMailProps, ResponseMailProps } from "pages/api/mail";
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
import {
|
import { randomInt } from "queries/helpers";
|
||||||
getLocalesFromLanguages,
|
|
||||||
prettySlug,
|
|
||||||
randomInt,
|
|
||||||
} from "queries/helpers";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
interface Props extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
|
@ -29,200 +17,170 @@ interface Props extends AppStaticProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function AboutUs(props: Props): JSX.Element {
|
export default function AboutUs(props: Props): JSX.Element {
|
||||||
const { langui, post } = props;
|
const { post, langui, languages, currencies } = props;
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [formResponse, setFormResponse] = useState("");
|
const [formResponse, setFormResponse] = useState("");
|
||||||
const [formState, setFormState] = useState<"completed" | "ongoing" | "stale">(
|
const [formState, setFormState] = useState<"completed" | "ongoing" | "stale">(
|
||||||
"stale"
|
"stale"
|
||||||
);
|
);
|
||||||
const locales = getLocalesFromLanguages(post?.translations_languages);
|
|
||||||
|
|
||||||
const [randomNumber1, setRandomNumber1] = useState(randomInt(0, 10));
|
const [randomNumber1, setRandomNumber1] = useState(randomInt(0, 10));
|
||||||
const [randomNumber2, setRandomNumber2] = useState(randomInt(0, 10));
|
const [randomNumber2, setRandomNumber2] = useState(randomInt(0, 10));
|
||||||
|
|
||||||
const body = post?.translations?.[0]?.body ?? "";
|
const contactForm = (
|
||||||
const title = post?.translations?.[0]?.title ?? prettySlug(post?.slug);
|
<div className="flex flex-col gap-8 text-center">
|
||||||
|
<form
|
||||||
|
className={`gap-8 grid ${
|
||||||
|
formState !== "stale" &&
|
||||||
|
"opacity-60 cursor-not-allowed touch-none pointer-events-none"
|
||||||
|
}`}
|
||||||
|
onSubmit={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
const subPanel = (
|
const fields = event.target as unknown as {
|
||||||
<SubPanel>
|
verif: HTMLInputElement;
|
||||||
<ReturnButton
|
name: HTMLInputElement;
|
||||||
href="/about-us"
|
email: HTMLInputElement;
|
||||||
displayOn={ReturnButtonType.desktop}
|
message: HTMLInputElement;
|
||||||
langui={langui}
|
};
|
||||||
title={langui.about_us}
|
|
||||||
horizontalLine
|
|
||||||
/>
|
|
||||||
<TOC text={body} title={title} />
|
|
||||||
</SubPanel>
|
|
||||||
);
|
|
||||||
|
|
||||||
const contentPanel = (
|
setFormState("ongoing");
|
||||||
<ContentPanel>
|
|
||||||
<ReturnButton
|
|
||||||
href="/about-us"
|
|
||||||
displayOn={ReturnButtonType.mobile}
|
|
||||||
langui={langui}
|
|
||||||
title={langui.about_us}
|
|
||||||
className="mb-10"
|
|
||||||
/>
|
|
||||||
{locales.includes(router.locale ?? "en") ? (
|
|
||||||
<Markdawn text={body} />
|
|
||||||
) : (
|
|
||||||
<LanguageSwitcher
|
|
||||||
locales={locales}
|
|
||||||
languages={props.languages}
|
|
||||||
langui={props.langui}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className="flex flex-col gap-8 text-center">
|
if (
|
||||||
<form
|
parseInt(fields.verif.value, 10) ===
|
||||||
className={`gap-8 grid ${
|
randomNumber1 + randomNumber2 &&
|
||||||
formState !== "stale" &&
|
formState !== "completed"
|
||||||
"opacity-60 cursor-not-allowed touch-none pointer-events-none"
|
) {
|
||||||
}`}
|
const content: RequestMailProps = {
|
||||||
onSubmit={(event) => {
|
name: fields.name.value,
|
||||||
event.preventDefault();
|
email: fields.email.value,
|
||||||
|
message: fields.message.value,
|
||||||
const fields = event.target as unknown as {
|
formName: "Contact Form",
|
||||||
verif: HTMLInputElement;
|
|
||||||
name: HTMLInputElement;
|
|
||||||
email: HTMLInputElement;
|
|
||||||
message: HTMLInputElement;
|
|
||||||
};
|
};
|
||||||
|
fetch("/api/mail", {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(content),
|
||||||
|
headers: {
|
||||||
|
"Content-type": "application/json; charset=UTF-8",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then(async (responseJson) => responseJson.json())
|
||||||
|
.then((response: ResponseMailProps) => {
|
||||||
|
switch (response.code) {
|
||||||
|
case "OKAY":
|
||||||
|
setFormResponse(langui.response_email_success ?? "");
|
||||||
|
setFormState("completed");
|
||||||
|
|
||||||
setFormState("ongoing");
|
break;
|
||||||
|
|
||||||
if (
|
case "EENVELOPE":
|
||||||
parseInt(fields.verif.value, 10) ===
|
setFormResponse(langui.response_invalid_email ?? "");
|
||||||
randomNumber1 + randomNumber2 &&
|
setFormState("stale");
|
||||||
formState !== "completed"
|
break;
|
||||||
) {
|
|
||||||
const content: RequestMailProps = {
|
|
||||||
name: fields.name.value,
|
|
||||||
email: fields.email.value,
|
|
||||||
message: fields.message.value,
|
|
||||||
formName: "Contact Form",
|
|
||||||
};
|
|
||||||
fetch("/api/mail", {
|
|
||||||
method: "POST",
|
|
||||||
body: JSON.stringify(content),
|
|
||||||
headers: {
|
|
||||||
"Content-type": "application/json; charset=UTF-8",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then(async (responseJson) => responseJson.json())
|
|
||||||
.then((response: ResponseMailProps) => {
|
|
||||||
switch (response.code) {
|
|
||||||
case "OKAY":
|
|
||||||
setFormResponse(langui.response_email_success ?? "");
|
|
||||||
setFormState("completed");
|
|
||||||
|
|
||||||
break;
|
default:
|
||||||
|
setFormResponse(response.message ?? "");
|
||||||
|
setFormState("stale");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setFormResponse(langui.response_invalid_code ?? "");
|
||||||
|
setFormState("stale");
|
||||||
|
setRandomNumber1(randomInt(0, 10));
|
||||||
|
setRandomNumber2(randomInt(0, 10));
|
||||||
|
}
|
||||||
|
|
||||||
case "EENVELOPE":
|
router.replace("#send-response");
|
||||||
setFormResponse(langui.response_invalid_email ?? "");
|
fields.verif.value = "";
|
||||||
setFormState("stale");
|
}}
|
||||||
break;
|
>
|
||||||
|
<div className="flex flex-col place-items-center gap-1">
|
||||||
default:
|
<label htmlFor="name">{langui.name}:</label>
|
||||||
setFormResponse(response.message ?? "");
|
<input
|
||||||
setFormState("stale");
|
type="text"
|
||||||
break;
|
className="mobile:w-full"
|
||||||
}
|
name="name"
|
||||||
});
|
id="name"
|
||||||
} else {
|
required
|
||||||
setFormResponse(langui.response_invalid_code ?? "");
|
disabled={formState !== "stale"}
|
||||||
setFormState("stale");
|
/>
|
||||||
setRandomNumber1(randomInt(0, 10));
|
|
||||||
setRandomNumber2(randomInt(0, 10));
|
|
||||||
}
|
|
||||||
|
|
||||||
router.replace("#send-response");
|
|
||||||
fields.verif.value = "";
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className="flex flex-col place-items-center gap-1">
|
|
||||||
<label htmlFor="name">{langui.name}:</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
className="mobile:w-full"
|
|
||||||
name="name"
|
|
||||||
id="name"
|
|
||||||
required
|
|
||||||
disabled={formState !== "stale"}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex flex-col place-items-center gap-1">
|
|
||||||
<label htmlFor="email">{langui.email}:</label>
|
|
||||||
<input
|
|
||||||
type="email"
|
|
||||||
className="mobile:w-full"
|
|
||||||
name="email"
|
|
||||||
id="email"
|
|
||||||
required
|
|
||||||
disabled={formState !== "stale"}
|
|
||||||
/>
|
|
||||||
<p className="text-sm text-dark italic opacity-70">
|
|
||||||
{langui.email_gdpr_notice}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex flex-col place-items-center gap-1 w-full">
|
|
||||||
<label htmlFor="message">{langui.message}:</label>
|
|
||||||
<textarea
|
|
||||||
name="message"
|
|
||||||
id="message"
|
|
||||||
className="w-full"
|
|
||||||
rows={8}
|
|
||||||
required
|
|
||||||
disabled={formState !== "stale"}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="grid grid-cols-2 place-items-center">
|
|
||||||
<div className="flex flex-row place-items-center gap-2">
|
|
||||||
<label
|
|
||||||
className="flex-shrink-0"
|
|
||||||
htmlFor="verif"
|
|
||||||
>{`${randomNumber1} + ${randomNumber2} =`}</label>
|
|
||||||
<input
|
|
||||||
className="w-24"
|
|
||||||
type="number"
|
|
||||||
name="verif"
|
|
||||||
id="verif"
|
|
||||||
required
|
|
||||||
disabled={formState !== "stale"}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<input
|
|
||||||
type="submit"
|
|
||||||
value={langui.send ?? "Send"}
|
|
||||||
className="w-min !px-6"
|
|
||||||
disabled={formState !== "stale"}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<div id="send-response">
|
|
||||||
{formResponse && (
|
|
||||||
<InsetBox>
|
|
||||||
<p>{formResponse}</p>
|
|
||||||
</InsetBox>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col place-items-center gap-1">
|
||||||
|
<label htmlFor="email">{langui.email}:</label>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
className="mobile:w-full"
|
||||||
|
name="email"
|
||||||
|
id="email"
|
||||||
|
required
|
||||||
|
disabled={formState !== "stale"}
|
||||||
|
/>
|
||||||
|
<p className="text-sm text-dark italic opacity-70">
|
||||||
|
{langui.email_gdpr_notice}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col place-items-center gap-1 w-full">
|
||||||
|
<label htmlFor="message">{langui.message}:</label>
|
||||||
|
<textarea
|
||||||
|
name="message"
|
||||||
|
id="message"
|
||||||
|
className="w-full"
|
||||||
|
rows={8}
|
||||||
|
required
|
||||||
|
disabled={formState !== "stale"}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-2 place-items-center">
|
||||||
|
<div className="flex flex-row place-items-center gap-2">
|
||||||
|
<label
|
||||||
|
className="flex-shrink-0"
|
||||||
|
htmlFor="verif"
|
||||||
|
>{`${randomNumber1} + ${randomNumber2} =`}</label>
|
||||||
|
<input
|
||||||
|
className="w-24"
|
||||||
|
type="number"
|
||||||
|
name="verif"
|
||||||
|
id="verif"
|
||||||
|
required
|
||||||
|
disabled={formState !== "stale"}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input
|
||||||
|
type="submit"
|
||||||
|
value={langui.send ?? "Send"}
|
||||||
|
className="w-min !px-6"
|
||||||
|
disabled={formState !== "stale"}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div id="send-response">
|
||||||
|
{formResponse && (
|
||||||
|
<InsetBox>
|
||||||
|
<p>{formResponse}</p>
|
||||||
|
</InsetBox>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</ContentPanel>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppLayout
|
<Post
|
||||||
navTitle={"Contact"}
|
currencies={currencies}
|
||||||
subPanel={subPanel}
|
languages={languages}
|
||||||
contentPanel={contentPanel}
|
langui={langui}
|
||||||
{...props}
|
post={post}
|
||||||
|
returnHref="/about-us/"
|
||||||
|
returnTitle={langui.about_us}
|
||||||
|
displayToc
|
||||||
|
appendBody={contactForm}
|
||||||
|
displayLanguageSwitcher
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,8 @@
|
||||||
import AppLayout from "components/AppLayout";
|
import Post from "components/Post";
|
||||||
import LanguageSwitcher from "components/LanguageSwitcher";
|
|
||||||
import Markdawn from "components/Markdown/Markdawn";
|
|
||||||
import TOC from "components/Markdown/TOC";
|
|
||||||
import ReturnButton, {
|
|
||||||
ReturnButtonType,
|
|
||||||
} from "components/PanelComponents/ReturnButton";
|
|
||||||
import ContentPanel from "components/Panels/ContentPanel";
|
|
||||||
import SubPanel from "components/Panels/SubPanel";
|
|
||||||
import { GetPostQuery } from "graphql/generated";
|
import { GetPostQuery } from "graphql/generated";
|
||||||
import { getReadySdk } from "graphql/sdk";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import { GetStaticPropsContext } from "next";
|
import { GetStaticPropsContext } from "next";
|
||||||
import { useRouter } from "next/router";
|
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
import { getLocalesFromLanguages, prettySlug } from "queries/helpers";
|
|
||||||
|
|
||||||
interface Props extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
post: Exclude<
|
post: Exclude<
|
||||||
|
@ -22,53 +12,17 @@ interface Props extends AppStaticProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function SiteInformation(props: Props): JSX.Element {
|
export default function SiteInformation(props: Props): JSX.Element {
|
||||||
const { langui, post } = props;
|
const { post, langui, languages, currencies } = props;
|
||||||
const router = useRouter();
|
|
||||||
const locales = getLocalesFromLanguages(post?.translations_languages);
|
|
||||||
|
|
||||||
const body = post?.translations?.[0]?.body ?? "";
|
|
||||||
const title = post?.translations?.[0]?.title ?? prettySlug(post?.slug);
|
|
||||||
|
|
||||||
const subPanel = (
|
|
||||||
<SubPanel>
|
|
||||||
<ReturnButton
|
|
||||||
href="/about-us"
|
|
||||||
displayOn={ReturnButtonType.desktop}
|
|
||||||
langui={langui}
|
|
||||||
title={langui.about_us}
|
|
||||||
horizontalLine
|
|
||||||
/>
|
|
||||||
<TOC text={body} title={title} />
|
|
||||||
</SubPanel>
|
|
||||||
);
|
|
||||||
|
|
||||||
const contentPanel = (
|
|
||||||
<ContentPanel>
|
|
||||||
<ReturnButton
|
|
||||||
href="/about-us"
|
|
||||||
displayOn={ReturnButtonType.mobile}
|
|
||||||
langui={langui}
|
|
||||||
title={langui.about_us}
|
|
||||||
className="mb-10"
|
|
||||||
/>
|
|
||||||
{locales.includes(router.locale ?? "en") ? (
|
|
||||||
<Markdawn text={body} />
|
|
||||||
) : (
|
|
||||||
<LanguageSwitcher
|
|
||||||
locales={locales}
|
|
||||||
languages={props.languages}
|
|
||||||
langui={props.langui}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</ContentPanel>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppLayout
|
<Post
|
||||||
navTitle={title}
|
currencies={currencies}
|
||||||
subPanel={subPanel}
|
languages={languages}
|
||||||
contentPanel={contentPanel}
|
langui={langui}
|
||||||
{...props}
|
post={post}
|
||||||
|
returnHref="/about-us/"
|
||||||
|
returnTitle={langui.about_us}
|
||||||
|
displayToc
|
||||||
|
displayLanguageSwitcher
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,8 @@
|
||||||
import AppLayout from "components/AppLayout";
|
import Post from "components/Post";
|
||||||
import LanguageSwitcher from "components/LanguageSwitcher";
|
|
||||||
import Markdawn from "components/Markdown/Markdawn";
|
|
||||||
import TOC from "components/Markdown/TOC";
|
|
||||||
import ReturnButton, {
|
|
||||||
ReturnButtonType,
|
|
||||||
} from "components/PanelComponents/ReturnButton";
|
|
||||||
import ContentPanel from "components/Panels/ContentPanel";
|
|
||||||
import SubPanel from "components/Panels/SubPanel";
|
|
||||||
import { GetPostQuery } from "graphql/generated";
|
import { GetPostQuery } from "graphql/generated";
|
||||||
import { getReadySdk } from "graphql/sdk";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import { GetStaticPropsContext } from "next";
|
import { GetStaticPropsContext } from "next";
|
||||||
import { useRouter } from "next/router";
|
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
import { getLocalesFromLanguages, prettySlug } from "queries/helpers";
|
|
||||||
|
|
||||||
interface Props extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
post: Exclude<
|
post: Exclude<
|
||||||
|
@ -21,53 +11,17 @@ interface Props extends AppStaticProps {
|
||||||
>["data"][number]["attributes"];
|
>["data"][number]["attributes"];
|
||||||
}
|
}
|
||||||
export default function SharingPolicy(props: Props): JSX.Element {
|
export default function SharingPolicy(props: Props): JSX.Element {
|
||||||
const { langui, post } = props;
|
const { post, langui, languages, currencies } = props;
|
||||||
const locales = getLocalesFromLanguages(post?.translations_languages);
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const body = post?.translations?.[0]?.body ?? "";
|
|
||||||
const title = post?.translations?.[0]?.title ?? prettySlug(post?.slug);
|
|
||||||
|
|
||||||
const subPanel = (
|
|
||||||
<SubPanel>
|
|
||||||
<ReturnButton
|
|
||||||
href="/about-us"
|
|
||||||
displayOn={ReturnButtonType.desktop}
|
|
||||||
langui={langui}
|
|
||||||
title={langui.about_us}
|
|
||||||
horizontalLine
|
|
||||||
/>
|
|
||||||
<TOC text={body} title={title} />
|
|
||||||
</SubPanel>
|
|
||||||
);
|
|
||||||
|
|
||||||
const contentPanel = (
|
|
||||||
<ContentPanel>
|
|
||||||
<ReturnButton
|
|
||||||
href="/about-us"
|
|
||||||
displayOn={ReturnButtonType.mobile}
|
|
||||||
langui={langui}
|
|
||||||
title={langui.about_us}
|
|
||||||
className="mb-10"
|
|
||||||
/>
|
|
||||||
{locales.includes(router.locale ?? "en") ? (
|
|
||||||
<Markdawn text={body} />
|
|
||||||
) : (
|
|
||||||
<LanguageSwitcher
|
|
||||||
locales={locales}
|
|
||||||
languages={props.languages}
|
|
||||||
langui={props.langui}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</ContentPanel>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppLayout
|
<Post
|
||||||
navTitle={title}
|
currencies={currencies}
|
||||||
subPanel={subPanel}
|
languages={languages}
|
||||||
contentPanel={contentPanel}
|
langui={langui}
|
||||||
{...props}
|
post={post}
|
||||||
|
returnHref="/about-us/"
|
||||||
|
returnTitle={langui.about_us}
|
||||||
|
displayToc
|
||||||
|
displayLanguageSwitcher
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import ContentPanel from "components/Panels/ContentPanel";
|
||||||
import SubPanel from "components/Panels/SubPanel";
|
import SubPanel from "components/Panels/SubPanel";
|
||||||
import RecorderChip from "components/RecorderChip";
|
import RecorderChip from "components/RecorderChip";
|
||||||
import ToolTip from "components/ToolTip";
|
import ToolTip from "components/ToolTip";
|
||||||
|
import { useAppLayout } from "contexts/AppLayoutContext";
|
||||||
import { GetContentTextQuery } from "graphql/generated";
|
import { GetContentTextQuery } from "graphql/generated";
|
||||||
import { getReadySdk } from "graphql/sdk";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import {
|
import {
|
||||||
|
@ -23,7 +24,7 @@ import {
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
import {
|
import {
|
||||||
getLocalesFromLanguages,
|
getPreferredLanguage,
|
||||||
getStatusDescription,
|
getStatusDescription,
|
||||||
prettyinlineTitle,
|
prettyinlineTitle,
|
||||||
prettyLanguage,
|
prettyLanguage,
|
||||||
|
@ -31,6 +32,7 @@ import {
|
||||||
prettyTestError,
|
prettyTestError,
|
||||||
prettyTestWarning,
|
prettyTestWarning,
|
||||||
} from "queries/helpers";
|
} from "queries/helpers";
|
||||||
|
import { useEffect, useMemo, useState } from "react";
|
||||||
|
|
||||||
interface Props extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
content: Exclude<
|
content: Exclude<
|
||||||
|
@ -47,7 +49,49 @@ export default function Content(props: Props): JSX.Element {
|
||||||
useTesting(props);
|
useTesting(props);
|
||||||
const { langui, content, languages } = props;
|
const { langui, content, languages } = props;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const locales = getLocalesFromLanguages(content?.text_set_languages);
|
const appLayout = useAppLayout();
|
||||||
|
|
||||||
|
const [selectedTextSet, setSelectedTextSet] = useState<
|
||||||
|
| Exclude<
|
||||||
|
Exclude<Props["content"], null | undefined>["text_set"],
|
||||||
|
null | undefined
|
||||||
|
>[number]
|
||||||
|
>();
|
||||||
|
const [selectedTitle, setSelectedTitle] = useState<
|
||||||
|
| Exclude<
|
||||||
|
Exclude<Props["content"], null | undefined>["titles"],
|
||||||
|
null | undefined
|
||||||
|
>[number]
|
||||||
|
>();
|
||||||
|
const textSetLocales: Map<string, number> = new Map();
|
||||||
|
|
||||||
|
const [selectedTextSetIndex, setSelectedTextSetIndex] = useState<
|
||||||
|
number | undefined
|
||||||
|
>();
|
||||||
|
|
||||||
|
if (content?.text_set) {
|
||||||
|
content.text_set.map((textSet, index) => {
|
||||||
|
if (textSet?.language?.data?.attributes?.code && textSet.text) {
|
||||||
|
textSetLocales.set(textSet.language.data.attributes.code, index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
useMemo(() => {
|
||||||
|
setSelectedTextSetIndex(
|
||||||
|
getPreferredLanguage(
|
||||||
|
appLayout.preferredLanguages ?? [router.locale],
|
||||||
|
textSetLocales
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}, [appLayout.preferredLanguages]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedTextSetIndex !== undefined)
|
||||||
|
setSelectedTextSet(content?.text_set?.[selectedTextSetIndex]);
|
||||||
|
if (selectedTextSetIndex !== undefined)
|
||||||
|
setSelectedTitle(content?.titles?.[selectedTextSetIndex]);
|
||||||
|
}, [selectedTextSetIndex]);
|
||||||
|
|
||||||
const subPanel = (
|
const subPanel = (
|
||||||
<SubPanel>
|
<SubPanel>
|
||||||
|
@ -59,27 +103,25 @@ export default function Content(props: Props): JSX.Element {
|
||||||
horizontalLine
|
horizontalLine
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{content?.text_set?.[0]?.source_language?.data?.attributes && (
|
{selectedTextSet?.source_language?.data?.attributes && (
|
||||||
<div className="grid gap-5">
|
<div className="grid gap-5">
|
||||||
<h2 className="text-xl">
|
<h2 className="text-xl">
|
||||||
{content.text_set[0].source_language.data.attributes.code ===
|
{selectedTextSet.source_language.data.attributes.code ===
|
||||||
router.locale
|
selectedTextSet.language?.data?.attributes?.code
|
||||||
? langui.transcript_notice
|
? langui.transcript_notice
|
||||||
: langui.translation_notice}
|
: langui.translation_notice}
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
{content.text_set[0].source_language.data.attributes.code !==
|
{selectedTextSet.source_language.data.attributes.code !==
|
||||||
router.locale && (
|
selectedTextSet.language?.data?.attributes?.code && (
|
||||||
<div className="grid place-items-center gap-2">
|
<div className="grid place-items-center gap-2">
|
||||||
<p className="font-headers">{langui.source_language}:</p>
|
<p className="font-headers">{langui.source_language}:</p>
|
||||||
<Button
|
<Button
|
||||||
href={router.asPath}
|
href={router.asPath}
|
||||||
locale={
|
locale={selectedTextSet.source_language.data.attributes.code}
|
||||||
content.text_set[0].source_language.data.attributes.code
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{prettyLanguage(
|
{prettyLanguage(
|
||||||
content.text_set[0].source_language.data.attributes.code,
|
selectedTextSet.source_language.data.attributes.code,
|
||||||
languages
|
languages
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -90,19 +132,19 @@ export default function Content(props: Props): JSX.Element {
|
||||||
<p className="font-headers">{langui.status}:</p>
|
<p className="font-headers">{langui.status}:</p>
|
||||||
|
|
||||||
<ToolTip
|
<ToolTip
|
||||||
content={getStatusDescription(content.text_set[0].status, langui)}
|
content={getStatusDescription(selectedTextSet.status, langui)}
|
||||||
maxWidth={"20rem"}
|
maxWidth={"20rem"}
|
||||||
>
|
>
|
||||||
<Chip>{content.text_set[0].status}</Chip>
|
<Chip>{selectedTextSet.status}</Chip>
|
||||||
</ToolTip>
|
</ToolTip>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{content.text_set[0].transcribers &&
|
{selectedTextSet.transcribers &&
|
||||||
content.text_set[0].transcribers.data.length > 0 && (
|
selectedTextSet.transcribers.data.length > 0 && (
|
||||||
<div>
|
<div>
|
||||||
<p className="font-headers">{langui.transcribers}:</p>
|
<p className="font-headers">{langui.transcribers}:</p>
|
||||||
<div className="grid place-items-center place-content-center gap-2">
|
<div className="grid place-items-center place-content-center gap-2">
|
||||||
{content.text_set[0].transcribers.data.map((recorder) => (
|
{selectedTextSet.transcribers.data.map((recorder) => (
|
||||||
<>
|
<>
|
||||||
{recorder.attributes && (
|
{recorder.attributes && (
|
||||||
<RecorderChip
|
<RecorderChip
|
||||||
|
@ -117,12 +159,12 @@ export default function Content(props: Props): JSX.Element {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{content.text_set[0].translators &&
|
{selectedTextSet.translators &&
|
||||||
content.text_set[0].translators.data.length > 0 && (
|
selectedTextSet.translators.data.length > 0 && (
|
||||||
<div>
|
<div>
|
||||||
<p className="font-headers">{langui.translators}:</p>
|
<p className="font-headers">{langui.translators}:</p>
|
||||||
<div className="grid place-items-center place-content-center gap-2">
|
<div className="grid place-items-center place-content-center gap-2">
|
||||||
{content.text_set[0].translators.data.map((recorder) => (
|
{selectedTextSet.translators.data.map((recorder) => (
|
||||||
<>
|
<>
|
||||||
{recorder.attributes && (
|
{recorder.attributes && (
|
||||||
<RecorderChip
|
<RecorderChip
|
||||||
|
@ -137,12 +179,12 @@ export default function Content(props: Props): JSX.Element {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{content.text_set[0].proofreaders &&
|
{selectedTextSet.proofreaders &&
|
||||||
content.text_set[0].proofreaders.data.length > 0 && (
|
selectedTextSet.proofreaders.data.length > 0 && (
|
||||||
<div>
|
<div>
|
||||||
<p className="font-headers">{langui.proofreaders}:</p>
|
<p className="font-headers">{langui.proofreaders}:</p>
|
||||||
<div className="grid place-items-center place-content-center gap-2">
|
<div className="grid place-items-center place-content-center gap-2">
|
||||||
{content.text_set[0].proofreaders.data.map((recorder) => (
|
{selectedTextSet.proofreaders.data.map((recorder) => (
|
||||||
<>
|
<>
|
||||||
{recorder.attributes && (
|
{recorder.attributes && (
|
||||||
<RecorderChip
|
<RecorderChip
|
||||||
|
@ -159,25 +201,23 @@ export default function Content(props: Props): JSX.Element {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{content?.text_set &&
|
{selectedTextSet && content?.text_set && selectedTextSet.text && (
|
||||||
content.text_set.length > 0 &&
|
<>
|
||||||
content.text_set[0]?.text && (
|
<HorizontalLine />
|
||||||
<>
|
<TOC
|
||||||
<HorizontalLine />
|
text={selectedTextSet.text}
|
||||||
<TOC
|
title={
|
||||||
text={content.text_set[0].text}
|
content.titles && content.titles.length > 0 && selectedTitle
|
||||||
title={
|
? prettyinlineTitle(
|
||||||
content.titles && content.titles.length > 0 && content.titles[0]
|
selectedTitle.pre_title,
|
||||||
? prettyinlineTitle(
|
selectedTitle.title,
|
||||||
content.titles[0].pre_title,
|
selectedTitle.subtitle
|
||||||
content.titles[0].title,
|
)
|
||||||
content.titles[0].subtitle
|
: prettySlug(content.slug)
|
||||||
)
|
}
|
||||||
: prettySlug(content.slug)
|
/>
|
||||||
}
|
</>
|
||||||
/>
|
)}
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</SubPanel>
|
</SubPanel>
|
||||||
);
|
);
|
||||||
const contentPanel = (
|
const contentPanel = (
|
||||||
|
@ -189,46 +229,37 @@ export default function Content(props: Props): JSX.Element {
|
||||||
displayOn={ReturnButtonType.mobile}
|
displayOn={ReturnButtonType.mobile}
|
||||||
className="mb-10"
|
className="mb-10"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{content && (
|
{content && (
|
||||||
<div className="grid place-items-center">
|
<div className="grid place-items-center">
|
||||||
<ThumbnailHeader
|
<ThumbnailHeader
|
||||||
thumbnail={content.thumbnail?.data?.attributes}
|
thumbnail={content.thumbnail?.data?.attributes}
|
||||||
pre_title={
|
pre_title={
|
||||||
content.titles && content.titles.length > 0
|
selectedTitle?.pre_title ?? content.titles?.[0]?.pre_title
|
||||||
? content.titles[0]?.pre_title
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
title={
|
|
||||||
content.titles && content.titles.length > 0
|
|
||||||
? content.titles[0]?.title
|
|
||||||
: prettySlug(content.slug)
|
|
||||||
}
|
|
||||||
subtitle={
|
|
||||||
content.titles && content.titles.length > 0
|
|
||||||
? content.titles[0]?.subtitle
|
|
||||||
: undefined
|
|
||||||
}
|
}
|
||||||
|
title={selectedTitle?.title ?? content.titles?.[0]?.title}
|
||||||
|
subtitle={selectedTitle?.subtitle ?? content.titles?.[0]?.subtitle}
|
||||||
description={
|
description={
|
||||||
content.titles && content.titles.length > 0
|
selectedTitle?.description ?? content.titles?.[0]?.description
|
||||||
? content.titles[0]?.description
|
|
||||||
: undefined
|
|
||||||
}
|
}
|
||||||
type={content.type}
|
type={content.type}
|
||||||
categories={content.categories}
|
categories={content.categories}
|
||||||
langui={langui}
|
langui={langui}
|
||||||
|
languageSwitcher={
|
||||||
|
selectedTextSet ? (
|
||||||
|
<LanguageSwitcher
|
||||||
|
locales={textSetLocales}
|
||||||
|
languages={props.languages}
|
||||||
|
localesIndex={selectedTextSetIndex}
|
||||||
|
setLocalesIndex={setSelectedTextSetIndex}
|
||||||
|
/>
|
||||||
|
) : undefined
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<HorizontalLine />
|
<HorizontalLine />
|
||||||
|
|
||||||
{locales.includes(router.locale ?? "en") ? (
|
<Markdawn text={selectedTextSet?.text ?? ""} />
|
||||||
<Markdawn text={content.text_set?.[0]?.text ?? ""} />
|
|
||||||
) : (
|
|
||||||
<LanguageSwitcher
|
|
||||||
locales={locales}
|
|
||||||
languages={props.languages}
|
|
||||||
langui={props.langui}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</ContentPanel>
|
</ContentPanel>
|
||||||
|
@ -276,7 +307,7 @@ export async function getStaticProps(
|
||||||
context: GetStaticPropsContext
|
context: GetStaticPropsContext
|
||||||
): Promise<{ notFound: boolean } | { props: Props }> {
|
): Promise<{ notFound: boolean } | { props: Props }> {
|
||||||
const sdk = getReadySdk();
|
const sdk = getReadySdk();
|
||||||
const slug = context.params?.slug?.toString() ?? "";
|
const slug = context.params?.slug.toString() ?? "";
|
||||||
const content = await sdk.getContentText({
|
const content = await sdk.getContentText({
|
||||||
slug: slug,
|
slug: slug,
|
||||||
language_code: context.locale ?? "en",
|
language_code: context.locale ?? "en",
|
||||||
|
|
|
@ -1,13 +1,8 @@
|
||||||
import AppLayout from "components/AppLayout";
|
import Post from "components/Post";
|
||||||
import LanguageSwitcher from "components/LanguageSwitcher";
|
|
||||||
import Markdawn from "components/Markdown/Markdawn";
|
|
||||||
import ContentPanel from "components/Panels/ContentPanel";
|
|
||||||
import { GetPostQuery } from "graphql/generated";
|
import { GetPostQuery } from "graphql/generated";
|
||||||
import { getReadySdk } from "graphql/sdk";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import { GetStaticPropsContext } from "next";
|
import { GetStaticPropsContext } from "next";
|
||||||
import { useRouter } from "next/router";
|
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
import { getLocalesFromLanguages, prettySlug } from "queries/helpers";
|
|
||||||
|
|
||||||
interface Props extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
post: Exclude<
|
post: Exclude<
|
||||||
|
@ -17,35 +12,26 @@ interface Props extends AppStaticProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Home(props: Props): JSX.Element {
|
export default function Home(props: Props): JSX.Element {
|
||||||
const { post } = props;
|
const { post, langui, languages, currencies } = props;
|
||||||
const locales = getLocalesFromLanguages(post?.translations_languages);
|
return (
|
||||||
const router = useRouter();
|
<Post
|
||||||
|
currencies={currencies}
|
||||||
const body = post?.translations?.[0]?.body ?? "";
|
languages={languages}
|
||||||
const title = post?.translations?.[0]?.title ?? prettySlug(post?.slug);
|
langui={langui}
|
||||||
|
post={post}
|
||||||
const contentPanel = (
|
prependBody={
|
||||||
<ContentPanel>
|
<div className="grid place-items-center place-content-center w-full gap-5 text-center">
|
||||||
<div className="grid place-items-center place-content-center w-full gap-5 text-center">
|
<div className="[mask:url('/icons/accords.svg')] [mask-size:contain] [mask-repeat:no-repeat] [mask-position:center] w-32 aspect-square mobile:w-[50vw] bg-black" />
|
||||||
<div className="[mask:url('/icons/accords.svg')] [mask-size:contain] [mask-repeat:no-repeat] [mask-position:center] w-32 aspect-square mobile:w-[50vw] bg-black" />
|
<h1 className="text-5xl mb-0">Accord’s Library</h1>
|
||||||
<h1 className="text-5xl mb-0">Accord’s Library</h1>
|
<h2 className="text-xl -mt-5">
|
||||||
<h2 className="text-xl -mt-5">
|
Discover • Analyze • Translate • Archive
|
||||||
Discover • Analyze • Translate • Archive
|
</h2>
|
||||||
</h2>
|
</div>
|
||||||
</div>
|
}
|
||||||
{locales.includes(router.locale ?? "en") ? (
|
displayTitle={false}
|
||||||
<Markdawn text={body} />
|
displayLanguageSwitcher
|
||||||
) : (
|
/>
|
||||||
<LanguageSwitcher
|
|
||||||
locales={locales}
|
|
||||||
languages={props.languages}
|
|
||||||
langui={props.langui}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</ContentPanel>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return <AppLayout navTitle={title} contentPanel={contentPanel} {...props} />;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getStaticProps(
|
export async function getStaticProps(
|
||||||
|
|
|
@ -1,17 +1,4 @@
|
||||||
import AppLayout from "components/AppLayout";
|
import Post from "components/Post";
|
||||||
import Chip from "components/Chip";
|
|
||||||
import ThumbnailHeader from "components/Content/ThumbnailHeader";
|
|
||||||
import HorizontalLine from "components/HorizontalLine";
|
|
||||||
import LanguageSwitcher from "components/LanguageSwitcher";
|
|
||||||
import Markdawn from "components/Markdown/Markdawn";
|
|
||||||
import TOC from "components/Markdown/TOC";
|
|
||||||
import ReturnButton, {
|
|
||||||
ReturnButtonType,
|
|
||||||
} from "components/PanelComponents/ReturnButton";
|
|
||||||
import ContentPanel from "components/Panels/ContentPanel";
|
|
||||||
import SubPanel from "components/Panels/SubPanel";
|
|
||||||
import RecorderChip from "components/RecorderChip";
|
|
||||||
import ToolTip from "components/ToolTip";
|
|
||||||
import { GetPostQuery } from "graphql/generated";
|
import { GetPostQuery } from "graphql/generated";
|
||||||
import { getReadySdk } from "graphql/sdk";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import {
|
import {
|
||||||
|
@ -19,13 +6,7 @@ import {
|
||||||
GetStaticPathsResult,
|
GetStaticPathsResult,
|
||||||
GetStaticPropsContext,
|
GetStaticPropsContext,
|
||||||
} from "next";
|
} from "next";
|
||||||
import { useRouter } from "next/router";
|
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
import {
|
|
||||||
getLocalesFromLanguages,
|
|
||||||
getStatusDescription,
|
|
||||||
prettySlug,
|
|
||||||
} from "queries/helpers";
|
|
||||||
|
|
||||||
interface Props extends AppStaticProps {
|
interface Props extends AppStaticProps {
|
||||||
post: Exclude<
|
post: Exclude<
|
||||||
|
@ -39,106 +20,18 @@ interface Props extends AppStaticProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function LibrarySlug(props: Props): JSX.Element {
|
export default function LibrarySlug(props: Props): JSX.Element {
|
||||||
const { post, langui } = props;
|
const { post, langui, languages, currencies } = props;
|
||||||
const locales = getLocalesFromLanguages(post?.translations_languages);
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const thumbnail = post?.translations?.[0]?.thumbnail?.data
|
|
||||||
? post.translations[0].thumbnail.data.attributes
|
|
||||||
: post?.thumbnail?.data
|
|
||||||
? post.thumbnail.data.attributes
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
const body = post?.translations?.[0]?.body ?? "";
|
|
||||||
const title = post?.translations?.[0]?.title ?? prettySlug(post?.slug);
|
|
||||||
const except = post?.translations?.[0]?.excerpt ?? "";
|
|
||||||
|
|
||||||
const subPanel = (
|
|
||||||
<SubPanel>
|
|
||||||
<ReturnButton
|
|
||||||
href="/news"
|
|
||||||
title={langui.news}
|
|
||||||
langui={langui}
|
|
||||||
displayOn={ReturnButtonType.desktop}
|
|
||||||
horizontalLine
|
|
||||||
/>
|
|
||||||
|
|
||||||
{post?.translations?.[0] && (
|
|
||||||
<div className="grid grid-flow-col place-items-center place-content-center gap-2">
|
|
||||||
<p className="font-headers">{langui.status}:</p>
|
|
||||||
|
|
||||||
<ToolTip
|
|
||||||
content={getStatusDescription(post.translations[0].status, langui)}
|
|
||||||
maxWidth={"20rem"}
|
|
||||||
>
|
|
||||||
<Chip>{post.translations[0].status}</Chip>
|
|
||||||
</ToolTip>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{post?.authors && post.authors.data.length > 0 && (
|
|
||||||
<div>
|
|
||||||
<p className="font-headers">{"Authors"}:</p>
|
|
||||||
<div className="grid place-items-center place-content-center gap-2">
|
|
||||||
{post.authors.data.map((author) => (
|
|
||||||
<>
|
|
||||||
{author.attributes && (
|
|
||||||
<RecorderChip
|
|
||||||
key={author.id}
|
|
||||||
langui={langui}
|
|
||||||
recorder={author.attributes}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<HorizontalLine />
|
|
||||||
|
|
||||||
<TOC text={body} title={title} />
|
|
||||||
</SubPanel>
|
|
||||||
);
|
|
||||||
const contentPanel = (
|
|
||||||
<ContentPanel>
|
|
||||||
<ReturnButton
|
|
||||||
href="/news"
|
|
||||||
title={langui.news}
|
|
||||||
langui={langui}
|
|
||||||
displayOn={ReturnButtonType.mobile}
|
|
||||||
className="mb-10"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ThumbnailHeader
|
|
||||||
thumbnail={thumbnail}
|
|
||||||
title={title}
|
|
||||||
description={except}
|
|
||||||
langui={langui}
|
|
||||||
categories={post?.categories}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<HorizontalLine />
|
|
||||||
|
|
||||||
{locales.includes(router.locale ?? "en") ? (
|
|
||||||
<Markdawn text={body} />
|
|
||||||
) : (
|
|
||||||
<LanguageSwitcher
|
|
||||||
locales={locales}
|
|
||||||
languages={props.languages}
|
|
||||||
langui={props.langui}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</ContentPanel>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppLayout
|
<Post
|
||||||
navTitle={title}
|
currencies={currencies}
|
||||||
contentPanel={contentPanel}
|
languages={languages}
|
||||||
subPanel={subPanel}
|
langui={langui}
|
||||||
thumbnail={thumbnail ?? undefined}
|
post={post}
|
||||||
{...props}
|
returnHref="/news"
|
||||||
|
returnTitle={langui.news}
|
||||||
|
displayCredits
|
||||||
|
displayThumbnailHeader
|
||||||
|
displayToc
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -480,3 +480,15 @@ export function arrayMove<T>(arr: T[], old_index: number, new_index: number) {
|
||||||
arr.splice(new_index, 0, arr.splice(old_index, 1)[0]);
|
arr.splice(new_index, 0, arr.splice(old_index, 1)[0]);
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getPreferredLanguage(
|
||||||
|
preferredLanguages: (string | undefined)[],
|
||||||
|
availableLanguages: Map<string, number>
|
||||||
|
): number | undefined {
|
||||||
|
for (const locale of preferredLanguages) {
|
||||||
|
if (locale && availableLanguages.has(locale)) {
|
||||||
|
return availableLanguages.get(locale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue