Abstracted Image component for Strapi images + fixed key react problem
This commit is contained in:
parent
1a4b73f1f5
commit
c89fdbb499
|
@ -205,8 +205,6 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
|
||||||
<h2 className="text-2xl">Select a language</h2>
|
<h2 className="text-2xl">Select a language</h2>
|
||||||
<div className="flex flex-wrap flex-row gap-2">
|
<div className="flex flex-wrap flex-row gap-2">
|
||||||
{router.locales?.sort().map((locale) => (
|
{router.locales?.sort().map((locale) => (
|
||||||
<>
|
|
||||||
{locale !== "xx" ? (
|
|
||||||
<Button
|
<Button
|
||||||
key={locale}
|
key={locale}
|
||||||
active={locale === router.locale}
|
active={locale === router.locale}
|
||||||
|
@ -215,10 +213,6 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
|
||||||
>
|
>
|
||||||
{prettyLanguage(locale)}
|
{prettyLanguage(locale)}
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
|
||||||
""
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,9 +2,9 @@ import {
|
||||||
GetContentQuery,
|
GetContentQuery,
|
||||||
GetWebsiteInterfaceQuery,
|
GetWebsiteInterfaceQuery,
|
||||||
} from "graphql/operations-types";
|
} from "graphql/operations-types";
|
||||||
import { getAssetURL, ImageQuality, prettySlug } from "queries/helpers";
|
import { prettySlug } from "queries/helpers";
|
||||||
import Image from "next/image";
|
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
|
import Img, { ImageQuality } from "components/Img";
|
||||||
|
|
||||||
export type ThumbnailHeaderProps = {
|
export type ThumbnailHeaderProps = {
|
||||||
content: {
|
content: {
|
||||||
|
@ -28,12 +28,11 @@ export default function ThumbnailHeader(
|
||||||
<div className="grid place-items-center gap-12 mb-12">
|
<div className="grid place-items-center gap-12 mb-12">
|
||||||
<div className="drop-shadow-dark-lg">
|
<div className="drop-shadow-dark-lg">
|
||||||
{content.thumbnail.data ? (
|
{content.thumbnail.data ? (
|
||||||
<Image
|
<Img
|
||||||
className=" rounded-xl"
|
className=" rounded-xl"
|
||||||
src={getAssetURL(content.thumbnail.data.attributes.url, ImageQuality.Medium)}
|
image={content.thumbnail.data.attributes}
|
||||||
alt={content.thumbnail.data.attributes.alternativeText}
|
quality={ImageQuality.Medium}
|
||||||
width={content.thumbnail.data.attributes.width}
|
priority
|
||||||
height={content.thumbnail.data.attributes.height}
|
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="w-full aspect-[4/3] bg-light rounded-xl"></div>
|
<div className="w-full aspect-[4/3] bg-light rounded-xl"></div>
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
import { GetLibraryItemsPreviewQuery } from "graphql/operations-types";
|
||||||
|
import { ImageProps } from "next/image";
|
||||||
|
import Image from "next/image";
|
||||||
|
|
||||||
|
export enum ImageQuality {
|
||||||
|
Small = "small",
|
||||||
|
Medium = "medium",
|
||||||
|
Large = "large",
|
||||||
|
Og = "og",
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getAssetURL(url: string, quality?: ImageQuality): string {
|
||||||
|
if (!quality) quality = ImageQuality.Small;
|
||||||
|
url = url.replace(/^\/uploads/, "/" + quality);
|
||||||
|
url = url.replace(/.jpg$/, ".webp");
|
||||||
|
url = url.replace(/.png$/, ".webp");
|
||||||
|
return process.env.NEXT_PUBLIC_URL_IMG + url;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getImgSizesByMaxSize(
|
||||||
|
width: number,
|
||||||
|
height: number,
|
||||||
|
maxSize: number
|
||||||
|
): { width: number; height: number } {
|
||||||
|
if (width > height) {
|
||||||
|
if (width < maxSize) return { width: width, height: height };
|
||||||
|
return { width: maxSize, height: (height / width) * maxSize };
|
||||||
|
} else {
|
||||||
|
if (height < maxSize) return { width: width, height: height };
|
||||||
|
return { width: (width / height) * maxSize, height: maxSize };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getImgSizesByQuality(
|
||||||
|
width: number,
|
||||||
|
height: number,
|
||||||
|
quality: ImageQuality
|
||||||
|
): { width: number; height: number } {
|
||||||
|
switch (quality) {
|
||||||
|
case ImageQuality.Og:
|
||||||
|
return getImgSizesByMaxSize(width, height, 512);
|
||||||
|
case ImageQuality.Small:
|
||||||
|
return getImgSizesByMaxSize(width, height, 512);
|
||||||
|
case ImageQuality.Medium:
|
||||||
|
return getImgSizesByMaxSize(width, height, 1024);
|
||||||
|
case ImageQuality.Large:
|
||||||
|
return getImgSizesByMaxSize(width, height, 2048);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImgProps = {
|
||||||
|
className?: string;
|
||||||
|
image: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["thumbnail"]["data"]["attributes"];
|
||||||
|
quality?: ImageQuality;
|
||||||
|
alt?: ImageProps["alt"];
|
||||||
|
layout?: ImageProps["layout"];
|
||||||
|
objectFit?: ImageProps["objectFit"];
|
||||||
|
priority?: ImageProps["priority"];
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function Img(props: ImgProps): JSX.Element {
|
||||||
|
if (props.layout == "fill") {
|
||||||
|
return (
|
||||||
|
<Image
|
||||||
|
src={getAssetURL(props.image.url, props.quality)}
|
||||||
|
alt={props.alt ? props.alt : props.image.alternativeText}
|
||||||
|
layout={props.layout}
|
||||||
|
objectFit={props.objectFit}
|
||||||
|
priority={props.priority}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<Image
|
||||||
|
src={getAssetURL(props.image.url, props.quality)}
|
||||||
|
alt={props.alt ? props.alt : props.image.alternativeText}
|
||||||
|
{...getImgSizesByQuality(
|
||||||
|
props.image.width,
|
||||||
|
props.image.height,
|
||||||
|
props.quality ? props.quality : ImageQuality.Small
|
||||||
|
)}
|
||||||
|
layout={props.layout}
|
||||||
|
objectFit={props.objectFit}
|
||||||
|
priority={props.priority}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { GetContentsQuery } from "graphql/operations-types";
|
import { GetContentsQuery } from "graphql/operations-types";
|
||||||
import { getAssetURL, prettySlug } from "queries/helpers";
|
import { prettySlug } from "queries/helpers";
|
||||||
import Image from "next/image";
|
|
||||||
import Chip from "components/Chip";
|
import Chip from "components/Chip";
|
||||||
|
import Img, { ImageQuality } from "components/Img";
|
||||||
|
|
||||||
export type LibraryContentPreviewProps = {
|
export type LibraryContentPreviewProps = {
|
||||||
item: {
|
item: {
|
||||||
|
@ -23,12 +23,10 @@ export default function LibraryContentPreview(
|
||||||
<Link href={"/library/content/" + item.slug} passHref>
|
<Link href={"/library/content/" + item.slug} passHref>
|
||||||
<div className="drop-shadow-dark-xl cursor-pointer grid items-end fine:[--cover-opacity:0] hover:[--cover-opacity:1] hover:scale-[1.02] transition-transform">
|
<div className="drop-shadow-dark-xl cursor-pointer grid items-end fine:[--cover-opacity:0] hover:[--cover-opacity:1] hover:scale-[1.02] transition-transform">
|
||||||
{item.thumbnail.data ? (
|
{item.thumbnail.data ? (
|
||||||
<Image
|
<Img
|
||||||
className="rounded-md coarse:rounded-b-none"
|
className="rounded-md coarse:rounded-b-none"
|
||||||
src={getAssetURL(item.thumbnail.data.attributes.url)}
|
image={item.thumbnail.data.attributes}
|
||||||
alt={item.thumbnail.data.attributes.alternativeText}
|
quality={ImageQuality.Medium}
|
||||||
height={item.thumbnail.data.attributes.height}
|
|
||||||
width={item.thumbnail.data.attributes.width}
|
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="w-full aspect-[3/2] bg-light rounded-lg"></div>
|
<div className="w-full aspect-[3/2] bg-light rounded-lg"></div>
|
||||||
|
|
|
@ -1,20 +1,11 @@
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import {
|
import { GetLibraryItemsPreviewQuery } from "graphql/operations-types";
|
||||||
GetLibraryItemsPreviewQuery,
|
import { prettyDate, prettyPrice, prettyItemSubType } from "queries/helpers";
|
||||||
GetWebsiteInterfaceQuery,
|
|
||||||
} from "graphql/operations-types";
|
|
||||||
import {
|
|
||||||
getAssetURL,
|
|
||||||
prettyDate,
|
|
||||||
prettyPrice,
|
|
||||||
prettyItemSubType,
|
|
||||||
} from "queries/helpers";
|
|
||||||
import Image from "next/image";
|
|
||||||
import Chip from "components/Chip";
|
import Chip from "components/Chip";
|
||||||
|
import Img, { ImageQuality } from "components/Img";
|
||||||
|
|
||||||
export type LibraryItemsPreviewProps = {
|
export type LibraryItemsPreviewProps = {
|
||||||
className?: string;
|
className?: string;
|
||||||
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"];
|
|
||||||
item: {
|
item: {
|
||||||
slug: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["slug"];
|
slug: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["slug"];
|
||||||
thumbnail: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["thumbnail"];
|
thumbnail: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["thumbnail"];
|
||||||
|
@ -30,7 +21,6 @@ export default function LibraryItemsPreview(
|
||||||
props: LibraryItemsPreviewProps
|
props: LibraryItemsPreviewProps
|
||||||
): JSX.Element {
|
): JSX.Element {
|
||||||
const item = props.item;
|
const item = props.item;
|
||||||
const langui = props.langui;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link href={"/library/items/" + item.slug} passHref>
|
<Link href={"/library/items/" + item.slug} passHref>
|
||||||
|
@ -38,11 +28,9 @@ export default function LibraryItemsPreview(
|
||||||
className={`drop-shadow-dark-xl cursor-pointer grid items-end hover:rounded-3xl fine:[--cover-opacity:0] hover:[--cover-opacity:1] hover:scale-[1.02] transition-transform ${props.className}`}
|
className={`drop-shadow-dark-xl cursor-pointer grid items-end hover:rounded-3xl fine:[--cover-opacity:0] hover:[--cover-opacity:1] hover:scale-[1.02] transition-transform ${props.className}`}
|
||||||
>
|
>
|
||||||
{item.thumbnail.data ? (
|
{item.thumbnail.data ? (
|
||||||
<Image
|
<Img
|
||||||
src={getAssetURL(item.thumbnail.data.attributes.url)}
|
image={item.thumbnail.data.attributes}
|
||||||
alt={item.thumbnail.data.attributes.alternativeText}
|
quality={ImageQuality.Medium}
|
||||||
height={item.thumbnail.data.attributes.height}
|
|
||||||
width={item.thumbnail.data.attributes.width}
|
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="w-full aspect-[21/29.7] bg-light rounded-lg"></div>
|
<div className="w-full aspect-[21/29.7] bg-light rounded-lg"></div>
|
||||||
|
|
|
@ -31,7 +31,11 @@ export default function NavOption(props: NavOptionProps): JSX.Element {
|
||||||
data-tip={`
|
data-tip={`
|
||||||
<div class="px-4 py-3">
|
<div class="px-4 py-3">
|
||||||
<h3 class="text-2xl">${props.title}</h3>
|
<h3 class="text-2xl">${props.title}</h3>
|
||||||
${props.subtitle ? `<p class="max-w-[10rem]">${props.subtitle}</p>` : ""}
|
${
|
||||||
|
props.subtitle
|
||||||
|
? `<p class="max-w-[10rem]">${props.subtitle}</p>`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
`}
|
`}
|
||||||
data-for={props.tooltipId}
|
data-for={props.tooltipId}
|
||||||
|
|
|
@ -29,7 +29,9 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
id="mainPanel"
|
id="mainPanel"
|
||||||
className={`flex flex-col justify-center content-start gap-y-2 justify-items-center text-center p-8 ${mainPanelReduced && "px-4"}`}
|
className={`flex flex-col justify-center content-start gap-y-2 justify-items-center text-center p-8 ${
|
||||||
|
mainPanelReduced && "px-4"
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
{mainPanelReduced && isDesktop ? (
|
{mainPanelReduced && isDesktop ? (
|
||||||
<div className="grid place-items-center gap-4">
|
<div className="grid place-items-center gap-4">
|
||||||
|
|
|
@ -38,10 +38,10 @@ export function useMediaThin() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useMediaMobile() {
|
export function useMediaMobile() {
|
||||||
return useMediaQuery("(max-width: 150ch)");
|
return useMediaQuery("(max-width: 120ch)");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useMediaDesktop() {
|
export function useMediaDesktop() {
|
||||||
return useMediaQuery("(min-width: 150ch)");
|
return useMediaQuery("(min-width: 120ch)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,10 @@ class MyDocument extends Document {
|
||||||
<meta name="twitter:title" content={siteTitle}></meta>
|
<meta name="twitter:title" content={siteTitle}></meta>
|
||||||
<meta name="twitter:description" content={siteDescription}></meta>
|
<meta name="twitter:description" content={siteDescription}></meta>
|
||||||
<meta name="twitter:image" content={thumbnailImage}></meta>
|
<meta name="twitter:image" content={thumbnailImage}></meta>
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
<meta
|
||||||
|
name="apple-mobile-web-app-status-bar-style"
|
||||||
|
content="black-translucent"
|
||||||
|
/>
|
||||||
<link rel="manifest" href="manifest.json" />
|
<link rel="manifest" href="manifest.json" />
|
||||||
<meta name="theme-color" content="#FFEDD8" />
|
<meta name="theme-color" content="#FFEDD8" />
|
||||||
</Head>
|
</Head>
|
||||||
|
|
|
@ -20,7 +20,13 @@ export default function AboutUs(props: AboutUsProps): JSX.Element {
|
||||||
/>
|
/>
|
||||||
</SubPanel>
|
</SubPanel>
|
||||||
);
|
);
|
||||||
return <AppLayout title={langui.main_about_us} langui={langui} subPanel={subPanel} />;
|
return (
|
||||||
|
<AppLayout
|
||||||
|
title={langui.main_about_us}
|
||||||
|
langui={langui}
|
||||||
|
subPanel={subPanel}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getStaticProps: GetStaticProps = async (context) => {
|
export const getStaticProps: GetStaticProps = async (context) => {
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
|
||||||
import type { NextApiRequest, NextApiResponse } from "next";
|
|
||||||
|
|
||||||
type Data = {
|
|
||||||
name: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function handler(
|
|
||||||
req: NextApiRequest,
|
|
||||||
res: NextApiResponse<Data>
|
|
||||||
) {
|
|
||||||
res.status(200).json({ name: "John Lenon" });
|
|
||||||
}
|
|
|
@ -20,7 +20,13 @@ export default function Archives(props: ArchivesProps): JSX.Element {
|
||||||
/>
|
/>
|
||||||
</SubPanel>
|
</SubPanel>
|
||||||
);
|
);
|
||||||
return <AppLayout title={langui.main_archives} langui={langui} subPanel={subPanel} />;
|
return (
|
||||||
|
<AppLayout
|
||||||
|
title={langui.main_archives}
|
||||||
|
langui={langui}
|
||||||
|
subPanel={subPanel}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getStaticProps: GetStaticProps = async (context) => {
|
export const getStaticProps: GetStaticProps = async (context) => {
|
||||||
|
|
|
@ -20,7 +20,13 @@ export default function Chronicles(props: ChroniclesProps): JSX.Element {
|
||||||
/>
|
/>
|
||||||
</SubPanel>
|
</SubPanel>
|
||||||
);
|
);
|
||||||
return <AppLayout title={langui.main_chronicles} langui={langui} subPanel={subPanel} />;
|
return (
|
||||||
|
<AppLayout
|
||||||
|
title={langui.main_chronicles}
|
||||||
|
langui={langui}
|
||||||
|
subPanel={subPanel}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getStaticProps: GetStaticProps = async (context) => {
|
export const getStaticProps: GetStaticProps = async (context) => {
|
||||||
|
|
|
@ -58,7 +58,7 @@ export default function Editor(props: EditorProps): JSX.Element {
|
||||||
codeBlockStyle: "fenced",
|
codeBlockStyle: "fenced",
|
||||||
bulletListMarker: "-",
|
bulletListMarker: "-",
|
||||||
emDelimiter: "*",
|
emDelimiter: "*",
|
||||||
strongDelimiter: "**"
|
strongDelimiter: "**",
|
||||||
});
|
});
|
||||||
|
|
||||||
let paste = event.clipboardData.getData("text/html");
|
let paste = event.clipboardData.getData("text/html");
|
||||||
|
|
|
@ -17,7 +17,11 @@ export default function Gallery(props: GalleryProps): JSX.Element {
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppLayout title={langui.main_gallery} langui={langui} contentPanel={contentPanel} />
|
<AppLayout
|
||||||
|
title={langui.main_gallery}
|
||||||
|
langui={langui}
|
||||||
|
contentPanel={contentPanel}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,8 @@ import {
|
||||||
} from "graphql/operations-types";
|
} from "graphql/operations-types";
|
||||||
import ContentPanel from "components/Panels/ContentPanel";
|
import ContentPanel from "components/Panels/ContentPanel";
|
||||||
import HorizontalLine from "components/HorizontalLine";
|
import HorizontalLine from "components/HorizontalLine";
|
||||||
import Markdown from "markdown-to-jsx";
|
|
||||||
import SubPanel from "components/Panels/SubPanel";
|
import SubPanel from "components/Panels/SubPanel";
|
||||||
import ReturnButton from "components/PanelComponents/ReturnButton";
|
import ReturnButton from "components/PanelComponents/ReturnButton";
|
||||||
import SceneBreak from "components/Markdown/SceneBreak";
|
|
||||||
import ThumbnailHeader from "components/Content/ThumbnailHeader";
|
import ThumbnailHeader from "components/Content/ThumbnailHeader";
|
||||||
import AppLayout from "components/AppLayout";
|
import AppLayout from "components/AppLayout";
|
||||||
import Markdawn from "components/Markdown/Markdawn";
|
import Markdawn from "components/Markdown/Markdawn";
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
import { GetStaticProps } from "next";
|
import { GetStaticProps } from "next";
|
||||||
import SubPanel from "components/Panels/SubPanel";
|
import SubPanel from "components/Panels/SubPanel";
|
||||||
import {
|
import { GetWebsiteInterfaceQuery } from "graphql/operations-types";
|
||||||
GetWebsiteInterfaceQuery,
|
import { getWebsiteInterface } from "graphql/operations";
|
||||||
} from "graphql/operations-types";
|
|
||||||
import {
|
|
||||||
getWebsiteInterface,
|
|
||||||
} from "graphql/operations";
|
|
||||||
import PanelHeader from "components/PanelComponents/PanelHeader";
|
import PanelHeader from "components/PanelComponents/PanelHeader";
|
||||||
import AppLayout from "components/AppLayout";
|
import AppLayout from "components/AppLayout";
|
||||||
import NavOption from "components/PanelComponents/NavOption";
|
import NavOption from "components/PanelComponents/NavOption";
|
||||||
|
@ -38,7 +34,13 @@ export default function Library(props: LibraryProps): JSX.Element {
|
||||||
</SubPanel>
|
</SubPanel>
|
||||||
);
|
);
|
||||||
|
|
||||||
return <AppLayout title={langui.main_library} langui={langui} subPanel={subPanel} />;
|
return (
|
||||||
|
<AppLayout
|
||||||
|
title={langui.main_library}
|
||||||
|
langui={langui}
|
||||||
|
subPanel={subPanel}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getStaticProps: GetStaticProps = async (context) => {
|
export const getStaticProps: GetStaticProps = async (context) => {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import ContentPanel, {
|
import ContentPanel, {
|
||||||
ContentPanelWidthSizes,
|
ContentPanelWidthSizes,
|
||||||
} from "components/Panels/ContentPanel";
|
} from "components/Panels/ContentPanel";
|
||||||
import Image from "next/image";
|
|
||||||
import { GetStaticPaths, GetStaticProps } from "next";
|
import { GetStaticPaths, GetStaticProps } from "next";
|
||||||
import {
|
import {
|
||||||
getLibraryItem,
|
getLibraryItem,
|
||||||
|
@ -16,14 +15,12 @@ import {
|
||||||
} from "graphql/operations-types";
|
} from "graphql/operations-types";
|
||||||
import {
|
import {
|
||||||
convertMmToInch,
|
convertMmToInch,
|
||||||
getAssetURL,
|
|
||||||
prettyDate,
|
prettyDate,
|
||||||
prettyinlineTitle,
|
prettyinlineTitle,
|
||||||
prettyItemType,
|
prettyItemType,
|
||||||
prettyItemSubType,
|
prettyItemSubType,
|
||||||
prettyPrice,
|
prettyPrice,
|
||||||
prettySlug,
|
prettySlug,
|
||||||
ImageQuality,
|
|
||||||
} from "queries/helpers";
|
} from "queries/helpers";
|
||||||
import SubPanel from "components/Panels/SubPanel";
|
import SubPanel from "components/Panels/SubPanel";
|
||||||
import ReturnButton from "components/PanelComponents/ReturnButton";
|
import ReturnButton from "components/PanelComponents/ReturnButton";
|
||||||
|
@ -36,6 +33,7 @@ import LibraryItemsPreview from "components/Library/LibraryItemsPreview";
|
||||||
import InsetBox from "components/InsetBox";
|
import InsetBox from "components/InsetBox";
|
||||||
import { setSubPanelOpen } from "redux/AppLayoutSlice";
|
import { setSubPanelOpen } from "redux/AppLayoutSlice";
|
||||||
import { useDispatch } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
|
import Img, { ImageQuality } from "components/Img";
|
||||||
|
|
||||||
type LibrarySlugProps = {
|
type LibrarySlugProps = {
|
||||||
libraryItem: GetLibraryItemQuery;
|
libraryItem: GetLibraryItemQuery;
|
||||||
|
@ -47,6 +45,11 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
||||||
const langui = props.langui.websiteInterfaces.data[0].attributes;
|
const langui = props.langui.websiteInterfaces.data[0].attributes;
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
const isVariantSet =
|
||||||
|
item.metadata.length > 0 &&
|
||||||
|
item.metadata[0].__typename === "ComponentMetadataOther" &&
|
||||||
|
item.metadata[0].subtype.data.attributes.slug === "variant-set";
|
||||||
|
|
||||||
const subPanel = (
|
const subPanel = (
|
||||||
<SubPanel>
|
<SubPanel>
|
||||||
<ReturnButton
|
<ReturnButton
|
||||||
|
@ -83,23 +86,16 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{item.subitems.data.length > 0 ? (
|
{item.subitems.data.length > 0 ? (
|
||||||
item.metadata.length > 0 &&
|
|
||||||
item.metadata[0].__typename === "ComponentMetadataOther" &&
|
|
||||||
item.metadata[0].subtype.data.attributes.slug === "variant-set" ? (
|
|
||||||
<NavOption
|
<NavOption
|
||||||
title={langui.library_item_variants}
|
title={
|
||||||
url="#variants"
|
isVariantSet
|
||||||
|
? langui.library_item_variants
|
||||||
|
: langui.library_item_subitems
|
||||||
|
}
|
||||||
|
url={isVariantSet ? "#variants" : "#subitems"}
|
||||||
border={true}
|
border={true}
|
||||||
onClick={() => dispatch(setSubPanelOpen(false))}
|
onClick={() => dispatch(setSubPanelOpen(false))}
|
||||||
/>
|
/>
|
||||||
) : (
|
|
||||||
<NavOption
|
|
||||||
title={langui.library_item_subitems}
|
|
||||||
url="#subitems"
|
|
||||||
border={true}
|
|
||||||
onClick={() => dispatch(setSubPanelOpen(false))}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
) : (
|
) : (
|
||||||
""
|
""
|
||||||
)}
|
)}
|
||||||
|
@ -120,18 +116,14 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
||||||
const contentPanel = (
|
const contentPanel = (
|
||||||
<ContentPanel width={ContentPanelWidthSizes.large}>
|
<ContentPanel width={ContentPanelWidthSizes.large}>
|
||||||
<div className="grid place-items-center gap-12">
|
<div className="grid place-items-center gap-12">
|
||||||
<div className="drop-shadow-dark-xl w-full h-[50vh] mobile:h-[80vh] mb-16 ">
|
<div className="drop-shadow-dark-xl w-full h-[50vh] mobile:h-[80vh] mb-16 relative">
|
||||||
{item.thumbnail.data ? (
|
{item.thumbnail.data ? (
|
||||||
<Image
|
<Img
|
||||||
src={getAssetURL(
|
image={item.thumbnail.data.attributes}
|
||||||
item.thumbnail.data.attributes.url,
|
quality={ImageQuality.Medium}
|
||||||
ImageQuality.Medium
|
|
||||||
)}
|
|
||||||
alt={item.thumbnail.data.attributes.alternativeText}
|
|
||||||
width={item.thumbnail.data.attributes.width}
|
|
||||||
height={item.thumbnail.data.attributes.height}
|
|
||||||
layout="fill"
|
layout="fill"
|
||||||
objectFit="contain"
|
objectFit="contain"
|
||||||
|
priority
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="w-full aspect-[21/29.7] bg-light rounded-xl"></div>
|
<div className="w-full aspect-[21/29.7] bg-light rounded-xl"></div>
|
||||||
|
@ -182,12 +174,9 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
||||||
className="relative aspect-square hover:scale-[1.02] transition-transform cursor-pointer"
|
className="relative aspect-square hover:scale-[1.02] transition-transform cursor-pointer"
|
||||||
>
|
>
|
||||||
<div className="bg-light absolute inset-0 rounded-lg shadow-md"></div>
|
<div className="bg-light absolute inset-0 rounded-lg shadow-md"></div>
|
||||||
<Image
|
<Img
|
||||||
className="rounded-lg"
|
className="rounded-lg"
|
||||||
src={getAssetURL(galleryItem.attributes.url)}
|
image={galleryItem.attributes}
|
||||||
alt={galleryItem.attributes.alternativeText}
|
|
||||||
width={galleryItem.attributes.width}
|
|
||||||
height={galleryItem.attributes.height}
|
|
||||||
layout="fill"
|
layout="fill"
|
||||||
objectFit="cover"
|
objectFit="cover"
|
||||||
/>
|
/>
|
||||||
|
@ -356,35 +345,24 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
||||||
</InsetBox>
|
</InsetBox>
|
||||||
|
|
||||||
{item.subitems.data.length > 0 ? (
|
{item.subitems.data.length > 0 ? (
|
||||||
item.metadata.length > 0 &&
|
<div
|
||||||
item.metadata[0].__typename === "ComponentMetadataOther" &&
|
id={isVariantSet ? "variants" : "subitems"}
|
||||||
item.metadata[0].subtype.data.attributes.slug === "variant-set" ? (
|
className="grid place-items-center gap-8 w-full"
|
||||||
<div id="variants" className="grid place-items-center gap-8 w-full">
|
>
|
||||||
<h2 className="text-2xl">{langui.library_item_variants}</h2>
|
<h2 className="text-2xl">
|
||||||
<div className="grid gap-8 items-end mobile:grid-cols-2 grid-cols-[repeat(auto-fill,minmax(15rem,1fr))] w-full">
|
{isVariantSet
|
||||||
{item.subitems.data.map((variant) => (
|
? langui.library_item_variants
|
||||||
<LibraryItemsPreview
|
: langui.library_item_subitems}
|
||||||
key={variant.id}
|
</h2>
|
||||||
item={variant.attributes}
|
|
||||||
langui={langui}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div id="subitems" className="grid place-items-center gap-8 w-full">
|
|
||||||
<h2 className="text-2xl">{langui.library_item_subitems}</h2>
|
|
||||||
<div className="grid gap-8 items-end mobile:grid-cols-2 grid-cols-[repeat(auto-fill,minmax(15rem,1fr))] w-full">
|
<div className="grid gap-8 items-end mobile:grid-cols-2 grid-cols-[repeat(auto-fill,minmax(15rem,1fr))] w-full">
|
||||||
{item.subitems.data.map((subitem) => (
|
{item.subitems.data.map((subitem) => (
|
||||||
<LibraryItemsPreview
|
<LibraryItemsPreview
|
||||||
key={subitem.id}
|
key={subitem.id}
|
||||||
item={subitem.attributes}
|
item={subitem.attributes}
|
||||||
langui={langui}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
|
||||||
) : (
|
) : (
|
||||||
""
|
""
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -43,11 +43,7 @@ export default function Library(props: LibraryProps): JSX.Element {
|
||||||
<ContentPanel width={ContentPanelWidthSizes.large}>
|
<ContentPanel width={ContentPanelWidthSizes.large}>
|
||||||
<div className="grid gap-8 items-end mobile:grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(13rem,1fr))]">
|
<div className="grid gap-8 items-end mobile:grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(13rem,1fr))]">
|
||||||
{props.libraryItems.libraryItems.data.map((item) => (
|
{props.libraryItems.libraryItems.data.map((item) => (
|
||||||
<LibraryItemsPreview
|
<LibraryItemsPreview key={item.id} item={item.attributes} />
|
||||||
key={item.id}
|
|
||||||
item={item.attributes}
|
|
||||||
langui={langui}
|
|
||||||
/>
|
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</ContentPanel>
|
</ContentPanel>
|
||||||
|
|
|
@ -21,7 +21,9 @@ export default function Merch(props: MerchProps): JSX.Element {
|
||||||
</SubPanel>
|
</SubPanel>
|
||||||
);
|
);
|
||||||
|
|
||||||
return <AppLayout title={langui.main_merch} langui={langui} subPanel={subPanel} />;
|
return (
|
||||||
|
<AppLayout title={langui.main_merch} langui={langui} subPanel={subPanel} />
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getStaticProps: GetStaticProps = async (context) => {
|
export const getStaticProps: GetStaticProps = async (context) => {
|
||||||
|
|
|
@ -21,7 +21,9 @@ export default function News(props: NewsProps): JSX.Element {
|
||||||
</SubPanel>
|
</SubPanel>
|
||||||
);
|
);
|
||||||
|
|
||||||
return <AppLayout title={langui.main_news} langui={langui} subPanel={subPanel} />;
|
return (
|
||||||
|
<AppLayout title={langui.main_news} langui={langui} subPanel={subPanel} />
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getStaticProps: GetStaticProps = async (context) => {
|
export const getStaticProps: GetStaticProps = async (context) => {
|
||||||
|
|
|
@ -72,7 +72,11 @@ export default function DataChronology(
|
||||||
<NavOption
|
<NavOption
|
||||||
key={era.id}
|
key={era.id}
|
||||||
url={"#" + era.attributes.slug}
|
url={"#" + era.attributes.slug}
|
||||||
title={era.attributes.title.length > 0 ? era.attributes.title[0].title : prettySlug(era.attributes.slug)}
|
title={
|
||||||
|
era.attributes.title.length > 0
|
||||||
|
? era.attributes.title[0].title
|
||||||
|
: prettySlug(era.attributes.slug)
|
||||||
|
}
|
||||||
subtitle={
|
subtitle={
|
||||||
era.attributes.starting_year + " → " + era.attributes.ending_year
|
era.attributes.starting_year + " → " + era.attributes.ending_year
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,20 +3,6 @@ import {
|
||||||
GetWebsiteInterfaceQuery,
|
GetWebsiteInterfaceQuery,
|
||||||
} from "graphql/operations-types";
|
} from "graphql/operations-types";
|
||||||
|
|
||||||
export enum ImageQuality {
|
|
||||||
Small = "small",
|
|
||||||
Medium = "medium",
|
|
||||||
Large = "large"
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getAssetURL(url: string, quality?: ImageQuality): string {
|
|
||||||
if (!quality) quality = ImageQuality.Small;
|
|
||||||
url = url.replace(/^\/uploads/, "/" + quality);
|
|
||||||
url = url.replace(/.jpg$/, ".webp");
|
|
||||||
url = url.replace(/.png$/, ".webp");
|
|
||||||
return process.env.NEXT_PUBLIC_URL_IMG + url;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function prettyDate(
|
export function prettyDate(
|
||||||
datePicker: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["release_date"]
|
datePicker: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["release_date"]
|
||||||
): string {
|
): string {
|
||||||
|
|
|
@ -15,8 +15,8 @@ module.exports = {
|
||||||
monospace: ["monospace"],
|
monospace: ["monospace"],
|
||||||
},
|
},
|
||||||
screens: {
|
screens: {
|
||||||
desktop: { min: "150ch" },
|
desktop: { min: "120ch" },
|
||||||
mobile: { max: "150ch" },
|
mobile: { max: "120ch" },
|
||||||
thin: { max: "50ch" },
|
thin: { max: "50ch" },
|
||||||
coarse: { raw: "(pointer: coarse)" },
|
coarse: { raw: "(pointer: coarse)" },
|
||||||
fine: { raw: "(pointer: fine)" },
|
fine: { raw: "(pointer: fine)" },
|
||||||
|
|
Loading…
Reference in New Issue