Content pages now display the table of content
This commit is contained in:
parent
6d3a9c84b3
commit
b213447c49
|
@ -2,10 +2,11 @@ import {
|
|||
GetContentQuery,
|
||||
GetWebsiteInterfaceQuery,
|
||||
} from "graphql/operations-types";
|
||||
import { prettySlug } from "queries/helpers";
|
||||
import { prettyinlineTitle, prettySlug, slugify } from "queries/helpers";
|
||||
import Button from "components/Button";
|
||||
import Img, { ImageQuality } from "components/Img";
|
||||
import InsetBox from "components/InsetBox";
|
||||
import Chip from "components/Chip";
|
||||
|
||||
export type ThumbnailHeaderProps = {
|
||||
content: {
|
||||
|
@ -39,7 +40,18 @@ export default function ThumbnailHeader(
|
|||
<div className="w-full aspect-[4/3] bg-light rounded-xl"></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 ? (
|
||||
<>
|
||||
<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">
|
||||
{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>
|
||||
<Button>
|
||||
{content.type.data.attributes.titles.length > 0
|
||||
? content.type.data.attributes.titles[0].title
|
||||
: prettySlug(content.type.data.attributes.slug)}
|
||||
</Button>
|
||||
<div className="flex flex-row flex-wrap">
|
||||
<Chip>
|
||||
{content.type.data.attributes.titles.length > 0
|
||||
? content.type.data.attributes.titles[0].title
|
||||
: prettySlug(content.type.data.attributes.slug)}
|
||||
</Chip>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{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>
|
||||
{content.categories.data.map((category) => (
|
||||
<Button key={category.id}>{category.attributes.name}</Button>
|
||||
))}
|
||||
<div className="flex flex-row flex-wrap place-content-center gap-2">
|
||||
{content.categories.data.map((category) => (
|
||||
<Chip key={category.id}>{category.attributes.name}</Chip>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
@ -117,6 +117,8 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
|||
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||
/>
|
||||
|
||||
{/*
|
||||
|
||||
<NavOption
|
||||
url="/wiki"
|
||||
icon="travel_explore"
|
||||
|
@ -136,6 +138,8 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
|||
reduced={appLayout.mainPanelReduced && isDesktop}
|
||||
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||
/>
|
||||
|
||||
*/}
|
||||
|
||||
<HorizontalLine />
|
||||
|
||||
|
@ -147,7 +151,7 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
|||
reduced={appLayout.mainPanelReduced && isDesktop}
|
||||
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||
/>
|
||||
|
||||
{/*
|
||||
<NavOption
|
||||
url="/merch"
|
||||
icon="store"
|
||||
|
@ -156,6 +160,8 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
|||
reduced={appLayout.mainPanelReduced && isDesktop}
|
||||
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||
/>
|
||||
|
||||
*/}
|
||||
|
||||
<NavOption
|
||||
url="/gallery"
|
||||
|
@ -166,6 +172,8 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
|||
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||
/>
|
||||
|
||||
{/*
|
||||
|
||||
<NavOption
|
||||
url="/archives"
|
||||
icon="inventory"
|
||||
|
@ -175,6 +183,9 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
|||
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||
/>
|
||||
|
||||
|
||||
*/}
|
||||
|
||||
<NavOption
|
||||
url="/about-us"
|
||||
icon="info"
|
||||
|
|
|
@ -26,6 +26,7 @@ import Chip from "components/Chip";
|
|||
import ReactTooltip from "react-tooltip";
|
||||
import RecorderChip from "components/RecorderChip";
|
||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||
import TOC from "components/Markdown/TOC";
|
||||
|
||||
interface ContentReadProps extends AppStaticProps {
|
||||
content: GetContentTextQuery["contents"]["data"][number]["attributes"];
|
||||
|
@ -141,6 +142,20 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
|
|||
)}
|
||||
</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>
|
||||
);
|
||||
const contentPanel = (
|
||||
|
|
|
@ -3,7 +3,10 @@ import SubPanel from "components/Panels/SubPanel";
|
|||
import ContentPanel, {
|
||||
ContentPanelWidthSizes,
|
||||
} from "components/Panels/ContentPanel";
|
||||
import { GetContentsQuery } from "graphql/operations-types";
|
||||
import {
|
||||
GetContentsQuery,
|
||||
GetWebsiteInterfaceQuery,
|
||||
} from "graphql/operations-types";
|
||||
import { getContents } from "graphql/operations";
|
||||
import PanelHeader from "components/PanelComponents/PanelHeader";
|
||||
import AppLayout from "components/AppLayout";
|
||||
|
@ -12,6 +15,7 @@ import { prettyinlineTitle, prettySlug } from "queries/helpers";
|
|||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||
import Select from "components/Select";
|
||||
import { useEffect, useState } from "react";
|
||||
import Chip from "components/Chip";
|
||||
|
||||
interface ContentsProps extends AppStaticProps {
|
||||
contents: GetContentsQuery["contents"]["data"];
|
||||
|
@ -25,11 +29,11 @@ export default function Contents(props: ContentsProps): JSX.Element {
|
|||
const [groupingMethod, setGroupingMethod] = useState<number>(-1);
|
||||
|
||||
const [groups, setGroups] = useState<GroupContentItems>(
|
||||
getGroups(groupingMethod, contents)
|
||||
getGroups(langui, groupingMethod, contents)
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setGroups(getGroups(groupingMethod, contents));
|
||||
setGroups(getGroups(langui, groupingMethod, contents));
|
||||
}, [langui, groupingMethod, contents]);
|
||||
|
||||
const subPanel = (
|
||||
|
@ -61,9 +65,14 @@ export default function Contents(props: ContentsProps): JSX.Element {
|
|||
{name && (
|
||||
<h2
|
||||
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}
|
||||
<Chip>{`${items.length} ${
|
||||
items.length <= 1
|
||||
? langui.result.toLowerCase()
|
||||
: langui.results.toLowerCase()
|
||||
}`}</Chip>
|
||||
</h2>
|
||||
)}
|
||||
<div
|
||||
|
@ -127,6 +136,7 @@ export const getStaticProps: GetStaticProps = async (context) => {
|
|||
};
|
||||
|
||||
function getGroups(
|
||||
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"],
|
||||
groupByType: number,
|
||||
items: ContentsProps["contents"]
|
||||
): GroupContentItems {
|
||||
|
@ -150,11 +160,11 @@ function getGroups(
|
|||
typeGroup.set("Bakuken", []);
|
||||
typeGroup.set("YoRHa", []);
|
||||
typeGroup.set("YoRHa Boys", []);
|
||||
typeGroup.set("No category", []);
|
||||
typeGroup.set(langui.no_category, []);
|
||||
|
||||
items.map((item) => {
|
||||
if (item.attributes.categories.data.length === 0) {
|
||||
typeGroup.get("No category")?.push(item);
|
||||
typeGroup.get(langui.no_category)?.push(item);
|
||||
} else {
|
||||
item.attributes.categories.data.map((category) => {
|
||||
typeGroup.get(category.attributes.name)?.push(item);
|
||||
|
|
|
@ -218,13 +218,11 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
|||
</div>
|
||||
|
||||
{item.categories.data.length > 0 && (
|
||||
<div>
|
||||
<div className="flex flex-col place-items-center gap-2">
|
||||
<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) => (
|
||||
<Chip key={category.id}>
|
||||
{category.attributes.short}
|
||||
</Chip>
|
||||
<Chip key={category.id}>{category.attributes.name}</Chip>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -17,6 +17,7 @@ import { useEffect, useState } from "react";
|
|||
import { convertPrice, prettyDate, prettyinlineTitle } from "queries/helpers";
|
||||
import Switch from "components/Switch";
|
||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||
import Chip from "components/Chip";
|
||||
|
||||
interface LibraryProps extends AppStaticProps {
|
||||
items: GetLibraryItemsPreviewQuery["libraryItems"]["data"];
|
||||
|
@ -116,9 +117,14 @@ export default function Library(props: LibraryProps): JSX.Element {
|
|||
{name && (
|
||||
<h2
|
||||
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}
|
||||
<Chip>{`${items.length} ${
|
||||
items.length <= 1
|
||||
? langui.result.toLowerCase()
|
||||
: langui.results.toLowerCase()
|
||||
}`}</Chip>
|
||||
</h2>
|
||||
)}
|
||||
<div
|
||||
|
@ -188,11 +194,11 @@ function getGroups(
|
|||
typeGroup.set("Bakuken", []);
|
||||
typeGroup.set("YoRHa", []);
|
||||
typeGroup.set("YoRHa Boys", []);
|
||||
typeGroup.set("No category", []);
|
||||
typeGroup.set(langui.no_category, []);
|
||||
|
||||
items.map((item) => {
|
||||
if (item.attributes.categories.data.length === 0) {
|
||||
typeGroup.get("No category")?.push(item);
|
||||
typeGroup.get(langui.no_category)?.push(item);
|
||||
} else {
|
||||
item.attributes.categories.data.map((category) => {
|
||||
typeGroup.get(category.attributes.name)?.push(item);
|
||||
|
|
|
@ -256,3 +256,20 @@ export function sortContent(
|
|||
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