Skip to content

Commit

Permalink
Merge pull request #192 from NieR-Rein-Guide/feat-stories
Browse files Browse the repository at this point in the history
Add stories
  • Loading branch information
KeziahMoselle authored May 5, 2023
2 parents 1323477 + f734cf6 commit 85c47d7
Show file tree
Hide file tree
Showing 14 changed files with 1,094 additions and 92 deletions.
60 changes: 60 additions & 0 deletions databases/dump/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ model character {
name String?
image_path String?
debris_id Int?
character_stories Json?
ex_stories Json?
rod_stories Json?
hidden_stories Json?
debris debris? @relation(fields: [debris_id], references: [debris_id], onDelete: NoAction, onUpdate: NoAction, map: "fk_character_debris_debris_id")
character_rank_bonus character_rank_bonus[]
costume costume[]
Expand Down Expand Up @@ -360,3 +364,59 @@ model weapon_story_link {
@@id([weapon_id, weapon_story_id], map: "pk_weapon_story_link")
@@index([weapon_story_id], map: "ix_weapon_story_link_weapon_story_id")
}

model card_story {
id Int @id(map: "pk_card_story") @default(autoincrement())
name String?
stories Json?
}

model event {
id Int @id(map: "pk_event") @default(autoincrement())
name String?
image_path String?
start_date DateTime @db.Timestamptz(6)
end_date DateTime @db.Timestamptz(6)
stories Json?
}

model lost_archive {
id Int @id(map: "pk_lost_archive") @default(autoincrement())
name String?
number String?
order Int
story String?
image_path String?
}

model main_quest_chapter {
chapter_id Int
chapter_text_asset_id Int
route_id Int
chapter_number String?
chapter_title String?
order Decimal @db.Decimal
stories Json?
main_quest_route main_quest_route @relation(fields: [route_id], references: [route_id], onDelete: Cascade, onUpdate: NoAction, map: "fk_main_quest_chapter_main_quest_route_route_id")
@@id([chapter_id, chapter_text_asset_id], map: "pk_main_quest_chapter")
@@index([route_id], map: "ix_main_quest_chapter_route_id")
}

model main_quest_route {
route_id Int @id(map: "pk_main_quest_route") @default(autoincrement())
season_id Int
route_name String?
order Int
main_quest_chapter main_quest_chapter[]
main_quest_season main_quest_season @relation(fields: [season_id], references: [season_id], onDelete: Cascade, onUpdate: NoAction, map: "fk_main_quest_route_main_quest_season_season_id")
@@index([season_id], map: "ix_main_quest_route_season_id")
}

model main_quest_season {
season_id Int @id(map: "pk_main_quest_season") @default(autoincrement())
season_name String?
order Int
main_quest_route main_quest_route[]
}
92 changes: 92 additions & 0 deletions src/components/Layout/StoriesLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import Link from "next/link";
import classNames from "classnames";
import { useRouter } from "next/router";

const ITEMS = [
{
label: "Main story",
href: "/database/stories/main",
},
{
label: "Characters",
href: "/database/stories/characters",
},
{
label: "EX characters",
href: "/database/stories/ex-characters",
},
{
label: "Recollections of Dusk",
href: "/database/stories/rod-characters",
},
{
label: "Events",
href: "/database/stories/events",
},
{
label: "Anecdotes",
href: "/database/stories/anecdotes",
},
{
label: "Hidden stories",
href: "/database/stories/hidden-stories",
disabled: true,
},
{
label: "Lost archives",
href: "/database/stories/lost-archives",
},
{
label: "Costumes",
href: "/database/stories/costumes",
},
{
label: "Weapons",
href: "/database/stories/weapons",
},
{
label: "Companions",
href: "/database/stories/companions",
},
{
label: "Memoirs",
href: "/database/stories/memoirs",
},
];

export default function StoriesLayout({ children }): JSX.Element {
const router = useRouter();

return (
<div className="grid grid-cols-1 lg:grid-cols-12 gap-4">
<aside className="col-span-1 flex flex-col mb-8 lg:col-span-3 lg:mb-0">
{ITEMS.map((item) => (
<Link
key={item.label}
href={item.href}
className={classNames(
"flex items-center justify-center text-center p-4 transition-colors ease-out-cubic relative bordered",
item.disabled ? "pointer-events-none opacity-40" : "",
router.asPath.includes(item.href)
? "active bg-beige active"
: "bg-grey-lighter"
)}
>
<span
className={classNames(
"font-display font-bold text-xl tracking-wider transition-colors ease-out-cubic",
router.asPath.includes(item.href)
? "text-grey-lighter"
: "text-beige"
)}
>
{item.label}
</span>
</Link>
))}
</aside>

<div className="col-span-1 lg:col-span-9">{children}</div>
</div>
);
}
102 changes: 102 additions & 0 deletions src/pages/database/stories/anecdotes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import Layout from "@components/Layout";
import Meta from "@components/Meta";
import Link from "next/link";
import SVG from "react-inlinesvg";
import prisma from "@libs/prisma";
import { card_story } from "@prisma/client";
import { CDN_URL } from "@config/constants";
import { useState } from "react";
import { FormControl, InputLabel, MenuItem, Select } from "@mui/material";
import Squares from "@components/decorations/Squares";
import StoriesLayout from "@components/Layout/StoriesLayout";

interface Props {
anecdotes: card_story[];
}

export default function DatabaseStories({ anecdotes }: Props): JSX.Element {
const [anecdoteIndex, setAnecdoteIndex] = useState(anecdotes[0].id);

return (
<Layout>
<Meta
title="Anecdotes stories - Database"
description="Anecdotes stories"
cover="https://nierrein.guide/cover-stories.jpg"
/>

<nav className="mb-16">
<Link href="/database" passHref={true} className="btn">
<SVG src="/decorations/arrow-left.svg" className="h-6" />
<span>Return to Database</span>
</Link>
</nav>

<StoriesLayout>
<div className="relative">
<div className="flex items-center gap-y-4 gap-x-4 bg-grey-dark border border-beige border-opacity-50 p-4 mb-8">
<FormControl className="flex-1">
<InputLabel id="season-index">Anecdote</InputLabel>
<Select
labelId="season-index"
value={anecdoteIndex}
label="Type"
onChange={(e) => {
setAnecdoteIndex(e.target.value);
}}
>
{anecdotes.map((anecdote) => (
<MenuItem
className="flex items-center justify-between"
key={anecdote.id}
value={anecdote.id}
>
<span>{anecdote.name}</span>
</MenuItem>
))}
</Select>
</FormControl>
</div>

<article className="relative bordered bg-grey-dark p-4 rounded-lg">
<Squares />
{anecdotes
.filter((anecdote) => anecdote.id === anecdoteIndex)
.map((anecdote) => (
<div key={anecdote.id}>
{anecdote.stories.map(({ story, image_path }, index) => (
<div key={index} className="my-4">
<img
className="mb-4"
src={`${CDN_URL}${image_path}`}
alt={`Story ${index + 1} image`}
loading="lazy"
/>
<p
className="whitespace-pre-wrap mb-4 pl-4"
dangerouslySetInnerHTML={{
__html: story,
}}
></p>
</div>
))}
</div>
))}
</article>
</div>
</StoriesLayout>
</Layout>
);
}

export async function getStaticProps() {
const anecdotes = await prisma.dump.card_story.findMany();

return {
props: JSON.parse(
JSON.stringify({
anecdotes,
})
),
};
}
107 changes: 107 additions & 0 deletions src/pages/database/stories/characters.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import Layout from "@components/Layout";
import Meta from "@components/Meta";
import Link from "next/link";
import SVG from "react-inlinesvg";
import prisma from "@libs/prisma";
import { character } from "@prisma/client";
import { CDN_URL } from "@config/constants";
import { useState } from "react";
import { FormControl, InputLabel, MenuItem, Select } from "@mui/material";
import Squares from "@components/decorations/Squares";
import StoriesLayout from "@components/Layout/StoriesLayout";

interface Props {
characters: character[];
}

export default function DatabaseStories({ characters }: Props): JSX.Element {
const [characterIndex, setCharacterIndex] = useState(
characters[0].character_id
);

return (
<Layout>
<Meta
title="Characters stories - Database"
description="Characters stories"
cover="https://nierrein.guide/cover-stories.jpg"
/>

<nav className="mb-16">
<Link href="/database" passHref={true} className="btn">
<SVG src="/decorations/arrow-left.svg" className="h-6" />
<span>Return to Database</span>
</Link>
</nav>

<StoriesLayout>
<div className="relative">
<div className="flex items-center gap-y-4 gap-x-4 bg-grey-dark border border-beige border-opacity-50 p-4 mb-8">
<FormControl className="flex-1">
<InputLabel id="season-index">Character</InputLabel>
<Select
labelId="season-index"
value={characterIndex}
label="Type"
onChange={(e) => {
setCharacterIndex(e.target.value);
}}
>
{characters.map((character) => (
<MenuItem
key={character.character_id}
value={character.character_id}
>
{character.name}
</MenuItem>
))}
</Select>
</FormControl>
</div>

<article className="relative bordered bg-grey-dark p-4 rounded-lg">
<Squares />
{characters
.filter((character) => character.character_id === characterIndex)
.map((character) => (
<div key={character.character_id}>
{character.character_stories.map(
({ story, image_path }, index) => (
<div key={index} className="my-4">
<img
className="mb-4"
src={`${CDN_URL}${image_path}`}
alt={`Story ${index + 1} image`}
loading="lazy"
/>
<p
className="whitespace-pre-wrap mb-4 pl-4"
dangerouslySetInnerHTML={{
__html: story,
}}
></p>
</div>
)
)}
</div>
))}
</article>
</div>
</StoriesLayout>
</Layout>
);
}

export async function getStaticProps() {
const characters = await prisma.dump.character.findMany();

return {
props: JSON.parse(
JSON.stringify({
characters: characters.filter(
(character) => character.character_stories.length > 0
),
})
),
};
}
Loading

0 comments on commit 85c47d7

Please sign in to comment.