Compare commits
	
		
			1 Commits
		
	
	
		
			main
			...
			rein-costu
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					5adae32429 | 
							
								
								
									
										27
									
								
								src/graphql/fragments/reinCostume.graphql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/graphql/fragments/reinCostume.graphql
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
			
		||||
fragment reinCostume on ReinCostume {
 | 
			
		||||
  slug
 | 
			
		||||
  sprite {
 | 
			
		||||
    data {
 | 
			
		||||
      attributes {
 | 
			
		||||
        ...uploadImage
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  translations {
 | 
			
		||||
    id
 | 
			
		||||
    language {
 | 
			
		||||
      data {
 | 
			
		||||
        attributes {
 | 
			
		||||
          code
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    name
 | 
			
		||||
    description
 | 
			
		||||
  }
 | 
			
		||||
  emblem {
 | 
			
		||||
    data {
 | 
			
		||||
      id
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								src/graphql/operations/getReinCostumes.graphql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/graphql/operations/getReinCostumes.graphql
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
			
		||||
query getReinCostumes {
 | 
			
		||||
  reinCostumes(pagination: { limit: -1 }) {
 | 
			
		||||
    data {
 | 
			
		||||
      id
 | 
			
		||||
      attributes {
 | 
			
		||||
        slug
 | 
			
		||||
        sprite {
 | 
			
		||||
          data {
 | 
			
		||||
            attributes {
 | 
			
		||||
              ...uploadImage
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        translations {
 | 
			
		||||
          id
 | 
			
		||||
          language {
 | 
			
		||||
            data {
 | 
			
		||||
              attributes {
 | 
			
		||||
                code
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          name
 | 
			
		||||
          description
 | 
			
		||||
        }
 | 
			
		||||
        emblem {
 | 
			
		||||
          data {
 | 
			
		||||
            id
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								src/graphql/operations/getReinCostumesWithoutEmblem.graphql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/graphql/operations/getReinCostumesWithoutEmblem.graphql
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
query getReinCostumesWithoutEmblem {
 | 
			
		||||
  reinCostumes(filters: { emblem: { id: { null: true } } }, pagination: { limit: -1 }) {
 | 
			
		||||
    data {
 | 
			
		||||
      id
 | 
			
		||||
      attributes {
 | 
			
		||||
        ...reinCostume
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								src/graphql/operations/getReinEmblem.graphql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/graphql/operations/getReinEmblem.graphql
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
			
		||||
query getReinEmblem($slug: String) {
 | 
			
		||||
  reinEmblems(filters: { slug: { eq: $slug } }) {
 | 
			
		||||
    data {
 | 
			
		||||
      id
 | 
			
		||||
      attributes {
 | 
			
		||||
        slug
 | 
			
		||||
        translations {
 | 
			
		||||
          id
 | 
			
		||||
          name
 | 
			
		||||
          description
 | 
			
		||||
          language {
 | 
			
		||||
            data {
 | 
			
		||||
              attributes {
 | 
			
		||||
                code
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        costumes {
 | 
			
		||||
          data {
 | 
			
		||||
            id
 | 
			
		||||
            attributes {
 | 
			
		||||
              ...reinCostume
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								src/graphql/operations/getReinEmblems.graphql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/graphql/operations/getReinEmblems.graphql
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
query getReinEmblems {
 | 
			
		||||
  reinEmblems(pagination: { limit: -1 }) {
 | 
			
		||||
    data {
 | 
			
		||||
      id
 | 
			
		||||
      attributes {
 | 
			
		||||
        slug
 | 
			
		||||
        translations {
 | 
			
		||||
          id
 | 
			
		||||
          name
 | 
			
		||||
          description
 | 
			
		||||
          language {
 | 
			
		||||
            data {
 | 
			
		||||
              attributes {
 | 
			
		||||
                code
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								src/graphql/operations/getReinEmblemsSlugs.graphql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/graphql/operations/getReinEmblemsSlugs.graphql
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
query getReinEmblemsSlugs {
 | 
			
		||||
  reinEmblems(pagination: { limit: -1 }) {
 | 
			
		||||
    data {
 | 
			
		||||
      id
 | 
			
		||||
      attributes {
 | 
			
		||||
        slug
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -167,6 +167,13 @@ const Wiki = (props: Props): JSX.Element => {
 | 
			
		||||
        onClick={closeSubPanel}
 | 
			
		||||
        border
 | 
			
		||||
      />
 | 
			
		||||
      <NavOption
 | 
			
		||||
        title={"Re[in]carnation"}
 | 
			
		||||
        subtitle={format("costume", { count: Infinity })}
 | 
			
		||||
        url="/wiki/rein/costumes"
 | 
			
		||||
        onClick={closeSubPanel}
 | 
			
		||||
        border
 | 
			
		||||
      />
 | 
			
		||||
    </SubPanel>
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										206
									
								
								src/pages/wiki/rein/costumes.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										206
									
								
								src/pages/wiki/rein/costumes.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,206 @@
 | 
			
		||||
import { GetStaticProps } from "next";
 | 
			
		||||
import { useCallback } from "react";
 | 
			
		||||
import Markdown from "markdown-to-jsx";
 | 
			
		||||
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
 | 
			
		||||
import { getFormat } from "helpers/i18n";
 | 
			
		||||
import { getOpenGraph } from "helpers/openGraph";
 | 
			
		||||
import { ReinCostume, ReinEmblemCostume } from "types/types";
 | 
			
		||||
import { getReadySdk } from "graphql/sdk";
 | 
			
		||||
import { filterHasAttributes, isDefinedAndNotEmpty, isUndefined } from "helpers/asserts";
 | 
			
		||||
import { ContentPanel, ContentPanelWidthSizes } from "components/Containers/ContentPanel";
 | 
			
		||||
import { TranslatedProps } from "types/TranslatedProps";
 | 
			
		||||
import { useSmartLanguage } from "hooks/useSmartLanguage";
 | 
			
		||||
import { prettySlug } from "helpers/formatters";
 | 
			
		||||
import { ElementsSeparator } from "helpers/component";
 | 
			
		||||
import { SubPanel } from "components/Containers/SubPanel";
 | 
			
		||||
import { ReturnButton } from "components/PanelComponents/ReturnButton";
 | 
			
		||||
import { useFormat } from "hooks/useFormat";
 | 
			
		||||
import { PanelHeader } from "components/PanelComponents/PanelHeader";
 | 
			
		||||
import { TranslatedNavOption } from "components/PanelComponents/NavOption";
 | 
			
		||||
import { Img } from "components/Img";
 | 
			
		||||
import { TranslatedPreviewCard } from "components/PreviewCard";
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *                                           ╭────────╮
 | 
			
		||||
 * ──────────────────────────────────────────╯  PAGE  ╰─────────────────────────────────────────────
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
interface Props extends AppLayoutRequired {
 | 
			
		||||
  emblems: ReinEmblemCostume[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const ReincarnationCostumes = ({ emblems, ...otherProps }: Props): JSX.Element => {
 | 
			
		||||
  const { format } = useFormat();
 | 
			
		||||
 | 
			
		||||
  const subPanel = (
 | 
			
		||||
    <SubPanel>
 | 
			
		||||
      <ElementsSeparator>
 | 
			
		||||
        {[
 | 
			
		||||
          <>
 | 
			
		||||
            <ReturnButton
 | 
			
		||||
              href="/wiki"
 | 
			
		||||
              title={format("wiki")}
 | 
			
		||||
              displayOnlyOn="3ColumnsLayout"
 | 
			
		||||
              className="mb-10"
 | 
			
		||||
            />
 | 
			
		||||
 | 
			
		||||
            <PanelHeader
 | 
			
		||||
              icon="accessibility_new"
 | 
			
		||||
              title={format("costume", { count: Infinity })}
 | 
			
		||||
              description={format("costume_description")}
 | 
			
		||||
            />
 | 
			
		||||
          </>,
 | 
			
		||||
 | 
			
		||||
          <>
 | 
			
		||||
            {emblems.map((emblem) => (
 | 
			
		||||
              <TranslatedNavOption
 | 
			
		||||
                key={emblem.id}
 | 
			
		||||
                translations={filterHasAttributes(emblem.attributes.translations, [
 | 
			
		||||
                  "language.data.attributes.code",
 | 
			
		||||
                ] as const).map((translation) => ({
 | 
			
		||||
                  language: translation.language.data.attributes.code,
 | 
			
		||||
                  title: translation.name,
 | 
			
		||||
                }))}
 | 
			
		||||
                fallback={{ title: prettySlug(emblem.attributes.slug) }}
 | 
			
		||||
                url={`#${emblem.attributes.slug}`}
 | 
			
		||||
              />
 | 
			
		||||
            ))}
 | 
			
		||||
          </>,
 | 
			
		||||
        ]}
 | 
			
		||||
      </ElementsSeparator>
 | 
			
		||||
    </SubPanel>
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  const contentPanel = (
 | 
			
		||||
    <ContentPanel width={ContentPanelWidthSizes.Full}>
 | 
			
		||||
      <div className="grid gap-12">
 | 
			
		||||
        <ElementsSeparator>
 | 
			
		||||
          {emblems.map((emblem) => (
 | 
			
		||||
            <TranslatedEmblemCostume
 | 
			
		||||
              key={emblem.id}
 | 
			
		||||
              translations={filterHasAttributes(emblem.attributes.translations, [
 | 
			
		||||
                "language.data.attributes.code",
 | 
			
		||||
              ] as const).map((translation) => ({
 | 
			
		||||
                language: translation.language.data.attributes.code,
 | 
			
		||||
                title: translation.name,
 | 
			
		||||
                description: translation.description,
 | 
			
		||||
              }))}
 | 
			
		||||
              fallback={{ title: prettySlug(emblem.attributes.slug) }}
 | 
			
		||||
              slug={emblem.attributes.slug}
 | 
			
		||||
              costumes={emblem.attributes.costumes}
 | 
			
		||||
            />
 | 
			
		||||
          ))}
 | 
			
		||||
        </ElementsSeparator>
 | 
			
		||||
      </div>
 | 
			
		||||
    </ContentPanel>
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  return <AppLayout subPanel={subPanel} contentPanel={contentPanel} {...otherProps} />;
 | 
			
		||||
};
 | 
			
		||||
export default ReincarnationCostumes;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *                                    ╭──────────────────────╮
 | 
			
		||||
 * ───────────────────────────────────╯  NEXT DATA FETCHING  ╰──────────────────────────────────────
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
  const sdk = getReadySdk();
 | 
			
		||||
  const { format } = getFormat(context.locale);
 | 
			
		||||
 | 
			
		||||
  const emblems = (await sdk.getReinEmblems()).reinEmblems?.data;
 | 
			
		||||
  const costumes = (await sdk.getReinCostumes()).reinCostumes?.data;
 | 
			
		||||
 | 
			
		||||
  if (isUndefined(emblems) || isUndefined(costumes)) {
 | 
			
		||||
    return { notFound: true };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const processedEmblems: ReinEmblemCostume[] = [];
 | 
			
		||||
 | 
			
		||||
  filterHasAttributes(emblems, ["id", "attributes"] as const).forEach(({ id, attributes }) => {
 | 
			
		||||
    const costumesOfCurrentEmblem = costumes.filter(
 | 
			
		||||
      (costume) => costume.attributes?.emblem?.data?.id === id
 | 
			
		||||
    );
 | 
			
		||||
    const emblemCostume: ReinEmblemCostume = {
 | 
			
		||||
      id,
 | 
			
		||||
      attributes: { ...attributes, costumes: costumesOfCurrentEmblem },
 | 
			
		||||
    };
 | 
			
		||||
    processedEmblems.push(emblemCostume);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const costumesWithoutEmblem = costumes.filter((costume) =>
 | 
			
		||||
    isUndefined(costume.attributes?.emblem?.data)
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  processedEmblems.push({
 | 
			
		||||
    id: "others",
 | 
			
		||||
    attributes: { slug: "others", costumes: costumesWithoutEmblem },
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const props: Props = {
 | 
			
		||||
    emblems: processedEmblems,
 | 
			
		||||
    openGraph: getOpenGraph(format, format("costume", { count: Infinity })),
 | 
			
		||||
  };
 | 
			
		||||
  return {
 | 
			
		||||
    props: props,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *                                    ╭──────────────────────╮
 | 
			
		||||
 * ───────────────────────────────────╯  PRIVATE COMPONENTS  ╰──────────────────────────────────────
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
interface EmblemCostumeProps {
 | 
			
		||||
  slug: string;
 | 
			
		||||
  title: string;
 | 
			
		||||
  description?: string;
 | 
			
		||||
  costumes: ReinCostume[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const EmblemCostume = ({ slug, title, description, costumes }: EmblemCostumeProps): JSX.Element => (
 | 
			
		||||
  <div>
 | 
			
		||||
    <h2 id={slug} className="text-2xl">
 | 
			
		||||
      {title}
 | 
			
		||||
    </h2>
 | 
			
		||||
    {isDefinedAndNotEmpty(description) && <Markdown>{description}</Markdown>}
 | 
			
		||||
    <div className="grid grid-cols-[repeat(auto-fill,_minmax(12rem,1fr))] items-end gap-x-6 gap-y-8">
 | 
			
		||||
      {costumes.map((costume) => (
 | 
			
		||||
        <TranslatedPreviewCard
 | 
			
		||||
          key={costume.id}
 | 
			
		||||
          translations={filterHasAttributes(costume.attributes?.translations, [
 | 
			
		||||
            "language.data.attributes.code",
 | 
			
		||||
          ] as const).map((translation) => ({
 | 
			
		||||
            language: translation.language.data.attributes.code,
 | 
			
		||||
            title: translation.name,
 | 
			
		||||
          }))}
 | 
			
		||||
          thumbnail={costume.attributes?.sprite?.data?.attributes}
 | 
			
		||||
          keepInfoVisible
 | 
			
		||||
          thumbnailAspectRatio="1/1"
 | 
			
		||||
          thumbnailForceAspectRatio
 | 
			
		||||
          thumbnailFitMethod="contain"
 | 
			
		||||
          fallback={{ title: prettySlug(costume.attributes?.slug) }}
 | 
			
		||||
          href="#"
 | 
			
		||||
        />
 | 
			
		||||
      ))}
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
export const TranslatedEmblemCostume = ({
 | 
			
		||||
  translations,
 | 
			
		||||
  fallback,
 | 
			
		||||
  ...otherProps
 | 
			
		||||
}: TranslatedProps<EmblemCostumeProps, "description" | "title">): JSX.Element => {
 | 
			
		||||
  const [selectedTranslation] = useSmartLanguage({
 | 
			
		||||
    items: translations,
 | 
			
		||||
    languageExtractor: useCallback((item: { language: string }): string => item.language, []),
 | 
			
		||||
  });
 | 
			
		||||
  return (
 | 
			
		||||
    <EmblemCostume
 | 
			
		||||
      title={selectedTranslation?.title ?? fallback.title}
 | 
			
		||||
      description={selectedTranslation?.description ?? fallback.description}
 | 
			
		||||
      {...otherProps}
 | 
			
		||||
    />
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										148
									
								
								src/pages/wiki/rein/emblems/[slug].tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								src/pages/wiki/rein/emblems/[slug].tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,148 @@
 | 
			
		||||
import { GetStaticPaths, GetStaticPathsResult, GetStaticProps } from "next";
 | 
			
		||||
import Markdown from "markdown-to-jsx";
 | 
			
		||||
import { useCallback } from "react";
 | 
			
		||||
import { getReadySdk } from "graphql/sdk";
 | 
			
		||||
import { filterHasAttributes, isDefined, isDefinedAndNotEmpty, isUndefined } from "helpers/asserts";
 | 
			
		||||
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
 | 
			
		||||
import { useFormat } from "hooks/useFormat";
 | 
			
		||||
import { GetReinEmblemQuery, ReinCostumeFragment } from "graphql/generated";
 | 
			
		||||
import { ContentPanel, ContentPanelWidthSizes } from "components/Containers/ContentPanel";
 | 
			
		||||
import { Img } from "components/Img";
 | 
			
		||||
import { TranslatedProps } from "types/TranslatedProps";
 | 
			
		||||
import { useSmartLanguage } from "hooks/useSmartLanguage";
 | 
			
		||||
import { prettySlug } from "helpers/formatters";
 | 
			
		||||
import { getFormat } from "helpers/i18n";
 | 
			
		||||
import { getOpenGraph } from "helpers/openGraph";
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *                                           ╭────────╮
 | 
			
		||||
 * ──────────────────────────────────────────╯  PAGE  ╰─────────────────────────────────────────────
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
interface Props extends AppLayoutRequired {
 | 
			
		||||
  emblem: NonNullable<
 | 
			
		||||
    NonNullable<NonNullable<GetReinEmblemQuery["reinEmblems"]>["data"][number]>["attributes"]
 | 
			
		||||
  >;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const ReinEmblem = ({ emblem, ...otherProps }: Props): JSX.Element => {
 | 
			
		||||
  const { format } = useFormat();
 | 
			
		||||
 | 
			
		||||
  const contentPanel = (
 | 
			
		||||
    <ContentPanel width={ContentPanelWidthSizes.Full}>
 | 
			
		||||
      <div>
 | 
			
		||||
        <TranslatedEmblemCostume
 | 
			
		||||
          translations={filterHasAttributes(emblem.translations, [
 | 
			
		||||
            "language.data.attributes.code",
 | 
			
		||||
          ] as const).map((translation) => ({
 | 
			
		||||
            language: translation.language.data.attributes.code,
 | 
			
		||||
            title: translation.name,
 | 
			
		||||
            description: translation.description,
 | 
			
		||||
          }))}
 | 
			
		||||
          fallback={{ title: prettySlug(emblem.slug) }}
 | 
			
		||||
          slug={emblem.slug}
 | 
			
		||||
          costumes={filterHasAttributes(emblem.costumes?.data, ["attributes"] as const).map(
 | 
			
		||||
            (costume) => costume.attributes
 | 
			
		||||
          )}
 | 
			
		||||
        />
 | 
			
		||||
      </div>
 | 
			
		||||
    </ContentPanel>
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  return <AppLayout contentPanel={contentPanel} {...otherProps} />;
 | 
			
		||||
};
 | 
			
		||||
export default ReinEmblem;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *                                    ╭──────────────────────╮
 | 
			
		||||
 * ───────────────────────────────────╯  NEXT DATA FETCHING  ╰──────────────────────────────────────
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
  const sdk = getReadySdk();
 | 
			
		||||
  const { format } = getFormat(context.locale);
 | 
			
		||||
 | 
			
		||||
  const slug =
 | 
			
		||||
    context.params && isDefined(context.params.slug) ? context.params.slug.toString() : "";
 | 
			
		||||
  const emblem = (await sdk.getReinEmblem({ slug })).reinEmblems?.data?.[0]?.attributes;
 | 
			
		||||
 | 
			
		||||
  if (isUndefined(emblem)) {
 | 
			
		||||
    return { notFound: true };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const props: Props = {
 | 
			
		||||
    emblem,
 | 
			
		||||
    openGraph: getOpenGraph(format, format("costume", { count: Infinity })),
 | 
			
		||||
  };
 | 
			
		||||
  return {
 | 
			
		||||
    props: props,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | 
			
		||||
 | 
			
		||||
export const getStaticPaths: GetStaticPaths = async (context) => {
 | 
			
		||||
  const sdk = getReadySdk();
 | 
			
		||||
  const contents = await sdk.getReinEmblemsSlugs();
 | 
			
		||||
  const paths: GetStaticPathsResult["paths"] = [];
 | 
			
		||||
  filterHasAttributes(contents.reinEmblems?.data, ["attributes"] as const).map((emblem) => {
 | 
			
		||||
    context.locales?.map((local) =>
 | 
			
		||||
      paths.push({
 | 
			
		||||
        params: { slug: emblem.attributes.slug },
 | 
			
		||||
        locale: local,
 | 
			
		||||
      })
 | 
			
		||||
    );
 | 
			
		||||
  });
 | 
			
		||||
  return {
 | 
			
		||||
    paths,
 | 
			
		||||
    fallback: "blocking",
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *                                    ╭──────────────────────╮
 | 
			
		||||
 * ───────────────────────────────────╯  PRIVATE COMPONENTS  ╰──────────────────────────────────────
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
interface EmblemCostumeProps {
 | 
			
		||||
  slug: string;
 | 
			
		||||
  title: string;
 | 
			
		||||
  description?: string;
 | 
			
		||||
  costumes: ReinCostumeFragment[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const EmblemCostume = ({ slug, title, description, costumes }: EmblemCostumeProps): JSX.Element => (
 | 
			
		||||
  <div>
 | 
			
		||||
    <h2 id={slug} className="text-2xl">
 | 
			
		||||
      {title}
 | 
			
		||||
    </h2>
 | 
			
		||||
    {isDefinedAndNotEmpty(description) && <Markdown>{description}</Markdown>}
 | 
			
		||||
    <div className="grid grid-cols-[repeat(auto-fill,_minmax(12rem,1fr))] items-start gap-x-6 gap-y-8">
 | 
			
		||||
      {costumes.map((costume) => (
 | 
			
		||||
        <div key={costume.slug}>
 | 
			
		||||
          {costume.sprite?.data?.attributes && <Img src={costume.sprite.data.attributes} />}
 | 
			
		||||
          <h3 className="text-xl">{costume.translations?.[0]?.name}</h3>
 | 
			
		||||
          <Markdown>{costume.translations?.[0]?.description ?? ""}</Markdown>
 | 
			
		||||
        </div>
 | 
			
		||||
      ))}
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
export const TranslatedEmblemCostume = ({
 | 
			
		||||
  translations,
 | 
			
		||||
  fallback,
 | 
			
		||||
  ...otherProps
 | 
			
		||||
}: TranslatedProps<EmblemCostumeProps, "description" | "title">): JSX.Element => {
 | 
			
		||||
  const [selectedTranslation] = useSmartLanguage({
 | 
			
		||||
    items: translations,
 | 
			
		||||
    languageExtractor: useCallback((item: { language: string }): string => item.language, []),
 | 
			
		||||
  });
 | 
			
		||||
  return (
 | 
			
		||||
    <EmblemCostume
 | 
			
		||||
      title={selectedTranslation?.title ?? fallback.title}
 | 
			
		||||
      description={selectedTranslation?.description ?? fallback.description}
 | 
			
		||||
      {...otherProps}
 | 
			
		||||
    />
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
@ -2,6 +2,8 @@ import {
 | 
			
		||||
  GetChronicleQuery,
 | 
			
		||||
  GetContentTextQuery,
 | 
			
		||||
  GetPostQuery,
 | 
			
		||||
  GetReinCostumesQuery,
 | 
			
		||||
  GetReinEmblemsQuery,
 | 
			
		||||
  GetWeaponQuery,
 | 
			
		||||
  GetWikiPageQuery,
 | 
			
		||||
} from "graphql/generated";
 | 
			
		||||
@ -68,6 +70,17 @@ export type WeaponGroupPreview = NonNullable<
 | 
			
		||||
 | 
			
		||||
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | 
			
		||||
 | 
			
		||||
type ReinEmblem = NonNullable<GetReinEmblemsQuery["reinEmblems"]>["data"][number];
 | 
			
		||||
 | 
			
		||||
export type ReinCostume = NonNullable<GetReinCostumesQuery["reinCostumes"]>["data"][number];
 | 
			
		||||
 | 
			
		||||
export type ReinEmblemCostume = {
 | 
			
		||||
  id: ReinEmblem["id"];
 | 
			
		||||
  attributes: NonNullable<ReinEmblem["attributes"]> & { costumes: ReinCostume[] };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | 
			
		||||
 | 
			
		||||
export enum LibraryItemUserStatus {
 | 
			
		||||
  None = 0,
 | 
			
		||||
  Want = 1,
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user