117 lines
3.7 KiB
TypeScript
117 lines
3.7 KiB
TypeScript
import { AppLayout } from "components/AppLayout";
|
|
import { Switch } from "components/Inputs/Switch";
|
|
import { PanelHeader } from "components/PanelComponents/PanelHeader";
|
|
import {
|
|
ContentPanel,
|
|
ContentPanelWidthSizes,
|
|
} from "components/Panels/ContentPanel";
|
|
import { SubPanel } from "components/Panels/SubPanel";
|
|
import { PreviewCard } from "components/PreviewCard";
|
|
import { GetPostsPreviewQuery } from "graphql/generated";
|
|
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
|
|
import { getReadySdk } from "graphql/sdk";
|
|
import { prettyDate, prettySlug } from "helpers/formatters";
|
|
import { Immutable } from "helpers/types";
|
|
import { GetStaticPropsContext } from "next";
|
|
import { Fragment, useState } from "react";
|
|
|
|
interface Props extends AppStaticProps {
|
|
posts: NonNullable<GetPostsPreviewQuery["posts"]>["data"];
|
|
}
|
|
|
|
export default function News(props: Immutable<Props>): JSX.Element {
|
|
const { langui } = props;
|
|
const posts = sortPosts(props.posts);
|
|
|
|
const [keepInfoVisible, setKeepInfoVisible] = useState(true);
|
|
|
|
const subPanel = (
|
|
<SubPanel>
|
|
<PanelHeader
|
|
icon="feed"
|
|
title={langui.news}
|
|
description={langui.news_description}
|
|
/>
|
|
|
|
<div className="flex flex-row place-items-center gap-2 coarse:hidden">
|
|
<p className="flex-shrink-0">{langui.always_show_info}:</p>
|
|
<Switch setState={setKeepInfoVisible} state={keepInfoVisible} />
|
|
</div>
|
|
</SubPanel>
|
|
);
|
|
|
|
const contentPanel = (
|
|
<ContentPanel width={ContentPanelWidthSizes.large}>
|
|
<div
|
|
className="grid grid-cols-1 items-end gap-8
|
|
desktop:grid-cols-[repeat(auto-fill,_minmax(20rem,1fr))]"
|
|
>
|
|
{posts.map((post) => (
|
|
<Fragment key={post.id}>
|
|
{post.attributes && (
|
|
<PreviewCard
|
|
href={`/news/${post.attributes.slug}`}
|
|
title={
|
|
post.attributes.translations?.[0]?.title ??
|
|
prettySlug(post.attributes.slug)
|
|
}
|
|
description={post.attributes.translations?.[0]?.excerpt}
|
|
thumbnail={post.attributes.thumbnail?.data?.attributes}
|
|
bottomChips={post.attributes.categories?.data.map(
|
|
(category) => category.attributes?.short ?? ""
|
|
)}
|
|
thumbnailAspectRatio="3/2"
|
|
keepInfoVisible={keepInfoVisible}
|
|
metadata={{
|
|
release_date: post.attributes.date,
|
|
position: "Top",
|
|
}}
|
|
/>
|
|
)}
|
|
</Fragment>
|
|
))}
|
|
</div>
|
|
</ContentPanel>
|
|
);
|
|
|
|
return (
|
|
<AppLayout
|
|
navTitle={langui.news}
|
|
subPanel={subPanel}
|
|
contentPanel={contentPanel}
|
|
{...props}
|
|
/>
|
|
);
|
|
}
|
|
|
|
export async function getStaticProps(
|
|
context: GetStaticPropsContext
|
|
): Promise<{ notFound: boolean } | { props: Props }> {
|
|
const sdk = getReadySdk();
|
|
const posts = await sdk.getPostsPreview({
|
|
language_code: context.locale ?? "en",
|
|
});
|
|
if (!posts.posts) return { notFound: true };
|
|
const props: Props = {
|
|
...(await getAppStaticProps(context)),
|
|
posts: posts.posts.data,
|
|
};
|
|
return {
|
|
props: props,
|
|
};
|
|
}
|
|
|
|
function sortPosts(
|
|
posts: Immutable<Props["posts"]>
|
|
): Immutable<Props["posts"]> {
|
|
const sortedPosts = [...posts] as Props["posts"];
|
|
sortedPosts
|
|
.sort((a, b) => {
|
|
const dateA = a.attributes?.date ? prettyDate(a.attributes.date) : "9999";
|
|
const dateB = b.attributes?.date ? prettyDate(b.attributes.date) : "9999";
|
|
return dateA.localeCompare(dateB);
|
|
})
|
|
.reverse();
|
|
return sortedPosts as Immutable<Props["posts"]>;
|
|
}
|