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-type-alias": "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-type-arguments": "warn",
|
||||
"@typescript-eslint/prefer-enum-initializers": "error",
|
||||
|
|
|
@ -11,42 +11,61 @@ interface Props {
|
|||
target?: "_blank";
|
||||
onClick?: MouseEventHandler<HTMLDivElement>;
|
||||
draggable?: boolean;
|
||||
badgeNumber?: number;
|
||||
}
|
||||
|
||||
export default function Button(props: Props): JSX.Element {
|
||||
const {
|
||||
draggable,
|
||||
id,
|
||||
onClick,
|
||||
active,
|
||||
className,
|
||||
children,
|
||||
target,
|
||||
href,
|
||||
locale,
|
||||
badgeNumber,
|
||||
} = props;
|
||||
const router = useRouter();
|
||||
|
||||
const button = (
|
||||
<div
|
||||
draggable={props.draggable}
|
||||
id={props.id}
|
||||
onClick={props.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 ${
|
||||
props.className
|
||||
} ${
|
||||
props.active
|
||||
draggable={draggable}
|
||||
id={id}
|
||||
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 hover:[--opacityBadge:0] --opacityBadge:100 ${className} ${
|
||||
active
|
||||
? "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"
|
||||
}`}
|
||||
>
|
||||
{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>
|
||||
);
|
||||
|
||||
if (props.target) {
|
||||
if (target) {
|
||||
return (
|
||||
<a href={props.href} target={props.target} rel="noreferrer">
|
||||
<div>{button}</div>
|
||||
<a href={href} target={target} rel="noreferrer">
|
||||
<div className="relative">{button}</div>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className="relative"
|
||||
onClick={() => {
|
||||
if (props.href || props.locale)
|
||||
router.push(props.href ?? router.asPath, props.href, {
|
||||
locale: props.locale,
|
||||
if (href || locale)
|
||||
router.push(href ?? router.asPath, href, {
|
||||
locale: locale,
|
||||
});
|
||||
}}
|
||||
>
|
||||
|
|
|
@ -26,6 +26,7 @@ interface Props {
|
|||
>["categories"];
|
||||
thumbnail?: UploadImageFragment | null | undefined;
|
||||
langui: AppStaticProps["langui"];
|
||||
languageSwitcher?: JSX.Element;
|
||||
}
|
||||
|
||||
export default function ThumbnailHeader(props: Props): JSX.Element {
|
||||
|
@ -38,6 +39,7 @@ export default function ThumbnailHeader(props: Props): JSX.Element {
|
|||
type,
|
||||
categories,
|
||||
description,
|
||||
languageSwitcher,
|
||||
} = props;
|
||||
|
||||
return (
|
||||
|
@ -67,7 +69,7 @@ export default function ThumbnailHeader(props: Props): JSX.Element {
|
|||
</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 && (
|
||||
<div className="flex flex-col place-items-center gap-2">
|
||||
<h3 className="text-xl">{langui.type}</h3>
|
||||
|
@ -92,6 +94,7 @@ export default function ThumbnailHeader(props: Props): JSX.Element {
|
|||
</div>
|
||||
</div>
|
||||
)}
|
||||
{languageSwitcher}
|
||||
</div>
|
||||
{description && <InsetBox className="mt-8">{description}</InsetBox>}
|
||||
</>
|
||||
|
|
|
@ -1,33 +1,31 @@
|
|||
import { useRouter } from "next/router";
|
||||
import { AppStaticProps } from "queries/getAppStaticProps";
|
||||
import { prettyLanguage } from "queries/helpers";
|
||||
import { Dispatch, SetStateAction } from "react";
|
||||
import Button from "./Button";
|
||||
import ToolTip from "./ToolTip";
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
locales: (string | undefined)[];
|
||||
languages: AppStaticProps["languages"];
|
||||
langui: AppStaticProps["langui"];
|
||||
href?: string;
|
||||
locales: Map<string, number>;
|
||||
localesIndex: number | undefined;
|
||||
setLocalesIndex: Dispatch<SetStateAction<number | undefined>>;
|
||||
}
|
||||
|
||||
export default function LanguageSwitcher(props: Props): JSX.Element {
|
||||
const { locales, langui, href } = props;
|
||||
const router = useRouter();
|
||||
const { locales, localesIndex, setLocalesIndex } = props;
|
||||
|
||||
return (
|
||||
<div className="w-full grid place-content-center">
|
||||
<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">
|
||||
<p>{langui.language_switch_message}</p>
|
||||
<div className="flex flex-wrap flex-row gap-2">
|
||||
{locales.map((locale, index) => (
|
||||
<ToolTip
|
||||
content={
|
||||
<div className="flex flex-col gap-2">
|
||||
{[...locales].map(([locale, value], index) => (
|
||||
<>
|
||||
{locale && (
|
||||
<Button
|
||||
key={index}
|
||||
active={locale === router.locale}
|
||||
href={href}
|
||||
locale={locale}
|
||||
active={value === localesIndex}
|
||||
onClick={() => setLocalesIndex(value)}
|
||||
>
|
||||
{prettyLanguage(locale, props.languages)}
|
||||
</Button>
|
||||
|
@ -35,7 +33,11 @@ export default function LanguageSwitcher(props: Props): JSX.Element {
|
|||
</>
|
||||
))}
|
||||
</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
|
||||
attributes {
|
||||
slug
|
||||
titles(filters: { language: { code: { eq: $language_code } } }) {
|
||||
titles {
|
||||
pre_title
|
||||
title
|
||||
subtitle
|
||||
|
@ -56,7 +56,9 @@ query getContentText($slug: String, $language_code: String) {
|
|||
}
|
||||
}
|
||||
}
|
||||
text_set_languages: text_set {
|
||||
text_set {
|
||||
status
|
||||
text
|
||||
language {
|
||||
data {
|
||||
attributes {
|
||||
|
@ -64,10 +66,6 @@ query getContentText($slug: String, $language_code: String) {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
text_set(filters: { language: { code: { eq: $language_code } } }) {
|
||||
status
|
||||
text
|
||||
source_language {
|
||||
data {
|
||||
attributes {
|
||||
|
|
|
@ -29,7 +29,8 @@ query getLibraryItemScans($slug: String, $language_code: String) {
|
|||
ending_time
|
||||
}
|
||||
}
|
||||
scan_set_languages: scan_set {
|
||||
scan_set {
|
||||
status
|
||||
language {
|
||||
data {
|
||||
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 {
|
||||
data {
|
||||
attributes {
|
||||
|
|
|
@ -33,7 +33,7 @@ query getPost($slug: String, $language_code: String) {
|
|||
}
|
||||
}
|
||||
}
|
||||
translations_languages: translations {
|
||||
translations {
|
||||
language {
|
||||
data {
|
||||
attributes {
|
||||
|
@ -41,8 +41,6 @@ query getPost($slug: String, $language_code: String) {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
translations(filters: { language: { code: { eq: $language_code } } }) {
|
||||
status
|
||||
title
|
||||
excerpt
|
||||
|
|
|
@ -1,18 +1,8 @@
|
|||
import AppLayout from "components/AppLayout";
|
||||
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 Post from "components/Post";
|
||||
import { GetPostQuery } from "graphql/generated";
|
||||
import { getReadySdk } from "graphql/sdk";
|
||||
import { GetStaticPropsContext } from "next";
|
||||
import { useRouter } from "next/router";
|
||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||
import { getLocalesFromLanguages, prettySlug } from "queries/helpers";
|
||||
|
||||
interface Props extends AppStaticProps {
|
||||
post: Exclude<
|
||||
|
@ -22,53 +12,17 @@ interface Props extends AppStaticProps {
|
|||
}
|
||||
|
||||
export default function AccordsHandbook(props: Props): JSX.Element {
|
||||
const { langui, post } = 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>
|
||||
);
|
||||
|
||||
const { post, langui, languages, currencies } = props;
|
||||
return (
|
||||
<AppLayout
|
||||
navTitle={title}
|
||||
subPanel={subPanel}
|
||||
contentPanel={contentPanel}
|
||||
{...props}
|
||||
<Post
|
||||
currencies={currencies}
|
||||
languages={languages}
|
||||
langui={langui}
|
||||
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 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 Post from "components/Post";
|
||||
import { GetPostQuery } from "graphql/generated";
|
||||
import { getReadySdk } from "graphql/sdk";
|
||||
import { GetStaticPropsContext } from "next";
|
||||
import { useRouter } from "next/router";
|
||||
import { RequestMailProps, ResponseMailProps } from "pages/api/mail";
|
||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||
import {
|
||||
getLocalesFromLanguages,
|
||||
prettySlug,
|
||||
randomInt,
|
||||
} from "queries/helpers";
|
||||
import { randomInt } from "queries/helpers";
|
||||
import { useState } from "react";
|
||||
|
||||
interface Props extends AppStaticProps {
|
||||
|
@ -29,200 +17,170 @@ interface Props extends AppStaticProps {
|
|||
}
|
||||
|
||||
export default function AboutUs(props: Props): JSX.Element {
|
||||
const { langui, post } = props;
|
||||
const { post, langui, languages, currencies } = props;
|
||||
|
||||
const router = useRouter();
|
||||
const [formResponse, setFormResponse] = useState("");
|
||||
const [formState, setFormState] = useState<"completed" | "ongoing" | "stale">(
|
||||
"stale"
|
||||
);
|
||||
const locales = getLocalesFromLanguages(post?.translations_languages);
|
||||
|
||||
const [randomNumber1, setRandomNumber1] = useState(randomInt(0, 10));
|
||||
const [randomNumber2, setRandomNumber2] = useState(randomInt(0, 10));
|
||||
|
||||
const body = post?.translations?.[0]?.body ?? "";
|
||||
const title = post?.translations?.[0]?.title ?? prettySlug(post?.slug);
|
||||
const contactForm = (
|
||||
<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 = (
|
||||
<SubPanel>
|
||||
<ReturnButton
|
||||
href="/about-us"
|
||||
displayOn={ReturnButtonType.desktop}
|
||||
langui={langui}
|
||||
title={langui.about_us}
|
||||
horizontalLine
|
||||
/>
|
||||
<TOC text={body} title={title} />
|
||||
</SubPanel>
|
||||
);
|
||||
const fields = event.target as unknown as {
|
||||
verif: HTMLInputElement;
|
||||
name: HTMLInputElement;
|
||||
email: HTMLInputElement;
|
||||
message: HTMLInputElement;
|
||||
};
|
||||
|
||||
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}
|
||||
/>
|
||||
)}
|
||||
setFormState("ongoing");
|
||||
|
||||
<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 fields = event.target as unknown as {
|
||||
verif: HTMLInputElement;
|
||||
name: HTMLInputElement;
|
||||
email: HTMLInputElement;
|
||||
message: HTMLInputElement;
|
||||
if (
|
||||
parseInt(fields.verif.value, 10) ===
|
||||
randomNumber1 + randomNumber2 &&
|
||||
formState !== "completed"
|
||||
) {
|
||||
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");
|
||||
|
||||
setFormState("ongoing");
|
||||
break;
|
||||
|
||||
if (
|
||||
parseInt(fields.verif.value, 10) ===
|
||||
randomNumber1 + randomNumber2 &&
|
||||
formState !== "completed"
|
||||
) {
|
||||
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");
|
||||
case "EENVELOPE":
|
||||
setFormResponse(langui.response_invalid_email ?? "");
|
||||
setFormState("stale");
|
||||
break;
|
||||
|
||||
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":
|
||||
setFormResponse(langui.response_invalid_email ?? "");
|
||||
setFormState("stale");
|
||||
break;
|
||||
|
||||
default:
|
||||
setFormResponse(response.message ?? "");
|
||||
setFormState("stale");
|
||||
break;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
setFormResponse(langui.response_invalid_code ?? "");
|
||||
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>
|
||||
)}
|
||||
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>
|
||||
</ContentPanel>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<AppLayout
|
||||
navTitle={"Contact"}
|
||||
subPanel={subPanel}
|
||||
contentPanel={contentPanel}
|
||||
{...props}
|
||||
<Post
|
||||
currencies={currencies}
|
||||
languages={languages}
|
||||
langui={langui}
|
||||
post={post}
|
||||
returnHref="/about-us/"
|
||||
returnTitle={langui.about_us}
|
||||
displayToc
|
||||
appendBody={contactForm}
|
||||
displayLanguageSwitcher
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,18 +1,8 @@
|
|||
import AppLayout from "components/AppLayout";
|
||||
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 Post from "components/Post";
|
||||
import { GetPostQuery } from "graphql/generated";
|
||||
import { getReadySdk } from "graphql/sdk";
|
||||
import { GetStaticPropsContext } from "next";
|
||||
import { useRouter } from "next/router";
|
||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||
import { getLocalesFromLanguages, prettySlug } from "queries/helpers";
|
||||
|
||||
interface Props extends AppStaticProps {
|
||||
post: Exclude<
|
||||
|
@ -22,53 +12,17 @@ interface Props extends AppStaticProps {
|
|||
}
|
||||
|
||||
export default function SiteInformation(props: Props): JSX.Element {
|
||||
const { langui, post } = 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>
|
||||
);
|
||||
|
||||
const { post, langui, languages, currencies } = props;
|
||||
return (
|
||||
<AppLayout
|
||||
navTitle={title}
|
||||
subPanel={subPanel}
|
||||
contentPanel={contentPanel}
|
||||
{...props}
|
||||
<Post
|
||||
currencies={currencies}
|
||||
languages={languages}
|
||||
langui={langui}
|
||||
post={post}
|
||||
returnHref="/about-us/"
|
||||
returnTitle={langui.about_us}
|
||||
displayToc
|
||||
displayLanguageSwitcher
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,18 +1,8 @@
|
|||
import AppLayout from "components/AppLayout";
|
||||
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 Post from "components/Post";
|
||||
import { GetPostQuery } from "graphql/generated";
|
||||
import { getReadySdk } from "graphql/sdk";
|
||||
import { GetStaticPropsContext } from "next";
|
||||
import { useRouter } from "next/router";
|
||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||
import { getLocalesFromLanguages, prettySlug } from "queries/helpers";
|
||||
|
||||
interface Props extends AppStaticProps {
|
||||
post: Exclude<
|
||||
|
@ -21,53 +11,17 @@ interface Props extends AppStaticProps {
|
|||
>["data"][number]["attributes"];
|
||||
}
|
||||
export default function SharingPolicy(props: Props): JSX.Element {
|
||||
const { langui, post } = 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>
|
||||
);
|
||||
|
||||
const { post, langui, languages, currencies } = props;
|
||||
return (
|
||||
<AppLayout
|
||||
navTitle={title}
|
||||
subPanel={subPanel}
|
||||
contentPanel={contentPanel}
|
||||
{...props}
|
||||
<Post
|
||||
currencies={currencies}
|
||||
languages={languages}
|
||||
langui={langui}
|
||||
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 RecorderChip from "components/RecorderChip";
|
||||
import ToolTip from "components/ToolTip";
|
||||
import { useAppLayout } from "contexts/AppLayoutContext";
|
||||
import { GetContentTextQuery } from "graphql/generated";
|
||||
import { getReadySdk } from "graphql/sdk";
|
||||
import {
|
||||
|
@ -23,7 +24,7 @@ import {
|
|||
import { useRouter } from "next/router";
|
||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||
import {
|
||||
getLocalesFromLanguages,
|
||||
getPreferredLanguage,
|
||||
getStatusDescription,
|
||||
prettyinlineTitle,
|
||||
prettyLanguage,
|
||||
|
@ -31,6 +32,7 @@ import {
|
|||
prettyTestError,
|
||||
prettyTestWarning,
|
||||
} from "queries/helpers";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
|
||||
interface Props extends AppStaticProps {
|
||||
content: Exclude<
|
||||
|
@ -47,7 +49,49 @@ export default function Content(props: Props): JSX.Element {
|
|||
useTesting(props);
|
||||
const { langui, content, languages } = props;
|
||||
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 = (
|
||||
<SubPanel>
|
||||
|
@ -59,27 +103,25 @@ export default function Content(props: Props): JSX.Element {
|
|||
horizontalLine
|
||||
/>
|
||||
|
||||
{content?.text_set?.[0]?.source_language?.data?.attributes && (
|
||||
{selectedTextSet?.source_language?.data?.attributes && (
|
||||
<div className="grid gap-5">
|
||||
<h2 className="text-xl">
|
||||
{content.text_set[0].source_language.data.attributes.code ===
|
||||
router.locale
|
||||
{selectedTextSet.source_language.data.attributes.code ===
|
||||
selectedTextSet.language?.data?.attributes?.code
|
||||
? langui.transcript_notice
|
||||
: langui.translation_notice}
|
||||
</h2>
|
||||
|
||||
{content.text_set[0].source_language.data.attributes.code !==
|
||||
router.locale && (
|
||||
{selectedTextSet.source_language.data.attributes.code !==
|
||||
selectedTextSet.language?.data?.attributes?.code && (
|
||||
<div className="grid place-items-center gap-2">
|
||||
<p className="font-headers">{langui.source_language}:</p>
|
||||
<Button
|
||||
href={router.asPath}
|
||||
locale={
|
||||
content.text_set[0].source_language.data.attributes.code
|
||||
}
|
||||
locale={selectedTextSet.source_language.data.attributes.code}
|
||||
>
|
||||
{prettyLanguage(
|
||||
content.text_set[0].source_language.data.attributes.code,
|
||||
selectedTextSet.source_language.data.attributes.code,
|
||||
languages
|
||||
)}
|
||||
</Button>
|
||||
|
@ -90,19 +132,19 @@ export default function Content(props: Props): JSX.Element {
|
|||
<p className="font-headers">{langui.status}:</p>
|
||||
|
||||
<ToolTip
|
||||
content={getStatusDescription(content.text_set[0].status, langui)}
|
||||
content={getStatusDescription(selectedTextSet.status, langui)}
|
||||
maxWidth={"20rem"}
|
||||
>
|
||||
<Chip>{content.text_set[0].status}</Chip>
|
||||
<Chip>{selectedTextSet.status}</Chip>
|
||||
</ToolTip>
|
||||
</div>
|
||||
|
||||
{content.text_set[0].transcribers &&
|
||||
content.text_set[0].transcribers.data.length > 0 && (
|
||||
{selectedTextSet.transcribers &&
|
||||
selectedTextSet.transcribers.data.length > 0 && (
|
||||
<div>
|
||||
<p className="font-headers">{langui.transcribers}:</p>
|
||||
<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 && (
|
||||
<RecorderChip
|
||||
|
@ -117,12 +159,12 @@ export default function Content(props: Props): JSX.Element {
|
|||
</div>
|
||||
)}
|
||||
|
||||
{content.text_set[0].translators &&
|
||||
content.text_set[0].translators.data.length > 0 && (
|
||||
{selectedTextSet.translators &&
|
||||
selectedTextSet.translators.data.length > 0 && (
|
||||
<div>
|
||||
<p className="font-headers">{langui.translators}:</p>
|
||||
<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 && (
|
||||
<RecorderChip
|
||||
|
@ -137,12 +179,12 @@ export default function Content(props: Props): JSX.Element {
|
|||
</div>
|
||||
)}
|
||||
|
||||
{content.text_set[0].proofreaders &&
|
||||
content.text_set[0].proofreaders.data.length > 0 && (
|
||||
{selectedTextSet.proofreaders &&
|
||||
selectedTextSet.proofreaders.data.length > 0 && (
|
||||
<div>
|
||||
<p className="font-headers">{langui.proofreaders}:</p>
|
||||
<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 && (
|
||||
<RecorderChip
|
||||
|
@ -159,25 +201,23 @@ export default function Content(props: Props): JSX.Element {
|
|||
</div>
|
||||
)}
|
||||
|
||||
{content?.text_set &&
|
||||
content.text_set.length > 0 &&
|
||||
content.text_set[0]?.text && (
|
||||
<>
|
||||
<HorizontalLine />
|
||||
<TOC
|
||||
text={content.text_set[0].text}
|
||||
title={
|
||||
content.titles && content.titles.length > 0 && content.titles[0]
|
||||
? prettyinlineTitle(
|
||||
content.titles[0].pre_title,
|
||||
content.titles[0].title,
|
||||
content.titles[0].subtitle
|
||||
)
|
||||
: prettySlug(content.slug)
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{selectedTextSet && content?.text_set && selectedTextSet.text && (
|
||||
<>
|
||||
<HorizontalLine />
|
||||
<TOC
|
||||
text={selectedTextSet.text}
|
||||
title={
|
||||
content.titles && content.titles.length > 0 && selectedTitle
|
||||
? prettyinlineTitle(
|
||||
selectedTitle.pre_title,
|
||||
selectedTitle.title,
|
||||
selectedTitle.subtitle
|
||||
)
|
||||
: prettySlug(content.slug)
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</SubPanel>
|
||||
);
|
||||
const contentPanel = (
|
||||
|
@ -189,46 +229,37 @@ export default function Content(props: Props): JSX.Element {
|
|||
displayOn={ReturnButtonType.mobile}
|
||||
className="mb-10"
|
||||
/>
|
||||
|
||||
{content && (
|
||||
<div className="grid place-items-center">
|
||||
<ThumbnailHeader
|
||||
thumbnail={content.thumbnail?.data?.attributes}
|
||||
pre_title={
|
||||
content.titles && content.titles.length > 0
|
||||
? 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
|
||||
selectedTitle?.pre_title ?? content.titles?.[0]?.pre_title
|
||||
}
|
||||
title={selectedTitle?.title ?? content.titles?.[0]?.title}
|
||||
subtitle={selectedTitle?.subtitle ?? content.titles?.[0]?.subtitle}
|
||||
description={
|
||||
content.titles && content.titles.length > 0
|
||||
? content.titles[0]?.description
|
||||
: undefined
|
||||
selectedTitle?.description ?? content.titles?.[0]?.description
|
||||
}
|
||||
type={content.type}
|
||||
categories={content.categories}
|
||||
langui={langui}
|
||||
languageSwitcher={
|
||||
selectedTextSet ? (
|
||||
<LanguageSwitcher
|
||||
locales={textSetLocales}
|
||||
languages={props.languages}
|
||||
localesIndex={selectedTextSetIndex}
|
||||
setLocalesIndex={setSelectedTextSetIndex}
|
||||
/>
|
||||
) : undefined
|
||||
}
|
||||
/>
|
||||
|
||||
<HorizontalLine />
|
||||
|
||||
{locales.includes(router.locale ?? "en") ? (
|
||||
<Markdawn text={content.text_set?.[0]?.text ?? ""} />
|
||||
) : (
|
||||
<LanguageSwitcher
|
||||
locales={locales}
|
||||
languages={props.languages}
|
||||
langui={props.langui}
|
||||
/>
|
||||
)}
|
||||
<Markdawn text={selectedTextSet?.text ?? ""} />
|
||||
</div>
|
||||
)}
|
||||
</ContentPanel>
|
||||
|
@ -276,7 +307,7 @@ export async function getStaticProps(
|
|||
context: GetStaticPropsContext
|
||||
): Promise<{ notFound: boolean } | { props: Props }> {
|
||||
const sdk = getReadySdk();
|
||||
const slug = context.params?.slug?.toString() ?? "";
|
||||
const slug = context.params?.slug.toString() ?? "";
|
||||
const content = await sdk.getContentText({
|
||||
slug: slug,
|
||||
language_code: context.locale ?? "en",
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
import AppLayout from "components/AppLayout";
|
||||
import LanguageSwitcher from "components/LanguageSwitcher";
|
||||
import Markdawn from "components/Markdown/Markdawn";
|
||||
import ContentPanel from "components/Panels/ContentPanel";
|
||||
import Post from "components/Post";
|
||||
import { GetPostQuery } from "graphql/generated";
|
||||
import { getReadySdk } from "graphql/sdk";
|
||||
import { GetStaticPropsContext } from "next";
|
||||
import { useRouter } from "next/router";
|
||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||
import { getLocalesFromLanguages, prettySlug } from "queries/helpers";
|
||||
|
||||
interface Props extends AppStaticProps {
|
||||
post: Exclude<
|
||||
|
@ -17,35 +12,26 @@ interface Props extends AppStaticProps {
|
|||
}
|
||||
|
||||
export default function Home(props: Props): JSX.Element {
|
||||
const { post } = 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 contentPanel = (
|
||||
<ContentPanel>
|
||||
<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" />
|
||||
<h1 className="text-5xl mb-0">Accord’s Library</h1>
|
||||
<h2 className="text-xl -mt-5">
|
||||
Discover • Analyze • Translate • Archive
|
||||
</h2>
|
||||
</div>
|
||||
{locales.includes(router.locale ?? "en") ? (
|
||||
<Markdawn text={body} />
|
||||
) : (
|
||||
<LanguageSwitcher
|
||||
locales={locales}
|
||||
languages={props.languages}
|
||||
langui={props.langui}
|
||||
/>
|
||||
)}
|
||||
</ContentPanel>
|
||||
const { post, langui, languages, currencies } = props;
|
||||
return (
|
||||
<Post
|
||||
currencies={currencies}
|
||||
languages={languages}
|
||||
langui={langui}
|
||||
post={post}
|
||||
prependBody={
|
||||
<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" />
|
||||
<h1 className="text-5xl mb-0">Accord’s Library</h1>
|
||||
<h2 className="text-xl -mt-5">
|
||||
Discover • Analyze • Translate • Archive
|
||||
</h2>
|
||||
</div>
|
||||
}
|
||||
displayTitle={false}
|
||||
displayLanguageSwitcher
|
||||
/>
|
||||
);
|
||||
|
||||
return <AppLayout navTitle={title} contentPanel={contentPanel} {...props} />;
|
||||
}
|
||||
|
||||
export async function getStaticProps(
|
||||
|
|
|
@ -1,17 +1,4 @@
|
|||
import AppLayout from "components/AppLayout";
|
||||
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 Post from "components/Post";
|
||||
import { GetPostQuery } from "graphql/generated";
|
||||
import { getReadySdk } from "graphql/sdk";
|
||||
import {
|
||||
|
@ -19,13 +6,7 @@ import {
|
|||
GetStaticPathsResult,
|
||||
GetStaticPropsContext,
|
||||
} from "next";
|
||||
import { useRouter } from "next/router";
|
||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||
import {
|
||||
getLocalesFromLanguages,
|
||||
getStatusDescription,
|
||||
prettySlug,
|
||||
} from "queries/helpers";
|
||||
|
||||
interface Props extends AppStaticProps {
|
||||
post: Exclude<
|
||||
|
@ -39,106 +20,18 @@ interface Props extends AppStaticProps {
|
|||
}
|
||||
|
||||
export default function LibrarySlug(props: Props): JSX.Element {
|
||||
const { post, langui } = 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>
|
||||
);
|
||||
|
||||
const { post, langui, languages, currencies } = props;
|
||||
return (
|
||||
<AppLayout
|
||||
navTitle={title}
|
||||
contentPanel={contentPanel}
|
||||
subPanel={subPanel}
|
||||
thumbnail={thumbnail ?? undefined}
|
||||
{...props}
|
||||
<Post
|
||||
currencies={currencies}
|
||||
languages={languages}
|
||||
langui={langui}
|
||||
post={post}
|
||||
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]);
|
||||
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