Lots of things including Chronicles
This commit is contained in:
		
							parent
							
								
									9fe7a777ff
								
							
						
					
					
						commit
						5edc2d7f27
					
				| @ -79,7 +79,7 @@ module.exports = { | ||||
|     "no-lone-blocks": "warn", | ||||
|     "no-lonely-if": "warn", | ||||
|     // "no-magic-numbers": "warn",
 | ||||
|     "no-mixed-operators": "warn", | ||||
|     // "no-mixed-operators": "warn",
 | ||||
|     "no-multi-assign": "warn", | ||||
|     "no-multi-str": "warn", | ||||
|     "no-negated-condition": "warn", | ||||
| @ -228,7 +228,7 @@ module.exports = { | ||||
|     // "import/no-internal-modules": "error",
 | ||||
|     "import/no-webpack-loader-syntax": "error", | ||||
|     "import/no-self-import": "error", | ||||
|     "import/no-cycle": "error", | ||||
|     // "import/no-cycle": "error",
 | ||||
|     "import/no-useless-path-segments": "error", | ||||
|     // "import/no-relative-parent-imports": "error",
 | ||||
|     "import/no-relative-packages": "error", | ||||
|  | ||||
							
								
								
									
										1
									
								
								public/icons/twitter-brands.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								public/icons/twitter-brands.svg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.1.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg> | ||||
| After Width: | Height: | Size: 1.0 KiB | 
							
								
								
									
										65
									
								
								src/components/Chronicles/ChroniclePreview.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/components/Chronicles/ChroniclePreview.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,65 @@ | ||||
| import Link from "next/link"; | ||||
| import { DatePickerFragment } from "graphql/generated"; | ||||
| import { cIf, cJoin } from "helpers/className"; | ||||
| 
 | ||||
| /* | ||||
|  *                                        ╭─────────────╮ | ||||
|  * ───────────────────────────────────────╯  COMPONENT  ╰─────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props { | ||||
|   date: DatePickerFragment; | ||||
|   title: string; | ||||
|   url: string; | ||||
|   isActive?: boolean; | ||||
| } | ||||
| 
 | ||||
| export const ChroniclePreview = ({ | ||||
|   date, | ||||
|   url, | ||||
|   title, | ||||
|   isActive, | ||||
| }: Props): JSX.Element => ( | ||||
|   <Link href={url}> | ||||
|     <div | ||||
|       className={cJoin( | ||||
|         `flex w-full cursor-pointer gap-4 rounded-2xl py-4 px-5
 | ||||
|          text-left align-top outline outline-2 outline-offset-[-2px] outline-mid transition-all | ||||
|          hover:bg-mid hover:shadow-inner-sm hover:shadow-shade | ||||
|          hover:outline-[transparent] hover:active:shadow-inner hover:active:shadow-shade`,
 | ||||
|         cIf( | ||||
|           isActive, | ||||
|           "bg-mid shadow-inner-sm shadow-shade outline-[transparent]" | ||||
|         ) | ||||
|       )} | ||||
|     > | ||||
|       <div className="text-right"> | ||||
|         <p>{date.year}</p> | ||||
|         <p className="text-sm text-dark"> | ||||
|           {prettyMonthDay(date.month, date.day)} | ||||
|         </p> | ||||
|       </div> | ||||
|       <p className="text-lg leading-tight">{title}</p> | ||||
|     </div> | ||||
|   </Link> | ||||
| ); | ||||
| 
 | ||||
| /* | ||||
|  *                                      ╭───────────────────╮ | ||||
|  * ─────────────────────────────────────╯  PRIVATE METHODS  ╰─────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| const prettyMonthDay = ( | ||||
|   month?: number | null | undefined, | ||||
|   day?: number | null | undefined | ||||
| ): string => { | ||||
|   let result = ""; | ||||
|   if (month) { | ||||
|     result += month.toString().padStart(2, "0"); | ||||
|     if (day) { | ||||
|       result += "/"; | ||||
|       result += day.toString().padStart(2, "0"); | ||||
|     } | ||||
|   } | ||||
|   return result; | ||||
| }; | ||||
							
								
								
									
										112
									
								
								src/components/Chronicles/ChroniclesList.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								src/components/Chronicles/ChroniclesList.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,112 @@ | ||||
| import { GetChroniclesChaptersQuery } from "graphql/generated"; | ||||
| import { filterHasAttributes } from "helpers/others"; | ||||
| import { TranslatedChroniclePreview } from "components/Translated"; | ||||
| import { prettyinlineTitle, prettySlug } from "helpers/formatters"; | ||||
| import { Ico, Icon } from "components/Ico"; | ||||
| import { useBoolean } from "hooks/useBoolean"; | ||||
| import { compareDate } from "helpers/date"; | ||||
| 
 | ||||
| /* | ||||
|  *                                        ╭─────────────╮ | ||||
|  * ───────────────────────────────────────╯  COMPONENT  ╰─────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props { | ||||
|   chronicles: NonNullable< | ||||
|     NonNullable< | ||||
|       NonNullable< | ||||
|         GetChroniclesChaptersQuery["chroniclesChapters"] | ||||
|       >["data"][number]["attributes"] | ||||
|     >["chronicles"] | ||||
|   >["data"]; | ||||
|   currentSlug?: string; | ||||
|   title: string; | ||||
| } | ||||
| 
 | ||||
| export const ChroniclesList = ({ | ||||
|   chronicles, | ||||
|   currentSlug, | ||||
|   title, | ||||
| }: Props): JSX.Element => { | ||||
|   const { state: isOpen, toggleState: toggleOpen } = useBoolean(false); | ||||
| 
 | ||||
|   return ( | ||||
|     <div> | ||||
|       <div className="grid place-content-center"> | ||||
|         <div | ||||
|           className="grid cursor-pointer grid-cols-[1em_1fr] gap-4" | ||||
|           onClick={toggleOpen} | ||||
|         > | ||||
|           <Ico | ||||
|             className="!text-xl" | ||||
|             icon={isOpen ? Icon.ArrowDropUp : Icon.ArrowDropDown} | ||||
|           /> | ||||
|           <p className="mb-4 font-headers text-xl">{title}</p> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div | ||||
|         className="grid gap-4 overflow-hidden transition-[max-height]" | ||||
|         style={{ maxHeight: isOpen ? `${8 * chronicles.length}rem` : 0 }} | ||||
|       > | ||||
|         {filterHasAttributes(chronicles, [ | ||||
|           "attributes.contents", | ||||
|           "attributes.translations", | ||||
|         ] as const) | ||||
|           .sort((a, b) => | ||||
|             compareDate(a.attributes.date_start, b.attributes.date_start) | ||||
|           ) | ||||
|           .map((chronicle) => ( | ||||
|             <div | ||||
|               key={chronicle.id} | ||||
|               id={`chronicle-${chronicle.attributes.slug}`} | ||||
|               className="scroll-m-[45vh]" | ||||
|             > | ||||
|               {chronicle.attributes.translations.length === 0 && | ||||
|               chronicle.attributes.contents.data.length === 1 | ||||
|                 ? filterHasAttributes(chronicle.attributes.contents.data, [ | ||||
|                     "attributes.translations", | ||||
|                   ] as const).map((content, index) => ( | ||||
|                     <TranslatedChroniclePreview | ||||
|                       key={index} | ||||
|                       isActive={chronicle.attributes.slug === currentSlug} | ||||
|                       date={chronicle.attributes.date_start} | ||||
|                       translations={filterHasAttributes( | ||||
|                         content.attributes.translations, | ||||
|                         ["language.data.attributes.code"] as const | ||||
|                       ).map((translation) => ({ | ||||
|                         title: prettyinlineTitle( | ||||
|                           translation.pre_title, | ||||
|                           translation.title, | ||||
|                           translation.subtitle | ||||
|                         ), | ||||
|                         language: translation.language.data.attributes.code, | ||||
|                       }))} | ||||
|                       fallback={{ | ||||
|                         title: prettySlug(chronicle.attributes.slug), | ||||
|                       }} | ||||
|                       url={`/chronicles/${chronicle.attributes.slug}/#chronicle-${chronicle.attributes.slug}`} | ||||
|                     /> | ||||
|                   )) | ||||
|                 : chronicle.attributes.translations.length > 0 && ( | ||||
|                     <TranslatedChroniclePreview | ||||
|                       date={chronicle.attributes.date_start} | ||||
|                       isActive={chronicle.attributes.slug === currentSlug} | ||||
|                       translations={filterHasAttributes( | ||||
|                         chronicle.attributes.translations, | ||||
|                         ["language.data.attributes.code", "title"] as const | ||||
|                       ).map((translation) => ({ | ||||
|                         title: translation.title, | ||||
|                         language: translation.language.data.attributes.code, | ||||
|                       }))} | ||||
|                       fallback={{ | ||||
|                         title: prettySlug(chronicle.attributes.slug), | ||||
|                       }} | ||||
|                       url={`/chronicles/${chronicle.attributes.slug}/#chronicle-${chronicle.attributes.slug}`} | ||||
|                     /> | ||||
|                   )} | ||||
|             </div> | ||||
|           ))} | ||||
|       </div> | ||||
|     </div> | ||||
|   ); | ||||
| }; | ||||
| @ -64,13 +64,14 @@ export const Button = ({ | ||||
|           id={id} | ||||
|           onClick={onClick} | ||||
|           className={cJoin( | ||||
|             `group grid cursor-pointer select-none grid-flow-col
 | ||||
|             place-content-center place-items-center gap-2 rounded-full border-[1px] border-dark py-3 px-4 | ||||
|             `group grid cursor-pointer select-none grid-flow-col place-content-center 
 | ||||
|             place-items-center gap-2 rounded-full border-[1px] border-dark py-3 px-4 | ||||
|             leading-none text-dark transition-all`,
 | ||||
|             cIf( | ||||
|               active, | ||||
|               "!border-black bg-black !text-light drop-shadow-black-lg", | ||||
|               "hover:bg-dark hover:text-light hover:drop-shadow-shade-lg" | ||||
|               `hover:bg-dark hover:text-light hover:drop-shadow-shade-lg active:hover:!border-black
 | ||||
|               active:hover:bg-black active:hover:!text-light active:hover:drop-shadow-black-lg` | ||||
|             ), | ||||
|             cIf(size === "small", "px-3 py-1 text-xs"), | ||||
|             className | ||||
|  | ||||
| @ -199,7 +199,7 @@ export const Markdawn = ({ | ||||
|             Line: { | ||||
|               component: (compProps) => ( | ||||
|                 <> | ||||
|                   <strong className="text-dark/60 mobile:!-mb-4 !my-0"> | ||||
|                   <strong className="!my-0 text-dark/60 mobile:!-mb-4"> | ||||
|                     <Markdawn text={compProps.name} /> | ||||
|                   </strong> | ||||
|                   <p className="whitespace-pre-line">{compProps.children}</p> | ||||
| @ -440,8 +440,6 @@ const preprocessMarkDawn = (text: string, playerName = ""): string => { | ||||
|         : "(player)" | ||||
|     ); | ||||
| 
 | ||||
|   console.log(); | ||||
| 
 | ||||
|   let scenebreakIndex = 0; | ||||
|   const visitedSlugs: string[] = []; | ||||
| 
 | ||||
|  | ||||
| @ -132,7 +132,6 @@ export const MainPanel = ({ langui }: Props): JSX.Element => { | ||||
|         reduced={mainPanelReduced && isDesktop} | ||||
|       /> | ||||
| 
 | ||||
|       {/* | ||||
|       <NavOption | ||||
|         url="/chronicles" | ||||
|         icon={Icon.WatchLater} | ||||
| @ -140,7 +139,6 @@ export const MainPanel = ({ langui }: Props): JSX.Element => { | ||||
|         subtitle={langui.chronicles_short_description} | ||||
|         reduced={mainPanelReduced && isDesktop} | ||||
|       /> | ||||
|       */} | ||||
| 
 | ||||
|       <HorizontalLine /> | ||||
| 
 | ||||
| @ -232,6 +230,15 @@ export const MainPanel = ({ langui }: Props): JSX.Element => { | ||||
|             target="_blank" | ||||
|             rel="noopener noreferrer" | ||||
|           ></a> | ||||
|           <a | ||||
|             aria-label="Follow us on Twitter" | ||||
|             className="aspect-square w-10 | ||||
|               bg-black transition-colors [mask:url('/icons/twitter-brands.svg')] | ||||
|               ![mask-size:contain] ![mask-repeat:no-repeat] ![mask-position:center] hover:bg-dark" | ||||
|             href="https://twitter.com/AccordsLibrary" | ||||
|             target="_blank" | ||||
|             rel="noopener noreferrer" | ||||
|           ></a> | ||||
|           <a | ||||
|             aria-label="Join our Discord server!" | ||||
|             className="aspect-square w-10 | ||||
|  | ||||
| @ -276,7 +276,10 @@ export const PreviewCard = ({ | ||||
|           </div> | ||||
|           {description && <p>{description}</p>} | ||||
|           {bottomChips && bottomChips.length > 0 && ( | ||||
|             <div className="grid grid-flow-col place-content-start gap-1 overflow-hidden"> | ||||
|             <div | ||||
|               className="grid grid-flow-col place-content-start gap-1 overflow-x-scroll | ||||
|               [scrollbar-width:none] webkit-scrollbar:w-0" | ||||
|             > | ||||
|               {bottomChips.map((text, index) => ( | ||||
|                 <Chip key={index} className="text-sm" text={text} /> | ||||
|               ))} | ||||
|  | ||||
| @ -39,7 +39,11 @@ export const PreviewLine = ({ | ||||
|     > | ||||
|       {thumbnail ? ( | ||||
|         <div className="aspect-[3/2] h-full"> | ||||
|           <Img className="h-full object-cover" image={thumbnail} quality={ImageQuality.Medium} /> | ||||
|           <Img | ||||
|             className="h-full object-cover" | ||||
|             image={thumbnail} | ||||
|             quality={ImageQuality.Medium} | ||||
|           /> | ||||
|         </div> | ||||
|       ) : ( | ||||
|         <div style={{ aspectRatio: thumbnailAspectRatio }}></div> | ||||
|  | ||||
| @ -25,6 +25,7 @@ interface Props<T> { | ||||
|   // Grouping
 | ||||
|   groupingFunction?: (item: T) => string[]; | ||||
|   groupSortingFunction?: (a: string, b: string) => number; | ||||
|   groupCountingFunction?: (item: T) => number; | ||||
|   // Filtering
 | ||||
|   filteringFunction?: (item: T) => boolean; | ||||
|   // Sorting
 | ||||
| @ -48,6 +49,7 @@ export const SmartList = <T,>({ | ||||
|   searchingCaseInsensitive = true, | ||||
|   groupingFunction = () => [""], | ||||
|   groupSortingFunction = (a, b) => a.localeCompare(b), | ||||
|   groupCountingFunction = () => 1, | ||||
|   filteringFunction = () => true, | ||||
|   sortingFunction = () => 0, | ||||
|   className, | ||||
| @ -159,7 +161,10 @@ export const SmartList = <T,>({ | ||||
|                     > | ||||
|                       {name} | ||||
|                       <Chip | ||||
|                         text={`${groupItems.length} ${ | ||||
|                         text={`${groupItems.reduce( | ||||
|                           (acc, item) => acc + groupCountingFunction(item), | ||||
|                           0 | ||||
|                         )} ${ | ||||
|                           groupItems.length <= 1 | ||||
|                             ? langui.result?.toLowerCase() ?? "" | ||||
|                             : langui.results?.toLowerCase() ?? "" | ||||
|  | ||||
| @ -2,13 +2,13 @@ import { PreviewCard } from "./PreviewCard"; | ||||
| import { PreviewLine } from "./PreviewLine"; | ||||
| import { ScanSet } from "./Library/ScanSet"; | ||||
| import { NavOption } from "./PanelComponents/NavOption"; | ||||
| import { AppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { ChroniclePreview } from "./Chronicles/ChroniclePreview"; | ||||
| import { ChroniclesList } from "./Chronicles/ChroniclesList"; | ||||
| import { useSmartLanguage } from "hooks/useSmartLanguage"; | ||||
| 
 | ||||
| type TranslatedProps<P, K extends keyof P> = Omit<P, K> & { | ||||
|   translations: (Pick<P, K> & { language: string })[]; | ||||
|   fallback: Pick<P, K>; | ||||
|   languages: AppStaticProps["languages"]; | ||||
| }; | ||||
| 
 | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| @ -18,18 +18,18 @@ type TranslatedPreviewCardProps = TranslatedProps< | ||||
|   "description" | "pre_title" | "subtitle" | "title" | ||||
| >; | ||||
| 
 | ||||
| const languageExtractor = (item: { language: string }): string => item.language; | ||||
| 
 | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| 
 | ||||
| export const TranslatedPreviewCard = ({ | ||||
|   translations, | ||||
|   languages, | ||||
|   fallback, | ||||
|   ...otherProps | ||||
| }: TranslatedPreviewCardProps): JSX.Element => { | ||||
|   const [selectedTranslation] = useSmartLanguage({ | ||||
|     items: translations, | ||||
|     languages: languages, | ||||
|     languageExtractor: (item) => item.language, | ||||
|     languageExtractor, | ||||
|   }); | ||||
| 
 | ||||
|   return ( | ||||
| @ -45,23 +45,18 @@ export const TranslatedPreviewCard = ({ | ||||
| 
 | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| 
 | ||||
| type TranslatedPreviewLineProps = TranslatedProps< | ||||
|   Parameters<typeof PreviewLine>[0], | ||||
|   "pre_title" | "subtitle" | "title" | ||||
| >; | ||||
| 
 | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| 
 | ||||
| export const TranslatedPreviewLine = ({ | ||||
|   translations, | ||||
|   languages, | ||||
|   fallback, | ||||
|   ...otherProps | ||||
| }: TranslatedPreviewLineProps): JSX.Element => { | ||||
| }: TranslatedProps< | ||||
|   Parameters<typeof PreviewLine>[0], | ||||
|   "pre_title" | "subtitle" | "title" | ||||
| >): JSX.Element => { | ||||
|   const [selectedTranslation] = useSmartLanguage({ | ||||
|     items: translations, | ||||
|     languages: languages, | ||||
|     languageExtractor: (item) => item.language, | ||||
| 
 | ||||
|     languageExtractor, | ||||
|   }); | ||||
| 
 | ||||
|   return ( | ||||
| @ -76,29 +71,19 @@ export const TranslatedPreviewLine = ({ | ||||
| 
 | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| 
 | ||||
| type TranslatedScanSetProps = TranslatedProps< | ||||
|   Parameters<typeof ScanSet>[0], | ||||
|   "title" | ||||
| >; | ||||
| 
 | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| 
 | ||||
| export const TranslatedScanSet = ({ | ||||
|   translations, | ||||
|   languages, | ||||
|   fallback, | ||||
|   ...otherProps | ||||
| }: TranslatedScanSetProps): JSX.Element => { | ||||
| }: TranslatedProps<Parameters<typeof ScanSet>[0], "title">): JSX.Element => { | ||||
|   const [selectedTranslation] = useSmartLanguage({ | ||||
|     items: translations, | ||||
|     languages: languages, | ||||
|     languageExtractor: (item) => item.language, | ||||
|     languageExtractor, | ||||
|   }); | ||||
| 
 | ||||
|   return ( | ||||
|     <ScanSet | ||||
|       title={selectedTranslation?.title ?? fallback.title} | ||||
|       languages={languages} | ||||
|       {...otherProps} | ||||
|     /> | ||||
|   ); | ||||
| @ -106,23 +91,17 @@ export const TranslatedScanSet = ({ | ||||
| 
 | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| 
 | ||||
| type TranslatedNavOptionProps = TranslatedProps< | ||||
|   Parameters<typeof NavOption>[0], | ||||
|   "subtitle" | "title" | ||||
| >; | ||||
| 
 | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| 
 | ||||
| export const TranslatedNavOption = ({ | ||||
|   translations, | ||||
|   languages, | ||||
|   fallback, | ||||
|   ...otherProps | ||||
| }: TranslatedNavOptionProps): JSX.Element => { | ||||
| }: TranslatedProps< | ||||
|   Parameters<typeof NavOption>[0], | ||||
|   "subtitle" | "title" | ||||
| >): JSX.Element => { | ||||
|   const [selectedTranslation] = useSmartLanguage({ | ||||
|     items: translations, | ||||
|     languages: languages, | ||||
|     languageExtractor: (item) => item.language, | ||||
|     languageExtractor, | ||||
|   }); | ||||
| 
 | ||||
|   return ( | ||||
| @ -133,3 +112,49 @@ export const TranslatedNavOption = ({ | ||||
|     /> | ||||
|   ); | ||||
| }; | ||||
| 
 | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| 
 | ||||
| export const TranslatedChroniclePreview = ({ | ||||
|   translations, | ||||
|   fallback, | ||||
|   ...otherProps | ||||
| }: TranslatedProps< | ||||
|   Parameters<typeof ChroniclePreview>[0], | ||||
|   "title" | ||||
| >): JSX.Element => { | ||||
|   const [selectedTranslation] = useSmartLanguage({ | ||||
|     items: translations, | ||||
|     languageExtractor, | ||||
|   }); | ||||
| 
 | ||||
|   return ( | ||||
|     <ChroniclePreview | ||||
|       title={selectedTranslation?.title ?? fallback.title} | ||||
|       {...otherProps} | ||||
|     /> | ||||
|   ); | ||||
| }; | ||||
| 
 | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| 
 | ||||
| export const TranslatedChroniclesList = ({ | ||||
|   translations, | ||||
|   fallback, | ||||
|   ...otherProps | ||||
| }: TranslatedProps< | ||||
|   Parameters<typeof ChroniclesList>[0], | ||||
|   "title" | ||||
| >): JSX.Element => { | ||||
|   const [selectedTranslation] = useSmartLanguage({ | ||||
|     items: translations, | ||||
|     languageExtractor, | ||||
|   }); | ||||
| 
 | ||||
|   return ( | ||||
|     <ChroniclesList | ||||
|       title={selectedTranslation?.title ?? fallback.title} | ||||
|       {...otherProps} | ||||
|     /> | ||||
|   ); | ||||
| }; | ||||
|  | ||||
| @ -6,7 +6,7 @@ fragment recorderChip on Recorder { | ||||
|   bio(filters: { language: { code: { eq: $language_code } } }) { | ||||
|     bio | ||||
|   } | ||||
|   languages { | ||||
|   languages(pagination: { limit: -1 }) { | ||||
|     data { | ||||
|       attributes { | ||||
|         code | ||||
|  | ||||
| @ -4,7 +4,7 @@ query devGetContents { | ||||
|       id | ||||
|       attributes { | ||||
|         slug | ||||
|         categories { | ||||
|         categories(pagination: { limit: -1 }) { | ||||
|           data { | ||||
|             id | ||||
|           } | ||||
| @ -15,12 +15,12 @@ query devGetContents { | ||||
|           } | ||||
|         } | ||||
| 
 | ||||
|         ranged_contents { | ||||
|         ranged_contents(pagination: { limit: -1 }) { | ||||
|           data { | ||||
|             id | ||||
|           } | ||||
|         } | ||||
|         translations { | ||||
|         translations(pagination: { limit: -1 }) { | ||||
|           language { | ||||
|             data { | ||||
|               id | ||||
| @ -41,17 +41,17 @@ query devGetContents { | ||||
|               } | ||||
|             } | ||||
|             status | ||||
|             transcribers { | ||||
|             transcribers(pagination: { limit: -1 }) { | ||||
|               data { | ||||
|                 id | ||||
|               } | ||||
|             } | ||||
|             translators { | ||||
|             translators(pagination: { limit: -1 }) { | ||||
|               data { | ||||
|                 id | ||||
|               } | ||||
|             } | ||||
|             proofreaders { | ||||
|             proofreaders(pagination: { limit: -1 }) { | ||||
|               data { | ||||
|                 id | ||||
|               } | ||||
|  | ||||
| @ -9,7 +9,7 @@ query devGetLibraryItems { | ||||
|             id | ||||
|           } | ||||
|         } | ||||
|         subitems { | ||||
|         subitems(pagination: { limit: -1 }) { | ||||
|           data { | ||||
|             id | ||||
|           } | ||||
| @ -41,7 +41,7 @@ query devGetLibraryItems { | ||||
|           month | ||||
|           day | ||||
|         } | ||||
|         descriptions { | ||||
|         descriptions(pagination: { limit: -1 }) { | ||||
|           description | ||||
|           language { | ||||
|             data { | ||||
| @ -49,13 +49,13 @@ query devGetLibraryItems { | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         contents { | ||||
|         contents(pagination: { limit: -1 }) { | ||||
|           data { | ||||
|             id | ||||
|           } | ||||
|         } | ||||
|         digital | ||||
|         categories { | ||||
|         categories(pagination: { limit: -1 }) { | ||||
|           data { | ||||
|             id | ||||
|           } | ||||
| @ -63,7 +63,7 @@ query devGetLibraryItems { | ||||
|         urls { | ||||
|           url | ||||
|         } | ||||
|         images { | ||||
|         images(pagination: { limit: -1 }) { | ||||
|           language { | ||||
|             data { | ||||
|               id | ||||
| @ -75,17 +75,17 @@ query devGetLibraryItems { | ||||
|             } | ||||
|           } | ||||
|           status | ||||
|           scanners { | ||||
|           scanners(pagination: { limit: -1 }) { | ||||
|             data { | ||||
|               id | ||||
|             } | ||||
|           } | ||||
|           cleaners { | ||||
|           cleaners(pagination: { limit: -1 }) { | ||||
|             data { | ||||
|               id | ||||
|             } | ||||
|           } | ||||
|           typesetters { | ||||
|           typesetters(pagination: { limit: -1 }) { | ||||
|             data { | ||||
|               id | ||||
|             } | ||||
|  | ||||
							
								
								
									
										165
									
								
								src/graphql/operations/getChronicle.graphql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								src/graphql/operations/getChronicle.graphql
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,165 @@ | ||||
| query getChronicle($slug: String, $language_code: String) { | ||||
|   chronicles(filters: { slug: { eq: $slug } }) { | ||||
|     data { | ||||
|       attributes { | ||||
|         slug | ||||
|         date_start { | ||||
|           year | ||||
|           month | ||||
|           day | ||||
|         } | ||||
|         date_end { | ||||
|           year | ||||
|           month | ||||
|           day | ||||
|         } | ||||
|         chapter { | ||||
|           data { | ||||
|             attributes { | ||||
|               slug | ||||
|               titles { | ||||
|                 title | ||||
|                 language { | ||||
|                   data { | ||||
|                     attributes { | ||||
|                       code | ||||
|                     } | ||||
|                   } | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         translations { | ||||
|           title | ||||
|           summary | ||||
|           language { | ||||
|             data { | ||||
|               attributes { | ||||
|                 code | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|           body { | ||||
|             source_language { | ||||
|               data { | ||||
|                 attributes { | ||||
|                   code | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|             status | ||||
|             body | ||||
|             authors { | ||||
|               data { | ||||
|                 attributes { | ||||
|                   ...recorderChip | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|             translators { | ||||
|               data { | ||||
|                 attributes { | ||||
|                   ...recorderChip | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|             proofreaders { | ||||
|               data { | ||||
|                 attributes { | ||||
|                   ...recorderChip | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         contents { | ||||
|           data { | ||||
|             id | ||||
|             attributes { | ||||
|               slug | ||||
|               categories(pagination: { limit: -1 }) { | ||||
|                 data { | ||||
|                   id | ||||
|                   attributes { | ||||
|                     name | ||||
|                     short | ||||
|                   } | ||||
|                 } | ||||
|               } | ||||
|               type { | ||||
|                 data { | ||||
|                   attributes { | ||||
|                     slug | ||||
|                     titles( | ||||
|                       filters: { language: { code: { eq: $language_code } } } | ||||
|                     ) { | ||||
|                       title | ||||
|                     } | ||||
|                   } | ||||
|                 } | ||||
|               } | ||||
|               translations(pagination: { limit: -1 }) { | ||||
|                 language { | ||||
|                   data { | ||||
|                     attributes { | ||||
|                       code | ||||
|                     } | ||||
|                   } | ||||
|                 } | ||||
|                 pre_title | ||||
|                 title | ||||
|                 subtitle | ||||
|                 description | ||||
|                 text_set { | ||||
|                   status | ||||
|                   text | ||||
|                   source_language { | ||||
|                     data { | ||||
|                       attributes { | ||||
|                         code | ||||
|                       } | ||||
|                     } | ||||
|                   } | ||||
|                   transcribers(pagination: { limit: -1 }) { | ||||
|                     data { | ||||
|                       id | ||||
|                       attributes { | ||||
|                         ...recorderChip | ||||
|                       } | ||||
|                     } | ||||
|                   } | ||||
|                   translators(pagination: { limit: -1 }) { | ||||
|                     data { | ||||
|                       id | ||||
|                       attributes { | ||||
|                         ...recorderChip | ||||
|                       } | ||||
|                     } | ||||
|                   } | ||||
|                   proofreaders(pagination: { limit: -1 }) { | ||||
|                     data { | ||||
|                       id | ||||
|                       attributes { | ||||
|                         ...recorderChip | ||||
|                       } | ||||
|                     } | ||||
|                   } | ||||
|                   notes | ||||
|                 } | ||||
|               } | ||||
| 
 | ||||
|               thumbnail { | ||||
|                 data { | ||||
|                   attributes { | ||||
|                     ...uploadImage | ||||
|                   } | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
							
								
								
									
										77
									
								
								src/graphql/operations/getChroniclesChapters.graphql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/graphql/operations/getChroniclesChapters.graphql
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,77 @@ | ||||
| query getChroniclesChapters { | ||||
|   chroniclesChapters(pagination: { limit: -1 }) { | ||||
|     data { | ||||
|       id | ||||
|       attributes { | ||||
|         slug | ||||
|         titles(pagination: { limit: -1 }) { | ||||
|           title | ||||
|           language { | ||||
|             data { | ||||
|               attributes { | ||||
|                 code | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         chronicles(pagination: { limit: -1 }) { | ||||
|           data { | ||||
|             id | ||||
|             attributes { | ||||
|               slug | ||||
|               contents(pagination: { limit: -1 }) { | ||||
|                 data { | ||||
|                   attributes { | ||||
|                     translations(pagination: { limit: -1 }) { | ||||
|                       pre_title | ||||
|                       title | ||||
|                       subtitle | ||||
|                       language { | ||||
|                         data { | ||||
|                           attributes { | ||||
|                             code | ||||
|                           } | ||||
|                         } | ||||
|                       } | ||||
|                     } | ||||
|                   } | ||||
|                 } | ||||
|               } | ||||
|               translations(pagination: { limit: -1 }) { | ||||
|                 title | ||||
|                 language { | ||||
|                   data { | ||||
|                     attributes { | ||||
|                       code | ||||
|                     } | ||||
|                   } | ||||
|                 } | ||||
|               } | ||||
|               date_start { | ||||
|                 year | ||||
|                 month | ||||
|                 day | ||||
|               } | ||||
|               chapter { | ||||
|                 data { | ||||
|                   attributes { | ||||
|                     titles(pagination: { limit: -1 }) { | ||||
|                       title | ||||
|                       language { | ||||
|                         data { | ||||
|                           attributes { | ||||
|                             code | ||||
|                           } | ||||
|                         } | ||||
|                       } | ||||
|                     } | ||||
|                   } | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
							
								
								
									
										9
									
								
								src/graphql/operations/getChroniclesSlugs.graphql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/graphql/operations/getChroniclesSlugs.graphql
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| query getChroniclesSlugs { | ||||
|   chronicles(pagination: { limit: -1 }) { | ||||
|     data { | ||||
|       attributes { | ||||
|         slug | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @ -1,4 +1,4 @@ | ||||
| query getChronologyItems($language_code: String) { | ||||
| query getChronologyItems { | ||||
|   chronologyItems( | ||||
|     pagination: { limit: -1 } | ||||
|     sort: ["year:asc", "month:asc", "day:asc"] | ||||
| @ -10,7 +10,7 @@ query getChronologyItems($language_code: String) { | ||||
|         month | ||||
|         day | ||||
|         displayed_date | ||||
|         events { | ||||
|         events(pagination: { limit: -1 }) { | ||||
|           id | ||||
|           source { | ||||
|             data { | ||||
| @ -19,9 +19,7 @@ query getChronologyItems($language_code: String) { | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|           translations( | ||||
|             filters: { language: { code: { eq: $language_code } } } | ||||
|           ) { | ||||
|           translations(pagination: { limit: -1 }) { | ||||
|             title | ||||
|             description | ||||
|             note | ||||
|  | ||||
| @ -4,8 +4,7 @@ query getContentText($slug: String, $language_code: String) { | ||||
|       id | ||||
|       attributes { | ||||
|         slug | ||||
| 
 | ||||
|         categories { | ||||
|         categories(pagination: { limit: -1 }) { | ||||
|           data { | ||||
|             id | ||||
|             attributes { | ||||
| @ -52,7 +51,7 @@ query getContentText($slug: String, $language_code: String) { | ||||
|                     price { | ||||
|                       ...pricePicker | ||||
|                     } | ||||
|                     categories { | ||||
|                     categories(pagination: { limit: -1 }) { | ||||
|                       data { | ||||
|                         id | ||||
|                         attributes { | ||||
| @ -80,7 +79,7 @@ query getContentText($slug: String, $language_code: String) { | ||||
|                         } | ||||
|                       } | ||||
|                       ... on ComponentMetadataGame { | ||||
|                         platforms { | ||||
|                         platforms(pagination: { limit: -1 }) { | ||||
|                           data { | ||||
|                             id | ||||
|                             attributes { | ||||
| @ -180,7 +179,7 @@ query getContentText($slug: String, $language_code: String) { | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|             transcribers { | ||||
|             transcribers(pagination: { limit: -1 }) { | ||||
|               data { | ||||
|                 id | ||||
|                 attributes { | ||||
| @ -188,7 +187,7 @@ query getContentText($slug: String, $language_code: String) { | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|             translators { | ||||
|             translators(pagination: { limit: -1 }) { | ||||
|               data { | ||||
|                 id | ||||
|                 attributes { | ||||
| @ -196,7 +195,7 @@ query getContentText($slug: String, $language_code: String) { | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|             proofreaders { | ||||
|             proofreaders(pagination: { limit: -1 }) { | ||||
|               data { | ||||
|                 id | ||||
|                 attributes { | ||||
| @ -222,7 +221,7 @@ query getContentText($slug: String, $language_code: String) { | ||||
|                 data { | ||||
|                   attributes { | ||||
|                     slug | ||||
|                     translations { | ||||
|                     translations(pagination: { limit: -1 }) { | ||||
|                       pre_title | ||||
|                       title | ||||
|                       subtitle | ||||
| @ -234,7 +233,7 @@ query getContentText($slug: String, $language_code: String) { | ||||
|                         } | ||||
|                       } | ||||
|                     } | ||||
|                     categories { | ||||
|                     categories(pagination: { limit: -1 }) { | ||||
|                       data { | ||||
|                         id | ||||
|                         attributes { | ||||
|  | ||||
| @ -4,7 +4,7 @@ query getContents($language_code: String) { | ||||
|       id | ||||
|       attributes { | ||||
|         slug | ||||
|         translations { | ||||
|         translations(pagination: { limit: -1 }) { | ||||
|           pre_title | ||||
|           title | ||||
|           subtitle | ||||
| @ -16,7 +16,7 @@ query getContents($language_code: String) { | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         categories { | ||||
|         categories(pagination: { limit: -1 }) { | ||||
|           data { | ||||
|             id | ||||
|             attributes { | ||||
| @ -35,7 +35,7 @@ query getContents($language_code: String) { | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         ranged_contents { | ||||
|         ranged_contents(pagination: { limit: -1 }) { | ||||
|           data { | ||||
|             id | ||||
|             attributes { | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| query getCurrencies { | ||||
|   currencies { | ||||
|   currencies(pagination: { limit: -1 }) { | ||||
|     data { | ||||
|       id | ||||
|       attributes { | ||||
|  | ||||
| @ -1,12 +1,12 @@ | ||||
| query getEras($language_code: String) { | ||||
|   chronologyEras(sort: "starting_year") { | ||||
| query getEras { | ||||
|   chronologyEras(pagination: { limit: -1 }, sort: "starting_year") { | ||||
|     data { | ||||
|       id | ||||
|       attributes { | ||||
|         slug | ||||
|         starting_year | ||||
|         ending_year | ||||
|         title(filters: { language: { code: { eq: $language_code } } }) { | ||||
|         title(pagination: { limit: -1 }) { | ||||
|           title | ||||
|           description | ||||
|         } | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| query getLanguages { | ||||
|   languages { | ||||
|   languages(pagination: { limit: -1 }) { | ||||
|     data { | ||||
|       id | ||||
|       attributes { | ||||
|  | ||||
| @ -30,7 +30,7 @@ query getLibraryItem($slug: String, $language_code: String) { | ||||
|         price { | ||||
|           ...pricePicker | ||||
|         } | ||||
|         categories { | ||||
|         categories(pagination: { limit: -1 }) { | ||||
|           data { | ||||
|             id | ||||
|             attributes { | ||||
| @ -39,7 +39,7 @@ query getLibraryItem($slug: String, $language_code: String) { | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         urls { | ||||
|         urls(pagination: { limit: -1 }) { | ||||
|           url | ||||
|         } | ||||
|         size { | ||||
| @ -47,7 +47,7 @@ query getLibraryItem($slug: String, $language_code: String) { | ||||
|           height | ||||
|           thickness | ||||
|         } | ||||
|         descriptions(filters: { language: { code: { eq: $language_code } } }) { | ||||
|         descriptions(pagination: { limit: -1 }) { | ||||
|           description | ||||
|         } | ||||
|         metadata { | ||||
| @ -68,7 +68,7 @@ query getLibraryItem($slug: String, $language_code: String) { | ||||
|             binding_type | ||||
|             page_count | ||||
|             page_order | ||||
|             languages { | ||||
|             languages(pagination: { limit: -1 }) { | ||||
|               data { | ||||
|                 attributes { | ||||
|                   code | ||||
| @ -92,7 +92,7 @@ query getLibraryItem($slug: String, $language_code: String) { | ||||
|             } | ||||
|           } | ||||
|           ... on ComponentMetadataGame { | ||||
|             platforms { | ||||
|             platforms(pagination: { limit: -1 }) { | ||||
|               data { | ||||
|                 id | ||||
|                 attributes { | ||||
| @ -100,7 +100,7 @@ query getLibraryItem($slug: String, $language_code: String) { | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|             audio_languages { | ||||
|             audio_languages(pagination: { limit: -1 }) { | ||||
|               data { | ||||
|                 attributes { | ||||
|                   code | ||||
| @ -108,7 +108,7 @@ query getLibraryItem($slug: String, $language_code: String) { | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|             sub_languages { | ||||
|             sub_languages(pagination: { limit: -1 }) { | ||||
|               data { | ||||
|                 attributes { | ||||
|                   code | ||||
| @ -116,7 +116,7 @@ query getLibraryItem($slug: String, $language_code: String) { | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|             interface_languages { | ||||
|             interface_languages(pagination: { limit: -1 }) { | ||||
|               data { | ||||
|                 attributes { | ||||
|                   code | ||||
| @ -196,7 +196,7 @@ query getLibraryItem($slug: String, $language_code: String) { | ||||
|               price { | ||||
|                 ...pricePicker | ||||
|               } | ||||
|               categories { | ||||
|               categories(pagination: { limit: -1 }) { | ||||
|                 data { | ||||
|                   id | ||||
|                   attributes { | ||||
| @ -299,7 +299,7 @@ query getLibraryItem($slug: String, $language_code: String) { | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         submerchs { | ||||
|         submerchs(pagination: { limit: -1 }) { | ||||
|           data { | ||||
|             id | ||||
|             attributes { | ||||
| @ -339,7 +339,7 @@ query getLibraryItem($slug: String, $language_code: String) { | ||||
|                 data { | ||||
|                   attributes { | ||||
|                     slug | ||||
|                     categories { | ||||
|                     categories(pagination: { limit: -1 }) { | ||||
|                       data { | ||||
|                         id | ||||
|                         attributes { | ||||
| @ -362,7 +362,7 @@ query getLibraryItem($slug: String, $language_code: String) { | ||||
|                         } | ||||
|                       } | ||||
|                     } | ||||
|                     translations { | ||||
|                     translations(pagination: { limit: -1 }) { | ||||
|                       language { | ||||
|                         data { | ||||
|                           attributes { | ||||
|  | ||||
| @ -6,7 +6,7 @@ query getLibraryItemScans($slug: String, $language_code: String) { | ||||
|         slug | ||||
|         title | ||||
|         subtitle | ||||
|         images { | ||||
|         images(pagination: { limit: -1 }) { | ||||
|           status | ||||
|           language { | ||||
|             data { | ||||
| @ -22,7 +22,7 @@ query getLibraryItemScans($slug: String, $language_code: String) { | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|           scanners { | ||||
|           scanners(pagination: { limit: -1 }) { | ||||
|             data { | ||||
|               id | ||||
|               attributes { | ||||
| @ -30,7 +30,7 @@ query getLibraryItemScans($slug: String, $language_code: String) { | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|           cleaners { | ||||
|           cleaners(pagination: { limit: -1 }) { | ||||
|             data { | ||||
|               id | ||||
|               attributes { | ||||
| @ -38,7 +38,7 @@ query getLibraryItemScans($slug: String, $language_code: String) { | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|           typesetters { | ||||
|           typesetters(pagination: { limit: -1 }) { | ||||
|             data { | ||||
|               id | ||||
|               attributes { | ||||
| @ -108,7 +108,7 @@ query getLibraryItemScans($slug: String, $language_code: String) { | ||||
|         price { | ||||
|           ...pricePicker | ||||
|         } | ||||
|         categories { | ||||
|         categories(pagination: { limit: -1 }) { | ||||
|           data { | ||||
|             id | ||||
|             attributes { | ||||
| @ -218,7 +218,7 @@ query getLibraryItemScans($slug: String, $language_code: String) { | ||||
|                 data { | ||||
|                   attributes { | ||||
|                     slug | ||||
|                     translations { | ||||
|                     translations(pagination: { limit: -1 }) { | ||||
|                       pre_title | ||||
|                       title | ||||
|                       subtitle | ||||
| @ -249,7 +249,7 @@ query getLibraryItemScans($slug: String, $language_code: String) { | ||||
|                     } | ||||
|                   } | ||||
|                 } | ||||
|                 scanners { | ||||
|                 scanners(pagination: { limit: -1 }) { | ||||
|                   data { | ||||
|                     id | ||||
|                     attributes { | ||||
| @ -257,7 +257,7 @@ query getLibraryItemScans($slug: String, $language_code: String) { | ||||
|                     } | ||||
|                   } | ||||
|                 } | ||||
|                 cleaners { | ||||
|                 cleaners(pagination: { limit: -1 }) { | ||||
|                   data { | ||||
|                     id | ||||
|                     attributes { | ||||
| @ -265,7 +265,7 @@ query getLibraryItemScans($slug: String, $language_code: String) { | ||||
|                     } | ||||
|                   } | ||||
|                 } | ||||
|                 typesetters { | ||||
|                 typesetters(pagination: { limit: -1 }) { | ||||
|                   data { | ||||
|                     id | ||||
|                     attributes { | ||||
|  | ||||
| @ -21,7 +21,7 @@ query getLibraryItemsPreview($language_code: String) { | ||||
|         price { | ||||
|           ...pricePicker | ||||
|         } | ||||
|         categories { | ||||
|         categories(pagination: { limit: -1 }) { | ||||
|           data { | ||||
|             id | ||||
|             attributes { | ||||
| @ -47,7 +47,7 @@ query getLibraryItemsPreview($language_code: String) { | ||||
|             } | ||||
|           } | ||||
|           ... on ComponentMetadataGame { | ||||
|             platforms { | ||||
|             platforms(pagination: { limit: -1 }) { | ||||
|               data { | ||||
|                 id | ||||
|                 attributes { | ||||
|  | ||||
| @ -8,7 +8,7 @@ query getPost($slug: String, $language_code: String) { | ||||
|         date { | ||||
|           ...datePicker | ||||
|         } | ||||
|         authors { | ||||
|         authors(pagination: { limit: -1 }) { | ||||
|           data { | ||||
|             id | ||||
|             attributes { | ||||
| @ -16,7 +16,7 @@ query getPost($slug: String, $language_code: String) { | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         categories { | ||||
|         categories(pagination: { limit: -1 }) { | ||||
|           data { | ||||
|             id | ||||
|             attributes { | ||||
| @ -33,7 +33,7 @@ query getPost($slug: String, $language_code: String) { | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         translations { | ||||
|         translations(pagination: { limit: -1 }) { | ||||
|           language { | ||||
|             data { | ||||
|               attributes { | ||||
|  | ||||
| @ -7,7 +7,7 @@ query getPostsPreview { | ||||
|         date { | ||||
|           ...datePicker | ||||
|         } | ||||
|         categories { | ||||
|         categories(pagination: { limit: -1 }) { | ||||
|           data { | ||||
|             id | ||||
|             attributes { | ||||
| @ -22,7 +22,7 @@ query getPostsPreview { | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         translations { | ||||
|         translations(pagination: { limit: -1 }) { | ||||
|           language { | ||||
|             data { | ||||
|               attributes { | ||||
|  | ||||
| @ -21,7 +21,7 @@ query getVideo($uid: String) { | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         categories { | ||||
|         categories(pagination: { limit: -1 }) { | ||||
|           data { | ||||
|             id | ||||
|             attributes { | ||||
| @ -32,7 +32,7 @@ query getVideo($uid: String) { | ||||
|         views | ||||
|         likes | ||||
|         source | ||||
|         audio_languages { | ||||
|         audio_languages(pagination: { limit: -1 }) { | ||||
|           data { | ||||
|             id | ||||
|             attributes { | ||||
| @ -40,7 +40,7 @@ query getVideo($uid: String) { | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         sub_languages { | ||||
|         sub_languages(pagination: { limit: -1 }) { | ||||
|           data { | ||||
|             id | ||||
|             attributes { | ||||
|  | ||||
| @ -14,7 +14,7 @@ query getVideoChannel($channel: String) { | ||||
|               views | ||||
|               duration | ||||
|               gone | ||||
|               categories { | ||||
|               categories(pagination: { limit: -1 }) { | ||||
|                 data { | ||||
|                   id | ||||
|                   attributes { | ||||
|  | ||||
| @ -8,7 +8,7 @@ query getVideosPreview { | ||||
|         views | ||||
|         duration | ||||
|         gone | ||||
|         categories { | ||||
|         categories(pagination: { limit: -1 }) { | ||||
|           data { | ||||
|             id | ||||
|             attributes { | ||||
|  | ||||
| @ -11,7 +11,7 @@ query getWikiPage($slug: String, $language_code: String) { | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         categories { | ||||
|         categories(pagination: { limit: -1 }) { | ||||
|           data { | ||||
|             id | ||||
|             attributes { | ||||
| @ -20,7 +20,7 @@ query getWikiPage($slug: String, $language_code: String) { | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         tags { | ||||
|         tags(pagination: { limit: -1 }) { | ||||
|           data { | ||||
|             id | ||||
|             attributes { | ||||
| @ -38,7 +38,7 @@ query getWikiPage($slug: String, $language_code: String) { | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         translations { | ||||
|         translations(pagination: { limit: -1 }) { | ||||
|           title | ||||
|           aliases { | ||||
|             alias | ||||
| @ -61,7 +61,7 @@ query getWikiPage($slug: String, $language_code: String) { | ||||
|             } | ||||
|             status | ||||
|             body | ||||
|             authors { | ||||
|             authors(pagination: { limit: -1 }) { | ||||
|               data { | ||||
|                 id | ||||
|                 attributes { | ||||
| @ -69,7 +69,7 @@ query getWikiPage($slug: String, $language_code: String) { | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|             translators { | ||||
|             translators(pagination: { limit: -1 }) { | ||||
|               data { | ||||
|                 id | ||||
|                 attributes { | ||||
| @ -77,7 +77,7 @@ query getWikiPage($slug: String, $language_code: String) { | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|             proofreaders { | ||||
|             proofreaders(pagination: { limit: -1 }) { | ||||
|               data { | ||||
|                 id | ||||
|                 attributes { | ||||
| @ -87,7 +87,7 @@ query getWikiPage($slug: String, $language_code: String) { | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         definitions { | ||||
|         definitions(pagination: { limit: -1 }) { | ||||
|           source { | ||||
|             data { | ||||
|               attributes { | ||||
| @ -95,7 +95,7 @@ query getWikiPage($slug: String, $language_code: String) { | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|           categories { | ||||
|           categories(pagination: { limit: -1 }) { | ||||
|             data { | ||||
|               id | ||||
|               attributes { | ||||
| @ -104,7 +104,7 @@ query getWikiPage($slug: String, $language_code: String) { | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|           translations { | ||||
|           translations(pagination: { limit: -1 }) { | ||||
|             language { | ||||
|               data { | ||||
|                 attributes { | ||||
|  | ||||
| @ -11,7 +11,7 @@ query getWikiPagesPreviews($language_code: String) { | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         categories { | ||||
|         categories(pagination: { limit: -1 }) { | ||||
|           data { | ||||
|             id | ||||
|             attributes { | ||||
| @ -20,7 +20,7 @@ query getWikiPagesPreviews($language_code: String) { | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         tags { | ||||
|         tags(pagination: { limit: -1 }) { | ||||
|           data { | ||||
|             id | ||||
|             attributes { | ||||
| @ -38,9 +38,9 @@ query getWikiPagesPreviews($language_code: String) { | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         translations { | ||||
|         translations(pagination: { limit: -1 }) { | ||||
|           title | ||||
|           aliases { | ||||
|           aliases(pagination: { limit: -1 }) { | ||||
|             alias | ||||
|           } | ||||
|           summary | ||||
|  | ||||
							
								
								
									
										10
									
								
								src/helpers/date.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/helpers/date.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| import { DatePickerFragment } from "graphql/generated"; | ||||
| 
 | ||||
| export const compareDate = ( | ||||
|   a: DatePickerFragment, | ||||
|   b: DatePickerFragment | ||||
| ): number => { | ||||
|   const dateA = (a.year ?? 99999) * 365 + (a.month ?? 12) * 31 + (a.day ?? 31); | ||||
|   const dateB = (b.year ?? 99999) * 365 + (b.month ?? 12) * 31 + (b.day ?? 31); | ||||
|   return dateA - dateB; | ||||
| }; | ||||
| @ -1,4 +1,5 @@ | ||||
| import { | ||||
|   GetChronicleQuery, | ||||
|   GetContentTextQuery, | ||||
|   GetPostQuery, | ||||
|   GetWikiPageQuery, | ||||
| @ -37,6 +38,17 @@ export interface WikiPageWithTranslations | ||||
| 
 | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| 
 | ||||
| type Chronicle = NonNullable< | ||||
|   NonNullable<GetChronicleQuery["chronicles"]>["data"][number]["attributes"] | ||||
| >; | ||||
| 
 | ||||
| export interface ChronicleWithTranslations | ||||
|   extends Omit<Chronicle, "translations"> { | ||||
|   translations: NonNullable<Chronicle["translations"]>; | ||||
| } | ||||
| 
 | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| 
 | ||||
| export type RequiredNonNullable<T> = { | ||||
|   [P in keyof T]-?: NonNullable<T[P]>; | ||||
| }; | ||||
|  | ||||
| @ -3,7 +3,7 @@ export type Report = { | ||||
|   lines: ReportLine[]; | ||||
| }; | ||||
| 
 | ||||
| export type ReportLine = { | ||||
| type ReportLine = { | ||||
|   subitems: string[]; | ||||
|   name: string; | ||||
|   type: "Error" | "Improvement" | "Missing"; | ||||
|  | ||||
| @ -7,7 +7,7 @@ import { filterDefined, isDefined } from "helpers/others"; | ||||
| 
 | ||||
| interface Props<T> { | ||||
|   items: T[]; | ||||
|   languages: AppStaticProps["languages"]; | ||||
|   languages?: AppStaticProps["languages"]; | ||||
|   languageExtractor: (item: NonNullable<T>) => string | undefined; | ||||
|   transform?: (item: NonNullable<T>) => NonNullable<T>; | ||||
| } | ||||
| @ -27,7 +27,7 @@ const getPreferredLanguage = ( | ||||
| export const useSmartLanguage = <T>({ | ||||
|   items, | ||||
|   languageExtractor, | ||||
|   languages, | ||||
|   languages = [], | ||||
|   transform = (item) => item, | ||||
| }: Props<T>): [ | ||||
|   T | undefined, | ||||
|  | ||||
							
								
								
									
										258
									
								
								src/pages/chronicles/[slug]/index.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										258
									
								
								src/pages/chronicles/[slug]/index.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,258 @@ | ||||
| import { GetStaticProps, GetStaticPaths, GetStaticPathsResult } from "next"; | ||||
| import { useCallback, useMemo } from "react"; | ||||
| import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { getReadySdk } from "graphql/sdk"; | ||||
| import { isDefined, filterHasAttributes } from "helpers/others"; | ||||
| import { ChronicleWithTranslations } from "helpers/types"; | ||||
| import { AppLayout } from "components/AppLayout"; | ||||
| import { useSmartLanguage } from "hooks/useSmartLanguage"; | ||||
| import { ContentPanel } from "components/Panels/ContentPanel"; | ||||
| import { Markdawn } from "components/Markdown/Markdawn"; | ||||
| import { SubPanel } from "components/Panels/SubPanel"; | ||||
| import { ThumbnailHeader } from "components/ThumbnailHeader"; | ||||
| import { HorizontalLine } from "components/HorizontalLine"; | ||||
| import { GetChroniclesChaptersQuery } from "graphql/generated"; | ||||
| import { prettySlug } from "helpers/formatters"; | ||||
| import { | ||||
|   ReturnButton, | ||||
|   ReturnButtonType, | ||||
| } from "components/PanelComponents/ReturnButton"; | ||||
| import { TranslatedChroniclesList } from "components/Translated"; | ||||
| import { Icon } from "components/Ico"; | ||||
| 
 | ||||
| /* | ||||
|  *                                           ╭────────╮ | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps { | ||||
|   chronicle: ChronicleWithTranslations; | ||||
|   chapters: NonNullable< | ||||
|     GetChroniclesChaptersQuery["chroniclesChapters"] | ||||
|   >["data"]; | ||||
| } | ||||
| 
 | ||||
| const Chronicle = ({ | ||||
|   chronicle, | ||||
|   chapters, | ||||
|   langui, | ||||
|   languages, | ||||
|   ...otherProps | ||||
| }: Props): JSX.Element => { | ||||
|   const [selectedTranslation, LanguageSwitcher, languageSwitcherProps] = | ||||
|     useSmartLanguage({ | ||||
|       items: chronicle.translations, | ||||
|       languages: languages, | ||||
|       languageExtractor: useCallback( | ||||
|         (item: ChronicleWithTranslations["translations"][number]) => | ||||
|           item?.language?.data?.attributes?.code, | ||||
|         [] | ||||
|       ), | ||||
|     }); | ||||
| 
 | ||||
|   const primaryContent = useMemo< | ||||
|     NonNullable< | ||||
|       ChronicleWithTranslations["contents"] | ||||
|     >["data"][number]["attributes"] | ||||
|   >( | ||||
|     () => | ||||
|       filterHasAttributes(chronicle.contents?.data, [ | ||||
|         "attributes.translations", | ||||
|       ] as const)[0]?.attributes, | ||||
|     [chronicle.contents?.data] | ||||
|   ); | ||||
| 
 | ||||
|   const [ | ||||
|     selectedContentTranslation, | ||||
|     ContentLanguageSwitcher, | ||||
|     ContentLanguageSwitcherProps, | ||||
|   ] = useSmartLanguage({ | ||||
|     items: primaryContent?.translations ?? [], | ||||
|     languages: languages, | ||||
|     languageExtractor: useCallback( | ||||
|       ( | ||||
|         item: NonNullable< | ||||
|           NonNullable< | ||||
|             NonNullable< | ||||
|               ChronicleWithTranslations["contents"] | ||||
|             >["data"][number]["attributes"] | ||||
|           >["translations"] | ||||
|         >[number] | ||||
|       ) => item?.language?.data?.attributes?.code, | ||||
|       [] | ||||
|     ), | ||||
|   }); | ||||
| 
 | ||||
|   const contentPanel = useMemo( | ||||
|     () => ( | ||||
|       <ContentPanel> | ||||
|         <ReturnButton | ||||
|           displayOn={ReturnButtonType.Mobile} | ||||
|           href="/chronicles" | ||||
|           title={langui.chronicles} | ||||
|           langui={langui} | ||||
|           className="mb-10" | ||||
|         /> | ||||
| 
 | ||||
|         {isDefined(selectedTranslation) ? ( | ||||
|           <> | ||||
|             <h1 className="mb-16 text-center text-3xl"> | ||||
|               {selectedTranslation.title} | ||||
|             </h1> | ||||
| 
 | ||||
|             {languageSwitcherProps.locales.size > 1 && ( | ||||
|               <LanguageSwitcher {...languageSwitcherProps} /> | ||||
|             )} | ||||
| 
 | ||||
|             {isDefined(selectedTranslation.body) && ( | ||||
|               <Markdawn text={selectedTranslation.body.body} /> | ||||
|             )} | ||||
|           </> | ||||
|         ) : ( | ||||
|           <> | ||||
|             {selectedContentTranslation && ( | ||||
|               <> | ||||
|                 <ThumbnailHeader | ||||
|                   pre_title={selectedContentTranslation.pre_title} | ||||
|                   title={selectedContentTranslation.title} | ||||
|                   subtitle={selectedContentTranslation.subtitle} | ||||
|                   languageSwitcher={ | ||||
|                     ContentLanguageSwitcherProps.locales.size > 1 ? ( | ||||
|                       <ContentLanguageSwitcher | ||||
|                         {...ContentLanguageSwitcherProps} | ||||
|                       /> | ||||
|                     ) : undefined | ||||
|                   } | ||||
|                   categories={primaryContent?.categories} | ||||
|                   type={primaryContent?.type} | ||||
|                   description={selectedContentTranslation.description} | ||||
|                   thumbnail={primaryContent?.thumbnail?.data?.attributes} | ||||
|                   langui={langui} | ||||
|                 /> | ||||
| 
 | ||||
|                 <HorizontalLine /> | ||||
| 
 | ||||
|                 {selectedContentTranslation.text_set?.text && ( | ||||
|                   <Markdawn text={selectedContentTranslation.text_set.text} /> | ||||
|                 )} | ||||
|               </> | ||||
|             )} | ||||
|           </> | ||||
|         )} | ||||
|       </ContentPanel> | ||||
|     ), | ||||
|     [ | ||||
|       selectedTranslation, | ||||
|       languageSwitcherProps, | ||||
|       LanguageSwitcher, | ||||
|       selectedContentTranslation, | ||||
|       ContentLanguageSwitcherProps, | ||||
|       ContentLanguageSwitcher, | ||||
|       primaryContent?.categories, | ||||
|       primaryContent?.type, | ||||
|       primaryContent?.thumbnail?.data?.attributes, | ||||
|       langui, | ||||
|     ] | ||||
|   ); | ||||
| 
 | ||||
|   const subPanel = useMemo( | ||||
|     () => ( | ||||
|       <SubPanel> | ||||
|         <ReturnButton | ||||
|           displayOn={ReturnButtonType.Desktop} | ||||
|           href="/chronicles" | ||||
|           title={langui.chronicles} | ||||
|           langui={langui} | ||||
|           horizontalLine | ||||
|         /> | ||||
|         <div className="grid gap-16"> | ||||
|           {filterHasAttributes(chapters, [ | ||||
|             "attributes.chronicles", | ||||
|             "id", | ||||
|           ] as const).map((chapter) => ( | ||||
|             <TranslatedChroniclesList | ||||
|               key={chapter.id} | ||||
|               chronicles={chapter.attributes.chronicles.data} | ||||
|               translations={filterHasAttributes(chapter.attributes.titles, [ | ||||
|                 "language.data.attributes.code", | ||||
|               ] as const).map((translation) => ({ | ||||
|                 title: translation.title, | ||||
|                 language: translation.language.data.attributes.code, | ||||
|               }))} | ||||
|               fallback={{ title: prettySlug(chapter.attributes.slug) }} | ||||
|               currentSlug={chronicle.slug} | ||||
|             /> | ||||
|           ))} | ||||
|         </div> | ||||
|       </SubPanel> | ||||
|     ), | ||||
|     [chapters, chronicle.slug, langui] | ||||
|   ); | ||||
| 
 | ||||
|   return ( | ||||
|     <AppLayout | ||||
|       navTitle={langui.chronicles} | ||||
|       contentPanel={contentPanel} | ||||
|       subPanel={subPanel} | ||||
|       langui={langui} | ||||
|       languages={languages} | ||||
|       subPanelIcon={Icon.FormatListNumbered} | ||||
|       {...otherProps} | ||||
|     /> | ||||
|   ); | ||||
| }; | ||||
| export default Chronicle; | ||||
| 
 | ||||
| /* | ||||
|  *                                    ╭──────────────────────╮ | ||||
|  * ───────────────────────────────────╯  NEXT DATA FETCHING  ╰────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const sdk = getReadySdk(); | ||||
|   const slug = | ||||
|     context.params && isDefined(context.params.slug) | ||||
|       ? context.params.slug.toString() | ||||
|       : ""; | ||||
|   const chronicle = await sdk.getChronicle({ | ||||
|     language_code: context.locale ?? "en", | ||||
|     slug: slug, | ||||
|   }); | ||||
|   const chronicles = await sdk.getChroniclesChapters(); | ||||
|   if ( | ||||
|     !chronicle.chronicles?.data[0].attributes?.translations || | ||||
|     !chronicles.chroniclesChapters?.data | ||||
|   ) | ||||
|     return { notFound: true }; | ||||
|   const props: Props = { | ||||
|     ...(await getAppStaticProps(context)), | ||||
|     chronicle: chronicle.chronicles.data[0] | ||||
|       .attributes as ChronicleWithTranslations, | ||||
|     chapters: chronicles.chroniclesChapters.data, | ||||
|   }; | ||||
|   return { | ||||
|     props: props, | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| 
 | ||||
| export const getStaticPaths: GetStaticPaths = async (context) => { | ||||
|   const sdk = getReadySdk(); | ||||
|   const contents = await sdk.getChroniclesSlugs(); | ||||
|   const paths: GetStaticPathsResult["paths"] = []; | ||||
|   filterHasAttributes(contents.chronicles?.data, ["attributes"] as const).map( | ||||
|     (wikiPage) => { | ||||
|       context.locales?.map((local) => | ||||
|         paths.push({ | ||||
|           params: { slug: wikiPage.attributes.slug }, | ||||
|           locale: local, | ||||
|         }) | ||||
|       ); | ||||
|     } | ||||
|   ); | ||||
|   return { | ||||
|     paths, | ||||
|     fallback: "blocking", | ||||
|   }; | ||||
| }; | ||||
| @ -5,15 +5,28 @@ import { PanelHeader } from "components/PanelComponents/PanelHeader"; | ||||
| import { SubPanel } from "components/Panels/SubPanel"; | ||||
| import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { Icon } from "components/Ico"; | ||||
| import { getReadySdk } from "graphql/sdk"; | ||||
| import { GetChroniclesChaptersQuery } from "graphql/generated"; | ||||
| import { filterHasAttributes } from "helpers/others"; | ||||
| import { prettySlug } from "helpers/formatters"; | ||||
| import { TranslatedChroniclesList } from "components/Translated"; | ||||
| 
 | ||||
| /* | ||||
|  *                                           ╭────────╮ | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps {} | ||||
| interface Props extends AppStaticProps { | ||||
|   chapters: NonNullable< | ||||
|     GetChroniclesChaptersQuery["chroniclesChapters"] | ||||
|   >["data"]; | ||||
| } | ||||
| 
 | ||||
| const Chronicles = ({ langui, ...otherProps }: Props): JSX.Element => { | ||||
| const Chronicles = ({ | ||||
|   langui, | ||||
|   chapters, | ||||
|   ...otherProps | ||||
| }: Props): JSX.Element => { | ||||
|   const subPanel = useMemo( | ||||
|     () => ( | ||||
|       <SubPanel> | ||||
| @ -22,9 +35,27 @@ const Chronicles = ({ langui, ...otherProps }: Props): JSX.Element => { | ||||
|           title={langui.chronicles} | ||||
|           description={langui.chronicles_description} | ||||
|         /> | ||||
|         <div className="grid gap-16"> | ||||
|           {filterHasAttributes(chapters, [ | ||||
|             "attributes.chronicles", | ||||
|             "id", | ||||
|           ] as const).map((chapter) => ( | ||||
|             <TranslatedChroniclesList | ||||
|               key={chapter.id} | ||||
|               chronicles={chapter.attributes.chronicles.data} | ||||
|               translations={filterHasAttributes(chapter.attributes.titles, [ | ||||
|                 "language.data.attributes.code", | ||||
|               ] as const).map((translation) => ({ | ||||
|                 title: translation.title, | ||||
|                 language: translation.language.data.attributes.code, | ||||
|               }))} | ||||
|               fallback={{ title: prettySlug(chapter.attributes.slug) }} | ||||
|             /> | ||||
|           ))} | ||||
|         </div> | ||||
|       </SubPanel> | ||||
|     ), | ||||
|     [langui] | ||||
|     [chapters, langui] | ||||
|   ); | ||||
| 
 | ||||
|   return ( | ||||
| @ -44,8 +75,12 @@ export default Chronicles; | ||||
|  */ | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const sdk = getReadySdk(); | ||||
|   const chronicles = await sdk.getChroniclesChapters(); | ||||
|   if (!chronicles.chroniclesChapters?.data) return { notFound: true }; | ||||
|   const props: Props = { | ||||
|     ...(await getAppStaticProps(context)), | ||||
|     chapters: chronicles.chroniclesChapters.data, | ||||
|   }; | ||||
|   return { | ||||
|     props: props, | ||||
|  | ||||
| @ -355,7 +355,6 @@ const Content = ({ | ||||
|                 fallback={{ | ||||
|                   title: prettySlug(previousContent.attributes.slug), | ||||
|                 }} | ||||
|                 languages={languages} | ||||
|                 thumbnail={ | ||||
|                   previousContent.attributes.thumbnail?.data?.attributes | ||||
|                 } | ||||
| @ -409,7 +408,6 @@ const Content = ({ | ||||
|                   language: translation.language.data.attributes.code, | ||||
|                 }))} | ||||
|                 fallback={{ title: nextContent.attributes.slug }} | ||||
|                 languages={languages} | ||||
|                 thumbnail={nextContent.attributes.thumbnail?.data?.attributes} | ||||
|                 thumbnailAspectRatio="3/2" | ||||
|                 topChips={ | ||||
| @ -446,7 +444,6 @@ const Content = ({ | ||||
|       content.type, | ||||
|       isMobile, | ||||
|       languageSwitcherProps, | ||||
|       languages, | ||||
|       langui, | ||||
|       nextContent?.attributes, | ||||
|       previousContent?.attributes, | ||||
|  | ||||
| @ -142,6 +142,17 @@ const Contents = ({ | ||||
|     [effectiveCombineRelatedContent, searchName] | ||||
|   ); | ||||
| 
 | ||||
|   const groupCountingFunction = useCallback( | ||||
|     ( | ||||
|       item: SelectiveNonNullable<Props["contents"][number], "attributes" | "id"> | ||||
|     ) => | ||||
|       item.attributes.group?.data?.attributes?.combine && | ||||
|       effectiveCombineRelatedContent | ||||
|         ? item.attributes.group.data.attributes.contents?.data.length ?? 1 | ||||
|         : 1, | ||||
|     [effectiveCombineRelatedContent] | ||||
|   ); | ||||
| 
 | ||||
|   const subPanel = useMemo( | ||||
|     () => ( | ||||
|       <SubPanel> | ||||
| @ -246,7 +257,6 @@ const Contents = ({ | ||||
|                 language: translation.language.data.attributes.code, | ||||
|               }))} | ||||
|               fallback={{ title: prettySlug(item.attributes.slug) }} | ||||
|               languages={languages} | ||||
|               thumbnail={item.attributes.thumbnail?.data?.attributes} | ||||
|               thumbnailAspectRatio="3/2" | ||||
|               thumbnailForceAspectRatio | ||||
| @ -273,6 +283,7 @@ const Contents = ({ | ||||
|           )} | ||||
|           className="grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))]" | ||||
|           groupingFunction={groupingFunction} | ||||
|           groupCountingFunction={groupCountingFunction} | ||||
|           filteringFunction={filteringFunction} | ||||
|           searchingTerm={searchName} | ||||
|           searchingBy={(item) => | ||||
| @ -296,9 +307,9 @@ const Contents = ({ | ||||
|       contents, | ||||
|       effectiveCombineRelatedContent, | ||||
|       filteringFunction, | ||||
|       groupCountingFunction, | ||||
|       groupingFunction, | ||||
|       keepInfoVisible, | ||||
|       languages, | ||||
|       langui, | ||||
|       searchName, | ||||
|     ] | ||||
|  | ||||
| @ -144,7 +144,6 @@ const LibrarySlug = ({ | ||||
|                           : undefined, | ||||
|                     }} | ||||
|                     border | ||||
|                     languages={languages} | ||||
|                   /> | ||||
|                 )} | ||||
|             </> | ||||
| @ -164,7 +163,6 @@ const LibrarySlug = ({ | ||||
|       item.thumbnail?.data?.attributes, | ||||
|       item.title, | ||||
|       itemId, | ||||
|       languages, | ||||
|       langui, | ||||
|     ] | ||||
|   ); | ||||
|  | ||||
| @ -41,12 +41,7 @@ interface Props extends AppStaticProps { | ||||
|   posts: NonNullable<GetPostsPreviewQuery["posts"]>["data"]; | ||||
| } | ||||
| 
 | ||||
| const News = ({ | ||||
|   langui, | ||||
|   posts, | ||||
|   languages, | ||||
|   ...otherProps | ||||
| }: Props): JSX.Element => { | ||||
| const News = ({ langui, posts, ...otherProps }: Props): JSX.Element => { | ||||
|   const hoverable = useMediaHoverable(); | ||||
|   const [searchName, setSearchName] = useState( | ||||
|     DEFAULT_FILTERS_STATE.searchName | ||||
| @ -121,7 +116,6 @@ const News = ({ | ||||
|                 description: translation.excerpt, | ||||
|               }))} | ||||
|               fallback={{ title: prettySlug(post.attributes.slug) }} | ||||
|               languages={languages} | ||||
|               thumbnail={post.attributes.thumbnail?.data?.attributes} | ||||
|               thumbnailAspectRatio="3/2" | ||||
|               thumbnailForceAspectRatio | ||||
| @ -145,7 +139,7 @@ const News = ({ | ||||
|         /> | ||||
|       </ContentPanel> | ||||
|     ), | ||||
|     [keepInfoVisible, languages, langui, posts, searchName] | ||||
|     [keepInfoVisible, langui, posts, searchName] | ||||
|   ); | ||||
| 
 | ||||
|   return ( | ||||
| @ -155,7 +149,6 @@ const News = ({ | ||||
|       contentPanel={contentPanel} | ||||
|       subPanelIcon={Icon.Search} | ||||
|       langui={langui} | ||||
|       languages={languages} | ||||
|       {...otherProps} | ||||
|     /> | ||||
|   ); | ||||
|  | ||||
| @ -162,12 +162,8 @@ export default Chronology; | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const sdk = getReadySdk(); | ||||
|   const chronologyItems = await sdk.getChronologyItems({ | ||||
|     language_code: context.locale ?? "en", | ||||
|   }); | ||||
|   const chronologyEras = await sdk.getEras({ | ||||
|     language_code: context.locale ?? "en", | ||||
|   }); | ||||
|   const chronologyItems = await sdk.getChronologyItems(); | ||||
|   const chronologyEras = await sdk.getEras(); | ||||
|   if (!chronologyItems.chronologyItems || !chronologyEras.chronologyEras) | ||||
|     return { notFound: true }; | ||||
|   const props: Props = { | ||||
|  | ||||
| @ -46,12 +46,7 @@ interface Props extends AppStaticProps { | ||||
|   pages: NonNullable<GetWikiPagesPreviewsQuery["wikiPages"]>["data"]; | ||||
| } | ||||
| 
 | ||||
| const Wiki = ({ | ||||
|   langui, | ||||
|   languages, | ||||
|   pages, | ||||
|   ...otherProps | ||||
| }: Props): JSX.Element => { | ||||
| const Wiki = ({ langui, pages, ...otherProps }: Props): JSX.Element => { | ||||
|   const hoverable = useMediaHoverable(); | ||||
| 
 | ||||
|   const [searchName, setSearchName] = useState( | ||||
| @ -188,7 +183,6 @@ const Wiki = ({ | ||||
|               thumbnailAspectRatio={"4/3"} | ||||
|               thumbnailRounded | ||||
|               thumbnailForceAspectRatio | ||||
|               languages={languages} | ||||
|               keepInfoVisible={keepInfoVisible} | ||||
|               topChips={filterHasAttributes(item.attributes.tags?.data, [ | ||||
|                 "attributes", | ||||
| @ -220,7 +214,7 @@ const Wiki = ({ | ||||
|         /> | ||||
|       </ContentPanel> | ||||
|     ), | ||||
|     [groupingFunction, keepInfoVisible, languages, langui, pages, searchName] | ||||
|     [groupingFunction, keepInfoVisible, langui, pages, searchName] | ||||
|   ); | ||||
| 
 | ||||
|   return ( | ||||
| @ -229,7 +223,6 @@ const Wiki = ({ | ||||
|       subPanel={subPanel} | ||||
|       contentPanel={contentPanel} | ||||
|       subPanelIcon={Icon.Search} | ||||
|       languages={languages} | ||||
|       langui={langui} | ||||
|       {...otherProps} | ||||
|     /> | ||||
|  | ||||
| @ -119,7 +119,7 @@ mark { | ||||
| } | ||||
| 
 | ||||
| .formatted pre > code { | ||||
|   @apply block whitespace-pre; | ||||
|   @apply block whitespace-pre-line; | ||||
| } | ||||
| 
 | ||||
| .formatted ul { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 DrMint
						DrMint