Mass use of Immutable

This commit is contained in:
DrMint 2022-05-08 21:37:41 +02:00
parent 02e03071a0
commit 0591fa22d4
65 changed files with 375 additions and 338 deletions

View File

@ -1,9 +1,10 @@
import Button from "components/Inputs/Button";
import { useAppLayout } from "contexts/AppLayoutContext";
import { UploadImageFragment } from "graphql/generated";
import { prettyLanguage, prettySlug } from "helpers/formatters";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { prettyLanguage, prettySlug } from "helpers/formatters";
import { getOgImage, ImageQuality, OgImage } from "helpers/img";
import { Immutable } from "helpers/types";
import { useMediaMobile } from "hooks/useMediaQuery";
import Head from "next/head";
import { useRouter } from "next/router";
@ -24,8 +25,19 @@ interface Props extends AppStaticProps {
description?: string;
}
export default function AppLayout(props: Props): JSX.Element {
const { langui, currencies, languages, subPanel, contentPanel } = props;
export default function AppLayout(props: Immutable<Props>): JSX.Element {
const {
langui,
currencies,
languages,
subPanel,
contentPanel,
thumbnail,
title,
navTitle,
description,
subPanelIcon,
} = props;
const router = useRouter();
const isMobile = useMediaMobile();
const appLayout = useAppLayout();
@ -58,8 +70,8 @@ export default function AppLayout(props: Props): JSX.Element {
const turnSubIntoContent = subPanel && !contentPanel;
const titlePrefix = "Accords Library";
const metaImage: OgImage = props.thumbnail
? getOgImage(ImageQuality.Og, props.thumbnail)
const metaImage: OgImage = thumbnail
? getOgImage(ImageQuality.Og, thumbnail)
: {
image: "/default_og.jpg",
width: 1200,
@ -67,9 +79,9 @@ export default function AppLayout(props: Props): JSX.Element {
alt: "Accord's Library Logo",
};
const ogTitle =
props.title ?? props.navTitle ?? prettySlug(router.asPath.split("/").pop());
title ?? navTitle ?? prettySlug(router.asPath.split("/").pop());
const metaDescription = props.description ?? langui.default_description ?? "";
const metaDescription = description ?? langui.default_description ?? "";
useEffect(() => {
document.getElementsByTagName("html")[0].style.fontSize = `${
@ -114,7 +126,7 @@ export default function AppLayout(props: Props): JSX.Element {
}, [currencySelect]);
let gridCol = "";
if (props.subPanel) {
if (subPanel) {
if (appLayout.mainPanelReduced) {
gridCol = "grid-cols-[6rem_20rem_1fr]";
} else {
@ -260,8 +272,8 @@ export default function AppLayout(props: Props): JSX.Element {
{subPanel && !turnSubIntoContent
? appLayout.subPanelOpen
? "close"
: props.subPanelIcon
? props.subPanelIcon
: subPanelIcon
? subPanelIcon
: "tune"
: ""}
</span>

View File

@ -1,9 +1,11 @@
import { Immutable } from "helpers/types";
interface Props {
className?: string;
children: React.ReactNode;
}
export default function Chip(props: Props): JSX.Element {
export default function Chip(props: Immutable<Props>): JSX.Element {
return (
<div
className={`grid place-content-center place-items-center text-xs pb-[0.14rem] whitespace-nowrap px-1.5 border-[1px] rounded-full opacity-70 transition-[color,_opacity,_border-color] hover:opacity-100 ${props.className}`}

View File

@ -1,8 +1,10 @@
import { Immutable } from "helpers/types";
interface Props {
className?: string;
}
export default function HorizontalLine(props: Props): JSX.Element {
export default function HorizontalLine(props: Immutable<Props>): JSX.Element {
return (
<div
className={`h-0 w-full my-8 border-t-[3px] border-dotted border-black ${props.className}`}

View File

@ -1,5 +1,6 @@
import { UploadImageFragment } from "graphql/generated";
import { ImageQuality, getImgSizesByQuality, getAssetURL } from "helpers/img";
import { getAssetURL, getImgSizesByQuality, ImageQuality } from "helpers/img";
import { Immutable } from "helpers/types";
import Image, { ImageProps } from "next/image";
interface Props {
@ -12,7 +13,7 @@ interface Props {
priority?: ImageProps["priority"];
}
export default function Img(props: Props): JSX.Element {
export default function Img(props: Immutable<Props>): JSX.Element {
if (typeof props.image === "string") {
return (
<img

View File

@ -1,3 +1,4 @@
import { Immutable } from "helpers/types";
import { useRouter } from "next/router";
import { MouseEventHandler } from "react";
@ -14,7 +15,7 @@ interface Props {
badgeNumber?: number;
}
export default function Button(props: Props): JSX.Element {
export default function Button(props: Immutable<Props>): JSX.Element {
const {
draggable,
id,
@ -39,11 +40,15 @@ export default function Button(props: Props): JSX.Element {
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"
: `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`
}`}
>
{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">
<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>
)}

View File

@ -1,5 +1,6 @@
import { prettyLanguage } from "helpers/formatters";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { prettyLanguage } from "helpers/formatters";
import { Immutable } from "helpers/types";
import { Dispatch, SetStateAction } from "react";
import ToolTip from "../ToolTip";
import Button from "./Button";
@ -12,7 +13,7 @@ interface Props {
setLocalesIndex: Dispatch<SetStateAction<number | undefined>>;
}
export default function LanguageSwitcher(props: Props): JSX.Element {
export default function LanguageSwitcher(props: Immutable<Props>): JSX.Element {
const { locales, className, localesIndex, setLocalesIndex } = props;
return (

View File

@ -1,4 +1,5 @@
import { arrayMove } from "helpers/others";
import { Immutable } from "helpers/types";
import { useEffect, useState } from "react";
interface Props {
@ -7,7 +8,7 @@ interface Props {
onChange?: (items: Map<string, string>) => void;
}
export default function OrderableList(props: Props): JSX.Element {
export default function OrderableList(props: Immutable<Props>): JSX.Element {
const [items, setItems] = useState<Map<string, string>>(props.items);
useEffect(() => {

View File

@ -1,3 +1,4 @@
import { Immutable } from "helpers/types";
import { Dispatch, SetStateAction } from "react";
import Button from "./Button";
@ -8,7 +9,7 @@ interface Props {
setPage: Dispatch<SetStateAction<number>>;
}
export default function PageSelector(props: Props): JSX.Element {
export default function PageSelector(props: Immutable<Props>): JSX.Element {
const { page, setPage, maxPage } = props;
return (

View File

@ -1,3 +1,4 @@
import { Immutable } from "helpers/types";
import { Dispatch, SetStateAction, useState } from "react";
interface Props {
@ -9,7 +10,7 @@ interface Props {
className?: string;
}
export default function Select(props: Props): JSX.Element {
export default function Select(props: Immutable<Props>): JSX.Element {
const [opened, setOpened] = useState(false);
return (

View File

@ -1,3 +1,4 @@
import { Immutable } from "helpers/types";
import { Dispatch, SetStateAction } from "react";
interface Props {
@ -6,7 +7,7 @@ interface Props {
className?: string;
}
export default function Switch(props: Props): JSX.Element {
export default function Switch(props: Immutable<Props>): JSX.Element {
return (
<div
className={`h-6 w-12 rounded-full border-2 border-mid grid transition-colors relative cursor-pointer ${

View File

@ -1,10 +1,12 @@
import { Immutable } from "helpers/types";
interface Props {
className?: string;
children: React.ReactNode;
id?: string;
}
export default function InsetBox(props: Props): JSX.Element {
export default function InsetBox(props: Immutable<Props>): JSX.Element {
return (
<div
id={props.id}

View File

@ -1,8 +1,9 @@
import Chip from "components/Chip";
import Button from "components/Inputs/Button";
import { GetLibraryItemQuery } from "graphql/generated";
import { prettyinlineTitle, prettySlug } from "helpers/formatters";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { prettyinlineTitle, prettySlug } from "helpers/formatters";
import { Immutable } from "helpers/types";
import { useState } from "react";
interface Props {
@ -20,7 +21,7 @@ interface Props {
langui: AppStaticProps["langui"];
}
export default function ContentLine(props: Props): JSX.Element {
export default function ContentLine(props: Immutable<Props>): JSX.Element {
const { content, langui, parentSlug } = props;
const [opened, setOpened] = useState(false);

View File

@ -5,9 +5,10 @@ import RecorderChip from "components/RecorderChip";
import ToolTip from "components/ToolTip";
import { GetLibraryItemScansQuery } from "graphql/generated";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { getStatusDescription } from "helpers/others";
import { getAssetFilename, getAssetURL, ImageQuality } from "helpers/img";
import { isInteger } from "helpers/numbers";
import { getStatusDescription } from "helpers/others";
import { Immutable } from "helpers/types";
import useSmartLanguage from "hooks/useSmartLanguage";
import { Dispatch, SetStateAction } from "react";
@ -50,7 +51,7 @@ interface Props {
>["content"];
}
export default function ScanSet(props: Props): JSX.Element {
export default function ScanSet(props: Immutable<Props>): JSX.Element {
const {
setLightboxOpen,
setLightboxImages,
@ -68,7 +69,8 @@ export default function ScanSet(props: Props): JSX.Element {
languages: languages,
languageExtractor: (item) => item?.language?.data?.attributes?.code,
transform: (item) => {
item?.pages?.data.sort((a, b) => {
const newItem = { ...item } as Props["scanSet"][number];
newItem?.pages?.data.sort((a, b) => {
if (a.attributes?.url && b.attributes?.url) {
let aName = getAssetFilename(a.attributes.url);
let bName = getAssetFilename(b.attributes.url);
@ -91,7 +93,7 @@ export default function ScanSet(props: Props): JSX.Element {
}
return 0;
});
return item;
return newItem;
},
});

View File

@ -7,8 +7,9 @@ import {
UploadImageFragment,
} from "graphql/generated";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { getStatusDescription } from "helpers/others";
import { getAssetURL, ImageQuality } from "helpers/img";
import { getStatusDescription } from "helpers/others";
import { Immutable } from "helpers/types";
import useSmartLanguage from "hooks/useSmartLanguage";
import { Dispatch, SetStateAction } from "react";
@ -30,7 +31,7 @@ interface Props {
langui: AppStaticProps["langui"];
}
export default function ScanSetCover(props: Props): JSX.Element {
export default function ScanSetCover(props: Immutable<Props>): JSX.Element {
const {
setLightboxOpen,
setLightboxImages,

View File

@ -1,3 +1,4 @@
import { Immutable } from "helpers/types";
import { Dispatch, SetStateAction } from "react";
import Hotkeys from "react-hot-keys";
import { useSwipeable } from "react-swipeable";
@ -15,7 +16,7 @@ interface Props {
setIndex: Dispatch<SetStateAction<number>>;
}
export default function LightBox(props: Props): JSX.Element {
export default function LightBox(props: Immutable<Props>): JSX.Element {
const { state, setState, images, index, setIndex } = props;
function handlePrevious() {

View File

@ -6,6 +6,7 @@ import ToolTip from "components/ToolTip";
import { useAppLayout } from "contexts/AppLayoutContext";
import { slugify } from "helpers/formatters";
import { getAssetURL, ImageQuality } from "helpers/img";
import { Immutable } from "helpers/types";
import Markdown from "markdown-to-jsx";
import { useRouter } from "next/router";
import React, { useState } from "react";
@ -16,7 +17,7 @@ interface Props {
text: string;
}
export default function Markdawn(props: Props): JSX.Element {
export default function Markdawn(props: Immutable<Props>): JSX.Element {
const appLayout = useAppLayout();
const text = preprocessMarkDawn(props.text);

View File

@ -1,4 +1,5 @@
import { slugify } from "helpers/formatters";
import { Immutable } from "helpers/types";
import { useRouter } from "next/router";
import { preprocessMarkDawn } from "./Markdawn";
@ -7,7 +8,7 @@ interface Props {
title?: string;
}
export default function TOCComponent(props: Props): JSX.Element {
export default function TOCComponent(props: Immutable<Props>): JSX.Element {
const { text, title } = props;
const toc = getTocFromMarkdawn(preprocessMarkDawn(text), title);
const router = useRouter();

View File

@ -1,4 +1,5 @@
import ToolTip from "components/ToolTip";
import { Immutable } from "helpers/types";
import { useRouter } from "next/router";
import { MouseEventHandler } from "react";
@ -12,7 +13,7 @@ interface Props {
onClick?: MouseEventHandler<HTMLDivElement>;
}
export default function NavOption(props: Props): JSX.Element {
export default function NavOption(props: Immutable<Props>): JSX.Element {
const router = useRouter();
const isActive = router.asPath.startsWith(props.url);
const divActive = "bg-mid shadow-inner-sm shadow-shade";

View File

@ -1,4 +1,5 @@
import HorizontalLine from "components/HorizontalLine";
import { Immutable } from "helpers/types";
interface Props {
icon?: string;
@ -6,7 +7,7 @@ interface Props {
description?: string | null | undefined;
}
export default function PanelHeader(props: Props): JSX.Element {
export default function PanelHeader(props: Immutable<Props>): JSX.Element {
return (
<>
<div className="w-full grid place-items-center">

View File

@ -2,6 +2,7 @@ import HorizontalLine from "components/HorizontalLine";
import Button from "components/Inputs/Button";
import { useAppLayout } from "contexts/AppLayoutContext";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { Immutable } from "helpers/types";
interface Props {
href: string;
@ -18,7 +19,7 @@ export enum ReturnButtonType {
both = "both",
}
export default function ReturnButton(props: Props): JSX.Element {
export default function ReturnButton(props: Immutable<Props>): JSX.Element {
const appLayout = useAppLayout();
return (

View File

@ -1,3 +1,5 @@
import { Immutable } from "helpers/types";
interface Props {
children: React.ReactNode;
autoformat?: boolean;
@ -9,7 +11,7 @@ export enum ContentPanelWidthSizes {
large = "large",
}
export default function ContentPanel(props: Props): JSX.Element {
export default function ContentPanel(props: Immutable<Props>): JSX.Element {
const width = props.width ? props.width : ContentPanelWidthSizes.default;
const widthCSS =
width === ContentPanelWidthSizes.default ? "max-w-2xl" : "w-full";

View File

@ -7,12 +7,13 @@ import { useMediaDesktop } from "hooks/useMediaQuery";
import Markdown from "markdown-to-jsx";
import Link from "next/link";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { Immutable } from "helpers/types";
interface Props {
langui: AppStaticProps["langui"];
}
export default function MainPanel(props: Props): JSX.Element {
export default function MainPanel(props: Immutable<Props>): JSX.Element {
const { langui } = props;
const isDesktop = useMediaDesktop();
const appLayout = useAppLayout();

View File

@ -1,8 +1,10 @@
import { Immutable } from "helpers/types";
interface Props {
children: React.ReactNode;
}
export default function SubPanel(props: Props): JSX.Element {
export default function SubPanel(props: Immutable<Props>): JSX.Element {
return (
<div className="grid pt-10 pb-20 px-6 desktop:py-8 desktop:px-10 gap-y-2 text-center">
{props.children}

View File

@ -1,4 +1,5 @@
import { useAppLayout } from "contexts/AppLayoutContext";
import { Immutable } from "helpers/types";
import { Dispatch, SetStateAction, useEffect } from "react";
import Hotkeys from "react-hot-keys";
@ -13,7 +14,7 @@ interface Props {
padding?: boolean;
}
export default function Popup(props: Props): JSX.Element {
export default function Popup(props: Immutable<Props>): JSX.Element {
const {
setState,
state,

View File

@ -1,7 +1,7 @@
import { prettySlug } from "helpers/formatters";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { prettySlug } from "helpers/formatters";
import { getStatusDescription } from "helpers/others";
import { Post } from "helpers/types";
import { Immutable, PostWithTranslations } from "helpers/types";
import useSmartLanguage from "hooks/useSmartLanguage";
import AppLayout from "./AppLayout";
import Chip from "./Chip";
@ -16,7 +16,7 @@ import ThumbnailHeader from "./ThumbnailHeader";
import ToolTip from "./ToolTip";
interface Props {
post: Post;
post: PostWithTranslations;
langui: AppStaticProps["langui"];
languages: AppStaticProps["languages"];
currencies: AppStaticProps["currencies"];
@ -31,7 +31,7 @@ interface Props {
appendBody?: JSX.Element;
}
export default function PostPage(props: Props): JSX.Element {
export default function PostPage(props: Immutable<Props>): JSX.Element {
const {
post,
langui,

View File

@ -4,14 +4,15 @@ import {
PricePickerFragment,
UploadImageFragment,
} from "graphql/generated";
import { AppStaticProps } from "graphql/getAppStaticProps";
import {
prettyDate,
prettyDuration,
prettyPrice,
prettyShortenNumber,
} from "helpers/formatters";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { ImageQuality } from "helpers/img";
import { Immutable } from "helpers/types";
import Link from "next/link";
import Chip from "./Chip";
import Img from "./Img";
@ -43,7 +44,7 @@ interface Props {
| { __typename: "anotherHoverlayName" };
}
export default function ThumbnailPreview(props: Props): JSX.Element {
export default function ThumbnailPreview(props: Immutable<Props>): JSX.Element {
const {
href,
thumbnail,

View File

@ -1,5 +1,6 @@
import { UploadImageFragment } from "graphql/generated";
import { ImageQuality } from "helpers/img";
import { Immutable } from "helpers/types";
import Link from "next/link";
import Chip from "./Chip";
import Img from "./Img";
@ -15,7 +16,7 @@ interface Props {
bottomChips?: string[];
}
export default function PreviewLine(props: Props): JSX.Element {
export default function PreviewLine(props: Immutable<Props>): JSX.Element {
const {
href,
thumbnail,

View File

@ -2,6 +2,7 @@ import Chip from "components/Chip";
import { RecorderChipFragment } from "graphql/generated";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { ImageQuality } from "helpers/img";
import { Immutable } from "helpers/types";
import Img from "./Img";
import Markdawn from "./Markdown/Markdawn";
import ToolTip from "./ToolTip";
@ -12,7 +13,7 @@ interface Props {
langui: AppStaticProps["langui"];
}
export default function RecorderChip(props: Props): JSX.Element {
export default function RecorderChip(props: Immutable<Props>): JSX.Element {
const { recorder, langui } = props;
return (
<ToolTip

View File

@ -1,3 +1,4 @@
import { Immutable } from "helpers/types";
import Image from "next/image";
interface Props {
@ -6,7 +7,7 @@ interface Props {
className?: string;
}
export default function SVG(props: Props): JSX.Element {
export default function SVG(props: Immutable<Props>): JSX.Element {
return (
<div className={props.className}>
<Image

View File

@ -3,9 +3,10 @@ import Img from "components/Img";
import InsetBox from "components/InsetBox";
import Markdawn from "components/Markdown/Markdawn";
import { GetContentQuery, UploadImageFragment } from "graphql/generated";
import { prettyinlineTitle, prettySlug, slugify } from "helpers/formatters";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { prettyinlineTitle, prettySlug, slugify } from "helpers/formatters";
import { ImageQuality } from "helpers/img";
import { Immutable } from "helpers/types";
interface Props {
pre_title?: string | null | undefined;
@ -31,7 +32,7 @@ interface Props {
languageSwitcher?: JSX.Element;
}
export default function ThumbnailHeader(props: Props): JSX.Element {
export default function ThumbnailHeader(props: Immutable<Props>): JSX.Element {
const {
langui,
pre_title,

View File

@ -4,12 +4,12 @@ import "tippy.js/animations/scale-subtle.css";
interface Props extends TippyProps {}
export default function ToolTip(props: Props): JSX.Element {
const newProps = { ...props };
// Set defaults
if (newProps.delay === undefined) newProps.delay = [150, 0];
if (newProps.interactive === undefined) newProps.interactive = true;
if (newProps.animation === undefined) newProps.animation = "scale-subtle";
const newProps: Props = {
delay: [150, 0],
interactive: true,
animation: "scale-subtle",
...props,
};
return (
<Tippy className={`text-[80%] ${newProps.className}`} {...newProps}>

View File

@ -6,6 +6,7 @@ import {
} from "graphql/generated";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { getStatusDescription } from "helpers/others";
import { Immutable } from "helpers/types";
interface Props {
item: Exclude<
@ -16,7 +17,9 @@ interface Props {
langui: AppStaticProps["langui"];
}
export default function ChronologyItemComponent(props: Props): JSX.Element {
export default function ChronologyItemComponent(
props: Immutable<Props>
): JSX.Element {
const { langui } = props;
function generateAnchor(

View File

@ -1,6 +1,7 @@
import ChronologyItemComponent from "components/Wiki/Chronology/ChronologyItemComponent";
import { GetChronologyItemsQuery } from "graphql/generated";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { Immutable } from "helpers/types";
interface Props {
year: number;
@ -11,7 +12,9 @@ interface Props {
langui: AppStaticProps["langui"];
}
export default function ChronologyYearComponent(props: Props): JSX.Element {
export default function ChronologyYearComponent(
props: Immutable<Props>
): JSX.Element {
const { langui } = props;
return (

View File

@ -1,3 +1,4 @@
import { Immutable } from "helpers/types";
import useDarkMode from "hooks/useDarkMode";
import useStateWithLocalStorage from "hooks/useStateWithLocalStorage";
import React, { ReactNode, useContext, useState } from "react";
@ -76,7 +77,7 @@ interface Props {
children: ReactNode;
}
export function AppContextProvider(props: Props): JSX.Element {
export function AppContextProvider(props: Immutable<Props>): JSX.Element {
const [subPanelOpen, setSubPanelOpen] = useStateWithLocalStorage<
boolean | undefined
>("subPanelOpen", initialState.subPanelOpen);

View File

@ -4,9 +4,10 @@ import {
GetWebsiteInterfaceQuery,
} from "graphql/generated";
import { getReadySdk } from "graphql/sdk";
import { Immutable } from "helpers/types";
import { GetStaticPropsContext } from "next";
export interface AppStaticProps {
export type AppStaticProps = Immutable<{
langui: Exclude<
Exclude<
GetWebsiteInterfaceQuery["websiteInterfaces"],
@ -19,7 +20,7 @@ export interface AppStaticProps {
null | undefined
>["data"];
languages: Exclude<GetLanguagesQuery["languages"], null | undefined>["data"];
}
}>;
export async function getAppStaticProps(
context: GetStaticPropsContext
@ -50,9 +51,11 @@ export async function getAppStaticProps(
})
).websiteInterfaces?.data[0].attributes;
return {
langui: langui ?? ({} as AppStaticProps["langui"]),
currencies: currencies?.data ?? ({} as AppStaticProps["currencies"]),
languages: languages?.data ?? ({} as AppStaticProps["languages"]),
const appStaticProps: AppStaticProps = {
langui: langui ?? {},
currencies: currencies?.data ?? [],
languages: languages?.data ?? [],
};
return appStaticProps;
}

View File

@ -0,0 +1,32 @@
import { PostWithTranslations } from "helpers/types";
import { GetStaticPropsContext } from "next";
import { AppStaticProps, getAppStaticProps } from "./getAppStaticProps";
import { getReadySdk } from "./sdk";
export interface PostStaticProps extends AppStaticProps {
post: PostWithTranslations;
}
export function getPostStaticProps(
slug: string
): (
context: GetStaticPropsContext
) => Promise<{ notFound: boolean } | { props: PostStaticProps }> {
return async (context: GetStaticPropsContext) => {
const sdk = getReadySdk();
const post = await sdk.getPost({
slug: slug,
language_code: context.locale ?? "en",
});
if (post.posts?.data[0].attributes?.translations) {
const props: PostStaticProps = {
...(await getAppStaticProps(context)),
post: post.posts.data[0].attributes as PostWithTranslations,
};
return {
props: props,
};
}
return { notFound: true };
};
}

View File

@ -1,8 +1,9 @@
import { DatePickerFragment, PricePickerFragment } from "graphql/generated";
import { AppStaticProps } from "../graphql/getAppStaticProps";
import { convertPrice } from "./numbers";
import { Immutable } from "./types";
export function prettyDate(datePicker: DatePickerFragment): string {
export function prettyDate(datePicker: Immutable<DatePickerFragment>): string {
let result = "";
if (datePicker.year) result += datePicker.year.toString();
if (datePicker.month)
@ -13,7 +14,7 @@ export function prettyDate(datePicker: DatePickerFragment): string {
}
export function prettyPrice(
pricePicker: PricePickerFragment,
pricePicker: Immutable<PricePickerFragment>,
currencies: AppStaticProps["currencies"],
targetCurrencyCode?: string
): string {
@ -57,7 +58,7 @@ export function prettyinlineTitle(
}
export function prettyItemType(
metadata: any,
metadata: Immutable<any>,
langui: AppStaticProps["langui"]
): string | undefined | null {
switch (metadata.__typename) {
@ -79,7 +80,7 @@ export function prettyItemType(
}
export function prettyItemSubType(
metadata:
metadata: Immutable<
| {
__typename: "ComponentMetadataAudio";
subtype?: {
@ -156,6 +157,7 @@ export function prettyItemSubType(
}
| { __typename: "Error" }
| null
>
): string {
if (metadata) {
switch (metadata.__typename) {

View File

@ -1,4 +1,5 @@
import { UploadImageFragment } from "graphql/generated";
import { Immutable } from "./types";
export enum ImageQuality {
Small = "small",
@ -24,7 +25,10 @@ export function getAssetFilename(path: string): string {
return result[0];
}
export function getAssetURL(url: string, quality: ImageQuality): string {
export function getAssetURL(
url: string,
quality: Immutable<ImageQuality>
): string {
let newUrl = url;
newUrl = newUrl.replace(/^\/uploads/u, `/${quality}`);
newUrl = newUrl.replace(/.jpg$/u, ".webp");
@ -67,8 +71,8 @@ export function getImgSizesByQuality(
}
export function getOgImage(
quality: ImageQuality,
image: UploadImageFragment
quality: Immutable<ImageQuality>,
image: Immutable<UploadImageFragment>
): OgImage {
const imgSize = getImgSizesByQuality(
image.width ?? 0,

View File

@ -1,11 +1,11 @@
import { GetCurrenciesQuery, PricePickerFragment } from "graphql/generated";
import { Immutable } from "./types";
export function convertPrice(
pricePicker: PricePickerFragment,
targetCurrency: Exclude<
GetCurrenciesQuery["currencies"],
null | undefined
>["data"][number]
pricePicker: Immutable<PricePickerFragment>,
targetCurrency: Immutable<
Exclude<GetCurrenciesQuery["currencies"], null | undefined>["data"][number]
>
): number {
if (
pricePicker.amount &&

View File

@ -4,36 +4,42 @@ import {
GetLibraryItemScansQuery,
} from "graphql/generated";
import { AppStaticProps } from "../graphql/getAppStaticProps";
import { Immutable } from "./types";
export function sortContent(
contents:
| Exclude<
Exclude<
GetLibraryItemQuery["libraryItems"],
null | undefined
>["data"][number]["attributes"],
type SortContentProps =
| Exclude<
Exclude<
GetLibraryItemQuery["libraryItems"],
null | undefined
>["contents"]
| Exclude<
Exclude<
GetLibraryItemScansQuery["libraryItems"],
null | undefined
>["data"][number]["attributes"],
>["data"][number]["attributes"],
null | undefined
>["contents"]
| Exclude<
Exclude<
GetLibraryItemScansQuery["libraryItems"],
null | undefined
>["contents"]
) {
contents?.data.sort((a, b) => {
if (
a.attributes?.range[0]?.__typename === "ComponentRangePageRange" &&
b.attributes?.range[0]?.__typename === "ComponentRangePageRange"
) {
return (
a.attributes.range[0].starting_page -
b.attributes.range[0].starting_page
);
}
return 0;
});
>["data"][number]["attributes"],
null | undefined
>["contents"];
export function sortContent(contents: Immutable<SortContentProps>) {
if (contents) {
const newContent = { ...contents } as SortContentProps;
newContent?.data.sort((a, b) => {
if (
a.attributes?.range[0]?.__typename === "ComponentRangePageRange" &&
b.attributes?.range[0]?.__typename === "ComponentRangePageRange"
) {
return (
a.attributes.range[0].starting_page -
b.attributes.range[0].starting_page
);
}
return 0;
});
return newContent as Immutable<SortContentProps>;
}
return contents;
}
export function getStatusDescription(

View File

@ -1,9 +1,22 @@
import { GetPostQuery } from "graphql/generated";
import React from "react";
export type Post = Exclude<
type Post = Exclude<
Exclude<
GetPostQuery["posts"],
null | undefined
>["data"][number]["attributes"],
null | undefined
>;
export interface PostWithTranslations extends Omit<Post, "translations"> {
translations: Exclude<Post["translations"], null | undefined>;
}
type ImmutableBlackList<T> = JSX.Element | React.ReactNode | Function;
export type Immutable<T> = {
readonly [K in keyof T]: T[K] extends ImmutableBlackList<T>
? T[K]
: Immutable<T[K]>;
};

View File

@ -1,14 +1,15 @@
import LanguageSwitcher from "components/Inputs/LanguageSwitcher";
import { useAppLayout } from "contexts/AppLayoutContext";
import { AppStaticProps } from "graphql/getAppStaticProps";
import { Immutable } from "helpers/types";
import { useRouter } from "next/router";
import { useEffect, useMemo, useState } from "react";
interface Props<T> {
items: T[];
items: Immutable<T[]>;
languages: AppStaticProps["languages"];
languageExtractor: (item: T) => string | undefined;
transform?: (item: T) => T;
languageExtractor: (item: Immutable<T>) => string | undefined;
transform?: (item: Immutable<T>) => Immutable<T>;
}
function getPreferredLanguage(
@ -25,7 +26,7 @@ function getPreferredLanguage(
export default function useSmartLanguage<T>(
props: Props<T>
): [T | undefined, () => JSX.Element] {
): [Immutable<T | undefined>, () => JSX.Element] {
const {
items,
languageExtractor,
@ -39,7 +40,8 @@ export default function useSmartLanguage<T>(
const [selectedTranslationIndex, setSelectedTranslationIndex] = useState<
number | undefined
>();
const [selectedTranslation, setSelectedTranslation] = useState<T>();
const [selectedTranslation, setSelectedTranslation] =
useState<Immutable<T>>();
useEffect(() => {
items.map((elem, index) => {
@ -58,8 +60,9 @@ export default function useSmartLanguage<T>(
}, [appLayout.preferredLanguages, availableLocales, router.locale]);
useEffect(() => {
if (selectedTranslationIndex !== undefined)
if (selectedTranslationIndex !== undefined) {
setSelectedTranslation(transform(items[selectedTranslationIndex]));
}
}, [items, selectedTranslationIndex, transform]);
return [

View File

@ -3,12 +3,13 @@ import ReturnButton, {
ReturnButtonType,
} from "components/PanelComponents/ReturnButton";
import ContentPanel from "components/Panels/ContentPanel";
import { GetStaticPropsContext } from "next";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Immutable } from "helpers/types";
import { GetStaticPropsContext } from "next";
interface Props extends AppStaticProps {}
export default function FourOhFour(props: Props): JSX.Element {
export default function FourOhFour(props: Immutable<Props>): JSX.Element {
const { langui } = props;
const contentPanel = (
<ContentPanel>

View File

@ -3,12 +3,13 @@ import ReturnButton, {
ReturnButtonType,
} from "components/PanelComponents/ReturnButton";
import ContentPanel from "components/Panels/ContentPanel";
import { GetStaticPropsContext } from "next";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Immutable } from "helpers/types";
import { GetStaticPropsContext } from "next";
interface Props extends AppStaticProps {}
export default function FiveHundred(props: Props): JSX.Element {
export default function FiveHundred(props: Immutable<Props>): JSX.Element {
const { langui } = props;
const contentPanel = (
<ContentPanel>

View File

@ -1,14 +1,13 @@
import PostPage from "components/PostPage";
import { getReadySdk } from "graphql/sdk";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Post } from "helpers/types";
import { GetStaticPropsContext } from "next";
import {
getPostStaticProps,
PostStaticProps,
} from "graphql/getPostStaticProps";
import { Immutable } from "helpers/types";
interface Props extends AppStaticProps {
post: Post;
}
export default function AccordsHandbook(props: Props): JSX.Element {
export default function AccordsHandbook(
props: Immutable<PostStaticProps>
): JSX.Element {
const { post, langui, languages, currencies } = props;
return (
<PostPage
@ -24,21 +23,4 @@ export default function AccordsHandbook(props: Props): JSX.Element {
);
}
export async function getStaticProps(
context: GetStaticPropsContext
): Promise<{ notFound: boolean } | { props: Props }> {
const sdk = getReadySdk();
const slug = "accords-handbook";
const post = await sdk.getPost({
slug: slug,
language_code: context.locale ?? "en",
});
if (!post.posts?.data[0].attributes) return { notFound: true };
const props: Props = {
...(await getAppStaticProps(context)),
post: post.posts.data[0].attributes,
};
return {
props: props,
};
}
export const getStaticProps = getPostStaticProps("accords-handbook");

View File

@ -1,19 +1,18 @@
import InsetBox from "components/InsetBox";
import PostPage from "components/PostPage";
import { randomInt } from "crypto";
import { getReadySdk } from "graphql/sdk";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Post } from "helpers/types";
import { GetStaticPropsContext } from "next";
import {
getPostStaticProps,
PostStaticProps,
} from "graphql/getPostStaticProps";
import { randomInt } from "helpers/numbers";
import { Immutable } from "helpers/types";
import { useRouter } from "next/router";
import { RequestMailProps, ResponseMailProps } from "pages/api/mail";
import { useState } from "react";
interface Props extends AppStaticProps {
post: Post;
}
export default function AboutUs(props: Props): JSX.Element {
export default function AboutUs(
props: Immutable<PostStaticProps>
): JSX.Element {
const { post, langui, languages, currencies } = props;
const router = useRouter();
@ -182,21 +181,4 @@ export default function AboutUs(props: Props): JSX.Element {
);
}
export async function getStaticProps(
context: GetStaticPropsContext
): Promise<{ notFound: boolean } | { props: Props }> {
const sdk = getReadySdk();
const slug = "contact";
const post = await sdk.getPost({
slug: slug,
language_code: context.locale ?? "en",
});
if (!post.posts?.data[0].attributes) return { notFound: true };
const props: Props = {
...(await getAppStaticProps(context)),
post: post.posts.data[0].attributes,
};
return {
props: props,
};
}
export const getStaticProps = getPostStaticProps("contact");

View File

@ -2,12 +2,13 @@ import AppLayout from "components/AppLayout";
import NavOption from "components/PanelComponents/NavOption";
import PanelHeader from "components/PanelComponents/PanelHeader";
import SubPanel from "components/Panels/SubPanel";
import { GetStaticPropsContext } from "next";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Immutable } from "helpers/types";
import { GetStaticPropsContext } from "next";
interface Props extends AppStaticProps {}
export default function AboutUs(props: Props): JSX.Element {
export default function AboutUs(props: Immutable<Props>): JSX.Element {
const { langui } = props;
const subPanel = (
<SubPanel>

View File

@ -1,14 +1,10 @@
import PostPage from "components/PostPage";
import { getReadySdk } from "graphql/sdk";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Post } from "helpers/types";
import { GetStaticPropsContext } from "next";
import {
getPostStaticProps,
PostStaticProps,
} from "graphql/getPostStaticProps";
interface Props extends AppStaticProps {
post: Post;
}
export default function SiteInformation(props: Props): JSX.Element {
export default function Legality(props: PostStaticProps): JSX.Element {
const { post, langui, languages, currencies } = props;
return (
<PostPage
@ -24,21 +20,4 @@ export default function SiteInformation(props: Props): JSX.Element {
);
}
export async function getStaticProps(
context: GetStaticPropsContext
): Promise<{ notFound: boolean } | { props: Props }> {
const sdk = getReadySdk();
const slug = "legality";
const post = await sdk.getPost({
slug: slug,
language_code: context.locale ?? "en",
});
if (!post.posts?.data[0].attributes) return { notFound: true };
const props: Props = {
...(await getAppStaticProps(context)),
post: post.posts.data[0].attributes,
};
return {
props: props,
};
}
export const getStaticProps = getPostStaticProps("legality");

View File

@ -1,13 +1,10 @@
import PostPage from "components/PostPage";
import { getReadySdk } from "graphql/sdk";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Post } from "helpers/types";
import { GetStaticPropsContext } from "next";
import {
getPostStaticProps,
PostStaticProps,
} from "graphql/getPostStaticProps";
interface Props extends AppStaticProps {
post: Post;
}
export default function SharingPolicy(props: Props): JSX.Element {
export default function SharingPolicy(props: PostStaticProps): JSX.Element {
const { post, langui, languages, currencies } = props;
return (
<PostPage
@ -23,21 +20,4 @@ export default function SharingPolicy(props: Props): JSX.Element {
);
}
export async function getStaticProps(
context: GetStaticPropsContext
): Promise<{ notFound: boolean } | { props: Props }> {
const sdk = getReadySdk();
const slug = "sharing-policy";
const post = await sdk.getPost({
slug: slug,
language_code: context.locale ?? "en",
});
if (!post.posts?.data[0].attributes) return { notFound: true };
const props: Props = {
...(await getAppStaticProps(context)),
post: post.posts.data[0].attributes,
};
return {
props: props,
};
}
export const getStaticProps = getPostStaticProps("sharing-policy");

View File

@ -2,12 +2,13 @@ import AppLayout from "components/AppLayout";
import NavOption from "components/PanelComponents/NavOption";
import PanelHeader from "components/PanelComponents/PanelHeader";
import SubPanel from "components/Panels/SubPanel";
import { GetStaticPropsContext } from "next";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Immutable } from "helpers/types";
import { GetStaticPropsContext } from "next";
interface Props extends AppStaticProps {}
export default function Archives(props: Props): JSX.Element {
export default function Archives(props: Immutable<Props>): JSX.Element {
const { langui } = props;
const subPanel = (
<SubPanel>

View File

@ -3,10 +3,11 @@ import PanelHeader from "components/PanelComponents/PanelHeader";
import SubPanel from "components/Panels/SubPanel";
import { GetStaticPropsContext } from "next";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Immutable } from "helpers/types";
interface Props extends AppStaticProps {}
export default function Chronicles(props: Props): JSX.Element {
export default function Chronicles(props: Immutable<Props>): JSX.Element {
const { langui } = props;
const subPanel = (
<SubPanel>

View File

@ -13,14 +13,15 @@ import RecorderChip from "components/RecorderChip";
import ThumbnailHeader from "components/ThumbnailHeader";
import ToolTip from "components/ToolTip";
import { GetContentTextQuery } from "graphql/generated";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk";
import {
prettyinlineTitle,
prettyLanguage,
prettySlug,
} from "helpers/formatters";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getStatusDescription } from "helpers/others";
import { Immutable } from "helpers/types";
import { useMediaMobile } from "hooks/useMediaQuery";
import useSmartLanguage from "hooks/useSmartLanguage";
import {
@ -40,7 +41,7 @@ interface Props extends AppStaticProps {
>["data"][number]["id"];
}
export default function Content(props: Props): JSX.Element {
export default function Content(props: Immutable<Props>): JSX.Element {
const { langui, content, languages } = props;
const isMobile = useMediaMobile();

View File

@ -9,19 +9,20 @@ import ContentPanel, {
import SubPanel from "components/Panels/SubPanel";
import ThumbnailPreview from "components/PreviewCard";
import { GetContentsQuery } from "graphql/generated";
import { getReadySdk } from "graphql/sdk";
import { GetStaticPropsContext } from "next";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk";
import { prettyinlineTitle, prettySlug } from "helpers/formatters";
import { Immutable } from "helpers/types";
import { GetStaticPropsContext } from "next";
import { useEffect, useState } from "react";
import { prettySlug, prettyinlineTitle } from "helpers/formatters";
interface Props extends AppStaticProps {
contents: Exclude<GetContentsQuery["contents"], null | undefined>["data"];
}
type GroupContentItems = Map<string, Props["contents"]>;
type GroupContentItems = Map<string, Immutable<Props["contents"]>>;
export default function Contents(props: Props): JSX.Element {
export default function Contents(props: Immutable<Props>): JSX.Element {
const { langui, contents } = props;
const [groupingMethod, setGroupingMethod] = useState<number>(-1);
@ -172,7 +173,7 @@ export async function getStaticProps(
function getGroups(
langui: AppStaticProps["langui"],
groupByType: number,
items: Props["contents"]
items: Immutable<Props["contents"]>
): GroupContentItems {
switch (groupByType) {
case 0: {
@ -209,7 +210,7 @@ function getGroups(
}
case 1: {
const group: GroupContentItems = new Map();
const group = new Map();
items.map((item) => {
const type =
item.attributes?.type?.data?.attributes?.titles?.[0]?.title ??

View File

@ -9,15 +9,16 @@ import {
DevGetContentsQuery,
Enum_Componentsetstextset_Status,
} from "graphql/generated";
import { getReadySdk } from "graphql/sdk";
import { GetStaticPropsContext } from "next";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk";
import { Immutable } from "helpers/types";
import { GetStaticPropsContext } from "next";
interface Props extends AppStaticProps {
contents: DevGetContentsQuery;
}
export default function CheckupContents(props: Props): JSX.Element {
export default function CheckupContents(props: Immutable<Props>): JSX.Element {
const { contents } = props;
const testReport = testingContent(contents);
@ -112,7 +113,7 @@ type ReportLine = {
frontendUrl: string;
};
function testingContent(contents: Props["contents"]): Report {
function testingContent(contents: Immutable<Props["contents"]>): Report {
const report: Report = {
title: "Contents",
lines: [],

View File

@ -9,15 +9,18 @@ import {
DevGetLibraryItemsQuery,
Enum_Componentcollectionscomponentlibraryimages_Status,
} from "graphql/generated";
import { getReadySdk } from "graphql/sdk";
import { GetStaticPropsContext } from "next";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk";
import { Immutable } from "helpers/types";
import { GetStaticPropsContext } from "next";
interface Props extends AppStaticProps {
libraryItems: DevGetLibraryItemsQuery;
}
export default function CheckupLibraryItems(props: Props): JSX.Element {
export default function CheckupLibraryItems(
props: Immutable<Props>
): JSX.Element {
const { libraryItems } = props;
const testReport = testingLibraryItem(libraryItems);
@ -113,7 +116,9 @@ type ReportLine = {
};
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function testingLibraryItem(libraryItems: Props["libraryItems"]): Report {
function testingLibraryItem(
libraryItems: Immutable<Props["libraryItems"]>
): Report {
const report: Report = {
title: "Contents",
lines: [],

View File

@ -6,14 +6,15 @@ import ContentPanel, {
} from "components/Panels/ContentPanel";
import Popup from "components/Popup";
import ToolTip from "components/ToolTip";
import { GetStaticPropsContext } from "next";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Immutable } from "helpers/types";
import { GetStaticPropsContext } from "next";
import { useCallback, useState } from "react";
import TurndownService from "turndown";
interface Props extends AppStaticProps {}
export default function Editor(props: Props): JSX.Element {
export default function Editor(props: Immutable<Props>): JSX.Element {
const handleInput = useCallback((text: string) => {
setMarkdown(text);
}, []);

View File

@ -1,10 +1,11 @@
import AppLayout from "components/AppLayout";
import { GetStaticPropsContext } from "next";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Immutable } from "helpers/types";
import { GetStaticPropsContext } from "next";
interface Props extends AppStaticProps {}
export default function Gallery(props: Props): JSX.Element {
export default function Gallery(props: Immutable<Props>): JSX.Element {
const { langui } = props;
const contentPanel = (
<iframe

View File

@ -1,14 +1,11 @@
import PostPage from "components/PostPage";
import { getReadySdk } from "graphql/sdk";
import { GetStaticPropsContext } from "next";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Post } from "helpers/types";
import {
getPostStaticProps,
PostStaticProps,
} from "graphql/getPostStaticProps";
import { Immutable } from "helpers/types";
interface Props extends AppStaticProps {
post: Post;
}
export default function Home(props: Props): JSX.Element {
export default function Home(props: Immutable<PostStaticProps>): JSX.Element {
const { post, langui, languages, currencies } = props;
return (
<PostPage
@ -31,21 +28,4 @@ export default function Home(props: Props): JSX.Element {
);
}
export async function getStaticProps(
context: GetStaticPropsContext
): Promise<{ notFound: boolean } | { props: Props }> {
const sdk = getReadySdk();
const slug = "home";
const post = await sdk.getPost({
slug: slug,
language_code: context.locale ?? "en",
});
if (!post.posts?.data[0].attributes) return { notFound: true };
const props: Props = {
...(await getAppStaticProps(context)),
post: post.posts.data[0].attributes,
};
return {
props: props,
};
}
export const getStaticProps = getPostStaticProps("home");

View File

@ -21,6 +21,7 @@ import {
Enum_Componentmetadatabooks_Page_Order,
GetLibraryItemQuery,
} from "graphql/generated";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk";
import {
prettyDate,
@ -30,10 +31,10 @@ import {
prettyPrice,
prettyURL,
} from "helpers/formatters";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { sortContent } from "helpers/others";
import { getAssetURL, ImageQuality } from "helpers/img";
import { convertMmToInch } from "helpers/numbers";
import { sortContent } from "helpers/others";
import { Immutable } from "helpers/types";
import {
GetStaticPathsContext,
GetStaticPathsResult,
@ -52,7 +53,7 @@ interface Props extends AppStaticProps {
>["data"][number]["id"];
}
export default function LibrarySlug(props: Props): JSX.Element {
export default function LibrarySlug(props: Immutable<Props>): JSX.Element {
const { item, langui, currencies } = props;
const appLayout = useAppLayout();

View File

@ -22,6 +22,7 @@ import {
GetStaticPropsContext,
} from "next";
import { useState } from "react";
import { Immutable } from "helpers/types";
interface Props extends AppStaticProps {
item: Exclude<
@ -34,7 +35,7 @@ interface Props extends AppStaticProps {
>["data"][number]["id"];
}
export default function LibrarySlug(props: Props): JSX.Element {
export default function LibrarySlug(props: Immutable<Props>): JSX.Element {
const { item, langui, languages } = props;
const appLayout = useAppLayout();

View File

@ -9,14 +9,15 @@ import ContentPanel, {
import SubPanel from "components/Panels/SubPanel";
import ThumbnailPreview from "components/PreviewCard";
import { GetLibraryItemsPreviewQuery } from "graphql/generated";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { getReadySdk } from "graphql/sdk";
import {
prettyDate,
prettyinlineTitle,
prettyItemSubType,
} from "helpers/formatters";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { convertPrice } from "helpers/numbers";
import { Immutable } from "helpers/types";
import { GetStaticPropsContext } from "next";
import { useEffect, useState } from "react";
@ -27,9 +28,9 @@ interface Props extends AppStaticProps {
>["data"];
}
type GroupLibraryItems = Map<string, Props["items"]>;
type GroupLibraryItems = Map<string, Immutable<Props["items"]>>;
export default function Library(props: Props): JSX.Element {
export default function Library(props: Immutable<Props>): JSX.Element {
const { langui, items: libraryItems, currencies } = props;
const [showSubitems, setShowSubitems] = useState<boolean>(false);
@ -39,7 +40,7 @@ export default function Library(props: Props): JSX.Element {
const [groupingMethod, setGroupingMethod] = useState<number>(-1);
const [keepInfoVisible, setKeepInfoVisible] = useState(false);
const [filteredItems, setFilteredItems] = useState<Props["items"]>(
const [filteredItems, setFilteredItems] = useState(
filterItems(
showSubitems,
showPrimaryItems,
@ -48,11 +49,11 @@ export default function Library(props: Props): JSX.Element {
)
);
const [sortedItems, setSortedItem] = useState<Props["items"]>(
const [sortedItems, setSortedItem] = useState(
sortBy(groupingMethod, filteredItems, currencies)
);
const [groups, setGroups] = useState<GroupLibraryItems>(
const [groups, setGroups] = useState(
getGroups(langui, groupingMethod, sortedItems)
);
@ -224,7 +225,7 @@ export async function getStaticProps(
function getGroups(
langui: AppStaticProps["langui"],
groupByType: number,
items: Props["items"]
items: Immutable<Props["items"]>
): GroupLibraryItems {
switch (groupByType) {
case 0: {
@ -262,7 +263,7 @@ function getGroups(
}
case 1: {
const group: GroupLibraryItems = new Map();
const group = new Map();
group.set(langui.audio ?? "Audio", []);
group.set(langui.game ?? "Game", []);
group.set(langui.textual ?? "Textual", []);
@ -334,7 +335,7 @@ function getGroups(
years.push(item.attributes.release_date.year);
}
});
const group: GroupLibraryItems = new Map();
const group = new Map();
years.sort((a, b) => a - b);
years.map((year) => {
group.set(year.toString(), []);
@ -352,7 +353,7 @@ function getGroups(
}
default: {
const group: GroupLibraryItems = new Map();
const group = new Map();
group.set("", items);
return group;
}
@ -363,9 +364,10 @@ function filterItems(
showSubitems: boolean,
showPrimaryItems: boolean,
showSecondaryItems: boolean,
items: Props["items"]
): Props["items"] {
return [...items].filter((item) => {
items: Immutable<Props["items"]>
): Immutable<Props["items"]> {
const fileredItems = [...items] as Props["items"];
fileredItems.filter((item) => {
if (!showSubitems && !item.attributes?.root_item) return false;
if (
showSubitems &&
@ -380,13 +382,14 @@ function filterItems(
if (!item.attributes?.primary && !showSecondaryItems) return false;
return true;
});
return fileredItems as Immutable<Props["items"]>;
}
function sortBy(
orderByType: number,
items: Props["items"],
items: Immutable<Props["items"]>,
currencies: AppStaticProps["currencies"]
): Props["items"] {
): Immutable<Props["items"]> {
switch (orderByType) {
case 0:
return [...items].sort((a, b) => {

View File

@ -1,11 +1,12 @@
import AppLayout from "components/AppLayout";
import PanelHeader from "components/PanelComponents/PanelHeader";
import SubPanel from "components/Panels/SubPanel";
import { GetStaticPropsContext } from "next";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Immutable } from "helpers/types";
import { GetStaticPropsContext } from "next";
interface Props extends AppStaticProps {}
export default function Merch(props: Props): JSX.Element {
export default function Merch(props: Immutable<Props>): JSX.Element {
const { langui } = props;
const subPanel = (
<SubPanel>

View File

@ -1,23 +1,20 @@
import PostPage from "components/PostPage";
import { GetPostQuery } from "graphql/generated";
import { AppStaticProps } from "graphql/getAppStaticProps";
import {
getPostStaticProps,
PostStaticProps,
} from "graphql/getPostStaticProps";
import { getReadySdk } from "graphql/sdk";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Post } from "helpers/types";
import { Immutable } from "helpers/types";
import {
GetStaticPathsContext,
GetStaticPathsResult,
GetStaticPropsContext,
} from "next";
interface Props extends AppStaticProps {
post: Post;
postId: Exclude<
GetPostQuery["posts"],
null | undefined
>["data"][number]["id"];
}
interface Props extends AppStaticProps, PostStaticProps {}
export default function LibrarySlug(props: Props): JSX.Element {
export default function LibrarySlug(props: Immutable<Props>): JSX.Element {
const { post, langui, languages, currencies } = props;
return (
<PostPage
@ -37,21 +34,8 @@ export default function LibrarySlug(props: Props): JSX.Element {
export async function getStaticProps(
context: GetStaticPropsContext
): Promise<{ notFound: boolean } | { props: Props }> {
const sdk = getReadySdk();
const slug = context.params?.slug ? context.params.slug.toString() : "";
const post = await sdk.getPost({
slug: slug,
language_code: context.locale ?? "en",
});
if (!post.posts?.data[0].attributes) return { notFound: true };
const props: Props = {
...(await getAppStaticProps(context)),
post: post.posts.data[0].attributes,
postId: post.posts.data[0].id,
};
return {
props: props,
};
return await getPostStaticProps(slug)(context);
}
export async function getStaticPaths(

View File

@ -7,9 +7,10 @@ import ContentPanel, {
import SubPanel from "components/Panels/SubPanel";
import ThumbnailPreview 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 { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Immutable } from "helpers/types";
import { GetStaticPropsContext } from "next";
import { useState } from "react";
@ -17,19 +18,12 @@ interface Props extends AppStaticProps {
posts: Exclude<GetPostsPreviewQuery["posts"], null | undefined>["data"];
}
export default function News(props: Props): JSX.Element {
const { langui, posts } = props;
export default function News(props: Immutable<Props>): JSX.Element {
const { langui } = props;
const posts = sortPosts(props.posts);
const [keepInfoVisible, setKeepInfoVisible] = useState(true);
posts
.sort((a, b) => {
const dateA = a.attributes?.date ? prettyDate(a.attributes.date) : "9999";
const dateB = b.attributes?.date ? prettyDate(b.attributes.date) : "9999";
return dateA.localeCompare(dateB);
})
.reverse();
const subPanel = (
<SubPanel>
<PanelHeader
@ -103,3 +97,17 @@ export async function getStaticProps(
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"]>;
}

View File

@ -2,12 +2,13 @@ import AppLayout from "components/AppLayout";
import NavOption from "components/PanelComponents/NavOption";
import PanelHeader from "components/PanelComponents/PanelHeader";
import SubPanel from "components/Panels/SubPanel";
import { GetStaticPropsContext } from "next";
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
import { Immutable } from "helpers/types";
import { GetStaticPropsContext } from "next";
interface Props extends AppStaticProps {}
export default function Wiki(props: Props): JSX.Element {
export default function Wiki(props: Immutable<Props>): JSX.Element {
const { langui } = props;
const subPanel = (
<SubPanel>