Content pages now display the table of content
This commit is contained in:
parent
6d3a9c84b3
commit
b213447c49
|
@ -2,10 +2,11 @@ import {
|
||||||
GetContentQuery,
|
GetContentQuery,
|
||||||
GetWebsiteInterfaceQuery,
|
GetWebsiteInterfaceQuery,
|
||||||
} from "graphql/operations-types";
|
} from "graphql/operations-types";
|
||||||
import { prettySlug } from "queries/helpers";
|
import { prettyinlineTitle, prettySlug, slugify } from "queries/helpers";
|
||||||
import Button from "components/Button";
|
import Button from "components/Button";
|
||||||
import Img, { ImageQuality } from "components/Img";
|
import Img, { ImageQuality } from "components/Img";
|
||||||
import InsetBox from "components/InsetBox";
|
import InsetBox from "components/InsetBox";
|
||||||
|
import Chip from "components/Chip";
|
||||||
|
|
||||||
export type ThumbnailHeaderProps = {
|
export type ThumbnailHeaderProps = {
|
||||||
content: {
|
content: {
|
||||||
|
@ -39,7 +40,18 @@ export default function ThumbnailHeader(
|
||||||
<div className="w-full aspect-[4/3] bg-light rounded-xl"></div>
|
<div className="w-full aspect-[4/3] bg-light rounded-xl"></div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="grid place-items-center text-center">
|
<div
|
||||||
|
id={slugify(
|
||||||
|
content.titles.length > 0
|
||||||
|
? prettyinlineTitle(
|
||||||
|
content.titles[0].pre_title,
|
||||||
|
content.titles[0].title,
|
||||||
|
content.titles[0].subtitle
|
||||||
|
)
|
||||||
|
: prettySlug(content.slug)
|
||||||
|
)}
|
||||||
|
className="grid place-items-center text-center"
|
||||||
|
>
|
||||||
{content.titles.length > 0 ? (
|
{content.titles.length > 0 ? (
|
||||||
<>
|
<>
|
||||||
<p className="text-2xl">{content.titles[0].pre_title}</p>
|
<p className="text-2xl">{content.titles[0].pre_title}</p>
|
||||||
|
@ -54,22 +66,26 @@ export default function ThumbnailHeader(
|
||||||
|
|
||||||
<div className="grid grid-flow-col gap-8">
|
<div className="grid grid-flow-col gap-8">
|
||||||
{content.type && (
|
{content.type && (
|
||||||
<div className="grid place-items-center place-content-start gap-2">
|
<div className="flex flex-col place-items-center gap-2">
|
||||||
<h3 className="text-xl">{langui.type}</h3>
|
<h3 className="text-xl">{langui.type}</h3>
|
||||||
<Button>
|
<div className="flex flex-row flex-wrap">
|
||||||
{content.type.data.attributes.titles.length > 0
|
<Chip>
|
||||||
? content.type.data.attributes.titles[0].title
|
{content.type.data.attributes.titles.length > 0
|
||||||
: prettySlug(content.type.data.attributes.slug)}
|
? content.type.data.attributes.titles[0].title
|
||||||
</Button>
|
: prettySlug(content.type.data.attributes.slug)}
|
||||||
|
</Chip>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{content.categories.data.length > 0 && (
|
{content.categories.data.length > 0 && (
|
||||||
<div className="grid place-items-center place-content-start gap-2">
|
<div className="flex flex-col place-items-center gap-2">
|
||||||
<h3 className="text-xl">{langui.categories}</h3>
|
<h3 className="text-xl">{langui.categories}</h3>
|
||||||
{content.categories.data.map((category) => (
|
<div className="flex flex-row flex-wrap place-content-center gap-2">
|
||||||
<Button key={category.id}>{category.attributes.name}</Button>
|
{content.categories.data.map((category) => (
|
||||||
))}
|
<Chip key={category.id}>{category.attributes.name}</Chip>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -117,6 +117,8 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
||||||
onClick={() => appLayout.setMainPanelOpen(false)}
|
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/*
|
||||||
|
|
||||||
<NavOption
|
<NavOption
|
||||||
url="/wiki"
|
url="/wiki"
|
||||||
icon="travel_explore"
|
icon="travel_explore"
|
||||||
|
@ -136,6 +138,8 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
||||||
reduced={appLayout.mainPanelReduced && isDesktop}
|
reduced={appLayout.mainPanelReduced && isDesktop}
|
||||||
onClick={() => appLayout.setMainPanelOpen(false)}
|
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
*/}
|
||||||
|
|
||||||
<HorizontalLine />
|
<HorizontalLine />
|
||||||
|
|
||||||
|
@ -147,7 +151,7 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
||||||
reduced={appLayout.mainPanelReduced && isDesktop}
|
reduced={appLayout.mainPanelReduced && isDesktop}
|
||||||
onClick={() => appLayout.setMainPanelOpen(false)}
|
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||||
/>
|
/>
|
||||||
|
{/*
|
||||||
<NavOption
|
<NavOption
|
||||||
url="/merch"
|
url="/merch"
|
||||||
icon="store"
|
icon="store"
|
||||||
|
@ -156,6 +160,8 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
||||||
reduced={appLayout.mainPanelReduced && isDesktop}
|
reduced={appLayout.mainPanelReduced && isDesktop}
|
||||||
onClick={() => appLayout.setMainPanelOpen(false)}
|
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
*/}
|
||||||
|
|
||||||
<NavOption
|
<NavOption
|
||||||
url="/gallery"
|
url="/gallery"
|
||||||
|
@ -166,6 +172,8 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
||||||
onClick={() => appLayout.setMainPanelOpen(false)}
|
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/*
|
||||||
|
|
||||||
<NavOption
|
<NavOption
|
||||||
url="/archives"
|
url="/archives"
|
||||||
icon="inventory"
|
icon="inventory"
|
||||||
|
@ -175,6 +183,9 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
||||||
onClick={() => appLayout.setMainPanelOpen(false)}
|
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
*/}
|
||||||
|
|
||||||
<NavOption
|
<NavOption
|
||||||
url="/about-us"
|
url="/about-us"
|
||||||
icon="info"
|
icon="info"
|
||||||
|
|
|
@ -26,6 +26,7 @@ import Chip from "components/Chip";
|
||||||
import ReactTooltip from "react-tooltip";
|
import ReactTooltip from "react-tooltip";
|
||||||
import RecorderChip from "components/RecorderChip";
|
import RecorderChip from "components/RecorderChip";
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
|
import TOC from "components/Markdown/TOC";
|
||||||
|
|
||||||
interface ContentReadProps extends AppStaticProps {
|
interface ContentReadProps extends AppStaticProps {
|
||||||
content: GetContentTextQuery["contents"]["data"][number]["attributes"];
|
content: GetContentTextQuery["contents"]["data"][number]["attributes"];
|
||||||
|
@ -141,6 +142,20 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<HorizontalLine />
|
||||||
|
<TOC
|
||||||
|
text={content.text_set[0].text}
|
||||||
|
title={
|
||||||
|
content.titles.length > 0
|
||||||
|
? prettyinlineTitle(
|
||||||
|
content.titles[0].pre_title,
|
||||||
|
content.titles[0].title,
|
||||||
|
content.titles[0].subtitle
|
||||||
|
)
|
||||||
|
: prettySlug(content.slug)
|
||||||
|
}
|
||||||
|
/>
|
||||||
</SubPanel>
|
</SubPanel>
|
||||||
);
|
);
|
||||||
const contentPanel = (
|
const contentPanel = (
|
||||||
|
|
|
@ -3,7 +3,10 @@ import SubPanel from "components/Panels/SubPanel";
|
||||||
import ContentPanel, {
|
import ContentPanel, {
|
||||||
ContentPanelWidthSizes,
|
ContentPanelWidthSizes,
|
||||||
} from "components/Panels/ContentPanel";
|
} from "components/Panels/ContentPanel";
|
||||||
import { GetContentsQuery } from "graphql/operations-types";
|
import {
|
||||||
|
GetContentsQuery,
|
||||||
|
GetWebsiteInterfaceQuery,
|
||||||
|
} from "graphql/operations-types";
|
||||||
import { getContents } from "graphql/operations";
|
import { getContents } 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";
|
||||||
|
@ -12,6 +15,7 @@ import { prettyinlineTitle, prettySlug } from "queries/helpers";
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
import Select from "components/Select";
|
import Select from "components/Select";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
import Chip from "components/Chip";
|
||||||
|
|
||||||
interface ContentsProps extends AppStaticProps {
|
interface ContentsProps extends AppStaticProps {
|
||||||
contents: GetContentsQuery["contents"]["data"];
|
contents: GetContentsQuery["contents"]["data"];
|
||||||
|
@ -25,11 +29,11 @@ export default function Contents(props: ContentsProps): JSX.Element {
|
||||||
const [groupingMethod, setGroupingMethod] = useState<number>(-1);
|
const [groupingMethod, setGroupingMethod] = useState<number>(-1);
|
||||||
|
|
||||||
const [groups, setGroups] = useState<GroupContentItems>(
|
const [groups, setGroups] = useState<GroupContentItems>(
|
||||||
getGroups(groupingMethod, contents)
|
getGroups(langui, groupingMethod, contents)
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setGroups(getGroups(groupingMethod, contents));
|
setGroups(getGroups(langui, groupingMethod, contents));
|
||||||
}, [langui, groupingMethod, contents]);
|
}, [langui, groupingMethod, contents]);
|
||||||
|
|
||||||
const subPanel = (
|
const subPanel = (
|
||||||
|
@ -61,9 +65,14 @@ export default function Contents(props: ContentsProps): JSX.Element {
|
||||||
{name && (
|
{name && (
|
||||||
<h2
|
<h2
|
||||||
key={"h2" + name}
|
key={"h2" + name}
|
||||||
className="text-2xl pb-2 pt-10 first-of-type:pt-0"
|
className="text-2xl pb-2 pt-10 first-of-type:pt-0 flex flex-row place-items-center gap-2"
|
||||||
>
|
>
|
||||||
{name}
|
{name}
|
||||||
|
<Chip>{`${items.length} ${
|
||||||
|
items.length <= 1
|
||||||
|
? langui.result.toLowerCase()
|
||||||
|
: langui.results.toLowerCase()
|
||||||
|
}`}</Chip>
|
||||||
</h2>
|
</h2>
|
||||||
)}
|
)}
|
||||||
<div
|
<div
|
||||||
|
@ -127,6 +136,7 @@ export const getStaticProps: GetStaticProps = async (context) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
function getGroups(
|
function getGroups(
|
||||||
|
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"],
|
||||||
groupByType: number,
|
groupByType: number,
|
||||||
items: ContentsProps["contents"]
|
items: ContentsProps["contents"]
|
||||||
): GroupContentItems {
|
): GroupContentItems {
|
||||||
|
@ -150,11 +160,11 @@ function getGroups(
|
||||||
typeGroup.set("Bakuken", []);
|
typeGroup.set("Bakuken", []);
|
||||||
typeGroup.set("YoRHa", []);
|
typeGroup.set("YoRHa", []);
|
||||||
typeGroup.set("YoRHa Boys", []);
|
typeGroup.set("YoRHa Boys", []);
|
||||||
typeGroup.set("No category", []);
|
typeGroup.set(langui.no_category, []);
|
||||||
|
|
||||||
items.map((item) => {
|
items.map((item) => {
|
||||||
if (item.attributes.categories.data.length === 0) {
|
if (item.attributes.categories.data.length === 0) {
|
||||||
typeGroup.get("No category")?.push(item);
|
typeGroup.get(langui.no_category)?.push(item);
|
||||||
} else {
|
} else {
|
||||||
item.attributes.categories.data.map((category) => {
|
item.attributes.categories.data.map((category) => {
|
||||||
typeGroup.get(category.attributes.name)?.push(item);
|
typeGroup.get(category.attributes.name)?.push(item);
|
||||||
|
|
|
@ -218,13 +218,11 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{item.categories.data.length > 0 && (
|
{item.categories.data.length > 0 && (
|
||||||
<div>
|
<div className="flex flex-col place-items-center gap-2">
|
||||||
<h3 className="text-xl">{langui.categories}</h3>
|
<h3 className="text-xl">{langui.categories}</h3>
|
||||||
<div className="flex flex-row flex-wrap place-items-center place-content-start gap-2">
|
<div className="flex flex-row flex-wrap place-content-center gap-2">
|
||||||
{item.categories.data.map((category) => (
|
{item.categories.data.map((category) => (
|
||||||
<Chip key={category.id}>
|
<Chip key={category.id}>{category.attributes.name}</Chip>
|
||||||
{category.attributes.short}
|
|
||||||
</Chip>
|
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -17,6 +17,7 @@ import { useEffect, useState } from "react";
|
||||||
import { convertPrice, prettyDate, prettyinlineTitle } from "queries/helpers";
|
import { convertPrice, prettyDate, prettyinlineTitle } from "queries/helpers";
|
||||||
import Switch from "components/Switch";
|
import Switch from "components/Switch";
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
|
import Chip from "components/Chip";
|
||||||
|
|
||||||
interface LibraryProps extends AppStaticProps {
|
interface LibraryProps extends AppStaticProps {
|
||||||
items: GetLibraryItemsPreviewQuery["libraryItems"]["data"];
|
items: GetLibraryItemsPreviewQuery["libraryItems"]["data"];
|
||||||
|
@ -116,9 +117,14 @@ export default function Library(props: LibraryProps): JSX.Element {
|
||||||
{name && (
|
{name && (
|
||||||
<h2
|
<h2
|
||||||
key={"h2" + name}
|
key={"h2" + name}
|
||||||
className="text-2xl pb-2 pt-10 first-of-type:pt-0"
|
className="text-2xl pb-2 pt-10 first-of-type:pt-0 flex flex-row place-items-center gap-2"
|
||||||
>
|
>
|
||||||
{name}
|
{name}
|
||||||
|
<Chip>{`${items.length} ${
|
||||||
|
items.length <= 1
|
||||||
|
? langui.result.toLowerCase()
|
||||||
|
: langui.results.toLowerCase()
|
||||||
|
}`}</Chip>
|
||||||
</h2>
|
</h2>
|
||||||
)}
|
)}
|
||||||
<div
|
<div
|
||||||
|
@ -188,11 +194,11 @@ function getGroups(
|
||||||
typeGroup.set("Bakuken", []);
|
typeGroup.set("Bakuken", []);
|
||||||
typeGroup.set("YoRHa", []);
|
typeGroup.set("YoRHa", []);
|
||||||
typeGroup.set("YoRHa Boys", []);
|
typeGroup.set("YoRHa Boys", []);
|
||||||
typeGroup.set("No category", []);
|
typeGroup.set(langui.no_category, []);
|
||||||
|
|
||||||
items.map((item) => {
|
items.map((item) => {
|
||||||
if (item.attributes.categories.data.length === 0) {
|
if (item.attributes.categories.data.length === 0) {
|
||||||
typeGroup.get("No category")?.push(item);
|
typeGroup.get(langui.no_category)?.push(item);
|
||||||
} else {
|
} else {
|
||||||
item.attributes.categories.data.map((category) => {
|
item.attributes.categories.data.map((category) => {
|
||||||
typeGroup.get(category.attributes.name)?.push(item);
|
typeGroup.get(category.attributes.name)?.push(item);
|
||||||
|
|
|
@ -256,3 +256,20 @@ export function sortContent(
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function slugify(str: string): string {
|
||||||
|
return str
|
||||||
|
.replace(/[ÀÁÂÃÄÅàáâãäåæÆ]/g, "a")
|
||||||
|
.replace(/[çÇ]/g, "c")
|
||||||
|
.replace(/[ðÐ]/g, "d")
|
||||||
|
.replace(/[ÈÉÊËéèêë]/g, "e")
|
||||||
|
.replace(/[ÏïÎîÍíÌì]/g, "i")
|
||||||
|
.replace(/[Ññ]/g, "n")
|
||||||
|
.replace(/[øØœŒÕõÔôÓóÒò]/g, "o")
|
||||||
|
.replace(/[ÜüÛûÚúÙù]/g, "u")
|
||||||
|
.replace(/[ŸÿÝý]/g, "y")
|
||||||
|
.replace(/[^a-z0-9- ]/gi, "")
|
||||||
|
.trim()
|
||||||
|
.replace(/ /gi, "-")
|
||||||
|
.toLowerCase();
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue