diff --git a/next.config.js b/next.config.js
index 0249033..b38fa01 100644
--- a/next.config.js
+++ b/next.config.js
@@ -2,7 +2,10 @@
module.exports = {
reactStrictMode: true,
i18n: {
- locales: ['en', 'fr', 'jp', 'pt-br', 'pt-pt'],
+ locales: ['en', 'fr', 'ja', 'pt-br', 'pt-pt'],
defaultLocale: 'en',
- }
+ },
+ images: {
+ domains: ['strapi.accords-library.com'],
+ },
}
diff --git a/src/pages/chronology/overview.tsx b/src/pages/chronology/overview.tsx
index 59e9c3f..6c22034 100644
--- a/src/pages/chronology/overview.tsx
+++ b/src/pages/chronology/overview.tsx
@@ -1,49 +1,49 @@
-import type { NextPage } from "next";
import { GetStaticProps } from "next";
import ContentPanel from "components/Panels/ContentPanel";
import SubPanel from "components/Panels/SubPanel";
import ReturnButton from "components/Panels/ReturnButton";
import NavOption from "components/Panels/NavOption";
-import { getChronologyEras, getChronologyItems } from "queries/queries";
+import {
+ getChronologyItems,
+ getChronologyEras,
+ ChronologyItem,
+ ChronologyEra,
+} from "queries/chronology/overview";
-const ChronologyOverview: NextPage = (props) => {
+type Props = {
+ chronologyItems: ChronologyItem[];
+ chronologyEras: ChronologyEra[];
+};
+export default function ChronologyOverview(props: Props): JSX.Element {
return (
<>
-
-
- {props.chronologyEras.map((era: any) => (
+
+ {console.log(props.chronologyEras)}
+
+ {props.chronologyEras.map((era: ChronologyEra) => (
))}
-
-
- {props.chronologyItems.map((item: any) => (
-
- {item.year} - {" "}
- {item.translations[0].title}
-
- ))}
-
+
>
);
-};
-export default ChronologyOverview;
+}
export const getStaticProps: GetStaticProps = async (context) => {
return {
props: {
- chronologyItems: await getChronologyItems(context.locale),
+ /*chronologyItems: await getChronologyItems(context.locale),*/
chronologyEras: await getChronologyEras(context.locale),
},
};
diff --git a/src/pages/library.tsx b/src/pages/library.tsx
deleted file mode 100644
index 1185ab9..0000000
--- a/src/pages/library.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import type { NextPage } from "next";
-import Head from "next/head";
-
-const Home: NextPage = () => {
- return (
- <>
-
- Library
-
-
-
- >
- );
-};
-
-export default Home;
diff --git a/src/pages/library/[...slug].tsx b/src/pages/library/[...slug].tsx
new file mode 100644
index 0000000..78c369a
--- /dev/null
+++ b/src/pages/library/[...slug].tsx
@@ -0,0 +1,88 @@
+import { useRouter } from "next/router";
+import SubPanel from "components/Panels/SubPanel";
+import ContentPanel from "components/Panels/ContentPanel";
+import { getAssetURL } from "queries/helpers";
+import {
+ getLibraryItem,
+ getRecursiveSlugs,
+ LibraryItem,
+ Subitem,
+} from "queries/library/[...slug]";
+import Image from "next/image";
+import Link from "next/link";
+
+type Props = {
+ libraryItem: LibraryItem;
+};
+
+export default function Library(props: Props): JSX.Element {
+ const router = useRouter();
+ return (
+ <>
+
+ {props.libraryItem.title}
+ {props.libraryItem.subtitle}
+
+
+ {props.libraryItem.subitems.map((subitem: Subitem) => (
+
+
+ {subitem.subitem_id.thumbnail ? (
+
+ ) : (
+ ""
+ )}
+
+
+ ))}
+
+ >
+ );
+}
+
+export async function getStaticProps({ params }) {
+ return {
+ props: {
+ libraryItem: await getLibraryItem(params.slug),
+ },
+ };
+}
+
+export async function getStaticPaths() {
+ const paths = await getAllSlugs();
+
+ /*
+ paths.map((item) => {
+ console.log(item.params.slug);
+ });
+ */
+
+ return {
+ paths,
+ fallback: false,
+ };
+}
+
+async function getAllSlugs() {
+ return (await getRecursiveSlugs()).map((item) => {
+ return {
+ params: {
+ slug: item,
+ },
+ };
+ });
+}
diff --git a/src/pages/library/index.tsx b/src/pages/library/index.tsx
new file mode 100644
index 0000000..f48c642
--- /dev/null
+++ b/src/pages/library/index.tsx
@@ -0,0 +1,72 @@
+import { GetStaticProps } from "next";
+import SubPanel from "components/Panels/SubPanel";
+import ContentPanel from "components/Panels/ContentPanel";
+import { LibraryItem, getLibraryItems } from "queries/library/index";
+import { getAssetURL } from "queries/helpers";
+import Image from "next/image";
+import Link from "next/link";
+
+type Props = {
+ libraryItems: LibraryItem[];
+};
+
+export default function Library(props: Props): JSX.Element {
+ return (
+ <>
+
+ Library
+
+ A comprehensive list of all Yokoverse’s side materials (books,
+ novellas, artbooks, stage plays, manga, drama CDs, and comics). For
+ each, we provide photos and/or scans of the content, information about
+ what it is, when and how it was released, size, initial price…
+
+
+
+
+
+ {props.libraryItems.map((item: LibraryItem) => (
+
+
+
+ {item.subitem_of.length > 0
+ ? prettyTitleSubtitle(
+ item.subitem_of[0].item_id.title,
+ item.subitem_of[0].item_id.subtitle
+ ) + " • "
+ : ""}
+ {prettyTitleSubtitle(item.title, item.subtitle)}
+
+
{item.release_date}
+
+ {item.thumbnail ? (
+
+ ) : (
+ ""
+ )}
+
+
+ ))}
+
+ >
+ );
+}
+
+export const getStaticProps: GetStaticProps = async (context) => {
+ return {
+ props: {
+ libraryItems: await getLibraryItems(),
+ },
+ };
+};
+
+function prettyTitleSubtitle(title: string, subtitle: string): string {
+ let result = title;
+ if (subtitle !== null) result += " - " + subtitle;
+ return result;
+}
diff --git a/src/queries/chronology/overview.ts b/src/queries/chronology/overview.ts
new file mode 100644
index 0000000..f222860
--- /dev/null
+++ b/src/queries/chronology/overview.ts
@@ -0,0 +1,75 @@
+import { queryGraphQL } from "queries/helpers";
+
+export type ChronologyItem = {
+ id: string;
+ year: number;
+ month: number;
+ day: number;
+ translations: ChronologyItemsTranslation[];
+};
+
+export type ChronologyItemsTranslation = {
+ title: string;
+};
+
+export async function getChronologyItems(
+ languages_code: String | undefined
+): Promise {
+ return (
+ await queryGraphQL(
+ `
+ {
+ chronology_items {
+ id
+ year
+ month
+ day
+ translations(filter: { languages_code: { code: { _eq: "` + languages_code + `" } } }) {
+ title
+ }
+ }
+ }
+ `
+ )
+ ).chronology_items;
+}
+
+export type ChronologyEra = {
+ id: string;
+ attributes: ChronologyEraAttributes;
+};
+
+export type ChronologyEraAttributes = {
+ starting_year: number;
+ ending_year: number;
+ slug: string;
+ title: ChronologyEraTranslation[];
+}
+
+export type ChronologyEraTranslation = {
+ title: string;
+};
+
+export async function getChronologyEras(
+ language_code: String | undefined
+): Promise {
+ return (
+ await queryGraphQL(
+ `
+ {
+ chronologyEras {
+ data {
+ attributes {
+ starting_year
+ ending_year
+ title (filters: {language: {code: {eq: "` + language_code + `"}}}){
+ title
+ }
+ }
+ }
+ }
+ }
+ `
+ )
+ ).chronologyEras.data;
+}
diff --git a/src/queries/helpers.ts b/src/queries/helpers.ts
new file mode 100644
index 0000000..e79ecbf
--- /dev/null
+++ b/src/queries/helpers.ts
@@ -0,0 +1,49 @@
+/*
+export const queryGraphQL = async (query: string) => {
+ const res = await fetch(
+ process.env.URL_GRAPHQL +
+ "?access_token=" +
+ process.env.ACCESS_TOKEN +
+ "&query=" +
+ query
+ );
+ return (await res.json()).data;
+};
+*/
+
+export const queryGraphQL = async (query: String) => {
+ const res = await fetch(process.env.URL_GRAPHQL, {
+ method: "POST",
+ body: JSON.stringify({
+ query: query,
+ }),
+ headers: {
+ "content-type": "application/json",
+ Authorization: "Bearer " + process.env.ACCESS_TOKEN,
+ },
+ });
+ return (await res.json()).data;
+};
+
+
+export const queryGraphQLSystem = async (query: string) => {
+ const res = await fetch(
+ process.env.URL_GRAPHQL_SYSTEM +
+ "?access_token=" +
+ process.env.ACCESS_TOKEN +
+ "&query=" +
+ query
+ );
+ return (await res.json()).data;
+};
+
+export type AssetImage = {
+ id: string;
+ title: string;
+ width: number;
+ height: number;
+};
+
+export function getAssetURL(id: string): string {
+ return "https://cms.accords-library.com/assets/" + id;
+}
\ No newline at end of file
diff --git a/src/queries/library/[...slug].ts b/src/queries/library/[...slug].ts
new file mode 100644
index 0000000..6502910
--- /dev/null
+++ b/src/queries/library/[...slug].ts
@@ -0,0 +1,170 @@
+import { queryGraphQL, AssetImage } from "queries/helpers";
+
+export type LibraryItem = {
+ title: string;
+ subtitle: string;
+ slug: string;
+ thumbnail: AssetImage;
+ subitems: Subitem[];
+};
+
+export type Subitem = {
+ subitem_id: LibrarySubitem;
+};
+
+export type LibrarySubitem = {
+ id: string;
+ title: string;
+ subtitle: string;
+ slug: string;
+ thumbnail: AssetImage;
+};
+
+export async function getLibraryItem(slug: string[]) {
+ return (
+ await queryGraphQL(
+ `
+ {
+ compendium_items(filter: {_and: [` + getFilterForItem(slug) + `]}) {
+ title
+ subtitle
+ slug
+ thumbnail {
+ id
+ title
+ width
+ height
+ }
+ subitems {
+ subitem_id {
+ id
+ title
+ subtitle
+ slug
+ thumbnail {
+ id
+ title
+ width
+ height
+ }
+ }
+ }
+ }
+ }
+ `
+ )
+ ).compendium_items[0];
+}
+
+export async function getRecursiveSlugs() {
+ const yetToExploreSlugs = level0Filtering(
+ (
+ await queryGraphQL(
+ `
+ {
+ compendium_items(
+ filter: { _and: [{ not_sold_separately: { _eq: false } }] }
+ ) {
+ subitem_of {
+ item_id {
+ virtual_set
+ }
+ }
+ slug
+ }
+ }
+ `
+ )
+ ).compendium_items
+ );
+
+ const result: string[][] = [];
+ while (yetToExploreSlugs.length > 0) {
+ const slug = yetToExploreSlugs.pop();
+ if (slug !== undefined) {
+ const subitems = levelnFiltering((await queryGraphQL(
+ `
+ {
+ compendium_items(filter: {_and: [` + getFilterForSubitemsOf(slug) + `]}) {
+ slug
+ }
+ }
+ `
+ )
+ ).compendium_items
+ );
+ result.push(slug);
+ subitems.map((subitemSlug) => {
+ const newSlug = [...slug];
+ newSlug.push(subitemSlug);
+ yetToExploreSlugs.push(newSlug);
+ });
+ }
+ }
+ return result;
+}
+
+export function getFilterForSubitemsOf(slug: string[]) {
+ let filter = "";
+ slug.map((segment, index) => {
+ const depth = slug.length - index;
+ filter += "{ subitem_of: { item_id: ".repeat(depth);
+ filter += '{ slug: { _eq: "' + segment + '" } } ';
+ filter += "} } ".repeat(depth);
+ filter += ",";
+ });
+ return filter;
+}
+
+export function getFilterForItem(slug: string[]) {
+ let filter = "";
+ slug.map((segment, index) => {
+ const depth = slug.length - index - 1;
+ filter += "{ subitem_of: { item_id: ".repeat(depth);
+ filter += '{ slug: { _eq: "' + segment + '" } } ';
+ filter += "} } ".repeat(depth);
+ filter += ",";
+ });
+ return filter;
+}
+
+
+function level0Filtering(data: SlugLvl0[]): string[][] {
+ // Remove element if their parent item is a virtual_set
+ let result: string[][] = [];
+ data.map((item: SlugLvl0) => {
+ if (item.subitem_of.length > 0) {
+ if (item.subitem_of[0].item_id.virtual_set === false) {
+ result.push([item.slug]);
+ }
+ } else {
+ result.push([item.slug]);
+ }
+ });
+ return result;
+}
+
+function levelnFiltering(data: SlugLvln[]): string[] {
+ let result: string[] = [];
+ data.map((item: SlugLvln) => {
+ result.push(item.slug);
+ });
+ return result;
+}
+
+type SlugLvl0 = {
+ subitem_of: SlugLvl0Subitem_of[];
+ slug: string;
+};
+
+type SlugLvl0Subitem_of = {
+ item_id: SlugLvl0Subitem;
+};
+
+type SlugLvl0Subitem = {
+ virtual_set: boolean;
+};
+
+type SlugLvln = {
+ slug: string;
+};
diff --git a/src/queries/library/index.ts b/src/queries/library/index.ts
new file mode 100644
index 0000000..2915040
--- /dev/null
+++ b/src/queries/library/index.ts
@@ -0,0 +1,72 @@
+import { queryGraphQL, AssetImage } from "queries/helpers";
+
+export type LibraryItem = {
+ id: string;
+ subitem_of: Subitem_of[];
+ title: string;
+ subtitle: string;
+ slug: string;
+ thumbnail: AssetImage;
+ release_date: string;
+ type: "Text" | "Video" | "Games" | "Soundtrack" | "Audiobooks" | "Other";
+};
+
+export type Subitem_of = {
+ item_id: LibrarySubitem;
+};
+
+export type LibrarySubitem = {
+ title: string;
+ subtitle: string;
+ virtual_set: boolean;
+};
+
+export async function getLibraryItems() {
+ return filterGetLibraryItems((await queryGraphQL(
+ `
+ {
+ compendium_items(
+ filter: { _and: [{ not_sold_separately: { _eq: false } }] }
+ sort: "title"
+ ) {
+ id
+ subitem_of {
+ item_id {
+ title
+ subtitle
+ virtual_set
+ }
+ }
+ title
+ subtitle
+ slug
+ thumbnail {
+ id
+ title
+ width
+ height
+ }
+ release_date
+ type
+ }
+ }
+ `
+ )
+ ).compendium_items);
+}
+
+function filterGetLibraryItems(data: LibraryItem[]): LibraryItem[] {
+
+ // Remove element if their parent item is a virtual_set
+ let result: LibraryItem[] = [];
+ data.map((item: LibraryItem) => {
+ if (item.subitem_of.length > 0) {
+ if (item.subitem_of[0].item_id.virtual_set === false) {
+ result.push(item);
+ }
+ } else {
+ result.push(item);
+ }
+ });
+ return result;
+}
\ No newline at end of file
diff --git a/src/queries/queries.ts b/src/queries/queries.ts
deleted file mode 100644
index 04271df..0000000
--- a/src/queries/queries.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-export async function getChronologyItems(languages_code: String | undefined) {
- return (
- await queryCMS(
- `
- {
- chronology_items {
- id
- year
- month
- day
- translations(filter: { languages_code: { code: { _eq: "` + languages_code + `" } } }) {
- title
- }
- }
- }
- `
- )
- ).chronology_items;
-}
-
-export async function getChronologyEras(languages_code: String | undefined) {
- return (
- await queryCMS(
- `
- {
- chronology_eras(sort: "starting_year") {
- id
- starting_year
- ending_year
- translations(filter: { languages_code: { code: { _eq: "` + languages_code + `" } } }) {
- title
- }
- }
- }
- `
- )
- ).chronology_eras;
-}
-
-export const queryCMS = async (query: String) => {
- const res = await fetch(
- process.env.GRAPHQL +
- "?access_token=" +
- process.env.ACCESS_TOKEN +
- "&query=" +
- query
- );
- return (await res.json()).data;
-};