Trying to make localdata works #39
| @ -9,7 +9,7 @@ module.exports = { | ||||
|     }, | ||||
|   }, | ||||
|   documents: [ | ||||
|     "src/graphql/operations/*.graphql", | ||||
|     "src/graphql/operations/**/*.graphql", | ||||
|     "src/graphql/fragments/*.graphql", | ||||
|   ], | ||||
|   generates: { | ||||
|  | ||||
| @ -1,19 +0,0 @@ | ||||
| module.exports = { | ||||
|   projects: { | ||||
|     app: { | ||||
|       schema: process.env.URL_GRAPHQL, | ||||
|       documents: [ | ||||
|         "src/graphql/operations/*.graphql", | ||||
|         "src/graphql/fragments/*.graphql", | ||||
|       ], | ||||
|       extensions: { | ||||
|         endpoints: { | ||||
|           default: { | ||||
|             url: process.env.URL_GRAPHQL, | ||||
|             headers: { Authorization: `Bearer ${process.env.ACCESS_TOKEN}` }, | ||||
|           }, | ||||
|         }, | ||||
|       }, | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
							
								
								
									
										1543
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1543
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										21
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								package.json
									
									
									
									
									
								
							| @ -3,9 +3,10 @@ | ||||
|   "private": true, | ||||
|   "scripts": { | ||||
|     "dev": "next dev -p 12499", | ||||
|     "precommit": "npm run generate && npm run prettier && npm run unused-exports && npm run eslint && npm run tsc && echo ALL PRECOMMIT CHECKS PASSED SUCCESSFULLY, LET\\'S FUCKING GO!", | ||||
|     "precommit": "npm run generate && npm run fetch-local-data && npm run prettier && npm run unused-exports && npm run eslint && npm run tsc && echo ALL PRECOMMIT CHECKS PASSED SUCCESSFULLY, LET\\'S FUCKING GO!", | ||||
|     "unused-exports": "ts-unused-exports ./tsconfig.json --excludePathsFromReport=src/pages --ignoreFiles=generated", | ||||
|     "prebuild": "npm run generate", | ||||
|     "fetch-local-data": "esrun src/graphql/fetchLocalData.ts", | ||||
|     "prebuild": "npm run generate && npm run fetch-local-data", | ||||
|     "build": "next build", | ||||
|     "postbuild": "next-sitemap --config next-sitemap.config.js", | ||||
|     "start": "next start -p 12500", | ||||
| @ -24,7 +25,7 @@ | ||||
|     "@tippyjs/react": "^4.2.6", | ||||
|     "@types/ua-parser-js": "^0.7.36", | ||||
|     "autoprefixer": "^10.4.8", | ||||
|     "graphql-request": "^4.3.0", | ||||
|     "graphql-request": "^5.0.0", | ||||
|     "markdown-to-jsx": "^7.1.7", | ||||
|     "meilisearch": "^0.27.0", | ||||
|     "next": "^12.2.5", | ||||
| @ -40,19 +41,21 @@ | ||||
|     "usehooks-ts": "^2.6.0" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@graphql-codegen/cli": "^2.11.6", | ||||
|     "@digitak/esrun": "^3.2.10", | ||||
|     "@graphql-codegen/cli": "^2.11.8", | ||||
|     "@graphql-codegen/typescript": "2.7.3", | ||||
|     "@graphql-codegen/typescript-graphql-request": "^4.5.3", | ||||
|     "@graphql-codegen/typescript-operations": "^2.5.3", | ||||
|     "@types/node": "18.7.9", | ||||
|     "@types/node": "18.7.13", | ||||
|     "@types/nodemailer": "^6.4.5", | ||||
|     "@types/react": "18.0.17", | ||||
|     "@types/react-dom": "^18.0.6", | ||||
|     "@types/throttle-debounce": "^5.0.0", | ||||
|     "@types/turndown": "^5.0.1", | ||||
|     "@typescript-eslint/eslint-plugin": "^5.33.1", | ||||
|     "@typescript-eslint/parser": "^5.33.1", | ||||
|     "eslint": "^8.22.0", | ||||
|     "@typescript-eslint/eslint-plugin": "^5.35.1", | ||||
|     "@typescript-eslint/parser": "^5.35.1", | ||||
|     "dotenv": "^16.0.1", | ||||
|     "eslint": "^8.23.0", | ||||
|     "eslint-config-next": "12.2.5", | ||||
|     "eslint-plugin-import": "^2.26.0", | ||||
|     "graphql": "^16.6.0", | ||||
| @ -61,6 +64,6 @@ | ||||
|     "prettier-plugin-tailwindcss": "^0.1.13", | ||||
|     "tailwindcss": "^3.1.8", | ||||
|     "ts-unused-exports": "^8.0.0", | ||||
|     "typescript": "^4.7.4" | ||||
|     "typescript": "^4.8.2" | ||||
|   } | ||||
| } | ||||
|  | ||||
							
								
								
									
										1
									
								
								public/local-data/currencies.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								public/local-data/currencies.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| {"currencies":{"data":[{"id":"1","attributes":{"code":"EUR","symbol":"€","rate_to_usd":1.1062771,"display_decimals":true}},{"id":"2","attributes":{"code":"CAD","symbol":"$","rate_to_usd":0.79319156,"display_decimals":true}},{"id":"3","attributes":{"code":"USD","symbol":"$","rate_to_usd":1,"display_decimals":true}},{"id":"4","attributes":{"code":"JPY","symbol":"¥","rate_to_usd":0.0083864261,"display_decimals":false}},{"id":"5","attributes":{"code":"BRL","symbol":"R$","rate_to_usd":0.19904328,"display_decimals":true}},{"id":"6","attributes":{"code":"GBP","symbol":"£","rate_to_usd":1.3181323,"display_decimals":true}},{"id":"7","attributes":{"code":"AUD","symbol":"$","rate_to_usd":0.7422,"display_decimals":true}},{"id":"8","attributes":{"code":"INR","symbol":"₹","rate_to_usd":0.013162881,"display_decimals":false}},{"id":"9","attributes":{"code":"NZD","symbol":"$","rate_to_usd":0.69089984,"display_decimals":true}},{"id":"10","attributes":{"code":"CHF","symbol":"CHF","rate_to_usd":1.0728706,"display_decimals":true}}]}} | ||||
							
								
								
									
										1
									
								
								public/local-data/languages.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								public/local-data/languages.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| {"languages":{"data":[{"id":"1","attributes":{"name":"French","code":"fr","localized_name":"Français"}},{"id":"2","attributes":{"name":"English","code":"en","localized_name":"English"}},{"id":"3","attributes":{"name":"Japanese","code":"ja","localized_name":"日本語"}},{"id":"4","attributes":{"name":"Spanish","code":"es","localized_name":"Español"}},{"id":"6","attributes":{"name":"Portuguese (Brazil)","code":"pt-br","localized_name":"Português (Brasil)"}},{"id":"8","attributes":{"name":"German","code":"de","localized_name":"Deutsch"}},{"id":"9","attributes":{"name":"Italian","code":"it","localized_name":"Italiano"}},{"id":"10","attributes":{"name":"Russian","code":"ru","localized_name":"русский"}},{"id":"11","attributes":{"name":"Korean","code":"ko","localized_name":"한국어"}},{"id":"12","attributes":{"name":"Chinese (Traditional)","code":"zh-cht","localized_name":"中文(繁體)"}}]}} | ||||
							
								
								
									
										1
									
								
								public/local-data/websiteInterfaces.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								public/local-data/websiteInterfaces.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @ -1,7 +1,7 @@ | ||||
| import { Ico, Icon } from "./Ico"; | ||||
| import { ToolTip } from "./ToolTip"; | ||||
| import { AppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { cJoin } from "helpers/className"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| 
 | ||||
| /* | ||||
|  *                                        ╭─────────────╮ | ||||
| @ -10,37 +10,39 @@ import { cJoin } from "helpers/className"; | ||||
| 
 | ||||
| interface Props { | ||||
|   id: string; | ||||
|   langui: AppStaticProps["langui"]; | ||||
|   className?: string; | ||||
| } | ||||
| 
 | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| 
 | ||||
| export const AnchorShare = ({ id, langui, className }: Props): JSX.Element => ( | ||||
|   <ToolTip | ||||
|     content={langui.copy_anchor_link} | ||||
|     trigger="mouseenter" | ||||
|     className="text-sm" | ||||
|   > | ||||
| export const AnchorShare = ({ id, className }: Props): JSX.Element => { | ||||
|   const { langui } = useAppLayout(); | ||||
|   return ( | ||||
|     <ToolTip | ||||
|       content={langui.anchor_link_copied} | ||||
|       trigger="click" | ||||
|       content={langui.copy_anchor_link} | ||||
|       trigger="mouseenter" | ||||
|       className="text-sm" | ||||
|     > | ||||
|       <Ico | ||||
|         icon={Icon.Link} | ||||
|         className={cJoin( | ||||
|           "transition-color cursor-pointer hover:text-dark", | ||||
|           className | ||||
|         )} | ||||
|         onClick={() => { | ||||
|           navigator.clipboard.writeText( | ||||
|             `${ | ||||
|               process.env.NEXT_PUBLIC_URL_SELF + window.location.pathname | ||||
|             }#${id}` | ||||
|           ); | ||||
|         }} | ||||
|       /> | ||||
|       <ToolTip | ||||
|         content={langui.anchor_link_copied} | ||||
|         trigger="click" | ||||
|         className="text-sm" | ||||
|       > | ||||
|         <Ico | ||||
|           icon={Icon.Link} | ||||
|           className={cJoin( | ||||
|             "transition-color cursor-pointer hover:text-dark", | ||||
|             className | ||||
|           )} | ||||
|           onClick={() => { | ||||
|             navigator.clipboard.writeText( | ||||
|               `${ | ||||
|                 process.env.NEXT_PUBLIC_URL_SELF + window.location.pathname | ||||
|               }#${id}` | ||||
|             ); | ||||
|           }} | ||||
|         /> | ||||
|       </ToolTip> | ||||
|     </ToolTip> | ||||
|   </ToolTip> | ||||
| ); | ||||
|   ); | ||||
| }; | ||||
|  | ||||
| @ -1,9 +1,10 @@ | ||||
| import Head from "next/head"; | ||||
| import { useRouter } from "next/router"; | ||||
| import { useEffect, useLayoutEffect, useMemo, useState } from "react"; | ||||
| import { useEffect, useMemo, useState } from "react"; | ||||
| import { useSwipeable } from "react-swipeable"; | ||||
| import UAParser from "ua-parser-js"; | ||||
| import { useBoolean, useIsClient } from "usehooks-ts"; | ||||
| import Script from "next/script"; | ||||
| import { layout } from "../../design.config"; | ||||
| import { Ico, Icon } from "./Ico"; | ||||
| import { ButtonGroup } from "./Inputs/ButtonGroup"; | ||||
| @ -13,20 +14,12 @@ import { TextInput } from "./Inputs/TextInput"; | ||||
| import { MainPanel } from "./Panels/MainPanel"; | ||||
| import { Popup } from "./Popup"; | ||||
| import { AnchorIds } from "hooks/useScrollTopOnChange"; | ||||
| import { | ||||
|   filterHasAttributes, | ||||
|   isDefined, | ||||
|   isDefinedAndNotEmpty, | ||||
|   isUndefined, | ||||
|   iterateMap, | ||||
| } from "helpers/others"; | ||||
| import { filterHasAttributes, isDefined, isUndefined } from "helpers/others"; | ||||
| import { prettyLanguage } from "helpers/formatters"; | ||||
| import { cIf, cJoin } from "helpers/className"; | ||||
| import { AppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| import { Button } from "components/Inputs/Button"; | ||||
| import { OpenGraph, TITLE_PREFIX, TITLE_SEPARATOR } from "helpers/openGraph"; | ||||
| import { getDefaultPreferredLanguages } from "helpers/locales"; | ||||
| import { | ||||
|   useIs1ColumnLayout, | ||||
|   useIsScreenAtLeast, | ||||
| @ -49,7 +42,7 @@ export interface AppLayoutRequired { | ||||
|   openGraph: OpenGraph; | ||||
| } | ||||
| 
 | ||||
| interface Props extends AppStaticProps, AppLayoutRequired { | ||||
| interface Props extends AppLayoutRequired { | ||||
|   subPanel?: React.ReactNode; | ||||
|   subPanelIcon?: Icon; | ||||
|   contentPanel?: React.ReactNode; | ||||
| @ -59,9 +52,6 @@ interface Props extends AppStaticProps, AppLayoutRequired { | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| 
 | ||||
| export const AppLayout = ({ | ||||
|   langui, | ||||
|   currencies, | ||||
|   languages, | ||||
|   subPanel, | ||||
|   contentPanel, | ||||
|   openGraph, | ||||
| @ -96,6 +86,9 @@ export const AppLayout = ({ | ||||
|     setScreenWidth, | ||||
|     setContentPanelWidth, | ||||
|     setSubPanelWidth, | ||||
|     langui, | ||||
|     currencies, | ||||
|     languages, | ||||
|   } = useAppLayout(); | ||||
| 
 | ||||
|   const router = useRouter(); | ||||
| @ -106,18 +99,6 @@ export const AppLayout = ({ | ||||
|   useOnResize(AnchorIds.ContentPanel, (width) => setContentPanelWidth(width)); | ||||
|   useOnResize(AnchorIds.SubPanel, (width) => setSubPanelWidth(width)); | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|     router.events.on("routeChangeStart", () => { | ||||
|       setConfigPanelOpen(false); | ||||
|       setMainPanelOpen(false); | ||||
|       setSubPanelOpen(false); | ||||
|     }); | ||||
| 
 | ||||
|     router.events.on("hashChangeStart", () => { | ||||
|       setSubPanelOpen(false); | ||||
|     }); | ||||
|   }, [router.events, setConfigPanelOpen, setMainPanelOpen, setSubPanelOpen]); | ||||
| 
 | ||||
|   const handlers = useSwipeable({ | ||||
|     onSwipedLeft: (SwipeEventData) => { | ||||
|       if (menuGestures) { | ||||
| @ -146,12 +127,6 @@ export const AppLayout = ({ | ||||
|     [contentPanel, subPanel] | ||||
|   ); | ||||
| 
 | ||||
|   useLayoutEffect(() => { | ||||
|     document.getElementsByTagName("html")[0].style.fontSize = `${ | ||||
|       fontSize * 100 | ||||
|     }%`;
 | ||||
|   }, [fontSize]); | ||||
| 
 | ||||
|   const currencyOptions = useMemo( | ||||
|     () => | ||||
|       filterHasAttributes(currencies, ["attributes"] as const).map( | ||||
| @ -171,26 +146,6 @@ export const AppLayout = ({ | ||||
|     if (currencySelect >= 0) setCurrency(currencyOptions[currencySelect]); | ||||
|   }, [currencyOptions, currencySelect, setCurrency]); | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|     if (preferredLanguages.length === 0) { | ||||
|       if (isDefinedAndNotEmpty(router.locale) && router.locales) { | ||||
|         setPreferredLanguages( | ||||
|           getDefaultPreferredLanguages(router.locale, router.locales) | ||||
|         ); | ||||
|       } | ||||
|     } else if (router.locale !== preferredLanguages[0]) { | ||||
|       router.replace(router.asPath, router.asPath, { | ||||
|         locale: preferredLanguages[0], | ||||
|       }); | ||||
|     } | ||||
|   }, [ | ||||
|     preferredLanguages, | ||||
|     router, | ||||
|     router.locale, | ||||
|     router.locales, | ||||
|     setPreferredLanguages, | ||||
|   ]); | ||||
| 
 | ||||
|   const isClient = useIsClient(); | ||||
|   const { value: hasDisgardSafariWarning, setTrue: disgardSafariWarning } = | ||||
|     useBoolean(false); | ||||
| @ -256,15 +211,15 @@ export const AppLayout = ({ | ||||
|           /> | ||||
|           <meta property="og:image:alt" content={openGraph.thumbnail.alt} /> | ||||
|           <meta property="og:image:type" content="image/jpeg" /> | ||||
| 
 | ||||
|           <script | ||||
|             async | ||||
|             defer | ||||
|             data-website-id={process.env.NEXT_PUBLIC_UMAMI_ID} | ||||
|             src={`${process.env.NEXT_PUBLIC_UMAMI_URL}/umami.js`} | ||||
|           /> | ||||
|         </Head> | ||||
| 
 | ||||
|         <Script | ||||
|           async | ||||
|           defer | ||||
|           data-website-id={process.env.NEXT_PUBLIC_UMAMI_ID} | ||||
|           src={`${process.env.NEXT_PUBLIC_UMAMI_URL}/umami.js`} | ||||
|         /> | ||||
| 
 | ||||
|         {/* Background when navbar is opened */} | ||||
|         <div | ||||
|           className={cJoin( | ||||
| @ -354,7 +309,7 @@ export const AppLayout = ({ | ||||
|             cIf(!mainPanelOpen && is1ColumnLayout, "-translate-x-full") | ||||
|           )} | ||||
|         > | ||||
|           <MainPanel langui={langui} /> | ||||
|           <MainPanel /> | ||||
|         </div> | ||||
| 
 | ||||
|         {/* Navbar */} | ||||
| @ -448,24 +403,24 @@ export const AppLayout = ({ | ||||
|                 <h3 className="text-xl">{langui.languages}</h3> | ||||
|                 {preferredLanguages.length > 0 && ( | ||||
|                   <OrderableList | ||||
|                     items={ | ||||
|                       new Map( | ||||
|                         preferredLanguages.map((locale) => [ | ||||
|                           locale, | ||||
|                           prettyLanguage(locale, languages), | ||||
|                         ]) | ||||
|                       ) | ||||
|                     } | ||||
|                     insertLabels={ | ||||
|                       new Map([ | ||||
|                         [0, langui.primary_language], | ||||
|                         [1, langui.secondary_language], | ||||
|                       ]) | ||||
|                     } | ||||
|                     items={preferredLanguages.map((locale) => ({ | ||||
|                       code: locale, | ||||
|                       name: prettyLanguage(locale, languages), | ||||
|                     }))} | ||||
|                     insertLabels={[ | ||||
|                       { | ||||
|                         insertAt: 0, | ||||
|                         name: langui.primary_language ?? "Primary language", | ||||
|                       }, | ||||
|                       { | ||||
|                         insertAt: 1, | ||||
|                         name: | ||||
|                           langui.secondary_language ?? "Secondary languages", | ||||
|                       }, | ||||
|                     ]} | ||||
|                     onChange={(items) => { | ||||
|                       const newPreferredLanguages = iterateMap( | ||||
|                         items, | ||||
|                         (code) => code | ||||
|                       const newPreferredLanguages = items.map( | ||||
|                         (item) => item.code | ||||
|                       ); | ||||
|                       setPreferredLanguages(newPreferredLanguages); | ||||
|                     }} | ||||
|  | ||||
| @ -2,10 +2,10 @@ import { Fragment } from "react"; | ||||
| import { ToolTip } from "../ToolTip"; | ||||
| import { Button } from "./Button"; | ||||
| import { Icon } from "components/Ico"; | ||||
| import { AppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { cJoin } from "helpers/className"; | ||||
| import { prettyLanguage } from "helpers/formatters"; | ||||
| import { iterateMap } from "helpers/others"; | ||||
| import { useLanguages } from "hooks/useLocalData"; | ||||
| 
 | ||||
| /* | ||||
|  *                                        ╭─────────────╮ | ||||
| @ -14,7 +14,6 @@ import { iterateMap } from "helpers/others"; | ||||
| 
 | ||||
| interface Props { | ||||
|   className?: string; | ||||
|   languages: AppStaticProps["languages"]; | ||||
|   locales: Map<string, number>; | ||||
|   localesIndex: number | undefined; | ||||
|   onLanguageChanged: (index: number) => void; | ||||
| @ -28,30 +27,32 @@ export const LanguageSwitcher = ({ | ||||
|   className, | ||||
|   locales, | ||||
|   localesIndex, | ||||
|   languages, | ||||
|   size, | ||||
|   onLanguageChanged, | ||||
|   showBadge = true, | ||||
| }: Props): JSX.Element => ( | ||||
|   <ToolTip | ||||
|     content={ | ||||
|       <div className={cJoin("flex flex-col gap-2", className)}> | ||||
|         {iterateMap(locales, (locale, value, index) => ( | ||||
|           <Fragment key={index}> | ||||
|             <Button | ||||
|               active={value === localesIndex} | ||||
|               onClick={() => onLanguageChanged(value)} | ||||
|               text={prettyLanguage(locale, languages)} | ||||
|             /> | ||||
|           </Fragment> | ||||
|         ))} | ||||
|       </div> | ||||
|     } | ||||
|   > | ||||
|     <Button | ||||
|       badgeNumber={showBadge && locales.size > 1 ? locales.size : undefined} | ||||
|       icon={Icon.Translate} | ||||
|       size={size} | ||||
|     /> | ||||
|   </ToolTip> | ||||
| ); | ||||
| }: Props): JSX.Element => { | ||||
|   const languages = useLanguages(); | ||||
|   return ( | ||||
|     <ToolTip | ||||
|       content={ | ||||
|         <div className={cJoin("flex flex-col gap-2", className)}> | ||||
|           {iterateMap(locales, (locale, value, index) => ( | ||||
|             <Fragment key={index}> | ||||
|               <Button | ||||
|                 active={value === localesIndex} | ||||
|                 onClick={() => onLanguageChanged(value)} | ||||
|                 text={prettyLanguage(locale, languages)} | ||||
|               /> | ||||
|             </Fragment> | ||||
|           ))} | ||||
|         </div> | ||||
|       } | ||||
|     > | ||||
|       <Button | ||||
|         badgeNumber={showBadge && locales.size > 1 ? locales.size : undefined} | ||||
|         icon={Icon.Translate} | ||||
|         size={size} | ||||
|       /> | ||||
|     </ToolTip> | ||||
|   ); | ||||
| }; | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| import { Fragment, useCallback, useState } from "react"; | ||||
| import { Fragment, useCallback } from "react"; | ||||
| import { Ico, Icon } from "components/Ico"; | ||||
| import { isDefinedAndNotEmpty, iterateMap, mapMoveEntry } from "helpers/others"; | ||||
| import { arrayMove, isDefinedAndNotEmpty } from "helpers/others"; | ||||
| 
 | ||||
| /* | ||||
|  *                                        ╭─────────────╮ | ||||
| @ -9,35 +9,32 @@ import { isDefinedAndNotEmpty, iterateMap, mapMoveEntry } from "helpers/others"; | ||||
| 
 | ||||
| interface Props { | ||||
|   className?: string; | ||||
|   items: Map<string, string>; | ||||
|   insertLabels?: Map<number, string | null | undefined>; | ||||
|   onChange?: (items: Map<string, string>) => void; | ||||
|   items: { code: string; name: string }[]; | ||||
|   insertLabels?: { insertAt: number; name: string }[]; | ||||
|   onChange?: (props: Props["items"]) => void; | ||||
| } | ||||
| 
 | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| 
 | ||||
| export const OrderableList = ({ | ||||
|   onChange, | ||||
|   items: propsItems, | ||||
|   items, | ||||
|   insertLabels, | ||||
| }: Props): JSX.Element => { | ||||
|   const [items, setItems] = useState<Map<string, string>>(propsItems); | ||||
| 
 | ||||
|   const updateOrder = useCallback( | ||||
|     (sourceIndex: number, targetIndex: number) => { | ||||
|       const newItems = mapMoveEntry(items, sourceIndex, targetIndex); | ||||
|       setItems(newItems); | ||||
|       onChange?.(newItems); | ||||
|       console.log("updateOrder"); | ||||
|       onChange?.(arrayMove(items, sourceIndex, targetIndex)); | ||||
|     }, | ||||
|     [items, onChange] | ||||
|   ); | ||||
| 
 | ||||
|   return ( | ||||
|     <div className="grid gap-2"> | ||||
|       {iterateMap(items, (key, value, index) => ( | ||||
|         <Fragment key={key}> | ||||
|           {insertLabels && isDefinedAndNotEmpty(insertLabels.get(index)) && ( | ||||
|             <p>{insertLabels.get(index)}</p> | ||||
|       {items.map((item, index) => ( | ||||
|         <Fragment key={index}> | ||||
|           {insertLabels && isDefinedAndNotEmpty(insertLabels[index]?.name) && ( | ||||
|             <p>{insertLabels[index].name}</p> | ||||
|           )} | ||||
|           <div | ||||
|             onDragStart={(event) => { | ||||
| @ -81,7 +78,7 @@ export const OrderableList = ({ | ||||
|                   }} | ||||
|                 /> | ||||
|               )} | ||||
|               {index < items.size - 1 && ( | ||||
|               {index < items.length - 1 && ( | ||||
|                 <Ico | ||||
|                   icon={Icon.ArrowDropDown} | ||||
|                   className="row-start-2 cursor-pointer" | ||||
| @ -91,7 +88,7 @@ export const OrderableList = ({ | ||||
|                 /> | ||||
|               )} | ||||
|             </div> | ||||
|             {value} | ||||
|             {item.name} | ||||
|           </div> | ||||
|         </Fragment> | ||||
|       ))} | ||||
|  | ||||
| @ -1,9 +1,8 @@ | ||||
| import { Icon } from "components/Ico"; | ||||
| import { Button } from "components/Inputs/Button"; | ||||
| import { ToolTip } from "components/ToolTip"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| import { AppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { LibraryItemUserStatus } from "helpers/types"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| 
 | ||||
| /* | ||||
|  *                                        ╭─────────────╮ | ||||
| @ -13,17 +12,13 @@ import { LibraryItemUserStatus } from "helpers/types"; | ||||
| interface Props { | ||||
|   id: string; | ||||
|   expand?: boolean; | ||||
|   langui: AppStaticProps["langui"]; | ||||
| } | ||||
| 
 | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| 
 | ||||
| export const PreviewCardCTAs = ({ | ||||
|   id, | ||||
|   expand = false, | ||||
|   langui, | ||||
| }: Props): JSX.Element => { | ||||
|   const { libraryItemUserStatus, setLibraryItemUserStatus } = useAppLayout(); | ||||
| export const PreviewCardCTAs = ({ id, expand = false }: Props): JSX.Element => { | ||||
|   const { libraryItemUserStatus, setLibraryItemUserStatus, langui } = | ||||
|     useAppLayout(); | ||||
|   return ( | ||||
|     <> | ||||
|       <div | ||||
|  | ||||
| @ -6,7 +6,6 @@ import { HorizontalLine } from "components/HorizontalLine"; | ||||
| import { Img } from "components/Img"; | ||||
| import { InsetBox } from "components/InsetBox"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| import { AppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { cIf, cJoin } from "helpers/className"; | ||||
| import { slugify } from "helpers/formatters"; | ||||
| import { getAssetURL, ImageQuality } from "helpers/img"; | ||||
| @ -26,7 +25,6 @@ import { useDeviceSupportsHover } from "hooks/useMediaQuery"; | ||||
| interface MarkdawnProps { | ||||
|   className?: string; | ||||
|   text: string; | ||||
|   langui: AppStaticProps["langui"]; | ||||
| } | ||||
| 
 | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| @ -34,7 +32,6 @@ interface MarkdawnProps { | ||||
| export const Markdawn = ({ | ||||
|   className, | ||||
|   text: rawText, | ||||
|   langui, | ||||
| }: MarkdawnProps): JSX.Element => { | ||||
|   const { playerName } = useAppLayout(); | ||||
|   const router = useRouter(); | ||||
| @ -93,7 +90,6 @@ export const Markdawn = ({ | ||||
|               }) => ( | ||||
|                 <Header | ||||
|                   title={compProps.children} | ||||
|                   langui={langui} | ||||
|                   level={parseInt(compProps.level, 10)} | ||||
|                   slug={compProps.id} | ||||
|                 /> | ||||
| @ -102,12 +98,7 @@ export const Markdawn = ({ | ||||
| 
 | ||||
|             SceneBreak: { | ||||
|               component: (compProps: { id: string }) => ( | ||||
|                 <Header | ||||
|                   title={"* * *"} | ||||
|                   langui={langui} | ||||
|                   level={6} | ||||
|                   slug={compProps.id} | ||||
|                 /> | ||||
|                 <Header title={"* * *"} level={6} slug={compProps.id} /> | ||||
|               ), | ||||
|             }, | ||||
| 
 | ||||
| @ -158,7 +149,7 @@ export const Markdawn = ({ | ||||
|                       cIf(!isContentPanelAtLeastLg, "!-mb-4") | ||||
|                     )} | ||||
|                   > | ||||
|                     <Markdawn text={compProps.name} langui={langui} /> | ||||
|                     <Markdawn text={compProps.name} /> | ||||
|                   </strong> | ||||
|                   <p className="whitespace-pre-line">{compProps.children}</p> | ||||
|                 </> | ||||
| @ -266,17 +257,18 @@ export const Markdawn = ({ | ||||
| interface TableOfContentsProps { | ||||
|   text: string; | ||||
|   title?: string; | ||||
|   langui: AppStaticProps["langui"]; | ||||
| 
 | ||||
|   horizontalLine?: boolean; | ||||
| } | ||||
| 
 | ||||
| export const TableOfContents = ({ | ||||
|   text, | ||||
|   title, | ||||
|   langui, | ||||
| 
 | ||||
|   horizontalLine = false, | ||||
| }: TableOfContentsProps): JSX.Element => { | ||||
|   const router = useRouter(); | ||||
|   const { langui } = useAppLayout(); | ||||
|   const toc = useMemo( | ||||
|     () => getTocFromMarkdawn(preprocessMarkDawn(text), title), | ||||
|     [text, title] | ||||
| @ -314,10 +306,9 @@ interface HeaderProps { | ||||
|   level: number; | ||||
|   title: string; | ||||
|   slug: string; | ||||
|   langui: AppStaticProps["langui"]; | ||||
| } | ||||
| 
 | ||||
| const Header = ({ level, title, slug, langui }: HeaderProps): JSX.Element => { | ||||
| const Header = ({ level, title, slug }: HeaderProps): JSX.Element => { | ||||
|   const isHoverable = useDeviceSupportsHover(); | ||||
|   const innerComponent = useMemo( | ||||
|     () => ( | ||||
| @ -338,12 +329,11 @@ const Header = ({ level, title, slug, langui }: HeaderProps): JSX.Element => { | ||||
|               "opacity-0 transition-opacity group-hover:opacity-100" | ||||
|             )} | ||||
|             id={slug} | ||||
|             langui={langui} | ||||
|           /> | ||||
|         </div> | ||||
|       </> | ||||
|     ), | ||||
|     [isHoverable, langui, slug, title] | ||||
|     [isHoverable, slug, title] | ||||
|   ); | ||||
| 
 | ||||
|   switch (level) { | ||||
|  | ||||
| @ -2,7 +2,6 @@ import { useCallback } from "react"; | ||||
| import { Icon } from "components/Ico"; | ||||
| import { Button } from "components/Inputs/Button"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| import { AppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { TranslatedProps } from "helpers/types/TranslatedProps"; | ||||
| import { useSmartLanguage } from "hooks/useSmartLanguage"; | ||||
| import { useIs3ColumnsLayout } from "hooks/useContainerQuery"; | ||||
| @ -16,7 +15,7 @@ import { isDefined } from "helpers/others"; | ||||
| interface Props { | ||||
|   href: string; | ||||
|   title: string | null | undefined; | ||||
|   langui: AppStaticProps["langui"]; | ||||
| 
 | ||||
|   displayOnlyOn?: "1ColumnLayout" | "3ColumnsLayout"; | ||||
|   className?: string; | ||||
| } | ||||
| @ -26,11 +25,10 @@ interface Props { | ||||
| export const ReturnButton = ({ | ||||
|   href, | ||||
|   title, | ||||
|   langui, | ||||
|   displayOnlyOn, | ||||
|   className, | ||||
| }: Props): JSX.Element => { | ||||
|   const { setSubPanelOpen } = useAppLayout(); | ||||
|   const { setSubPanelOpen, langui } = useAppLayout(); | ||||
|   const is3ColumnsLayout = useIs3ColumnsLayout(); | ||||
| 
 | ||||
|   return ( | ||||
|  | ||||
| @ -4,7 +4,6 @@ import { Button } from "components/Inputs/Button"; | ||||
| import { NavOption } from "components/PanelComponents/NavOption"; | ||||
| import { ToolTip } from "components/ToolTip"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| import { AppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { Icon } from "components/Ico"; | ||||
| import { cIf, cJoin } from "helpers/className"; | ||||
| import { isDefinedAndNotEmpty } from "helpers/others"; | ||||
| @ -16,18 +15,13 @@ import { useIs3ColumnsLayout } from "hooks/useContainerQuery"; | ||||
|  * ───────────────────────────────────────╯  COMPONENT  ╰─────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props { | ||||
|   langui: AppStaticProps["langui"]; | ||||
| } | ||||
| 
 | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| 
 | ||||
| export const MainPanel = ({ langui }: Props): JSX.Element => { | ||||
| export const MainPanel = (): JSX.Element => { | ||||
|   const is3ColumnsLayout = useIs3ColumnsLayout(); | ||||
|   const { | ||||
|     mainPanelReduced = false, | ||||
|     toggleMainPanelReduced, | ||||
|     setConfigPanelOpen, | ||||
|     langui, | ||||
|   } = useAppLayout(); | ||||
| 
 | ||||
|   return ( | ||||
|  | ||||
| @ -13,7 +13,7 @@ import { useSmartLanguage } from "hooks/useSmartLanguage"; | ||||
| import { PostWithTranslations } from "helpers/types"; | ||||
| import { filterHasAttributes, getStatusDescription } from "helpers/others"; | ||||
| import { prettySlug } from "helpers/formatters"; | ||||
| import { AppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| 
 | ||||
| /* | ||||
|  *                                        ╭─────────────╮ | ||||
| @ -22,9 +22,6 @@ import { AppStaticProps } from "graphql/getAppStaticProps"; | ||||
| 
 | ||||
| interface Props extends AppLayoutRequired { | ||||
|   post: PostWithTranslations; | ||||
|   langui: AppStaticProps["langui"]; | ||||
|   languages: AppStaticProps["languages"]; | ||||
|   currencies: AppStaticProps["currencies"]; | ||||
|   returnHref?: string; | ||||
|   returnTitle?: string | null | undefined; | ||||
|   displayCredits?: boolean; | ||||
| @ -40,8 +37,6 @@ interface Props extends AppLayoutRequired { | ||||
| 
 | ||||
| export const PostPage = ({ | ||||
|   post, | ||||
|   langui, | ||||
|   languages, | ||||
|   returnHref, | ||||
|   returnTitle, | ||||
|   displayCredits, | ||||
| @ -53,10 +48,10 @@ export const PostPage = ({ | ||||
|   displayTitle = true, | ||||
|   ...otherProps | ||||
| }: Props): JSX.Element => { | ||||
|   const { langui } = useAppLayout(); | ||||
|   const [selectedTranslation, LanguageSwitcher, languageSwitcherProps] = | ||||
|     useSmartLanguage({ | ||||
|       items: post.translations, | ||||
|       languages: languages, | ||||
|       languageExtractor: useCallback( | ||||
|         (item: NonNullable<PostWithTranslations["translations"][number]>) => | ||||
|           item.language?.data?.attributes?.code, | ||||
| @ -84,7 +79,6 @@ export const PostPage = ({ | ||||
|             <ReturnButton | ||||
|               href={returnHref} | ||||
|               title={returnTitle} | ||||
|               langui={langui} | ||||
|               displayOnlyOn={"3ColumnsLayout"} | ||||
|             /> | ||||
|           )} | ||||
| @ -118,10 +112,7 @@ export const PostPage = ({ | ||||
|                       "attributes", | ||||
|                     ] as const).map((author) => ( | ||||
|                       <Fragment key={author.id}> | ||||
|                         <RecorderChip | ||||
|                           langui={langui} | ||||
|                           recorder={author.attributes} | ||||
|                         /> | ||||
|                         <RecorderChip recorder={author.attributes} /> | ||||
|                       </Fragment> | ||||
|                     ))} | ||||
|                   </div> | ||||
| @ -131,12 +122,7 @@ export const PostPage = ({ | ||||
|           )} | ||||
| 
 | ||||
|           {displayToc && ( | ||||
|             <TableOfContents | ||||
|               text={body} | ||||
|               title={title} | ||||
|               langui={langui} | ||||
|               horizontalLine | ||||
|             /> | ||||
|             <TableOfContents text={body} title={title} horizontalLine /> | ||||
|           )} | ||||
|         </SubPanel> | ||||
|       ) : undefined, | ||||
| @ -160,7 +146,6 @@ export const PostPage = ({ | ||||
|           <ReturnButton | ||||
|             href={returnHref} | ||||
|             title={returnTitle} | ||||
|             langui={langui} | ||||
|             displayOnlyOn={"1ColumnLayout"} | ||||
|             className="mb-10" | ||||
|           /> | ||||
| @ -172,7 +157,6 @@ export const PostPage = ({ | ||||
|               thumbnail={thumbnail} | ||||
|               title={title} | ||||
|               description={excerpt} | ||||
|               langui={langui} | ||||
|               categories={post.categories} | ||||
|               languageSwitcher={ | ||||
|                 languageSwitcherProps.locales.size > 1 ? ( | ||||
| @ -200,7 +184,7 @@ export const PostPage = ({ | ||||
|         {body && ( | ||||
|           <> | ||||
|             {displayThumbnailHeader && <HorizontalLine />} | ||||
|             <Markdawn text={body} langui={langui} /> | ||||
|             <Markdawn text={body} /> | ||||
|           </> | ||||
|         )} | ||||
| 
 | ||||
| @ -216,7 +200,6 @@ export const PostPage = ({ | ||||
|       displayTitle, | ||||
|       excerpt, | ||||
|       languageSwitcherProps, | ||||
|       langui, | ||||
|       post.categories, | ||||
|       prependBody, | ||||
|       returnHref, | ||||
| @ -231,8 +214,6 @@ export const PostPage = ({ | ||||
|       {...otherProps} | ||||
|       contentPanel={contentPanel} | ||||
|       subPanel={subPanel} | ||||
|       languages={languages} | ||||
|       langui={langui} | ||||
|     /> | ||||
|   ); | ||||
| }; | ||||
|  | ||||
| @ -10,7 +10,6 @@ import { | ||||
|   PricePickerFragment, | ||||
|   UploadImageFragment, | ||||
| } from "graphql/generated"; | ||||
| import { AppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { cIf, cJoin } from "helpers/className"; | ||||
| import { | ||||
|   prettyDate, | ||||
| @ -22,6 +21,7 @@ import { ImageQuality } from "helpers/img"; | ||||
| import { useDeviceSupportsHover } from "hooks/useMediaQuery"; | ||||
| import { useSmartLanguage } from "hooks/useSmartLanguage"; | ||||
| import { TranslatedProps } from "helpers/types/TranslatedProps"; | ||||
| import { useCurrencies } from "hooks/useLocalData"; | ||||
| 
 | ||||
| /* | ||||
|  *                                        ╭─────────────╮ | ||||
| @ -43,7 +43,6 @@ interface Props { | ||||
|   keepInfoVisible?: boolean; | ||||
|   stackNumber?: number; | ||||
|   metadata?: { | ||||
|     currencies?: AppStaticProps["currencies"]; | ||||
|     releaseDate?: DatePickerFragment | null; | ||||
|     releaseDateFormat?: Intl.DateTimeFormatOptions["dateStyle"]; | ||||
|     price?: PricePickerFragment | null; | ||||
| @ -83,6 +82,7 @@ export const PreviewCard = ({ | ||||
|   const { currency } = useAppLayout(); | ||||
|   const isHoverable = useDeviceSupportsHover(); | ||||
|   const router = useRouter(); | ||||
|   const currencies = useCurrencies(); | ||||
| 
 | ||||
|   const metadataJSX = useMemo( | ||||
|     () => ( | ||||
| @ -98,13 +98,13 @@ export const PreviewCard = ({ | ||||
|                 {prettyDate(metadata.releaseDate, router.locale)} | ||||
|               </p> | ||||
|             )} | ||||
|             {metadata.price && metadata.currencies && ( | ||||
|             {metadata.price && ( | ||||
|               <p className="justify-self-end text-sm"> | ||||
|                 <Ico | ||||
|                   icon={Icon.ShoppingCart} | ||||
|                   className="mr-1 translate-y-[.15em] !text-base" | ||||
|                 /> | ||||
|                 {prettyPrice(metadata.price, metadata.currencies, currency)} | ||||
|                 {prettyPrice(metadata.price, currencies, currency)} | ||||
|               </p> | ||||
|             )} | ||||
|             {metadata.views && ( | ||||
| @ -129,7 +129,7 @@ export const PreviewCard = ({ | ||||
|         )} | ||||
|       </> | ||||
|     ), | ||||
|     [currency, metadata, router.locale] | ||||
|     [currencies, currency, metadata, router.locale] | ||||
|   ); | ||||
| 
 | ||||
|   return ( | ||||
|  | ||||
| @ -4,9 +4,9 @@ import { Markdawn } from "./Markdown/Markdawn"; | ||||
| import { ToolTip } from "./ToolTip"; | ||||
| import { Chip } from "components/Chip"; | ||||
| import { RecorderChipFragment } from "graphql/generated"; | ||||
| import { AppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { ImageQuality } from "helpers/img"; | ||||
| import { filterHasAttributes } from "helpers/others"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| 
 | ||||
| /* | ||||
|  *                                        ╭─────────────╮ | ||||
| @ -16,59 +16,60 @@ import { filterHasAttributes } from "helpers/others"; | ||||
| interface Props { | ||||
|   className?: string; | ||||
|   recorder: RecorderChipFragment; | ||||
|   langui: AppStaticProps["langui"]; | ||||
| } | ||||
| 
 | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| 
 | ||||
| export const RecorderChip = ({ recorder, langui }: Props): JSX.Element => ( | ||||
|   <ToolTip | ||||
|     content={ | ||||
|       <div className="grid gap-8 p-2 py-5 text-left"> | ||||
|         <div className="grid grid-flow-col place-content-start place-items-center gap-6"> | ||||
|           {recorder.avatar?.data?.attributes && ( | ||||
|             <Img | ||||
|               className="aspect-square w-20 rounded-full border-4 border-mid object-cover" | ||||
|               src={recorder.avatar.data.attributes} | ||||
|               quality={ImageQuality.Small} | ||||
|             /> | ||||
|           )} | ||||
|           <div className="grid gap-2"> | ||||
|             <h3 className=" text-2xl">{recorder.username}</h3> | ||||
|             {recorder.languages?.data && recorder.languages.data.length > 0 && ( | ||||
|               <div className="flex flex-row flex-wrap gap-1"> | ||||
|                 <p>{langui.languages}:</p> | ||||
|                 {filterHasAttributes(recorder.languages.data, [ | ||||
|                   "attributes", | ||||
|                 ] as const).map((language) => ( | ||||
|                   <Fragment key={language.__typename}> | ||||
|                     <Chip text={language.attributes.code.toUpperCase()} /> | ||||
|                   </Fragment> | ||||
|                 ))} | ||||
|               </div> | ||||
|             )} | ||||
|             {recorder.pronouns && ( | ||||
|               <div className="flex flex-row flex-wrap gap-1"> | ||||
|                 <p>{langui.pronouns}:</p> | ||||
|                 <Chip text={recorder.pronouns} /> | ||||
|               </div> | ||||
| export const RecorderChip = ({ recorder }: Props): JSX.Element => { | ||||
|   const { langui } = useAppLayout(); | ||||
| 
 | ||||
|   return ( | ||||
|     <ToolTip | ||||
|       content={ | ||||
|         <div className="grid gap-8 p-2 py-5 text-left"> | ||||
|           <div className="grid grid-flow-col place-content-start place-items-center gap-6"> | ||||
|             {recorder.avatar?.data?.attributes && ( | ||||
|               <Img | ||||
|                 className="aspect-square w-20 rounded-full border-4 border-mid object-cover" | ||||
|                 src={recorder.avatar.data.attributes} | ||||
|                 quality={ImageQuality.Small} | ||||
|               /> | ||||
|             )} | ||||
|             <div className="grid gap-2"> | ||||
|               <h3 className=" text-2xl">{recorder.username}</h3> | ||||
|               {recorder.languages?.data && recorder.languages.data.length > 0 && ( | ||||
|                 <div className="flex flex-row flex-wrap gap-1"> | ||||
|                   <p>{langui.languages}:</p> | ||||
|                   {filterHasAttributes(recorder.languages.data, [ | ||||
|                     "attributes", | ||||
|                   ] as const).map((language) => ( | ||||
|                     <Fragment key={language.__typename}> | ||||
|                       <Chip text={language.attributes.code.toUpperCase()} /> | ||||
|                     </Fragment> | ||||
|                   ))} | ||||
|                 </div> | ||||
|               )} | ||||
|               {recorder.pronouns && ( | ||||
|                 <div className="flex flex-row flex-wrap gap-1"> | ||||
|                   <p>{langui.pronouns}:</p> | ||||
|                   <Chip text={recorder.pronouns} /> | ||||
|                 </div> | ||||
|               )} | ||||
|             </div> | ||||
|           </div> | ||||
|           {recorder.bio?.[0] && <Markdawn text={recorder.bio[0].bio ?? ""} />} | ||||
|         </div> | ||||
|         {recorder.bio?.[0] && ( | ||||
|           <Markdawn text={recorder.bio[0].bio ?? ""} langui={langui} /> | ||||
|         )} | ||||
|       </div> | ||||
|     } | ||||
|     placement="top" | ||||
|   > | ||||
|     <Chip | ||||
|       key={recorder.anonymous_code} | ||||
|       text={ | ||||
|         recorder.anonymize | ||||
|           ? `Recorder#${recorder.anonymous_code}` | ||||
|           : recorder.username | ||||
|       } | ||||
|     /> | ||||
|   </ToolTip> | ||||
| ); | ||||
|       placement="top" | ||||
|     > | ||||
|       <Chip | ||||
|         key={recorder.anonymous_code} | ||||
|         text={ | ||||
|           recorder.anonymize | ||||
|             ? `Recorder#${recorder.anonymous_code}` | ||||
|             : recorder.username | ||||
|         } | ||||
|       /> | ||||
|     </ToolTip> | ||||
|   ); | ||||
| }; | ||||
|  | ||||
| @ -2,11 +2,11 @@ import { Fragment, useCallback, useEffect, useMemo, useState } from "react"; | ||||
| import { Chip } from "./Chip"; | ||||
| import { PageSelector } from "./Inputs/PageSelector"; | ||||
| import { Ico, Icon } from "./Ico"; | ||||
| import { AppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { cJoin } from "helpers/className"; | ||||
| import { isDefined, isDefinedAndNotEmpty } from "helpers/others"; | ||||
| import { AnchorIds, useScrollTopOnChange } from "hooks/useScrollTopOnChange"; | ||||
| import { useIs3ColumnsLayout } from "hooks/useContainerQuery"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| 
 | ||||
| interface Group<T> { | ||||
|   name: string; | ||||
| @ -46,7 +46,6 @@ interface Props<T> { | ||||
|   sortingFunction?: (a: T, b: T) => number; | ||||
|   // Other
 | ||||
|   className?: string; | ||||
|   langui: AppStaticProps["langui"]; | ||||
| } | ||||
| 
 | ||||
| export const SmartList = <T,>({ | ||||
| @ -67,10 +66,9 @@ export const SmartList = <T,>({ | ||||
|   filteringFunction = defaultFilteringFunction, | ||||
|   sortingFunction = defaultSortingFunction, | ||||
|   className, | ||||
|   langui, | ||||
| }: Props<T>): JSX.Element => { | ||||
|   const [page, setPage] = useState(0); | ||||
| 
 | ||||
|   const { langui } = useAppLayout(); | ||||
|   useScrollTopOnChange(AnchorIds.ContentPanel, [page], paginationScroolTop); | ||||
|   useEffect( | ||||
|     () => setPage(0), | ||||
| @ -220,7 +218,7 @@ export const SmartList = <T,>({ | ||||
|         ) : isDefined(RenderWhenEmpty) ? ( | ||||
|           <RenderWhenEmpty /> | ||||
|         ) : ( | ||||
|           <DefaultRenderWhenEmpty langui={langui} /> | ||||
|           <DefaultRenderWhenEmpty /> | ||||
|         )} | ||||
|       </div> | ||||
| 
 | ||||
| @ -241,12 +239,9 @@ export const SmartList = <T,>({ | ||||
|  * ───────────────────────────────────╯  PRIVATE COMPONENTS  ╰────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface DefaultRenderWhenEmptyProps { | ||||
|   langui: AppStaticProps["langui"]; | ||||
| } | ||||
| 
 | ||||
| const DefaultRenderWhenEmpty = ({ langui }: DefaultRenderWhenEmptyProps) => { | ||||
| const DefaultRenderWhenEmpty = () => { | ||||
|   const is3ColumnsLayout = useIs3ColumnsLayout(); | ||||
|   const { langui } = useAppLayout(); | ||||
|   return ( | ||||
|     <div className="grid h-full place-content-center"> | ||||
|       <div | ||||
|  | ||||
| @ -3,11 +3,11 @@ import { Img } from "components/Img"; | ||||
| import { InsetBox } from "components/InsetBox"; | ||||
| import { Markdawn } from "components/Markdown/Markdawn"; | ||||
| import { GetContentTextQuery, UploadImageFragment } from "graphql/generated"; | ||||
| import { AppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { prettyInlineTitle, prettySlug, slugify } from "helpers/formatters"; | ||||
| import { getAssetURL, ImageQuality } from "helpers/img"; | ||||
| import { filterHasAttributes } from "helpers/others"; | ||||
| import { useLightBox } from "hooks/useLightBox"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| 
 | ||||
| /* | ||||
|  *                                        ╭─────────────╮ | ||||
| @ -26,14 +26,13 @@ interface Props { | ||||
|     NonNullable<GetContentTextQuery["contents"]>["data"][number]["attributes"] | ||||
|   >["categories"]; | ||||
|   thumbnail?: UploadImageFragment | null | undefined; | ||||
|   langui: AppStaticProps["langui"]; | ||||
| 
 | ||||
|   languageSwitcher?: JSX.Element; | ||||
| } | ||||
| 
 | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| 
 | ||||
| export const ThumbnailHeader = ({ | ||||
|   langui, | ||||
|   pre_title, | ||||
|   title, | ||||
|   subtitle, | ||||
| @ -44,6 +43,7 @@ export const ThumbnailHeader = ({ | ||||
|   languageSwitcher, | ||||
| }: Props): JSX.Element => { | ||||
|   const [openLightBox, LightBox] = useLightBox(); | ||||
|   const { langui } = useAppLayout(); | ||||
| 
 | ||||
|   return ( | ||||
|     <> | ||||
| @ -106,9 +106,7 @@ export const ThumbnailHeader = ({ | ||||
|         {languageSwitcher} | ||||
|       </div> | ||||
|       {description && ( | ||||
|         <InsetBox className="mt-8"> | ||||
|           {<Markdawn text={description} langui={langui} />} | ||||
|         </InsetBox> | ||||
|         <InsetBox className="mt-8">{<Markdawn text={description} />}</InsetBox> | ||||
|       )} | ||||
|     </> | ||||
|   ); | ||||
|  | ||||
| @ -1,12 +1,12 @@ | ||||
| import { useCallback } from "react"; | ||||
| import { Chip } from "components/Chip"; | ||||
| import { ToolTip } from "components/ToolTip"; | ||||
| import { AppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { getStatusDescription } from "helpers/others"; | ||||
| import { useSmartLanguage } from "hooks/useSmartLanguage"; | ||||
| import { Button } from "components/Inputs/Button"; | ||||
| import { useIsContentPanelNoMoreThan } from "hooks/useContainerQuery"; | ||||
| import { cIf, cJoin } from "helpers/className"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| 
 | ||||
| /* | ||||
|  *                                        ╭─────────────╮ | ||||
| @ -23,8 +23,6 @@ interface Props { | ||||
|     definition: string | null | undefined; | ||||
|     status: string | undefined; | ||||
|   }[]; | ||||
|   languages: AppStaticProps["languages"]; | ||||
|   langui: AppStaticProps["langui"]; | ||||
|   index: number; | ||||
|   categories: string[]; | ||||
| } | ||||
| @ -34,16 +32,14 @@ interface Props { | ||||
| const DefinitionCard = ({ | ||||
|   source, | ||||
|   translations = [], | ||||
|   languages, | ||||
|   langui, | ||||
|   index, | ||||
|   categories, | ||||
| }: Props): JSX.Element => { | ||||
|   const isContentPanelNoMoreThanMd = useIsContentPanelNoMoreThan("md"); | ||||
|   const { langui } = useAppLayout(); | ||||
|   const [selectedTranslation, LanguageSwitcher, languageSwitcherProps] = | ||||
|     useSmartLanguage({ | ||||
|       items: translations, | ||||
|       languages: languages, | ||||
|       languageExtractor: useCallback( | ||||
|         (item: Props["translations"][number]) => item.language, | ||||
|         [] | ||||
|  | ||||
| @ -1,8 +1,19 @@ | ||||
| import React, { ReactNode, useContext, useState } from "react"; | ||||
| import React, { | ||||
|   ReactNode, | ||||
|   useContext, | ||||
|   useEffect, | ||||
|   useLayoutEffect, | ||||
|   useState, | ||||
| } from "react"; | ||||
| import { useRouter } from "next/router"; | ||||
| import { useLocalStorage } from "usehooks-ts"; | ||||
| import { isDefined } from "helpers/others"; | ||||
| import { isDefined, isDefinedAndNotEmpty } from "helpers/others"; | ||||
| import { LibraryItemUserStatus, RequiredNonNullable } from "helpers/types"; | ||||
| import { useDarkMode } from "hooks/useDarkMode"; | ||||
| import { Currencies, Languages, Langui } from "helpers/localData"; | ||||
| import { useCurrencies, useLanguages, useLangui } from "hooks/useLocalData"; | ||||
| import { getDefaultPreferredLanguages } from "helpers/locales"; | ||||
| import { useStateWithLocalStorage } from "hooks/useStateWithLocalStorage"; | ||||
| 
 | ||||
| interface AppLayoutState { | ||||
|   subPanelOpen: boolean; | ||||
| @ -17,12 +28,6 @@ interface AppLayoutState { | ||||
|     React.SetStateAction<AppLayoutState["configPanelOpen"]> | ||||
|   >; | ||||
| 
 | ||||
|   searchPanelOpen: boolean; | ||||
|   toggleSearchPanelOpen: () => void; | ||||
|   setSearchPanelOpen: React.Dispatch< | ||||
|     React.SetStateAction<AppLayoutState["searchPanelOpen"]> | ||||
|   >; | ||||
| 
 | ||||
|   mainPanelReduced: boolean; | ||||
|   toggleMainPanelReduced: () => void; | ||||
|   setMainPanelReduced: React.Dispatch< | ||||
| @ -90,6 +95,10 @@ interface AppLayoutState { | ||||
|   setSubPanelWidth: React.Dispatch< | ||||
|     React.SetStateAction<AppLayoutState["subPanelWidth"]> | ||||
|   >; | ||||
| 
 | ||||
|   langui: Langui; | ||||
|   languages: Languages; | ||||
|   currencies: Currencies; | ||||
| } | ||||
| 
 | ||||
| const initialState: RequiredNonNullable<AppLayoutState> = { | ||||
| @ -101,10 +110,6 @@ const initialState: RequiredNonNullable<AppLayoutState> = { | ||||
|   setConfigPanelOpen: () => null, | ||||
|   toggleConfigPanelOpen: () => null, | ||||
| 
 | ||||
|   searchPanelOpen: false, | ||||
|   setSearchPanelOpen: () => null, | ||||
|   toggleSearchPanelOpen: () => null, | ||||
| 
 | ||||
|   mainPanelReduced: false, | ||||
|   setMainPanelReduced: () => null, | ||||
|   toggleMainPanelReduced: () => null, | ||||
| @ -152,6 +157,10 @@ const initialState: RequiredNonNullable<AppLayoutState> = { | ||||
| 
 | ||||
|   subPanelWidth: 0, | ||||
|   setSubPanelWidth: () => null, | ||||
| 
 | ||||
|   currencies: [], | ||||
|   languages: [], | ||||
|   langui: {}, | ||||
| }; | ||||
| 
 | ||||
| const AppContext = React.createContext<AppLayoutState>(initialState); | ||||
| @ -163,7 +172,9 @@ interface Props { | ||||
| } | ||||
| 
 | ||||
| export const AppContextProvider = (props: Props): JSX.Element => { | ||||
|   const [subPanelOpen, setSubPanelOpen] = useLocalStorage( | ||||
|   const router = useRouter(); | ||||
| 
 | ||||
|   const [subPanelOpen, setSubPanelOpen] = useStateWithLocalStorage( | ||||
|     "subPanelOpen", | ||||
|     initialState.subPanelOpen | ||||
|   ); | ||||
| @ -178,7 +189,7 @@ export const AppContextProvider = (props: Props): JSX.Element => { | ||||
|     initialState.mainPanelReduced | ||||
|   ); | ||||
| 
 | ||||
|   const [mainPanelOpen, setMainPanelOpen] = useLocalStorage( | ||||
|   const [mainPanelOpen, setMainPanelOpen] = useStateWithLocalStorage( | ||||
|     "mainPanelOpen", | ||||
|     initialState.mainPanelOpen | ||||
|   ); | ||||
| @ -213,11 +224,6 @@ export const AppContextProvider = (props: Props): JSX.Element => { | ||||
| 
 | ||||
|   const [menuGestures, setMenuGestures] = useState(false); | ||||
| 
 | ||||
|   const [searchPanelOpen, setSearchPanelOpen] = useLocalStorage( | ||||
|     "searchPanelOpen", | ||||
|     initialState.searchPanelOpen | ||||
|   ); | ||||
| 
 | ||||
|   const [libraryItemUserStatus, setLibraryItemUserStatus] = useLocalStorage( | ||||
|     "libraryItemUserStatus", | ||||
|     initialState.libraryItemUserStatus | ||||
| @ -231,10 +237,6 @@ export const AppContextProvider = (props: Props): JSX.Element => { | ||||
|     setConfigPanelOpen((current) => (isDefined(current) ? !current : current)); | ||||
|   }; | ||||
| 
 | ||||
|   const toggleSearchPanelOpen = () => { | ||||
|     setSearchPanelOpen((current) => (isDefined(current) ? !current : current)); | ||||
|   }; | ||||
| 
 | ||||
|   const toggleMainPanelReduced = () => { | ||||
|     setMainPanelReduced((current) => (isDefined(current) ? !current : current)); | ||||
|   }; | ||||
| @ -265,12 +267,61 @@ export const AppContextProvider = (props: Props): JSX.Element => { | ||||
|   const [contentPanelWidth, setContentPanelWidth] = useState(0); | ||||
|   const [subPanelWidth, setSubPanelWidth] = useState(0); | ||||
| 
 | ||||
|   const langui = useLangui(); | ||||
|   const languages = useLanguages(); | ||||
|   const currencies = useCurrencies(); | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|     if (preferredLanguages.length === 0) { | ||||
|       if (isDefinedAndNotEmpty(router.locale) && router.locales) { | ||||
|         setPreferredLanguages( | ||||
|           getDefaultPreferredLanguages(router.locale, router.locales) | ||||
|         ); | ||||
|       } | ||||
|     } else if (router.locale !== preferredLanguages[0]) { | ||||
|       /* | ||||
|        * Using a timeout to the code getting stuck into a loop when reaching the website with a | ||||
|        * different preferredLanguages[0] from router.locale | ||||
|        */ | ||||
|       setTimeout( | ||||
|         async () => | ||||
|           router.replace(router.asPath, router.asPath, { | ||||
|             locale: preferredLanguages[0], | ||||
|           }), | ||||
|         250 | ||||
|       ); | ||||
|     } | ||||
|   }, [ | ||||
|     preferredLanguages, | ||||
|     router, | ||||
|     router.locale, | ||||
|     router.locales, | ||||
|     setPreferredLanguages, | ||||
|   ]); | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|     router.events.on("routeChangeStart", () => { | ||||
|       setConfigPanelOpen(false); | ||||
|       setMainPanelOpen(false); | ||||
|       setSubPanelOpen(false); | ||||
|     }); | ||||
| 
 | ||||
|     router.events.on("hashChangeStart", () => { | ||||
|       setSubPanelOpen(false); | ||||
|     }); | ||||
|   }, [router.events, setConfigPanelOpen, setMainPanelOpen, setSubPanelOpen]); | ||||
| 
 | ||||
|   useLayoutEffect(() => { | ||||
|     document.getElementsByTagName("html")[0].style.fontSize = `${ | ||||
|       fontSize * 100 | ||||
|     }%`;
 | ||||
|   }, [fontSize]); | ||||
| 
 | ||||
|   return ( | ||||
|     <AppContext.Provider | ||||
|       value={{ | ||||
|         subPanelOpen, | ||||
|         configPanelOpen, | ||||
|         searchPanelOpen, | ||||
|         mainPanelReduced, | ||||
|         mainPanelOpen, | ||||
|         darkMode, | ||||
| @ -287,7 +338,6 @@ export const AppContextProvider = (props: Props): JSX.Element => { | ||||
|         subPanelWidth, | ||||
|         setSubPanelOpen, | ||||
|         setConfigPanelOpen, | ||||
|         setSearchPanelOpen, | ||||
|         setMainPanelReduced, | ||||
|         setMainPanelOpen, | ||||
|         setDarkMode, | ||||
| @ -301,16 +351,18 @@ export const AppContextProvider = (props: Props): JSX.Element => { | ||||
|         setLibraryItemUserStatus, | ||||
|         toggleSubPanelOpen, | ||||
|         toggleConfigPanelOpen, | ||||
|         toggleSearchPanelOpen, | ||||
|         toggleMainPanelReduced, | ||||
|         toggleMainPanelOpen, | ||||
|         toggleDarkMode, | ||||
|         toggleMenuGestures, | ||||
|         toggleSelectedThemeMode, | ||||
|         toggleDyslexic, | ||||
|         setContentPanelWidth, | ||||
|         setScreenWidth, | ||||
|         setContentPanelWidth, | ||||
|         setSubPanelWidth, | ||||
|         languages, | ||||
|         langui, | ||||
|         currencies, | ||||
|       }} | ||||
|     > | ||||
|       {props.children} | ||||
|  | ||||
							
								
								
									
										43
									
								
								src/graphql/fetchLocalData.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/graphql/fetchLocalData.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | ||||
| /* eslint-disable import/no-nodejs-modules */ | ||||
| import { resolve } from "path"; | ||||
| import { readFileSync, writeFileSync } from "fs"; | ||||
| import { config } from "dotenv"; | ||||
| import { getReadySdk } from "./sdk"; | ||||
| import { LocalDataGetWebsiteInterfacesQuery } from "./generated"; | ||||
| import { processLangui, Langui } from "helpers/localData"; | ||||
| 
 | ||||
| config({ path: resolve(process.cwd(), ".env.local") }); | ||||
| 
 | ||||
| const LOCAL_DATA_FOLDER = `${process.cwd()}/public/local-data`; | ||||
| 
 | ||||
| const writeLocalData = (name: LocalDataFile, localData: unknown) => { | ||||
|   const path = `${LOCAL_DATA_FOLDER}/${name}.json`; | ||||
|   writeFileSync(path, JSON.stringify(localData), { encoding: "utf-8" }); | ||||
|   console.log(`${path} has been written!`) | ||||
| }; | ||||
| 
 | ||||
| const readLocalData = <T>(name: LocalDataFile): T => { | ||||
|   const path = `${LOCAL_DATA_FOLDER}/${name}.json`; | ||||
|   return JSON.parse(readFileSync(path, { encoding: "utf8" })); | ||||
| }; | ||||
| 
 | ||||
| const sdk = getReadySdk(); | ||||
| 
 | ||||
| (async () => { | ||||
|   writeLocalData( | ||||
|     "websiteInterfaces", | ||||
|     await sdk.localDataGetWebsiteInterfaces() | ||||
|   ); | ||||
|   writeLocalData("currencies", await sdk.localDataGetCurrencies()); | ||||
|   writeLocalData("languages", await sdk.localDataGetLanguages()); | ||||
| })(); | ||||
| 
 | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| 
 | ||||
| export type LocalDataFile = "currencies" | "languages" | "websiteInterfaces"; | ||||
| 
 | ||||
| export const getLangui = (locale: string | undefined): Langui => { | ||||
|   const websiteInterfaces = | ||||
|     readLocalData<LocalDataGetWebsiteInterfacesQuery>("websiteInterfaces"); | ||||
|   return processLangui(websiteInterfaces, locale); | ||||
| }; | ||||
| @ -1,55 +0,0 @@ | ||||
| import { GetStaticPropsContext } from "next"; | ||||
| import { | ||||
|   GetCurrenciesQuery, | ||||
|   GetLanguagesQuery, | ||||
|   GetWebsiteInterfaceQuery, | ||||
| } from "graphql/generated"; | ||||
| import { getReadySdk } from "graphql/sdk"; | ||||
| 
 | ||||
| export type AppStaticProps = { | ||||
|   langui: NonNullable< | ||||
|     NonNullable< | ||||
|       GetWebsiteInterfaceQuery["websiteInterfaces"] | ||||
|     >["data"][number]["attributes"] | ||||
|   >; | ||||
|   currencies: NonNullable<GetCurrenciesQuery["currencies"]>["data"]; | ||||
|   languages: NonNullable<GetLanguagesQuery["languages"]>["data"]; | ||||
| }; | ||||
| 
 | ||||
| export const getAppStaticProps = async ( | ||||
|   context: GetStaticPropsContext | ||||
| ): Promise<AppStaticProps> => { | ||||
|   const sdk = getReadySdk(); | ||||
|   const { languages } = await sdk.getLanguages(); | ||||
| 
 | ||||
|   if (languages?.data) { | ||||
|     languages.data.sort((a, b) => | ||||
|       a.attributes && b.attributes | ||||
|         ? a.attributes.localized_name.localeCompare(b.attributes.localized_name) | ||||
|         : 0 | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   const { currencies } = await sdk.getCurrencies(); | ||||
|   if (currencies?.data) { | ||||
|     currencies.data.sort((a, b) => | ||||
|       a.attributes && b.attributes | ||||
|         ? a.attributes.code.localeCompare(b.attributes.code) | ||||
|         : 0 | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   const langui = ( | ||||
|     await sdk.getWebsiteInterface({ | ||||
|       language_code: context.locale ?? "en", | ||||
|     }) | ||||
|   ).websiteInterfaces?.data[0].attributes; | ||||
| 
 | ||||
|   const appStaticProps: AppStaticProps = { | ||||
|     langui: langui ?? {}, | ||||
|     currencies: currencies?.data ?? [], | ||||
|     languages: languages?.data ?? [], | ||||
|   }; | ||||
| 
 | ||||
|   return appStaticProps; | ||||
| }; | ||||
| @ -1,8 +1,8 @@ | ||||
| import { GetStaticProps } from "next"; | ||||
| import { AppStaticProps, getAppStaticProps } from "./getAppStaticProps"; | ||||
| import { getReadySdk } from "./sdk"; | ||||
| import { getLangui } from "./fetchLocalData"; | ||||
| import { PostWithTranslations } from "helpers/types"; | ||||
| import { OpenGraph, getOpenGraph } from "helpers/openGraph"; | ||||
| import { getOpenGraph } from "helpers/openGraph"; | ||||
| import { prettyDate, prettySlug } from "helpers/formatters"; | ||||
| import { | ||||
|   getDefaultPreferredLanguages, | ||||
| @ -10,16 +10,17 @@ import { | ||||
| } from "helpers/locales"; | ||||
| import { filterHasAttributes, isDefined } from "helpers/others"; | ||||
| import { getDescription } from "helpers/description"; | ||||
| import { AppLayoutRequired } from "components/AppLayout"; | ||||
| 
 | ||||
| export interface PostStaticProps extends AppStaticProps { | ||||
| export interface PostStaticProps extends AppLayoutRequired { | ||||
|   post: PostWithTranslations; | ||||
|   openGraph: OpenGraph; | ||||
| } | ||||
| 
 | ||||
| export const getPostStaticProps = | ||||
|   (slug: string): GetStaticProps => | ||||
|   async (context) => { | ||||
|     const sdk = getReadySdk(); | ||||
|     const langui = getLangui(context.locale); | ||||
|     const post = await sdk.getPost({ | ||||
|       slug: slug, | ||||
|       language_code: context.locale ?? "en", | ||||
| @ -31,7 +32,6 @@ export const getPostStaticProps = | ||||
|       isDefined(context.locale) && | ||||
|       isDefined(context.locales) | ||||
|     ) { | ||||
|       const appStaticProps = await getAppStaticProps(context); | ||||
|       const selectedTranslation = staticSmartLanguage({ | ||||
|         items: post.posts.data[0].attributes.translations, | ||||
|         languageExtractor: (item) => item.language?.data?.attributes?.code, | ||||
| @ -44,10 +44,10 @@ export const getPostStaticProps = | ||||
|       const title = selectedTranslation?.title ?? prettySlug(slug); | ||||
| 
 | ||||
|       const description = getDescription(selectedTranslation?.excerpt, { | ||||
|         [appStaticProps.langui.release_date ?? "Release date"]: [ | ||||
|         [langui.release_date ?? "Release date"]: [ | ||||
|           prettyDate(post.posts.data[0].attributes.date, context.locale), | ||||
|         ], | ||||
|         [appStaticProps.langui.categories ?? "Categories"]: filterHasAttributes( | ||||
|         [langui.categories ?? "Categories"]: filterHasAttributes( | ||||
|           post.posts.data[0].attributes.categories?.data, | ||||
|           ["attributes"] as const | ||||
|         ).map((category) => category.attributes.short), | ||||
| @ -58,14 +58,8 @@ export const getPostStaticProps = | ||||
|         post.posts.data[0].attributes.thumbnail?.data?.attributes; | ||||
| 
 | ||||
|       const props: PostStaticProps = { | ||||
|         ...appStaticProps, | ||||
|         post: post.posts.data[0].attributes as PostWithTranslations, | ||||
|         openGraph: getOpenGraph( | ||||
|           appStaticProps.langui, | ||||
|           title, | ||||
|           description, | ||||
|           thumbnail | ||||
|         ), | ||||
|         openGraph: getOpenGraph(langui, title, description, thumbnail), | ||||
|       }; | ||||
|       return { | ||||
|         props: props, | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| query getCurrencies { | ||||
| query localDataGetCurrencies { | ||||
|   currencies(pagination: { limit: -1 }) { | ||||
|     data { | ||||
|       id | ||||
| @ -1,4 +1,4 @@ | ||||
| query getLanguages { | ||||
| query localDataGetLanguages { | ||||
|   languages(pagination: { limit: -1 }) { | ||||
|     data { | ||||
|       id | ||||
| @ -1,9 +1,14 @@ | ||||
| query getWebsiteInterface($language_code: String) { | ||||
|   websiteInterfaces( | ||||
|     filters: { ui_language: { code: { eq: $language_code } } } | ||||
|   ) { | ||||
| query localDataGetWebsiteInterfaces { | ||||
|   websiteInterfaces(pagination: { limit: -1 }) { | ||||
|     data { | ||||
|       attributes { | ||||
|         ui_language { | ||||
|           data { | ||||
|             attributes { | ||||
|               code | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         library | ||||
|         contents | ||||
|         wiki | ||||
| @ -1,7 +1,7 @@ | ||||
| import { AppStaticProps } from "../graphql/getAppStaticProps"; | ||||
| import { convertPrice } from "./numbers"; | ||||
| import { isDefinedAndNotEmpty, isUndefined } from "./others"; | ||||
| import { datePickerToDate } from "./date"; | ||||
| import { Currencies, Languages, Langui } from "./localData"; | ||||
| import { DatePickerFragment, PricePickerFragment } from "graphql/generated"; | ||||
| 
 | ||||
| export const prettyDate = ( | ||||
| @ -12,7 +12,7 @@ export const prettyDate = ( | ||||
| 
 | ||||
| export const prettyPrice = ( | ||||
|   pricePicker: PricePickerFragment, | ||||
|   currencies: AppStaticProps["currencies"], | ||||
|   currencies: Currencies, | ||||
|   targetCurrencyCode?: string | ||||
| ): string => { | ||||
|   if (!targetCurrencyCode) return ""; | ||||
| @ -58,10 +58,7 @@ export const prettyInlineTitle = ( | ||||
|   return result; | ||||
| }; | ||||
| 
 | ||||
| export const prettyItemType = ( | ||||
|   metadata: any, | ||||
|   langui: AppStaticProps["langui"] | ||||
| ): string => { | ||||
| export const prettyItemType = (metadata: any, langui: Langui): string => { | ||||
|   switch (metadata.__typename) { | ||||
|     case "ComponentMetadataAudio": | ||||
|       return langui.audio ?? "Audio"; | ||||
| @ -242,10 +239,7 @@ export const prettyDuration = (seconds: number): string => { | ||||
|   return result; | ||||
| }; | ||||
| 
 | ||||
| export const prettyLanguage = ( | ||||
|   code: string, | ||||
|   languages: AppStaticProps["languages"] | ||||
| ): string => { | ||||
| export const prettyLanguage = (code: string, languages: Languages): string => { | ||||
|   let result = code; | ||||
|   languages.forEach((language) => { | ||||
|     if (language.attributes?.code === code) | ||||
|  | ||||
							
								
								
									
										58
									
								
								src/helpers/localData.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/helpers/localData.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,58 @@ | ||||
| import { | ||||
|   LocalDataGetCurrenciesQuery, | ||||
|   LocalDataGetLanguagesQuery, | ||||
|   LocalDataGetWebsiteInterfacesQuery, | ||||
| } from "graphql/generated"; | ||||
| 
 | ||||
| export type Langui = NonNullable< | ||||
|   NonNullable< | ||||
|     LocalDataGetWebsiteInterfacesQuery["websiteInterfaces"] | ||||
|   >["data"][number]["attributes"] | ||||
| >; | ||||
| 
 | ||||
| export const processLangui = ( | ||||
|   websiteInterfaces: LocalDataGetWebsiteInterfacesQuery | undefined, | ||||
|   locale: string | undefined | ||||
| ): Langui => | ||||
|   websiteInterfaces?.websiteInterfaces?.data.find( | ||||
|     (langui) => | ||||
|       langui.attributes?.ui_language?.data?.attributes?.code === locale | ||||
|   )?.attributes ?? {}; | ||||
| 
 | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| 
 | ||||
| export type Currencies = NonNullable< | ||||
|   LocalDataGetCurrenciesQuery["currencies"] | ||||
| >["data"]; | ||||
| 
 | ||||
| export const processCurrencies = ( | ||||
|   currencies: LocalDataGetCurrenciesQuery | undefined | ||||
| ): Currencies => { | ||||
|   if (currencies?.currencies?.data) { | ||||
|     currencies.currencies.data.sort((a, b) => | ||||
|       a.attributes && b.attributes | ||||
|         ? a.attributes.code.localeCompare(b.attributes.code) | ||||
|         : 0 | ||||
|     ); | ||||
|   } | ||||
|   return currencies?.currencies?.data ?? []; | ||||
| }; | ||||
| 
 | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| 
 | ||||
| export type Languages = NonNullable< | ||||
|   LocalDataGetLanguagesQuery["languages"] | ||||
| >["data"]; | ||||
| 
 | ||||
| export const processLanguages = ( | ||||
|   languages: LocalDataGetLanguagesQuery | undefined | ||||
| ): Languages => { | ||||
|   if (languages?.languages?.data) { | ||||
|     languages.languages.data.sort((a, b) => | ||||
|       a.attributes && b.attributes | ||||
|         ? a.attributes.localized_name.localeCompare(b.attributes.localized_name) | ||||
|         : 0 | ||||
|     ); | ||||
|   } | ||||
|   return languages?.languages?.data ?? []; | ||||
| }; | ||||
| @ -1,8 +1,9 @@ | ||||
| import { GetCurrenciesQuery, PricePickerFragment } from "graphql/generated"; | ||||
| import { Currencies } from "./localData"; | ||||
| import { PricePickerFragment } from "graphql/generated"; | ||||
| 
 | ||||
| export const convertPrice = ( | ||||
|   pricePicker: PricePickerFragment, | ||||
|   targetCurrency: NonNullable<GetCurrenciesQuery["currencies"]>["data"][number] | ||||
|   targetCurrency: Currencies[number] | ||||
| ): number => { | ||||
|   if ( | ||||
|     pricePicker.amount && | ||||
|  | ||||
| @ -5,8 +5,8 @@ import { | ||||
|   getAssetURL, | ||||
| } from "./img"; | ||||
| import { isDefinedAndNotEmpty } from "./others"; | ||||
| import { Langui } from "./localData"; | ||||
| import { UploadImageFragment } from "graphql/generated"; | ||||
| import { AppStaticProps } from "graphql/getAppStaticProps"; | ||||
| 
 | ||||
| const DEFAULT_OG_THUMBNAIL = { | ||||
|   image: `${process.env.NEXT_PUBLIC_URL_SELF}/default_og.jpg`, | ||||
| @ -25,7 +25,7 @@ export interface OpenGraph { | ||||
| } | ||||
| 
 | ||||
| export const getOpenGraph = ( | ||||
|   langui: AppStaticProps["langui"], | ||||
|   langui: Langui, | ||||
|   title?: string | null | undefined, | ||||
|   description?: string | null | undefined, | ||||
|   thumbnail?: UploadImageFragment | null | undefined | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| import { AppStaticProps } from "../graphql/getAppStaticProps"; | ||||
| import { PathDot, SelectiveNonNullable } from "./types/SelectiveNonNullable"; | ||||
| import { Langui } from "./localData"; | ||||
| import { | ||||
|   Enum_Componentsetstextset_Status, | ||||
|   GetLibraryItemQuery, | ||||
| @ -35,7 +35,7 @@ export const sortRangedContent = (contents: SortRangedContentProps): void => { | ||||
| 
 | ||||
| export const getStatusDescription = ( | ||||
|   status: string, | ||||
|   langui: AppStaticProps["langui"] | ||||
|   langui: Langui | ||||
| ): string | null | undefined => { | ||||
|   switch (status) { | ||||
|     case Enum_Componentsetstextset_Status.Incomplete: | ||||
| @ -112,13 +112,11 @@ export const iterateMap = <K, V, U>( | ||||
|   return toList.map(([key, value], index) => callbackfn(key, value, index)); | ||||
| }; | ||||
| 
 | ||||
| export const mapMoveEntry = <K, V>( | ||||
|   map: Map<K, V>, | ||||
| export const arrayMove = <T>( | ||||
|   arr: T[], | ||||
|   sourceIndex: number, | ||||
|   targetIndex: number | ||||
| ): Map<K, V> => new Map(arrayMove([...map], sourceIndex, targetIndex)); | ||||
| 
 | ||||
| const arrayMove = <T>(arr: T[], sourceIndex: number, targetIndex: number) => { | ||||
| ): T[] => { | ||||
|   arr.splice(targetIndex, 0, arr.splice(sourceIndex, 1)[0]); | ||||
|   return arr; | ||||
| }; | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| import { useEffect } from "react"; | ||||
| import { useLocalStorage } from "usehooks-ts"; | ||||
| import { usePrefersDarkMode } from "./useMediaQuery"; | ||||
| import { useStateWithLocalStorage } from "./useStateWithLocalStorage"; | ||||
| 
 | ||||
| export const useDarkMode = ( | ||||
|   key: string, | ||||
| @ -11,9 +11,9 @@ export const useDarkMode = ( | ||||
|   React.Dispatch<React.SetStateAction<boolean>>, | ||||
|   React.Dispatch<React.SetStateAction<boolean>> | ||||
| ] => { | ||||
|   const [darkMode, setDarkMode] = useLocalStorage(key, initialValue); | ||||
|   const [darkMode, setDarkMode] = useStateWithLocalStorage(key, initialValue); | ||||
|   const prefersDarkMode = usePrefersDarkMode(); | ||||
|   const [selectedThemeMode, setSelectedThemeMode] = useLocalStorage( | ||||
|   const [selectedThemeMode, setSelectedThemeMode] = useStateWithLocalStorage( | ||||
|     "selectedThemeMode", | ||||
|     false | ||||
|   ); | ||||
|  | ||||
							
								
								
									
										35
									
								
								src/hooks/useLocalData.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/hooks/useLocalData.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,35 @@ | ||||
| import { useFetch } from "usehooks-ts"; | ||||
| import { useRouter } from "next/router"; | ||||
| import { useMemo } from "react"; | ||||
| import { LocalDataGetWebsiteInterfacesQuery } from "graphql/generated"; | ||||
| import { | ||||
|   Currencies, | ||||
|   Languages, | ||||
|   Langui, | ||||
|   processCurrencies, | ||||
|   processLanguages, | ||||
|   processLangui, | ||||
| } from "helpers/localData"; | ||||
| import { LocalDataFile } from "graphql/fetchLocalData"; | ||||
| 
 | ||||
| const useFetchLocalData = (name: LocalDataFile) => | ||||
|   useFetch<LocalDataGetWebsiteInterfacesQuery>(`/local-data/${name}.json`); | ||||
| 
 | ||||
| export const useLangui = (): Langui => { | ||||
|   const { locale } = useRouter(); | ||||
|   const { data: websiteInterfaces } = useFetchLocalData("websiteInterfaces"); | ||||
|   return useMemo( | ||||
|     () => processLangui(websiteInterfaces, locale), | ||||
|     [websiteInterfaces, locale] | ||||
|   ); | ||||
| }; | ||||
| 
 | ||||
| export const useCurrencies = (): Currencies => { | ||||
|   const { data: currencies } = useFetchLocalData("currencies"); | ||||
|   return useMemo(() => processCurrencies(currencies), [currencies]); | ||||
| }; | ||||
| 
 | ||||
| export const useLanguages = (): Languages => { | ||||
|   const { data: languages } = useFetchLocalData("languages"); | ||||
|   return useMemo(() => processLanguages(languages), [languages]); | ||||
| }; | ||||
| @ -1,14 +1,13 @@ | ||||
| import { useRouter } from "next/router"; | ||||
| import { useEffect, useMemo, useState } from "react"; | ||||
| import { useLanguages } from "./useLocalData"; | ||||
| import { LanguageSwitcher } from "components/Inputs/LanguageSwitcher"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| import { AppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { filterDefined, isDefined } from "helpers/others"; | ||||
| import { getPreferredLanguage } from "helpers/locales"; | ||||
| 
 | ||||
| interface Props<T> { | ||||
|   items: T[]; | ||||
|   languages?: AppStaticProps["languages"]; | ||||
|   languageExtractor: (item: NonNullable<T>) => string | undefined; | ||||
|   transform?: (item: NonNullable<T>) => NonNullable<T>; | ||||
| } | ||||
| @ -16,7 +15,6 @@ interface Props<T> { | ||||
| export const useSmartLanguage = <T>({ | ||||
|   items, | ||||
|   languageExtractor, | ||||
|   languages = [], | ||||
|   transform = (item) => item, | ||||
| }: Props<T>): [ | ||||
|   T | undefined, | ||||
| @ -24,6 +22,7 @@ export const useSmartLanguage = <T>({ | ||||
|   Parameters<typeof LanguageSwitcher>[0] | ||||
| ] => { | ||||
|   const { preferredLanguages } = useAppLayout(); | ||||
|   const languages = useLanguages(); | ||||
|   const router = useRouter(); | ||||
| 
 | ||||
|   const availableLocales = useMemo(() => { | ||||
|  | ||||
							
								
								
									
										31
									
								
								src/hooks/useStateWithLocalStorage.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/hooks/useStateWithLocalStorage.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| import { useEffect, useState } from "react"; | ||||
| import { isDefined } from "helpers/others"; | ||||
| 
 | ||||
| export const useStateWithLocalStorage = <T>( | ||||
|   key: string, | ||||
|   initialValue: T | ||||
| ): [T, React.Dispatch<React.SetStateAction<T>>] => { | ||||
|   const [value, setValue] = useState<T>(initialValue); | ||||
|   const [isFromLocaleStorage, setFromLocaleStorage] = useState<boolean>(false); | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|     try { | ||||
|       const item = localStorage.getItem(key); | ||||
|       if (isDefined(item)) { | ||||
|         setValue(JSON.parse(item) as T); | ||||
|       } else { | ||||
|         setValue(initialValue); | ||||
|       } | ||||
|       setFromLocaleStorage(true); | ||||
|     } catch (error) { | ||||
|       console.warn(`Error reading localStorage key “${key}”:`, error); | ||||
|       setValue(initialValue); | ||||
|     } | ||||
|   }, [initialValue, key]); | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|     if (isFromLocaleStorage) localStorage.setItem(key, JSON.stringify(value)); | ||||
|   }, [value, key, isFromLocaleStorage]); | ||||
| 
 | ||||
|   return [value, setValue]; | ||||
| }; | ||||
| @ -2,30 +2,25 @@ import { GetStaticProps } from "next"; | ||||
| import { AppLayout, AppLayoutRequired } from "components/AppLayout"; | ||||
| import { ReturnButton } from "components/PanelComponents/ReturnButton"; | ||||
| import { ContentPanel } from "components/Panels/ContentPanel"; | ||||
| import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { getOpenGraph } from "helpers/openGraph"; | ||||
| import { getLangui } from "graphql/fetchLocalData"; | ||||
| 
 | ||||
| /* | ||||
|  *                                           ╭────────╮ | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps, AppLayoutRequired {} | ||||
| interface Props extends AppLayoutRequired {} | ||||
| 
 | ||||
| const FourOhFour = ({ | ||||
|   langui, | ||||
|   openGraph, | ||||
|   ...otherProps | ||||
| }: Props): JSX.Element => ( | ||||
| const FourOhFour = ({ openGraph, ...otherProps }: Props): JSX.Element => ( | ||||
|   <AppLayout | ||||
|     contentPanel={ | ||||
|       <ContentPanel> | ||||
|         <h1>{openGraph.title}</h1> | ||||
|         <ReturnButton href="/" title="Home" langui={langui} /> | ||||
|         <ReturnButton href="/" title="Home" /> | ||||
|       </ContentPanel> | ||||
|     } | ||||
|     openGraph={openGraph} | ||||
|     langui={langui} | ||||
|     {...otherProps} | ||||
|   /> | ||||
| ); | ||||
| @ -36,14 +31,10 @@ export default FourOhFour; | ||||
|  * ───────────────────────────────────╯  NEXT DATA FETCHING  ╰────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const appStaticProps = await getAppStaticProps(context); | ||||
| export const getStaticProps: GetStaticProps = (context) => { | ||||
|   const langui = getLangui(context.locale); | ||||
|   const props: Props = { | ||||
|     ...appStaticProps, | ||||
|     openGraph: getOpenGraph( | ||||
|       appStaticProps.langui, | ||||
|       `404 - ${appStaticProps.langui.page_not_found}` | ||||
|     ), | ||||
|     openGraph: getOpenGraph(langui, `404 - ${langui.page_not_found}`), | ||||
|   }; | ||||
|   return { | ||||
|     props: props, | ||||
|  | ||||
| @ -2,30 +2,25 @@ import { GetStaticProps } from "next"; | ||||
| import { AppLayout, AppLayoutRequired } from "components/AppLayout"; | ||||
| import { ReturnButton } from "components/PanelComponents/ReturnButton"; | ||||
| import { ContentPanel } from "components/Panels/ContentPanel"; | ||||
| import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { getOpenGraph } from "helpers/openGraph"; | ||||
| import { getLangui } from "graphql/fetchLocalData"; | ||||
| 
 | ||||
| /* | ||||
|  *                                           ╭────────╮ | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps, AppLayoutRequired {} | ||||
| interface Props extends AppLayoutRequired {} | ||||
| 
 | ||||
| const FiveHundred = ({ | ||||
|   langui, | ||||
|   openGraph, | ||||
|   ...otherProps | ||||
| }: Props): JSX.Element => ( | ||||
| const FiveHundred = ({ openGraph, ...otherProps }: Props): JSX.Element => ( | ||||
|   <AppLayout | ||||
|     contentPanel={ | ||||
|       <ContentPanel> | ||||
|         <h1>{openGraph.title}</h1> | ||||
|         <ReturnButton href="/" title="Home" langui={langui} /> | ||||
|         <ReturnButton href="/" title="Home" /> | ||||
|       </ContentPanel> | ||||
|     } | ||||
|     openGraph={openGraph} | ||||
|     langui={langui} | ||||
|     {...otherProps} | ||||
|   /> | ||||
| ); | ||||
| @ -36,14 +31,10 @@ export default FiveHundred; | ||||
|  * ───────────────────────────────────╯  NEXT DATA FETCHING  ╰────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const appStaticProps = await getAppStaticProps(context); | ||||
| export const getStaticProps: GetStaticProps = (context) => { | ||||
|   const langui = getLangui(context.locale); | ||||
|   const props: Props = { | ||||
|     ...appStaticProps, | ||||
|     openGraph: getOpenGraph( | ||||
|       appStaticProps.langui, | ||||
|       "500 - Internal Server Error" | ||||
|     ), | ||||
|     openGraph: getOpenGraph(langui, "500 - Internal Server Error"), | ||||
|   }; | ||||
|   return { | ||||
|     props: props, | ||||
|  | ||||
| @ -3,21 +3,25 @@ import { | ||||
|   getPostStaticProps, | ||||
|   PostStaticProps, | ||||
| } from "graphql/getPostStaticProps"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| 
 | ||||
| /* | ||||
|  *                                           ╭────────╮ | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| const AccordsHandbook = (props: PostStaticProps): JSX.Element => ( | ||||
|   <PostPage | ||||
|     {...props} | ||||
|     returnHref="/about-us/" | ||||
|     returnTitle={props.langui.about_us} | ||||
|     displayToc | ||||
|     displayLanguageSwitcher | ||||
|   /> | ||||
| ); | ||||
| const AccordsHandbook = (props: PostStaticProps): JSX.Element => { | ||||
|   const { langui } = useAppLayout(); | ||||
|   return ( | ||||
|     <PostPage | ||||
|       {...props} | ||||
|       returnHref="/about-us/" | ||||
|       returnTitle={langui.about_us} | ||||
|       displayToc | ||||
|       displayLanguageSwitcher | ||||
|     /> | ||||
|   ); | ||||
| }; | ||||
| export default AccordsHandbook; | ||||
| 
 | ||||
| /* | ||||
|  | ||||
| @ -10,14 +10,16 @@ import { cIf, cJoin } from "helpers/className"; | ||||
| import { randomInt } from "helpers/numbers"; | ||||
| import { RequestMailProps, ResponseMailProps } from "pages/api/mail"; | ||||
| import { useIs1ColumnLayout } from "hooks/useContainerQuery"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| 
 | ||||
| /* | ||||
|  *                                           ╭────────╮ | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| const AboutUs = ({ langui, ...otherProps }: PostStaticProps): JSX.Element => { | ||||
| const AboutUs = (props: PostStaticProps): JSX.Element => { | ||||
|   const router = useRouter(); | ||||
|   const { langui } = useAppLayout(); | ||||
|   const is1ColumnLayout = useIs1ColumnLayout(); | ||||
|   const [formResponse, setFormResponse] = useState(""); | ||||
|   const [formState, setFormState] = useState<"completed" | "ongoing" | "stale">( | ||||
| @ -174,8 +176,7 @@ const AboutUs = ({ langui, ...otherProps }: PostStaticProps): JSX.Element => { | ||||
| 
 | ||||
|   return ( | ||||
|     <PostPage | ||||
|       {...otherProps} | ||||
|       langui={langui} | ||||
|       {...props} | ||||
|       returnHref="/about-us/" | ||||
|       returnTitle={langui.about_us} | ||||
|       displayToc | ||||
|  | ||||
| @ -4,47 +4,50 @@ import { Icon } from "components/Ico"; | ||||
| import { NavOption } from "components/PanelComponents/NavOption"; | ||||
| import { PanelHeader } from "components/PanelComponents/PanelHeader"; | ||||
| import { SubPanel } from "components/Panels/SubPanel"; | ||||
| import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { getOpenGraph } from "helpers/openGraph"; | ||||
| import { HorizontalLine } from "components/HorizontalLine"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| import { getLangui } from "graphql/fetchLocalData"; | ||||
| 
 | ||||
| /* | ||||
|  *                                           ╭────────╮ | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps, AppLayoutRequired {} | ||||
| interface Props extends AppLayoutRequired {} | ||||
| 
 | ||||
| const AboutUs = ({ langui, ...otherProps }: Props): JSX.Element => ( | ||||
|   <AppLayout | ||||
|     subPanel={ | ||||
|       <SubPanel> | ||||
|         <PanelHeader | ||||
|           icon={Icon.Info} | ||||
|           title={langui.about_us} | ||||
|           description={langui.about_us_description} | ||||
|         /> | ||||
| const AboutUs = (props: Props): JSX.Element => { | ||||
|   const { langui } = useAppLayout(); | ||||
|   return ( | ||||
|     <AppLayout | ||||
|       subPanel={ | ||||
|         <SubPanel> | ||||
|           <PanelHeader | ||||
|             icon={Icon.Info} | ||||
|             title={langui.about_us} | ||||
|             description={langui.about_us_description} | ||||
|           /> | ||||
| 
 | ||||
|         <HorizontalLine /> | ||||
|           <HorizontalLine /> | ||||
| 
 | ||||
|         <NavOption | ||||
|           title={langui.accords_handbook} | ||||
|           url="/about-us/accords-handbook" | ||||
|           border | ||||
|         /> | ||||
|         <NavOption title={langui.legality} url="/about-us/legality" border /> | ||||
|         <NavOption | ||||
|           title={langui.sharing_policy} | ||||
|           url="/about-us/sharing-policy" | ||||
|           border | ||||
|         /> | ||||
|         <NavOption title={langui.contact_us} url="/about-us/contact" border /> | ||||
|       </SubPanel> | ||||
|     } | ||||
|     langui={langui} | ||||
|     {...otherProps} | ||||
|   /> | ||||
| ); | ||||
|           <NavOption | ||||
|             title={langui.accords_handbook} | ||||
|             url="/about-us/accords-handbook" | ||||
|             border | ||||
|           /> | ||||
|           <NavOption title={langui.legality} url="/about-us/legality" border /> | ||||
|           <NavOption | ||||
|             title={langui.sharing_policy} | ||||
|             url="/about-us/sharing-policy" | ||||
|             border | ||||
|           /> | ||||
|           <NavOption title={langui.contact_us} url="/about-us/contact" border /> | ||||
|         </SubPanel> | ||||
|       } | ||||
|       {...props} | ||||
|     /> | ||||
|   ); | ||||
| }; | ||||
| export default AboutUs; | ||||
| 
 | ||||
| /* | ||||
| @ -52,14 +55,10 @@ export default AboutUs; | ||||
|  * ───────────────────────────────────╯  NEXT DATA FETCHING  ╰────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const appStaticProps = await getAppStaticProps(context); | ||||
| export const getStaticProps: GetStaticProps = (context) => { | ||||
|   const langui = getLangui(context.locale); | ||||
|   const props: Props = { | ||||
|     ...appStaticProps, | ||||
|     openGraph: getOpenGraph( | ||||
|       appStaticProps.langui, | ||||
|       appStaticProps.langui.about_us ?? "About us" | ||||
|     ), | ||||
|     openGraph: getOpenGraph(langui, langui.about_us ?? "About us"), | ||||
|   }; | ||||
|   return { | ||||
|     props: props, | ||||
|  | ||||
| @ -3,21 +3,25 @@ import { | ||||
|   getPostStaticProps, | ||||
|   PostStaticProps, | ||||
| } from "graphql/getPostStaticProps"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| 
 | ||||
| /* | ||||
|  *                                           ╭────────╮ | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| const Legality = (props: PostStaticProps): JSX.Element => ( | ||||
|   <PostPage | ||||
|     {...props} | ||||
|     returnHref="/about-us/" | ||||
|     returnTitle={props.langui.about_us} | ||||
|     displayToc | ||||
|     displayLanguageSwitcher | ||||
|   /> | ||||
| ); | ||||
| const Legality = (props: PostStaticProps): JSX.Element => { | ||||
|   const { langui } = useAppLayout(); | ||||
|   return ( | ||||
|     <PostPage | ||||
|       {...props} | ||||
|       returnHref="/about-us/" | ||||
|       returnTitle={langui.about_us} | ||||
|       displayToc | ||||
|       displayLanguageSwitcher | ||||
|     /> | ||||
|   ); | ||||
| }; | ||||
| export default Legality; | ||||
| 
 | ||||
| /* | ||||
|  | ||||
| @ -3,21 +3,25 @@ import { | ||||
|   getPostStaticProps, | ||||
|   PostStaticProps, | ||||
| } from "graphql/getPostStaticProps"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| 
 | ||||
| /* | ||||
|  *                                           ╭────────╮ | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| const SharingPolicy = (props: PostStaticProps): JSX.Element => ( | ||||
|   <PostPage | ||||
|     {...props} | ||||
|     returnHref="/about-us/" | ||||
|     returnTitle={props.langui.about_us} | ||||
|     displayToc | ||||
|     displayLanguageSwitcher | ||||
|   /> | ||||
| ); | ||||
| const SharingPolicy = (props: PostStaticProps): JSX.Element => { | ||||
|   const { langui } = useAppLayout(); | ||||
|   return ( | ||||
|     <PostPage | ||||
|       {...props} | ||||
|       returnHref="/about-us/" | ||||
|       returnTitle={langui.about_us} | ||||
|       displayToc | ||||
|       displayLanguageSwitcher | ||||
|     /> | ||||
|   ); | ||||
| }; | ||||
| export default SharingPolicy; | ||||
| 
 | ||||
| /* | ||||
|  | ||||
| @ -4,19 +4,21 @@ import { AppLayout, AppLayoutRequired } from "components/AppLayout"; | ||||
| import { NavOption } from "components/PanelComponents/NavOption"; | ||||
| import { PanelHeader } from "components/PanelComponents/PanelHeader"; | ||||
| import { SubPanel } from "components/Panels/SubPanel"; | ||||
| import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { Icon } from "components/Ico"; | ||||
| import { getOpenGraph } from "helpers/openGraph"; | ||||
| import { HorizontalLine } from "components/HorizontalLine"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| import { getLangui } from "graphql/fetchLocalData"; | ||||
| 
 | ||||
| /* | ||||
|  *                                           ╭────────╮ | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps, AppLayoutRequired {} | ||||
| interface Props extends AppLayoutRequired {} | ||||
| 
 | ||||
| const Archives = ({ langui, ...otherProps }: Props): JSX.Element => { | ||||
| const Archives = (props: Props): JSX.Element => { | ||||
|   const { langui } = useAppLayout(); | ||||
|   const subPanel = useMemo( | ||||
|     () => ( | ||||
|       <SubPanel> | ||||
| @ -31,7 +33,7 @@ const Archives = ({ langui, ...otherProps }: Props): JSX.Element => { | ||||
|     ), | ||||
|     [langui] | ||||
|   ); | ||||
|   return <AppLayout subPanel={subPanel} langui={langui} {...otherProps} />; | ||||
|   return <AppLayout subPanel={subPanel} {...props} />; | ||||
| }; | ||||
| export default Archives; | ||||
| 
 | ||||
| @ -40,14 +42,10 @@ export default Archives; | ||||
|  * ───────────────────────────────────╯  NEXT DATA FETCHING  ╰────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const appStaticProps = await getAppStaticProps(context); | ||||
| export const getStaticProps: GetStaticProps = (context) => { | ||||
|   const langui = getLangui(context.locale); | ||||
|   const props: Props = { | ||||
|     ...appStaticProps, | ||||
|     openGraph: getOpenGraph( | ||||
|       appStaticProps.langui, | ||||
|       appStaticProps.langui.archives ?? "Archives" | ||||
|     ), | ||||
|     openGraph: getOpenGraph(langui, langui.archives ?? "Archives"), | ||||
|   }; | ||||
|   return { | ||||
|     props: props, | ||||
|  | ||||
| @ -12,7 +12,6 @@ import { | ||||
| import { SubPanel } from "components/Panels/SubPanel"; | ||||
| import { PreviewCard } from "components/PreviewCard"; | ||||
| import { GetVideoChannelQuery } from "graphql/generated"; | ||||
| import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { getReadySdk } from "graphql/sdk"; | ||||
| import { getVideoThumbnailURL } from "helpers/videos"; | ||||
| import { Icon } from "components/Ico"; | ||||
| @ -26,6 +25,8 @@ import { SmartList } from "components/SmartList"; | ||||
| import { cIf } from "helpers/className"; | ||||
| import { useIsContentPanelAtLeast } from "hooks/useContainerQuery"; | ||||
| import { TextInput } from "components/Inputs/TextInput"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| import { getLangui } from "graphql/fetchLocalData"; | ||||
| 
 | ||||
| /* | ||||
|  *                                         ╭─────────────╮ | ||||
| @ -41,15 +42,16 @@ const DEFAULT_FILTERS_STATE = { | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps, AppLayoutRequired { | ||||
| interface Props extends AppLayoutRequired { | ||||
|   channel: NonNullable< | ||||
|     GetVideoChannelQuery["videoChannels"] | ||||
|   >["data"][number]["attributes"]; | ||||
| } | ||||
| 
 | ||||
| const Channel = ({ langui, channel, ...otherProps }: Props): JSX.Element => { | ||||
| const Channel = ({ channel, ...otherProps }: Props): JSX.Element => { | ||||
|   const { value: keepInfoVisible, toggle: toggleKeepInfoVisible } = | ||||
|     useBoolean(true); | ||||
|   const { langui } = useAppLayout(); | ||||
|   const hoverable = useDeviceSupportsHover(); | ||||
|   const isContentPanelAtLeast4xl = useIsContentPanelAtLeast("4xl"); | ||||
| 
 | ||||
| @ -63,7 +65,6 @@ const Channel = ({ langui, channel, ...otherProps }: Props): JSX.Element => { | ||||
|         <ReturnButton | ||||
|           href="/archives/videos/" | ||||
|           title={langui.videos} | ||||
|           langui={langui} | ||||
|           displayOnlyOn={"3ColumnsLayout"} | ||||
|           className="mb-10" | ||||
|         /> | ||||
| @ -122,7 +123,6 @@ const Channel = ({ langui, channel, ...otherProps }: Props): JSX.Element => { | ||||
|               }} | ||||
|             /> | ||||
|           )} | ||||
|           langui={langui} | ||||
|           className={cIf( | ||||
|             isContentPanelAtLeast4xl, | ||||
|             "grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))] gap-x-6 gap-y-8", | ||||
| @ -140,7 +140,6 @@ const Channel = ({ langui, channel, ...otherProps }: Props): JSX.Element => { | ||||
|       channel?.videos?.data, | ||||
|       isContentPanelAtLeast4xl, | ||||
|       keepInfoVisible, | ||||
|       langui, | ||||
|       searchName, | ||||
|     ] | ||||
|   ); | ||||
| @ -149,7 +148,6 @@ const Channel = ({ langui, channel, ...otherProps }: Props): JSX.Element => { | ||||
|     <AppLayout | ||||
|       subPanel={subPanel} | ||||
|       contentPanel={contentPanel} | ||||
|       langui={langui} | ||||
|       {...otherProps} | ||||
|     /> | ||||
|   ); | ||||
| @ -163,6 +161,7 @@ export default Channel; | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const sdk = getReadySdk(); | ||||
|   const langui = getLangui(context.locale); | ||||
|   const channel = await sdk.getVideoChannel({ | ||||
|     channel: | ||||
|       context.params && isDefined(context.params.uid) | ||||
| @ -177,12 +176,10 @@ export const getStaticProps: GetStaticProps = async (context) => { | ||||
|     ) | ||||
|     .reverse(); | ||||
| 
 | ||||
|   const appStaticProps = await getAppStaticProps(context); | ||||
|   const props: Props = { | ||||
|     ...appStaticProps, | ||||
|     channel: channel.videoChannels.data[0].attributes, | ||||
|     openGraph: getOpenGraph( | ||||
|       appStaticProps.langui, | ||||
|       langui, | ||||
|       channel.videoChannels.data[0].attributes.title | ||||
|     ), | ||||
|   }; | ||||
|  | ||||
| @ -16,7 +16,6 @@ import { | ||||
| import { SubPanel } from "components/Panels/SubPanel"; | ||||
| import { PreviewCard } from "components/PreviewCard"; | ||||
| import { GetVideosPreviewQuery } from "graphql/generated"; | ||||
| import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { getReadySdk } from "graphql/sdk"; | ||||
| import { filterHasAttributes } from "helpers/others"; | ||||
| import { getVideoThumbnailURL } from "helpers/videos"; | ||||
| @ -26,6 +25,8 @@ import { compareDate } from "helpers/date"; | ||||
| import { HorizontalLine } from "components/HorizontalLine"; | ||||
| import { cIf } from "helpers/className"; | ||||
| import { useIsContentPanelAtLeast } from "hooks/useContainerQuery"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| import { getLangui } from "graphql/fetchLocalData"; | ||||
| 
 | ||||
| /* | ||||
|  *                                         ╭─────────────╮ | ||||
| @ -41,11 +42,12 @@ const DEFAULT_FILTERS_STATE = { | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps, AppLayoutRequired { | ||||
| interface Props extends AppLayoutRequired { | ||||
|   videos: NonNullable<GetVideosPreviewQuery["videos"]>["data"]; | ||||
| } | ||||
| 
 | ||||
| const Videos = ({ langui, videos, ...otherProps }: Props): JSX.Element => { | ||||
| const Videos = ({ videos, ...otherProps }: Props): JSX.Element => { | ||||
|   const { langui } = useAppLayout(); | ||||
|   const hoverable = useDeviceSupportsHover(); | ||||
|   const isContentPanelAtLeast4xl = useIsContentPanelAtLeast("4xl"); | ||||
| 
 | ||||
| @ -62,7 +64,6 @@ const Videos = ({ langui, videos, ...otherProps }: Props): JSX.Element => { | ||||
|         <ReturnButton | ||||
|           href="/archives/" | ||||
|           title={"Archives"} | ||||
|           langui={langui} | ||||
|           displayOnlyOn={"3ColumnsLayout"} | ||||
|           className="mb-10" | ||||
|         /> | ||||
| @ -118,7 +119,6 @@ const Videos = ({ langui, videos, ...otherProps }: Props): JSX.Element => { | ||||
|               }} | ||||
|             /> | ||||
|           )} | ||||
|           langui={langui} | ||||
|           className={cIf( | ||||
|             isContentPanelAtLeast4xl, | ||||
|             "grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))] gap-x-6 gap-y-8", | ||||
| @ -130,13 +130,12 @@ const Videos = ({ langui, videos, ...otherProps }: Props): JSX.Element => { | ||||
|         /> | ||||
|       </ContentPanel> | ||||
|     ), | ||||
|     [isContentPanelAtLeast4xl, keepInfoVisible, langui, searchName, videos] | ||||
|     [isContentPanelAtLeast4xl, keepInfoVisible, searchName, videos] | ||||
|   ); | ||||
|   return ( | ||||
|     <AppLayout | ||||
|       subPanel={subPanel} | ||||
|       contentPanel={contentPanel} | ||||
|       langui={langui} | ||||
|       {...otherProps} | ||||
|     /> | ||||
|   ); | ||||
| @ -150,6 +149,7 @@ export default Videos; | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const sdk = getReadySdk(); | ||||
|   const langui = getLangui(context.locale); | ||||
|   const videos = await sdk.getVideosPreview(); | ||||
|   if (!videos.videos) return { notFound: true }; | ||||
|   videos.videos.data | ||||
| @ -157,14 +157,10 @@ export const getStaticProps: GetStaticProps = async (context) => { | ||||
|       compareDate(a.attributes?.published_date, b.attributes?.published_date) | ||||
|     ) | ||||
|     .reverse(); | ||||
|   const appStaticProps = await getAppStaticProps(context); | ||||
| 
 | ||||
|   const props: Props = { | ||||
|     ...appStaticProps, | ||||
|     videos: videos.videos.data, | ||||
|     openGraph: getOpenGraph( | ||||
|       appStaticProps.langui, | ||||
|       appStaticProps.langui.videos ?? "Videos" | ||||
|     ), | ||||
|     openGraph: getOpenGraph(langui, langui.videos ?? "Videos"), | ||||
|   }; | ||||
|   return { | ||||
|     props: props, | ||||
|  | ||||
| @ -15,28 +15,28 @@ import { | ||||
| import { SubPanel } from "components/Panels/SubPanel"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| import { GetVideoQuery } from "graphql/generated"; | ||||
| import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { getReadySdk } from "graphql/sdk"; | ||||
| import { prettyDate, prettyShortenNumber } from "helpers/formatters"; | ||||
| import { filterHasAttributes, isDefined } from "helpers/others"; | ||||
| import { getVideoFile } from "helpers/videos"; | ||||
| import { getOpenGraph } from "helpers/openGraph"; | ||||
| import { useIsContentPanelAtLeast } from "hooks/useContainerQuery"; | ||||
| import { getLangui } from "graphql/fetchLocalData"; | ||||
| 
 | ||||
| /* | ||||
|  *                                           ╭────────╮ | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps, AppLayoutRequired { | ||||
| interface Props extends AppLayoutRequired { | ||||
|   video: NonNullable< | ||||
|     NonNullable<GetVideoQuery["videos"]>["data"][number]["attributes"] | ||||
|   >; | ||||
| } | ||||
| 
 | ||||
| const Video = ({ langui, video, ...otherProps }: Props): JSX.Element => { | ||||
| const Video = ({ video, ...otherProps }: Props): JSX.Element => { | ||||
|   const isContentPanelAtLeast4xl = useIsContentPanelAtLeast("4xl"); | ||||
|   const { setSubPanelOpen } = useAppLayout(); | ||||
|   const { setSubPanelOpen, langui } = useAppLayout(); | ||||
|   const router = useRouter(); | ||||
| 
 | ||||
|   const subPanel = useMemo( | ||||
| @ -45,7 +45,6 @@ const Video = ({ langui, video, ...otherProps }: Props): JSX.Element => { | ||||
|         <ReturnButton | ||||
|           href="/archives/videos/" | ||||
|           title={langui.videos} | ||||
|           langui={langui} | ||||
|           displayOnlyOn={"3ColumnsLayout"} | ||||
|         /> | ||||
| 
 | ||||
| @ -82,7 +81,6 @@ const Video = ({ langui, video, ...otherProps }: Props): JSX.Element => { | ||||
|         <ReturnButton | ||||
|           href="/library/" | ||||
|           title={langui.library} | ||||
|           langui={langui} | ||||
|           displayOnlyOn={"1ColumnLayout"} | ||||
|           className="mb-10" | ||||
|         /> | ||||
| @ -201,7 +199,6 @@ const Video = ({ langui, video, ...otherProps }: Props): JSX.Element => { | ||||
|     <AppLayout | ||||
|       subPanel={subPanel} | ||||
|       contentPanel={contentPanel} | ||||
|       langui={langui} | ||||
|       {...otherProps} | ||||
|     /> | ||||
|   ); | ||||
| @ -215,6 +212,7 @@ export default Video; | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const sdk = getReadySdk(); | ||||
|   const langui = getLangui(context.locale); | ||||
|   const videos = await sdk.getVideo({ | ||||
|     uid: | ||||
|       context.params && isDefined(context.params.uid) | ||||
| @ -222,14 +220,10 @@ export const getStaticProps: GetStaticProps = async (context) => { | ||||
|         : "", | ||||
|   }); | ||||
|   if (!videos.videos?.data[0]?.attributes) return { notFound: true }; | ||||
|   const appStaticProps = await getAppStaticProps(context); | ||||
| 
 | ||||
|   const props: Props = { | ||||
|     ...appStaticProps, | ||||
|     video: videos.videos.data[0].attributes, | ||||
|     openGraph: getOpenGraph( | ||||
|       appStaticProps.langui, | ||||
|       videos.videos.data[0].attributes.title | ||||
|     ), | ||||
|     openGraph: getOpenGraph(langui, videos.videos.data[0].attributes.title), | ||||
|   }; | ||||
|   return { | ||||
|     props: props, | ||||
|  | ||||
| @ -1,6 +1,5 @@ | ||||
| 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"; | ||||
| @ -22,13 +21,15 @@ import { | ||||
| } from "helpers/locales"; | ||||
| import { getDescription } from "helpers/description"; | ||||
| import { TranslatedChroniclesList } from "components/Chronicles/ChroniclesList"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| import { getLangui } from "graphql/fetchLocalData"; | ||||
| 
 | ||||
| /* | ||||
|  *                                           ╭────────╮ | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps, AppLayoutRequired { | ||||
| interface Props extends AppLayoutRequired { | ||||
|   chronicle: ChronicleWithTranslations; | ||||
|   chapters: NonNullable< | ||||
|     GetChroniclesChaptersQuery["chroniclesChapters"] | ||||
| @ -38,14 +39,12 @@ interface Props extends AppStaticProps, AppLayoutRequired { | ||||
| const Chronicle = ({ | ||||
|   chronicle, | ||||
|   chapters, | ||||
|   langui, | ||||
|   languages, | ||||
|   ...otherProps | ||||
| }: Props): JSX.Element => { | ||||
|   const { langui } = useAppLayout(); | ||||
|   const [selectedTranslation, LanguageSwitcher, languageSwitcherProps] = | ||||
|     useSmartLanguage({ | ||||
|       items: chronicle.translations, | ||||
|       languages: languages, | ||||
|       languageExtractor: useCallback( | ||||
|         (item: ChronicleWithTranslations["translations"][number]) => | ||||
|           item?.language?.data?.attributes?.code, | ||||
| @ -71,7 +70,6 @@ const Chronicle = ({ | ||||
|     ContentLanguageSwitcherProps, | ||||
|   ] = useSmartLanguage({ | ||||
|     items: primaryContent?.translations ?? [], | ||||
|     languages: languages, | ||||
|     languageExtractor: useCallback( | ||||
|       ( | ||||
|         item: NonNullable< | ||||
| @ -93,7 +91,6 @@ const Chronicle = ({ | ||||
|           displayOnlyOn={"1ColumnLayout"} | ||||
|           href="/chronicles" | ||||
|           title={langui.chronicles} | ||||
|           langui={langui} | ||||
|           className="mb-10" | ||||
|         /> | ||||
| 
 | ||||
| @ -108,7 +105,7 @@ const Chronicle = ({ | ||||
|             )} | ||||
| 
 | ||||
|             {isDefined(selectedTranslation.body) && ( | ||||
|               <Markdawn text={selectedTranslation.body.body} langui={langui} /> | ||||
|               <Markdawn text={selectedTranslation.body.body} /> | ||||
|             )} | ||||
|           </> | ||||
|         ) : ( | ||||
| @ -130,16 +127,12 @@ const Chronicle = ({ | ||||
|                   type={primaryContent?.type} | ||||
|                   description={selectedContentTranslation.description} | ||||
|                   thumbnail={primaryContent?.thumbnail?.data?.attributes} | ||||
|                   langui={langui} | ||||
|                 /> | ||||
| 
 | ||||
|                 {selectedContentTranslation.text_set?.text && ( | ||||
|                   <> | ||||
|                     <HorizontalLine /> | ||||
|                     <Markdawn | ||||
|                       text={selectedContentTranslation.text_set.text} | ||||
|                       langui={langui} | ||||
|                     /> | ||||
|                     <Markdawn text={selectedContentTranslation.text_set.text} /> | ||||
|                   </> | ||||
|                 )} | ||||
|               </> | ||||
| @ -169,7 +162,6 @@ const Chronicle = ({ | ||||
|           displayOnlyOn={"3ColumnsLayout"} | ||||
|           href="/chronicles" | ||||
|           title={langui.chronicles} | ||||
|           langui={langui} | ||||
|         /> | ||||
| 
 | ||||
|         <HorizontalLine /> | ||||
| @ -202,8 +194,6 @@ const Chronicle = ({ | ||||
|     <AppLayout | ||||
|       contentPanel={contentPanel} | ||||
|       subPanel={subPanel} | ||||
|       langui={langui} | ||||
|       languages={languages} | ||||
|       subPanelIcon={Icon.FormatListNumbered} | ||||
|       {...otherProps} | ||||
|     /> | ||||
| @ -218,6 +208,7 @@ export default Chronicle; | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const sdk = getReadySdk(); | ||||
|   const langui = getLangui(context.locale); | ||||
|   const slug = | ||||
|     context.params && isDefined(context.params.slug) | ||||
|       ? context.params.slug.toString() | ||||
| @ -232,7 +223,6 @@ export const getStaticProps: GetStaticProps = async (context) => { | ||||
|     !chronicles.chroniclesChapters?.data | ||||
|   ) | ||||
|     return { notFound: true }; | ||||
|   const appStaticProps = await getAppStaticProps(context); | ||||
| 
 | ||||
|   const { title, description } = (() => { | ||||
|     if (context.locale && context.locales) { | ||||
| @ -260,16 +250,15 @@ export const getStaticProps: GetStaticProps = async (context) => { | ||||
|             description: getDescription( | ||||
|               selectedContentTranslation.description, | ||||
|               { | ||||
|                 [appStaticProps.langui.type ?? "Type"]: [ | ||||
|                 [langui.type ?? "Type"]: [ | ||||
|                   chronicle.chronicles.data[0].attributes.contents.data[0] | ||||
|                     .attributes.type?.data?.attributes?.titles?.[0]?.title, | ||||
|                 ], | ||||
|                 [appStaticProps.langui.categories ?? "Categories"]: | ||||
|                   filterHasAttributes( | ||||
|                     chronicle.chronicles.data[0].attributes.contents.data[0] | ||||
|                       .attributes.categories?.data, | ||||
|                     ["attributes"] as const | ||||
|                   ).map((category) => category.attributes.short), | ||||
|                 [langui.categories ?? "Categories"]: filterHasAttributes( | ||||
|                   chronicle.chronicles.data[0].attributes.contents.data[0] | ||||
|                     .attributes.categories?.data, | ||||
|                   ["attributes"] as const | ||||
|                 ).map((category) => category.attributes.short), | ||||
|               } | ||||
|             ), | ||||
|           }; | ||||
| @ -304,16 +293,10 @@ export const getStaticProps: GetStaticProps = async (context) => { | ||||
|       : undefined; | ||||
| 
 | ||||
|   const props: Props = { | ||||
|     ...appStaticProps, | ||||
|     chronicle: chronicle.chronicles.data[0] | ||||
|       .attributes as ChronicleWithTranslations, | ||||
|     chapters: chronicles.chroniclesChapters.data, | ||||
|     openGraph: getOpenGraph( | ||||
|       appStaticProps.langui, | ||||
|       title, | ||||
|       description, | ||||
|       thumbnail | ||||
|     ), | ||||
|     openGraph: getOpenGraph(langui, title, description, thumbnail), | ||||
|   }; | ||||
|   return { | ||||
|     props: props, | ||||
|  | ||||
| @ -3,7 +3,6 @@ import { useMemo } from "react"; | ||||
| import { AppLayout, AppLayoutRequired } from "components/AppLayout"; | ||||
| 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"; | ||||
| @ -12,23 +11,22 @@ import { prettySlug } from "helpers/formatters"; | ||||
| import { getOpenGraph } from "helpers/openGraph"; | ||||
| import { TranslatedChroniclesList } from "components/Chronicles/ChroniclesList"; | ||||
| import { HorizontalLine } from "components/HorizontalLine"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| import { getLangui } from "graphql/fetchLocalData"; | ||||
| 
 | ||||
| /* | ||||
|  *                                           ╭────────╮ | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps, AppLayoutRequired { | ||||
| interface Props extends AppLayoutRequired { | ||||
|   chapters: NonNullable< | ||||
|     GetChroniclesChaptersQuery["chroniclesChapters"] | ||||
|   >["data"]; | ||||
| } | ||||
| 
 | ||||
| const Chronicles = ({ | ||||
|   langui, | ||||
|   chapters, | ||||
|   ...otherProps | ||||
| }: Props): JSX.Element => { | ||||
| const Chronicles = ({ chapters, ...otherProps }: Props): JSX.Element => { | ||||
|   const { langui } = useAppLayout(); | ||||
|   const subPanel = useMemo( | ||||
|     () => ( | ||||
|       <SubPanel> | ||||
| @ -63,7 +61,7 @@ const Chronicles = ({ | ||||
|     [chapters, langui] | ||||
|   ); | ||||
| 
 | ||||
|   return <AppLayout subPanel={subPanel} langui={langui} {...otherProps} />; | ||||
|   return <AppLayout subPanel={subPanel} {...otherProps} />; | ||||
| }; | ||||
| export default Chronicles; | ||||
| 
 | ||||
| @ -74,16 +72,13 @@ export default Chronicles; | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const sdk = getReadySdk(); | ||||
|   const langui = getLangui(context.locale); | ||||
|   const chronicles = await sdk.getChroniclesChapters(); | ||||
|   if (!chronicles.chroniclesChapters?.data) return { notFound: true }; | ||||
|   const appStaticProps = await getAppStaticProps(context); | ||||
| 
 | ||||
|   const props: Props = { | ||||
|     ...appStaticProps, | ||||
|     chapters: chronicles.chroniclesChapters.data, | ||||
|     openGraph: getOpenGraph( | ||||
|       appStaticProps.langui, | ||||
|       appStaticProps.langui.chronicles ?? "Chronicles" | ||||
|     ), | ||||
|     openGraph: getOpenGraph(langui, langui.chronicles ?? "Chronicles"), | ||||
|   }; | ||||
|   return { | ||||
|     props: props, | ||||
|  | ||||
| @ -12,7 +12,6 @@ import { PreviewCard } from "components/PreviewCard"; | ||||
| import { RecorderChip } from "components/RecorderChip"; | ||||
| import { ThumbnailHeader } from "components/ThumbnailHeader"; | ||||
| import { ToolTip } from "components/ToolTip"; | ||||
| import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { getReadySdk } from "graphql/sdk"; | ||||
| import { | ||||
|   prettyInlineTitle, | ||||
| @ -41,30 +40,26 @@ import { | ||||
|   useIsContentPanelAtLeast, | ||||
| } from "hooks/useContainerQuery"; | ||||
| import { cIf } from "helpers/className"; | ||||
| import { getLangui } from "graphql/fetchLocalData"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| 
 | ||||
| /* | ||||
|  *                                           ╭────────╮ | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps, AppLayoutRequired { | ||||
| interface Props extends AppLayoutRequired { | ||||
|   content: ContentWithTranslations; | ||||
| } | ||||
| 
 | ||||
| const Content = ({ | ||||
|   langui, | ||||
|   content, | ||||
|   languages, | ||||
|   currencies, | ||||
|   ...otherProps | ||||
| }: Props): JSX.Element => { | ||||
| const Content = ({ content, ...otherProps }: Props): JSX.Element => { | ||||
|   const isContentPanelAtLeast2xl = useIsContentPanelAtLeast("2xl"); | ||||
|   const is1ColumnLayout = useIs1ColumnLayout(); | ||||
|   const { langui, languages } = useAppLayout(); | ||||
| 
 | ||||
|   const [selectedTranslation, LanguageSwitcher, languageSwitcherProps] = | ||||
|     useSmartLanguage({ | ||||
|       items: content.translations, | ||||
|       languages: languages, | ||||
|       languageExtractor: useCallback( | ||||
|         (item: NonNullable<Props["content"]["translations"][number]>) => | ||||
|           item.language?.data?.attributes?.code, | ||||
| @ -182,10 +177,7 @@ const Content = ({ | ||||
|                         ["attributes", "id"] as const | ||||
|                       ).map((recorder) => ( | ||||
|                         <Fragment key={recorder.id}> | ||||
|                           <RecorderChip | ||||
|                             langui={langui} | ||||
|                             recorder={recorder.attributes} | ||||
|                           /> | ||||
|                           <RecorderChip recorder={recorder.attributes} /> | ||||
|                         </Fragment> | ||||
|                       ))} | ||||
|                     </div> | ||||
| @ -204,10 +196,7 @@ const Content = ({ | ||||
|                         ["attributes", "id"] as const | ||||
|                       ).map((recorder) => ( | ||||
|                         <Fragment key={recorder.id}> | ||||
|                           <RecorderChip | ||||
|                             langui={langui} | ||||
|                             recorder={recorder.attributes} | ||||
|                           /> | ||||
|                           <RecorderChip recorder={recorder.attributes} /> | ||||
|                         </Fragment> | ||||
|                       ))} | ||||
|                     </div> | ||||
| @ -226,10 +215,7 @@ const Content = ({ | ||||
|                         ["attributes", "id"] as const | ||||
|                       ).map((recorder) => ( | ||||
|                         <Fragment key={recorder.id}> | ||||
|                           <RecorderChip | ||||
|                             langui={langui} | ||||
|                             recorder={recorder.attributes} | ||||
|                           /> | ||||
|                           <RecorderChip recorder={recorder.attributes} /> | ||||
|                         </Fragment> | ||||
|                       ))} | ||||
|                     </div> | ||||
| @ -240,10 +226,7 @@ const Content = ({ | ||||
|                 <div> | ||||
|                   <p className="font-headers font-bold">{langui.notes}:</p> | ||||
|                   <div className="grid place-content-center place-items-center gap-2"> | ||||
|                     <Markdawn | ||||
|                       text={selectedTranslation.text_set.notes} | ||||
|                       langui={langui} | ||||
|                     /> | ||||
|                     <Markdawn text={selectedTranslation.text_set.notes} /> | ||||
|                   </div> | ||||
|                 </div> | ||||
|               )} | ||||
| @ -260,7 +243,6 @@ const Content = ({ | ||||
|                 selectedTranslation.title, | ||||
|                 selectedTranslation.subtitle | ||||
|               )} | ||||
|               langui={langui} | ||||
|               horizontalLine | ||||
|             /> | ||||
|           </> | ||||
| @ -311,7 +293,6 @@ const Content = ({ | ||||
|                             ["attributes"] as const | ||||
|                           ).map((category) => category.attributes.short)} | ||||
|                           metadata={{ | ||||
|                             currencies: currencies, | ||||
|                             releaseDate: libraryItem.attributes.release_date, | ||||
|                             price: libraryItem.attributes.price, | ||||
|                             position: "Bottom", | ||||
| @ -319,12 +300,7 @@ const Content = ({ | ||||
|                           infoAppend={ | ||||
|                             !isUntangibleGroupItem( | ||||
|                               libraryItem.attributes.metadata?.[0] | ||||
|                             ) && ( | ||||
|                               <PreviewCardCTAs | ||||
|                                 id={libraryItem.id} | ||||
|                                 langui={langui} | ||||
|                               /> | ||||
|                             ) | ||||
|                             ) && <PreviewCardCTAs id={libraryItem.id} /> | ||||
|                           } | ||||
|                         /> | ||||
|                       </div> | ||||
| @ -338,7 +314,6 @@ const Content = ({ | ||||
|     ), | ||||
|     [ | ||||
|       content.ranged_contents?.data, | ||||
|       currencies, | ||||
|       languages, | ||||
|       langui, | ||||
|       returnButtonProps, | ||||
| @ -365,7 +340,6 @@ const Content = ({ | ||||
|             description={selectedTranslation?.description} | ||||
|             type={content.type} | ||||
|             categories={content.categories} | ||||
|             langui={langui} | ||||
|             languageSwitcher={ | ||||
|               languageSwitcherProps.locales.size > 1 ? ( | ||||
|                 <LanguageSwitcher {...languageSwitcherProps} /> | ||||
| @ -425,10 +399,7 @@ const Content = ({ | ||||
|           {selectedTranslation?.text_set?.text && ( | ||||
|             <> | ||||
|               <HorizontalLine /> | ||||
|               <Markdawn | ||||
|                 text={selectedTranslation.text_set.text} | ||||
|                 langui={langui} | ||||
|               /> | ||||
|               <Markdawn text={selectedTranslation.text_set.text} /> | ||||
|             </> | ||||
|           )} | ||||
| 
 | ||||
| @ -501,9 +472,6 @@ const Content = ({ | ||||
|     <AppLayout | ||||
|       contentPanel={contentPanel} | ||||
|       subPanel={subPanel} | ||||
|       currencies={currencies} | ||||
|       languages={languages} | ||||
|       langui={langui} | ||||
|       {...otherProps} | ||||
|     /> | ||||
|   ); | ||||
| @ -517,6 +485,7 @@ export default Content; | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const sdk = getReadySdk(); | ||||
|   const langui = getLangui(context.locale); | ||||
|   const slug = context.params?.slug ? context.params.slug.toString() : ""; | ||||
|   const content = await sdk.getContentText({ | ||||
|     slug: slug, | ||||
| @ -526,7 +495,6 @@ export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   if (!content.contents?.data[0]?.attributes?.translations) { | ||||
|     return { notFound: true }; | ||||
|   } | ||||
|   const appStaticProps = await getAppStaticProps(context); | ||||
| 
 | ||||
|   const { title, description } = (() => { | ||||
|     if (context.locale && context.locales) { | ||||
| @ -546,15 +514,14 @@ export const getStaticProps: GetStaticProps = async (context) => { | ||||
|             selectedTranslation.subtitle | ||||
|           ), | ||||
|           description: getDescription(selectedTranslation.description, { | ||||
|             [appStaticProps.langui.type ?? "Type"]: [ | ||||
|             [langui.type ?? "Type"]: [ | ||||
|               content.contents.data[0].attributes.type?.data?.attributes | ||||
|                 ?.titles?.[0]?.title, | ||||
|             ], | ||||
|             [appStaticProps.langui.categories ?? "Categories"]: | ||||
|               filterHasAttributes( | ||||
|                 content.contents.data[0].attributes.categories?.data, | ||||
|                 ["attributes"] as const | ||||
|               ).map((category) => category.attributes.short), | ||||
|             [langui.categories ?? "Categories"]: filterHasAttributes( | ||||
|               content.contents.data[0].attributes.categories?.data, | ||||
|               ["attributes"] as const | ||||
|             ).map((category) => category.attributes.short), | ||||
|           }), | ||||
|         }; | ||||
|       } | ||||
| @ -569,14 +536,8 @@ export const getStaticProps: GetStaticProps = async (context) => { | ||||
|     content.contents.data[0].attributes.thumbnail?.data?.attributes; | ||||
| 
 | ||||
|   const props: Props = { | ||||
|     ...appStaticProps, | ||||
|     content: content.contents.data[0].attributes as ContentWithTranslations, | ||||
|     openGraph: getOpenGraph( | ||||
|       appStaticProps.langui, | ||||
|       title, | ||||
|       description, | ||||
|       thumbnail | ||||
|     ), | ||||
|     openGraph: getOpenGraph(langui, title, description, thumbnail), | ||||
|   }; | ||||
|   return { | ||||
|     props: props, | ||||
|  | ||||
| @ -10,7 +10,6 @@ import { | ||||
|   ContentPanelWidthSizes, | ||||
| } from "components/Panels/ContentPanel"; | ||||
| import { SubPanel } from "components/Panels/SubPanel"; | ||||
| import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { getReadySdk } from "graphql/sdk"; | ||||
| import { prettyInlineTitle, prettySlug } from "helpers/formatters"; | ||||
| import { TextInput } from "components/Inputs/TextInput"; | ||||
| @ -27,6 +26,8 @@ import { HorizontalLine } from "components/HorizontalLine"; | ||||
| import { TranslatedPreviewCard } from "components/PreviewCard"; | ||||
| import { useIsContentPanelAtLeast } from "hooks/useContainerQuery"; | ||||
| import { cJoin, cIf } from "helpers/className"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| import { getLangui } from "graphql/fetchLocalData"; | ||||
| 
 | ||||
| /* | ||||
|  *                                         ╭─────────────╮ | ||||
| @ -44,17 +45,13 @@ const DEFAULT_FILTERS_STATE = { | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps, AppLayoutRequired { | ||||
| interface Props extends AppLayoutRequired { | ||||
|   contents: NonNullable<GetContentsQuery["contents"]>["data"]; | ||||
| } | ||||
| 
 | ||||
| const Contents = ({ | ||||
|   langui, | ||||
|   contents, | ||||
|   languages, | ||||
|   ...otherProps | ||||
| }: Props): JSX.Element => { | ||||
| const Contents = ({ contents, ...otherProps }: Props): JSX.Element => { | ||||
|   const hoverable = useDeviceSupportsHover(); | ||||
|   const { langui } = useAppLayout(); | ||||
|   const isContentPanelAtLeast4xl = useIsContentPanelAtLeast("4xl"); | ||||
| 
 | ||||
|   const [groupingMethod, setGroupingMethod] = useState<number>( | ||||
| @ -142,6 +139,7 @@ const Contents = ({ | ||||
| 
 | ||||
|         <Button | ||||
|           href="/contents" | ||||
|           /* TODO: Langui */ | ||||
|           text={"Switch to folder view"} | ||||
|           icon={Icon.Folder} | ||||
|         /> | ||||
| @ -262,7 +260,6 @@ const Contents = ({ | ||||
|               .join(" ")}` | ||||
|           } | ||||
|           paginationItemPerPage={50} | ||||
|           langui={langui} | ||||
|         /> | ||||
|       </ContentPanel> | ||||
|     ), | ||||
| @ -272,7 +269,6 @@ const Contents = ({ | ||||
|       filteringFunction, | ||||
|       groupingFunction, | ||||
|       keepInfoVisible, | ||||
|       langui, | ||||
|       searchName, | ||||
|     ] | ||||
|   ); | ||||
| @ -282,8 +278,6 @@ const Contents = ({ | ||||
|       subPanel={subPanel} | ||||
|       contentPanel={contentPanel} | ||||
|       subPanelIcon={Icon.Search} | ||||
|       languages={languages} | ||||
|       langui={langui} | ||||
|       {...otherProps} | ||||
|     /> | ||||
|   ); | ||||
| @ -297,6 +291,7 @@ export default Contents; | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const sdk = getReadySdk(); | ||||
|   const langui = getLangui(context.locale); | ||||
|   const contents = await sdk.getContents({ | ||||
|     language_code: context.locale ?? "en", | ||||
|   }); | ||||
| @ -307,14 +302,9 @@ export const getStaticProps: GetStaticProps = async (context) => { | ||||
|     return titleA.localeCompare(titleB); | ||||
|   }); | ||||
| 
 | ||||
|   const appStaticProps = await getAppStaticProps(context); | ||||
|   const props: Props = { | ||||
|     ...appStaticProps, | ||||
|     contents: contents.contents.data, | ||||
|     openGraph: getOpenGraph( | ||||
|       appStaticProps.langui, | ||||
|       appStaticProps.langui.contents ?? "Contents" | ||||
|     ), | ||||
|     openGraph: getOpenGraph(langui, langui.contents ?? "Contents"), | ||||
|   }; | ||||
|   return { | ||||
|     props: props, | ||||
|  | ||||
| @ -5,7 +5,6 @@ import { | ||||
|   ContentPanel, | ||||
|   ContentPanelWidthSizes, | ||||
| } from "components/Panels/ContentPanel"; | ||||
| import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { getOpenGraph } from "helpers/openGraph"; | ||||
| import { getReadySdk } from "graphql/sdk"; | ||||
| import { filterHasAttributes } from "helpers/others"; | ||||
| @ -27,13 +26,15 @@ import { TranslatedPreviewCard } from "components/PreviewCard"; | ||||
| import { HorizontalLine } from "components/HorizontalLine"; | ||||
| import { useIsContentPanelAtLeast } from "hooks/useContainerQuery"; | ||||
| import { cJoin, cIf } from "helpers/className"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| import { getLangui } from "graphql/fetchLocalData"; | ||||
| 
 | ||||
| /* | ||||
|  *                                           ╭────────╮ | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps, AppLayoutRequired { | ||||
| interface Props extends AppLayoutRequired { | ||||
|   folder: NonNullable< | ||||
|     NonNullable< | ||||
|       GetContentsFolderQuery["contentsFolders"] | ||||
| @ -42,11 +43,11 @@ interface Props extends AppStaticProps, AppLayoutRequired { | ||||
| } | ||||
| 
 | ||||
| const ContentsFolder = ({ | ||||
|   langui, | ||||
|   openGraph, | ||||
|   folder, | ||||
|   ...otherProps | ||||
| }: Props): JSX.Element => { | ||||
|   const { langui } = useAppLayout(); | ||||
|   const isContentPanelAtLeast4xl = useIsContentPanelAtLeast("4xl"); | ||||
| 
 | ||||
|   const subPanel = useMemo( | ||||
| @ -62,6 +63,7 @@ const ContentsFolder = ({ | ||||
| 
 | ||||
|         <Button | ||||
|           href="/contents/all" | ||||
|           /* TODO: Langui */ | ||||
|           text={"Switch to grid view"} | ||||
|           icon={Icon.Apps} | ||||
|         /> | ||||
| @ -142,7 +144,6 @@ const ContentsFolder = ({ | ||||
|             ) | ||||
|           )} | ||||
|           renderWhenEmpty={() => <></>} | ||||
|           langui={langui} | ||||
|           groupingFunction={() => [langui.folders ?? "Folders"]} | ||||
|         /> | ||||
| 
 | ||||
| @ -188,14 +189,11 @@ const ContentsFolder = ({ | ||||
|             "grid-cols-2 gap-x-3 gap-y-5" | ||||
|           )} | ||||
|           renderWhenEmpty={() => <></>} | ||||
|           langui={langui} | ||||
|           groupingFunction={() => [langui.contents ?? "Contents"]} | ||||
|         /> | ||||
| 
 | ||||
|         {folder.contents?.data.length === 0 && | ||||
|           folder.subfolders?.data.length === 0 && ( | ||||
|             <NoContentNorFolderMessage langui={langui} /> | ||||
|           )} | ||||
|           folder.subfolders?.data.length === 0 && <NoContentNorFolderMessage />} | ||||
|       </ContentPanel> | ||||
|     ), | ||||
|     [ | ||||
| @ -214,7 +212,6 @@ const ContentsFolder = ({ | ||||
|       subPanel={subPanel} | ||||
|       contentPanel={contentPanel} | ||||
|       openGraph={openGraph} | ||||
|       langui={langui} | ||||
|       {...otherProps} | ||||
|     /> | ||||
|   ); | ||||
| @ -228,6 +225,7 @@ export default ContentsFolder; | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const sdk = getReadySdk(); | ||||
|   const langui = getLangui(context.locale); | ||||
|   const slug = context.params?.slug ? context.params.slug.toString() : ""; | ||||
|   const contentsFolder = await sdk.getContentsFolder({ | ||||
|     slug: slug, | ||||
| @ -238,11 +236,10 @@ export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   } | ||||
| 
 | ||||
|   const folder = contentsFolder.contentsFolders.data[0].attributes; | ||||
|   const appStaticProps = await getAppStaticProps(context); | ||||
| 
 | ||||
|   const title = (() => { | ||||
|     if (slug === "root") { | ||||
|       return appStaticProps.langui.contents ?? "Contents"; | ||||
|       return langui.contents ?? "Contents"; | ||||
|     } | ||||
|     if (context.locale && context.locales) { | ||||
|       const selectedTranslation = staticSmartLanguage({ | ||||
| @ -261,8 +258,7 @@ export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   })(); | ||||
| 
 | ||||
|   const props: Props = { | ||||
|     ...appStaticProps, | ||||
|     openGraph: getOpenGraph(appStaticProps.langui, title), | ||||
|     openGraph: getOpenGraph(langui, title), | ||||
|     folder, | ||||
|   }; | ||||
|   return { | ||||
| @ -340,19 +336,16 @@ const TranslatedPreviewFolder = ({ | ||||
| 
 | ||||
| // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
 | ||||
| 
 | ||||
| interface NoContentNorFolderMessageProps { | ||||
|   langui: AppStaticProps["langui"]; | ||||
| } | ||||
| 
 | ||||
| const NoContentNorFolderMessage = ({ | ||||
|   langui, | ||||
| }: NoContentNorFolderMessageProps) => ( | ||||
|   <div className="grid place-content-center"> | ||||
|     <div | ||||
|       className="grid grid-flow-col place-items-center gap-9 rounded-2xl border-2 border-dotted | ||||
| const NoContentNorFolderMessage = () => { | ||||
|   const { langui } = useAppLayout(); | ||||
|   return ( | ||||
|     <div className="grid place-content-center"> | ||||
|       <div | ||||
|         className="grid grid-flow-col place-items-center gap-9 rounded-2xl border-2 border-dotted | ||||
|       border-dark p-8 text-dark opacity-40" | ||||
|     > | ||||
|       <p className="max-w-xs text-2xl">{langui.empty_folder_message}</p> | ||||
|       > | ||||
|         <p className="max-w-xs text-2xl">{langui.empty_folder_message}</p> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| ); | ||||
|   ); | ||||
| }; | ||||
|  | ||||
| @ -9,18 +9,18 @@ import { | ||||
| } from "components/Panels/ContentPanel"; | ||||
| import { ToolTip } from "components/ToolTip"; | ||||
| import { DevGetContentsQuery } from "graphql/generated"; | ||||
| import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { getReadySdk } from "graphql/sdk"; | ||||
| import { filterDefined, filterHasAttributes } from "helpers/others"; | ||||
| import { Report, Severity } from "helpers/types/Report"; | ||||
| import { getOpenGraph } from "helpers/openGraph"; | ||||
| import { getLangui } from "graphql/fetchLocalData"; | ||||
| 
 | ||||
| /* | ||||
|  *                                           ╭────────╮ | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps, AppLayoutRequired { | ||||
| interface Props extends AppLayoutRequired { | ||||
|   contents: DevGetContentsQuery; | ||||
| } | ||||
| 
 | ||||
| @ -99,12 +99,11 @@ export default CheckupContents; | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const sdk = getReadySdk(); | ||||
|   const langui = getLangui(context.locale); | ||||
|   const contents = await sdk.devGetContents(); | ||||
|   const appStaticProps = await getAppStaticProps(context); | ||||
|   const props: Props = { | ||||
|     ...appStaticProps, | ||||
|     contents: contents, | ||||
|     openGraph: getOpenGraph(appStaticProps.langui, "Checkup Contents"), | ||||
|     openGraph: getOpenGraph(langui, "Checkup Contents"), | ||||
|   }; | ||||
|   return { | ||||
|     props: props, | ||||
|  | ||||
| @ -12,17 +12,17 @@ import { | ||||
|   DevGetLibraryItemsQuery, | ||||
|   Enum_Componentcollectionscomponentlibraryimages_Status, | ||||
| } from "graphql/generated"; | ||||
| import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { getReadySdk } from "graphql/sdk"; | ||||
| import { Report, Severity } from "helpers/types/Report"; | ||||
| import { getOpenGraph } from "helpers/openGraph"; | ||||
| import { getLangui } from "graphql/fetchLocalData"; | ||||
| 
 | ||||
| /* | ||||
|  *                                           ╭────────╮ | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps, AppLayoutRequired { | ||||
| interface Props extends AppLayoutRequired { | ||||
|   libraryItems: DevGetLibraryItemsQuery; | ||||
| } | ||||
| 
 | ||||
| @ -104,12 +104,12 @@ export default CheckupLibraryItems; | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const sdk = getReadySdk(); | ||||
|   const langui = getLangui(context.locale); | ||||
|   const libraryItems = await sdk.devGetLibraryItems(); | ||||
|   const appStaticProps = await getAppStaticProps(context); | ||||
| 
 | ||||
|   const props: Props = { | ||||
|     ...appStaticProps, | ||||
|     libraryItems: libraryItems, | ||||
|     openGraph: getOpenGraph(appStaticProps.langui, "Checkup Library Items"), | ||||
|     openGraph: getOpenGraph(langui, "Checkup Library Items"), | ||||
|   }; | ||||
|   return { | ||||
|     props: props, | ||||
|  | ||||
| @ -10,18 +10,18 @@ import { | ||||
| } from "components/Panels/ContentPanel"; | ||||
| import { Popup } from "components/Popup"; | ||||
| import { ToolTip } from "components/ToolTip"; | ||||
| import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { Icon } from "components/Ico"; | ||||
| import { getOpenGraph } from "helpers/openGraph"; | ||||
| import { getLangui } from "graphql/fetchLocalData"; | ||||
| 
 | ||||
| /* | ||||
|  *                                           ╭────────╮ | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps, AppLayoutRequired {} | ||||
| interface Props extends AppLayoutRequired {} | ||||
| 
 | ||||
| const Editor = ({ langui, ...otherProps }: Props): JSX.Element => { | ||||
| const Editor = (props: Props): JSX.Element => { | ||||
|   const handleInput = useCallback((text: string) => { | ||||
|     setMarkdown(text); | ||||
|   }, []); | ||||
| @ -445,13 +445,13 @@ const Editor = ({ langui, ...otherProps }: Props): JSX.Element => { | ||||
|           <div> | ||||
|             <h2>Preview</h2> | ||||
|             <div className="h-[70vh] overflow-scroll rounded-xl bg-mid bg-opacity-40 p-8"> | ||||
|               <Markdawn className="w-full" text={markdown} langui={langui} /> | ||||
|               <Markdawn className="w-full" text={markdown} /> | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
| 
 | ||||
|         <div className="mt-8"> | ||||
|           <TableOfContents text={markdown} langui={langui} /> | ||||
|           <TableOfContents text={markdown} /> | ||||
|         </div> | ||||
|       </ContentPanel> | ||||
|     ), | ||||
| @ -460,7 +460,6 @@ const Editor = ({ langui, ...otherProps }: Props): JSX.Element => { | ||||
|       converterOpened, | ||||
|       handleInput, | ||||
|       insert, | ||||
|       langui, | ||||
|       markdown, | ||||
|       preline, | ||||
|       toggleWrap, | ||||
| @ -468,9 +467,7 @@ const Editor = ({ langui, ...otherProps }: Props): JSX.Element => { | ||||
|     ] | ||||
|   ); | ||||
| 
 | ||||
|   return ( | ||||
|     <AppLayout contentPanel={contentPanel} langui={langui} {...otherProps} /> | ||||
|   ); | ||||
|   return <AppLayout contentPanel={contentPanel} {...props} />; | ||||
| }; | ||||
| export default Editor; | ||||
| 
 | ||||
| @ -479,11 +476,10 @@ export default Editor; | ||||
|  * ───────────────────────────────────╯  NEXT DATA FETCHING  ╰────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const appStaticProps = await getAppStaticProps(context); | ||||
| export const getStaticProps: GetStaticProps = (context) => { | ||||
|   const langui = getLangui(context.locale); | ||||
|   const props: Props = { | ||||
|     ...appStaticProps, | ||||
|     openGraph: getOpenGraph(appStaticProps.langui, "Markdawn Editor"), | ||||
|     openGraph: getOpenGraph(langui, "Markdawn Editor"), | ||||
|   }; | ||||
|   return { | ||||
|     props: props, | ||||
|  | ||||
| @ -8,8 +8,8 @@ import { | ||||
|   ContentPanelWidthSizes, | ||||
| } from "components/Panels/ContentPanel"; | ||||
| import { ToolTip } from "components/ToolTip"; | ||||
| import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { getOpenGraph } from "helpers/openGraph"; | ||||
| import { getLangui } from "graphql/fetchLocalData"; | ||||
| 
 | ||||
| /* | ||||
|  *                                         ╭─────────────╮ | ||||
| @ -23,7 +23,7 @@ const SIZE_MULTIPLIER = 1000; | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps, AppLayoutRequired {} | ||||
| interface Props extends AppLayoutRequired {} | ||||
| 
 | ||||
| const replaceSelection = ( | ||||
|   text: string, | ||||
| @ -580,14 +580,10 @@ export default Transcript; | ||||
|  * ───────────────────────────────────╯  NEXT DATA FETCHING  ╰────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const appStaticProps = await getAppStaticProps(context); | ||||
| export const getStaticProps: GetStaticProps = (context) => { | ||||
|   const langui = getLangui(context.locale); | ||||
|   const props: Props = { | ||||
|     ...appStaticProps, | ||||
|     openGraph: getOpenGraph( | ||||
|       appStaticProps.langui, | ||||
|       "Japanese Transcription Tool" | ||||
|     ), | ||||
|     openGraph: getOpenGraph(langui, "Japanese Transcription Tool"), | ||||
|   }; | ||||
|   return { | ||||
|     props: props, | ||||
|  | ||||
| @ -3,18 +3,15 @@ import { | ||||
|   getPostStaticProps, | ||||
|   PostStaticProps, | ||||
| } from "graphql/getPostStaticProps"; | ||||
| import { getOpenGraph } from "helpers/openGraph"; | ||||
| 
 | ||||
| /* | ||||
|  *                                           ╭────────╮ | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| const Home = ({ langui, ...otherProps }: PostStaticProps): JSX.Element => ( | ||||
| const Home = ({ ...otherProps }: PostStaticProps): JSX.Element => ( | ||||
|   <PostPage | ||||
|     {...otherProps} | ||||
|     openGraph={getOpenGraph(langui)} | ||||
|     langui={langui} | ||||
|     prependBody={ | ||||
|       <div className="grid w-full place-content-center place-items-center gap-5 text-center"> | ||||
|         <div | ||||
|  | ||||
| @ -23,7 +23,6 @@ import { | ||||
|   Enum_Componentmetadatabooks_Page_Order, | ||||
|   GetLibraryItemQuery, | ||||
| } from "graphql/generated"; | ||||
| import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { getReadySdk } from "graphql/sdk"; | ||||
| import { | ||||
|   prettyDate, | ||||
| @ -56,6 +55,8 @@ import { getDescription } from "helpers/description"; | ||||
| import { useIntersectionList } from "hooks/useIntersectionList"; | ||||
| import { HorizontalLine } from "components/HorizontalLine"; | ||||
| import { useIsContentPanelNoMoreThan } from "hooks/useContainerQuery"; | ||||
| import { useCurrencies } from "hooks/useLocalData"; | ||||
| import { getLangui } from "graphql/fetchLocalData"; | ||||
| 
 | ||||
| /* | ||||
|  *                                         ╭─────────────╮ | ||||
| @ -75,7 +76,7 @@ const intersectionIds = [ | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps, AppLayoutRequired { | ||||
| interface Props extends AppLayoutRequired { | ||||
|   item: NonNullable< | ||||
|     NonNullable< | ||||
|       GetLibraryItemQuery["libraryItems"] | ||||
| @ -86,15 +87,10 @@ interface Props extends AppStaticProps, AppLayoutRequired { | ||||
|   >["data"][number]["id"]; | ||||
| } | ||||
| 
 | ||||
| const LibrarySlug = ({ | ||||
|   item, | ||||
|   itemId, | ||||
|   langui, | ||||
|   currencies, | ||||
|   languages, | ||||
|   ...otherProps | ||||
| }: Props): JSX.Element => { | ||||
| const LibrarySlug = ({ item, itemId, ...otherProps }: Props): JSX.Element => { | ||||
|   const { currency } = useAppLayout(); | ||||
|   const { langui } = useAppLayout(); | ||||
|   const currencies = useCurrencies(); | ||||
|   const isContentPanelNoMoreThan3xl = useIsContentPanelNoMoreThan("3xl"); | ||||
|   const isContentPanelNoMoreThanSm = useIsContentPanelNoMoreThan("sm"); | ||||
|   const hoverable = useDeviceSupportsHover(); | ||||
| @ -128,7 +124,6 @@ const LibrarySlug = ({ | ||||
|         <ReturnButton | ||||
|           href="/library/" | ||||
|           title={langui.library} | ||||
|           langui={langui} | ||||
|           displayOnlyOn="3ColumnsLayout" | ||||
|         /> | ||||
| 
 | ||||
| @ -196,7 +191,6 @@ const LibrarySlug = ({ | ||||
|         <ReturnButton | ||||
|           href="/library/" | ||||
|           title={langui.library} | ||||
|           langui={langui} | ||||
|           displayOnlyOn="1ColumnLayout" | ||||
|           className="mb-10" | ||||
|         /> | ||||
| @ -252,7 +246,7 @@ const LibrarySlug = ({ | ||||
| 
 | ||||
|               {!isUntangibleGroupItem(item.metadata?.[0]) && | ||||
|                 isDefinedAndNotEmpty(itemId) && ( | ||||
|                   <PreviewCardCTAs id={itemId} langui={langui} expand /> | ||||
|                   <PreviewCardCTAs id={itemId} expand /> | ||||
|                 )} | ||||
| 
 | ||||
|               {item.descriptions?.[0] && ( | ||||
| @ -571,7 +565,6 @@ const LibrarySlug = ({ | ||||
|                         (category) => category.attributes?.short ?? "" | ||||
|                       )} | ||||
|                       metadata={{ | ||||
|                         currencies: currencies, | ||||
|                         releaseDate: subitem.attributes.release_date, | ||||
|                         price: subitem.attributes.price, | ||||
|                         position: "Bottom", | ||||
| @ -579,7 +572,7 @@ const LibrarySlug = ({ | ||||
|                       infoAppend={ | ||||
|                         !isUntangibleGroupItem( | ||||
|                           subitem.attributes.metadata?.[0] | ||||
|                         ) && <PreviewCardCTAs id={subitem.id} langui={langui} /> | ||||
|                         ) && <PreviewCardCTAs id={subitem.id} /> | ||||
|                       } | ||||
|                     /> | ||||
|                   </Fragment> | ||||
| @ -635,7 +628,6 @@ const LibrarySlug = ({ | ||||
|                           } | ||||
|                         : undefined | ||||
|                     } | ||||
|                     langui={langui} | ||||
|                     rangeStart={ | ||||
|                       rangedContent.attributes.range[0]?.__typename === | ||||
|                       "ComponentRangePageRange" | ||||
| @ -645,7 +637,6 @@ const LibrarySlug = ({ | ||||
|                     slug={rangedContent.attributes.slug} | ||||
|                     parentSlug={item.slug} | ||||
|                     key={rangedContent.id} | ||||
|                     languages={languages} | ||||
|                     hasScanSet={ | ||||
|                       isDefined(rangedContent.attributes.scan_set) && | ||||
|                       rangedContent.attributes.scan_set.length > 0 | ||||
| @ -689,7 +680,6 @@ const LibrarySlug = ({ | ||||
|       keepInfoVisible, | ||||
|       displayOpenScans, | ||||
|       openLightBox, | ||||
|       languages, | ||||
|     ] | ||||
|   ); | ||||
| 
 | ||||
| @ -697,9 +687,6 @@ const LibrarySlug = ({ | ||||
|     <AppLayout | ||||
|       contentPanel={contentPanel} | ||||
|       subPanel={subPanel} | ||||
|       currencies={currencies} | ||||
|       languages={languages} | ||||
|       langui={langui} | ||||
|       {...otherProps} | ||||
|     /> | ||||
|   ); | ||||
| @ -713,6 +700,7 @@ export default LibrarySlug; | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const sdk = getReadySdk(); | ||||
|   const langui = getLangui(context.locale); | ||||
|   const item = await sdk.getLibraryItem({ | ||||
|     slug: | ||||
|       context.params && isDefined(context.params.slug) | ||||
| @ -722,22 +710,21 @@ export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   }); | ||||
|   if (!item.libraryItems?.data[0]?.attributes) return { notFound: true }; | ||||
|   sortRangedContent(item.libraryItems.data[0].attributes.contents); | ||||
|   const appStaticProps = await getAppStaticProps(context); | ||||
| 
 | ||||
|   const { title, thumbnail } = item.libraryItems.data[0].attributes; | ||||
| 
 | ||||
|   const description = getDescription( | ||||
|     item.libraryItems.data[0].attributes.descriptions?.[0]?.description, | ||||
|     { | ||||
|       [appStaticProps.langui.categories ?? "Categories"]: filterHasAttributes( | ||||
|       [langui.categories ?? "Categories"]: filterHasAttributes( | ||||
|         item.libraryItems.data[0].attributes.categories?.data, | ||||
|         ["attributes.short"] | ||||
|       ).map((category) => category.attributes.short), | ||||
|       [appStaticProps.langui.type ?? "Type"]: item.libraryItems.data[0] | ||||
|         .attributes.metadata?.[0] | ||||
|       [langui.type ?? "Type"]: item.libraryItems.data[0].attributes | ||||
|         .metadata?.[0] | ||||
|         ? [prettyItemSubType(item.libraryItems.data[0].attributes.metadata[0])] | ||||
|         : [], | ||||
|       [appStaticProps.langui.release_date ?? "Release date"]: [ | ||||
|       [langui.release_date ?? "Release date"]: [ | ||||
|         item.libraryItems.data[0].attributes.release_date | ||||
|           ? prettyDate( | ||||
|               item.libraryItems.data[0].attributes.release_date, | ||||
| @ -749,11 +736,10 @@ export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   ); | ||||
| 
 | ||||
|   const props: Props = { | ||||
|     ...appStaticProps, | ||||
|     item: item.libraryItems.data[0].attributes, | ||||
|     itemId: item.libraryItems.data[0].id, | ||||
|     openGraph: getOpenGraph( | ||||
|       appStaticProps.langui, | ||||
|       langui, | ||||
|       title, | ||||
|       description, | ||||
|       thumbnail?.data?.attributes | ||||
| @ -803,8 +789,7 @@ interface ContentLineProps { | ||||
|   rangeStart: string; | ||||
|   parentSlug: string; | ||||
|   slug: string; | ||||
|   langui: AppStaticProps["langui"]; | ||||
|   languages: AppStaticProps["languages"]; | ||||
| 
 | ||||
|   hasScanSet: boolean; | ||||
|   condensed: boolean; | ||||
| } | ||||
| @ -812,17 +797,15 @@ interface ContentLineProps { | ||||
| const ContentLine = ({ | ||||
|   rangeStart, | ||||
|   content, | ||||
|   langui, | ||||
|   languages, | ||||
|   hasScanSet, | ||||
|   slug, | ||||
|   parentSlug, | ||||
|   condensed, | ||||
| }: ContentLineProps): JSX.Element => { | ||||
|   const { langui } = useAppLayout(); | ||||
|   const { value: isOpened, toggle: toggleOpened } = useBoolean(false); | ||||
|   const [selectedTranslation] = useSmartLanguage({ | ||||
|     items: content?.translations ?? [], | ||||
|     languages: languages, | ||||
|     languageExtractor: useCallback( | ||||
|       ( | ||||
|         item: NonNullable<ContentLineProps["content"]>["translations"][number] | ||||
|  | ||||
| @ -11,7 +11,6 @@ import { | ||||
|   GetLibraryItemScansQuery, | ||||
|   UploadImageFragment, | ||||
| } from "graphql/generated"; | ||||
| import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { getReadySdk } from "graphql/sdk"; | ||||
| import { | ||||
|   prettyInlineTitle, | ||||
| @ -47,13 +46,15 @@ import { | ||||
|   useIsContentPanelNoMoreThan, | ||||
| } from "hooks/useContainerQuery"; | ||||
| import { cIf, cJoin } from "helpers/className"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| import { getLangui } from "graphql/fetchLocalData"; | ||||
| 
 | ||||
| /* | ||||
|  *                                           ╭────────╮ | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps, AppLayoutRequired { | ||||
| interface Props extends AppLayoutRequired { | ||||
|   item: NonNullable< | ||||
|     NonNullable< | ||||
|       GetLibraryItemScansQuery["libraryItems"] | ||||
| @ -64,16 +65,10 @@ interface Props extends AppStaticProps, AppLayoutRequired { | ||||
|   >; | ||||
| } | ||||
| 
 | ||||
| const LibrarySlug = ({ | ||||
|   item, | ||||
|   itemId, | ||||
|   langui, | ||||
|   languages, | ||||
|   currencies, | ||||
|   ...otherProps | ||||
| }: Props): JSX.Element => { | ||||
| const LibrarySlug = ({ item, itemId, ...otherProps }: Props): JSX.Element => { | ||||
|   const [openLightBox, LightBox] = useLightBox(); | ||||
|   const is1ColumnLayout = useIs1ColumnLayout(); | ||||
|   const { langui } = useAppLayout(); | ||||
| 
 | ||||
|   const ids = useMemo( | ||||
|     () => | ||||
| @ -90,7 +85,6 @@ const LibrarySlug = ({ | ||||
|         <ReturnButton | ||||
|           href={`/library/${item.slug}`} | ||||
|           title={langui.item} | ||||
|           langui={langui} | ||||
|           className="mb-4" | ||||
|           displayOnlyOn="3ColumnsLayout" | ||||
|         /> | ||||
| @ -113,14 +107,13 @@ const LibrarySlug = ({ | ||||
|                 "attributes", | ||||
|               ] as const).map((category) => category.attributes.short)} | ||||
|               metadata={{ | ||||
|                 currencies: currencies, | ||||
|                 releaseDate: item.release_date, | ||||
|                 price: item.price, | ||||
|                 position: "Bottom", | ||||
|               }} | ||||
|               infoAppend={ | ||||
|                 !isUntangibleGroupItem(item.metadata?.[0]) && ( | ||||
|                   <PreviewCardCTAs id={itemId} langui={langui} /> | ||||
|                   <PreviewCardCTAs id={itemId} /> | ||||
|                 ) | ||||
|               } | ||||
|             /> | ||||
| @ -180,7 +173,6 @@ const LibrarySlug = ({ | ||||
|       </SubPanel> | ||||
|     ), | ||||
|     [ | ||||
|       currencies, | ||||
|       currentIntersection, | ||||
|       item.categories?.data, | ||||
|       item.contents?.data, | ||||
| @ -205,18 +197,12 @@ const LibrarySlug = ({ | ||||
|         <ReturnButton | ||||
|           href={`/library/${item.slug}`} | ||||
|           title={langui.item} | ||||
|           langui={langui} | ||||
|           displayOnlyOn="1ColumnLayout" | ||||
|           className="mb-10" | ||||
|         /> | ||||
| 
 | ||||
|         {item.images && ( | ||||
|           <ScanSetCover | ||||
|             images={item.images} | ||||
|             openLightBox={openLightBox} | ||||
|             languages={languages} | ||||
|             langui={langui} | ||||
|           /> | ||||
|           <ScanSetCover images={item.images} openLightBox={openLightBox} /> | ||||
|         )} | ||||
| 
 | ||||
|         {item.contents?.data.map((content) => ( | ||||
| @ -240,8 +226,6 @@ const LibrarySlug = ({ | ||||
|                 fallback={{ | ||||
|                   title: prettySlug(content.attributes.slug, item.slug), | ||||
|                 }} | ||||
|                 languages={languages} | ||||
|                 langui={langui} | ||||
|                 content={content.attributes.content} | ||||
|               /> | ||||
|             )} | ||||
| @ -255,7 +239,6 @@ const LibrarySlug = ({ | ||||
|       item.contents?.data, | ||||
|       item.images, | ||||
|       item.slug, | ||||
|       languages, | ||||
|       langui, | ||||
|     ] | ||||
|   ); | ||||
| @ -264,9 +247,6 @@ const LibrarySlug = ({ | ||||
|     <AppLayout | ||||
|       contentPanel={contentPanel} | ||||
|       subPanel={subPanel} | ||||
|       languages={languages} | ||||
|       langui={langui} | ||||
|       currencies={currencies} | ||||
|       {...otherProps} | ||||
|     /> | ||||
|   ); | ||||
| @ -280,6 +260,7 @@ export default LibrarySlug; | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const sdk = getReadySdk(); | ||||
|   const langui = getLangui(context.locale); | ||||
|   const item = await sdk.getLibraryItemScans({ | ||||
|     slug: | ||||
|       context.params && isDefined(context.params.slug) | ||||
| @ -290,13 +271,12 @@ export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   if (!item.libraryItems?.data[0]?.attributes || !item.libraryItems.data[0]?.id) | ||||
|     return { notFound: true }; | ||||
|   sortRangedContent(item.libraryItems.data[0].attributes.contents); | ||||
|   const appStaticProps = await getAppStaticProps(context); | ||||
| 
 | ||||
|   const props: Props = { | ||||
|     ...appStaticProps, | ||||
|     item: item.libraryItems.data[0].attributes, | ||||
|     itemId: item.libraryItems.data[0].id, | ||||
|     openGraph: getOpenGraph( | ||||
|       appStaticProps.langui, | ||||
|       langui, | ||||
|       item.libraryItems.data[0].attributes.title, | ||||
|       undefined, | ||||
|       item.libraryItems.data[0].attributes.thumbnail?.data?.attributes | ||||
| @ -352,8 +332,7 @@ interface ScanSetProps { | ||||
|   >; | ||||
|   id: string; | ||||
|   title: string; | ||||
|   languages: AppStaticProps["languages"]; | ||||
|   langui: AppStaticProps["langui"]; | ||||
| 
 | ||||
|   content: NonNullable< | ||||
|     NonNullable< | ||||
|       NonNullable< | ||||
| @ -370,15 +349,13 @@ const ScanSet = ({ | ||||
|   scanSet, | ||||
|   id, | ||||
|   title, | ||||
|   languages, | ||||
|   langui, | ||||
|   content, | ||||
| }: ScanSetProps): JSX.Element => { | ||||
|   const is1ColumnLayout = useIsContentPanelNoMoreThan("2xl"); | ||||
|   const { langui } = useAppLayout(); | ||||
|   const [selectedScan, LanguageSwitcher, languageSwitcherProps] = | ||||
|     useSmartLanguage({ | ||||
|       items: scanSet, | ||||
|       languages: languages, | ||||
|       languageExtractor: useCallback( | ||||
|         (item: NonNullable<ScanSetProps["scanSet"][number]>) => | ||||
|           item.language?.data?.attributes?.code, | ||||
| @ -479,10 +456,7 @@ const ScanSet = ({ | ||||
|                     "attributes", | ||||
|                   ] as const).map((scanner) => ( | ||||
|                     <Fragment key={scanner.id}> | ||||
|                       <RecorderChip | ||||
|                         langui={langui} | ||||
|                         recorder={scanner.attributes} | ||||
|                       /> | ||||
|                       <RecorderChip recorder={scanner.attributes} /> | ||||
|                     </Fragment> | ||||
|                   ))} | ||||
|                 </div> | ||||
| @ -498,10 +472,7 @@ const ScanSet = ({ | ||||
|                     "attributes", | ||||
|                   ] as const).map((cleaner) => ( | ||||
|                     <Fragment key={cleaner.id}> | ||||
|                       <RecorderChip | ||||
|                         langui={langui} | ||||
|                         recorder={cleaner.attributes} | ||||
|                       /> | ||||
|                       <RecorderChip recorder={cleaner.attributes} /> | ||||
|                     </Fragment> | ||||
|                   ))} | ||||
|                 </div> | ||||
| @ -520,10 +491,7 @@ const ScanSet = ({ | ||||
|                       "attributes", | ||||
|                     ] as const).map((typesetter) => ( | ||||
|                       <Fragment key={typesetter.id}> | ||||
|                         <RecorderChip | ||||
|                           langui={langui} | ||||
|                           recorder={typesetter.attributes} | ||||
|                         /> | ||||
|                         <RecorderChip recorder={typesetter.attributes} /> | ||||
|                       </Fragment> | ||||
|                     ))} | ||||
|                   </div> | ||||
| @ -604,21 +572,17 @@ interface ScanSetCoverProps { | ||||
|       >["data"][number]["attributes"] | ||||
|     >["images"] | ||||
|   >; | ||||
|   languages: AppStaticProps["languages"]; | ||||
|   langui: AppStaticProps["langui"]; | ||||
| } | ||||
| 
 | ||||
| const ScanSetCover = ({ | ||||
|   openLightBox, | ||||
|   images, | ||||
|   languages, | ||||
|   langui, | ||||
| }: ScanSetCoverProps): JSX.Element => { | ||||
|   const is1ColumnLayout = useIsContentPanelNoMoreThan("4xl"); | ||||
|   const { langui } = useAppLayout(); | ||||
|   const [selectedScan, LanguageSwitcher, languageSwitcherProps] = | ||||
|     useSmartLanguage({ | ||||
|       items: images, | ||||
|       languages: languages, | ||||
|       languageExtractor: useCallback( | ||||
|         (item: NonNullable<ScanSetCoverProps["images"][number]>) => | ||||
|           item.language?.data?.attributes?.code, | ||||
| @ -687,10 +651,7 @@ const ScanSetCover = ({ | ||||
|                     "attributes", | ||||
|                   ] as const).map((scanner) => ( | ||||
|                     <Fragment key={scanner.id}> | ||||
|                       <RecorderChip | ||||
|                         langui={langui} | ||||
|                         recorder={scanner.attributes} | ||||
|                       /> | ||||
|                       <RecorderChip recorder={scanner.attributes} /> | ||||
|                     </Fragment> | ||||
|                   ))} | ||||
|                 </div> | ||||
| @ -706,10 +667,7 @@ const ScanSetCover = ({ | ||||
|                     "attributes", | ||||
|                   ] as const).map((cleaner) => ( | ||||
|                     <Fragment key={cleaner.id}> | ||||
|                       <RecorderChip | ||||
|                         langui={langui} | ||||
|                         recorder={cleaner.attributes} | ||||
|                       /> | ||||
|                       <RecorderChip recorder={cleaner.attributes} /> | ||||
|                     </Fragment> | ||||
|                   ))} | ||||
|                 </div> | ||||
| @ -728,10 +686,7 @@ const ScanSetCover = ({ | ||||
|                       "attributes", | ||||
|                     ] as const).map((typesetter) => ( | ||||
|                       <Fragment key={typesetter.id}> | ||||
|                         <RecorderChip | ||||
|                           langui={langui} | ||||
|                           recorder={typesetter.attributes} | ||||
|                         /> | ||||
|                         <RecorderChip recorder={typesetter.attributes} /> | ||||
|                       </Fragment> | ||||
|                     ))} | ||||
|                   </div> | ||||
|  | ||||
| @ -11,7 +11,6 @@ import { | ||||
| } from "components/Panels/ContentPanel"; | ||||
| import { SubPanel } from "components/Panels/SubPanel"; | ||||
| import { GetLibraryItemsPreviewQuery } from "graphql/generated"; | ||||
| import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { getReadySdk } from "graphql/sdk"; | ||||
| import { prettyInlineTitle, prettyItemSubType } from "helpers/formatters"; | ||||
| import { LibraryItemUserStatus } from "helpers/types"; | ||||
| @ -34,6 +33,8 @@ import { compareDate } from "helpers/date"; | ||||
| import { HorizontalLine } from "components/HorizontalLine"; | ||||
| import { useIsContentPanelAtLeast } from "hooks/useContainerQuery"; | ||||
| import { cIf, cJoin } from "helpers/className"; | ||||
| import { useCurrencies } from "hooks/useLocalData"; | ||||
| import { getLangui } from "graphql/fetchLocalData"; | ||||
| 
 | ||||
| /* | ||||
|  *                                         ╭─────────────╮ | ||||
| @ -56,17 +57,14 @@ const DEFAULT_FILTERS_STATE = { | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps, AppLayoutRequired { | ||||
| interface Props extends AppLayoutRequired { | ||||
|   items: NonNullable<GetLibraryItemsPreviewQuery["libraryItems"]>["data"]; | ||||
| } | ||||
| 
 | ||||
| const Library = ({ | ||||
|   langui, | ||||
|   items, | ||||
|   currencies, | ||||
|   ...otherProps | ||||
| }: Props): JSX.Element => { | ||||
| const Library = ({ items, ...otherProps }: Props): JSX.Element => { | ||||
|   const hoverable = useDeviceSupportsHover(); | ||||
|   const currencies = useCurrencies(); | ||||
|   const { langui } = useAppLayout(); | ||||
|   const { libraryItemUserStatus } = useAppLayout(); | ||||
|   const isContentPanelAtLeast4xl = useIsContentPanelAtLeast("4xl"); | ||||
| 
 | ||||
| @ -417,14 +415,13 @@ const Library = ({ | ||||
|                 (category) => category.attributes?.short ?? "" | ||||
|               )} | ||||
|               metadata={{ | ||||
|                 currencies: currencies, | ||||
|                 releaseDate: item.attributes.release_date, | ||||
|                 price: item.attributes.price, | ||||
|                 position: "Bottom", | ||||
|               }} | ||||
|               infoAppend={ | ||||
|                 !isUntangibleGroupItem(item.attributes.metadata?.[0]) && ( | ||||
|                   <PreviewCardCTAs id={item.id} langui={langui} /> | ||||
|                   <PreviewCardCTAs id={item.id} /> | ||||
|                 ) | ||||
|               } | ||||
|             /> | ||||
| @ -448,18 +445,15 @@ const Library = ({ | ||||
|           } | ||||
|           filteringFunction={filteringFunction} | ||||
|           paginationItemPerPage={25} | ||||
|           langui={langui} | ||||
|         /> | ||||
|       </ContentPanel> | ||||
|     ), | ||||
|     [ | ||||
|       currencies, | ||||
|       filteringFunction, | ||||
|       groupingFunction, | ||||
|       isContentPanelAtLeast4xl, | ||||
|       items, | ||||
|       keepInfoVisible, | ||||
|       langui, | ||||
|       searchName, | ||||
|       sortingFunction, | ||||
|     ] | ||||
| @ -470,8 +464,6 @@ const Library = ({ | ||||
|       subPanel={subPanel} | ||||
|       contentPanel={contentPanel} | ||||
|       subPanelIcon={Icon.Search} | ||||
|       currencies={currencies} | ||||
|       langui={langui} | ||||
|       {...otherProps} | ||||
|     /> | ||||
|   ); | ||||
| @ -485,18 +477,15 @@ export default Library; | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const sdk = getReadySdk(); | ||||
|   const langui = getLangui(context.locale); | ||||
|   const items = await sdk.getLibraryItemsPreview({ | ||||
|     language_code: context.locale ?? "en", | ||||
|   }); | ||||
|   if (!items.libraryItems?.data) return { notFound: true }; | ||||
|   const appStaticProps = await getAppStaticProps(context); | ||||
| 
 | ||||
|   const props: Props = { | ||||
|     ...appStaticProps, | ||||
|     items: items.libraryItems.data, | ||||
|     openGraph: getOpenGraph( | ||||
|       appStaticProps.langui, | ||||
|       appStaticProps.langui.library ?? "Library" | ||||
|     ), | ||||
|     openGraph: getOpenGraph(langui, langui.library ?? "Library"), | ||||
|   }; | ||||
|   return { | ||||
|     props: props, | ||||
|  | ||||
| @ -2,31 +2,34 @@ import { GetStaticProps } from "next"; | ||||
| import { AppLayout, AppLayoutRequired } from "components/AppLayout"; | ||||
| import { PanelHeader } from "components/PanelComponents/PanelHeader"; | ||||
| import { SubPanel } from "components/Panels/SubPanel"; | ||||
| import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { Icon } from "components/Ico"; | ||||
| import { getOpenGraph } from "helpers/openGraph"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| import { getLangui } from "graphql/fetchLocalData"; | ||||
| 
 | ||||
| /* | ||||
|  *                                           ╭────────╮ | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps, AppLayoutRequired {} | ||||
| const Merch = ({ langui, ...otherProps }: Props): JSX.Element => ( | ||||
|   <AppLayout | ||||
|     subPanel={ | ||||
|       <SubPanel> | ||||
|         <PanelHeader | ||||
|           icon={Icon.Store} | ||||
|           title={langui.merch} | ||||
|           description={langui.merch_description} | ||||
|         /> | ||||
|       </SubPanel> | ||||
|     } | ||||
|     langui={langui} | ||||
|     {...otherProps} | ||||
|   /> | ||||
| ); | ||||
| interface Props extends AppLayoutRequired {} | ||||
| const Merch = (props: Props): JSX.Element => { | ||||
|   const { langui } = useAppLayout(); | ||||
|   return ( | ||||
|     <AppLayout | ||||
|       subPanel={ | ||||
|         <SubPanel> | ||||
|           <PanelHeader | ||||
|             icon={Icon.Store} | ||||
|             title={langui.merch} | ||||
|             description={langui.merch_description} | ||||
|           /> | ||||
|         </SubPanel> | ||||
|       } | ||||
|       {...props} | ||||
|     /> | ||||
|   ); | ||||
| }; | ||||
| export default Merch; | ||||
| 
 | ||||
| /* | ||||
| @ -34,14 +37,10 @@ export default Merch; | ||||
|  * ───────────────────────────────────╯  NEXT DATA FETCHING  ╰────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const appStaticProps = await getAppStaticProps(context); | ||||
| export const getStaticProps: GetStaticProps = (context) => { | ||||
|   const langui = getLangui(context.locale); | ||||
|   const props: Props = { | ||||
|     ...appStaticProps, | ||||
|     openGraph: getOpenGraph( | ||||
|       appStaticProps.langui, | ||||
|       appStaticProps.langui.merch ?? "Merch" | ||||
|     ), | ||||
|     openGraph: getOpenGraph(langui, langui.merch ?? "Merch"), | ||||
|   }; | ||||
|   return { | ||||
|     props: props, | ||||
|  | ||||
| @ -1,30 +1,33 @@ | ||||
| import { GetStaticPaths, GetStaticPathsResult, GetStaticProps } from "next"; | ||||
| import { PostPage } from "components/PostPage"; | ||||
| import { AppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { | ||||
|   getPostStaticProps, | ||||
|   PostStaticProps, | ||||
| } from "graphql/getPostStaticProps"; | ||||
| import { getReadySdk } from "graphql/sdk"; | ||||
| import { filterHasAttributes, isDefined } from "helpers/others"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| 
 | ||||
| /* | ||||
|  *                                           ╭────────╮ | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps, PostStaticProps {} | ||||
| interface Props extends PostStaticProps {} | ||||
| 
 | ||||
| const LibrarySlug = (props: Props): JSX.Element => ( | ||||
|   <PostPage | ||||
|     returnHref="/news" | ||||
|     returnTitle={props.langui.news} | ||||
|     displayCredits | ||||
|     displayThumbnailHeader | ||||
|     displayToc | ||||
|     {...props} | ||||
|   /> | ||||
| ); | ||||
| const LibrarySlug = (props: Props): JSX.Element => { | ||||
|   const { langui } = useAppLayout(); | ||||
|   return ( | ||||
|     <PostPage | ||||
|       returnHref="/news" | ||||
|       returnTitle={langui.news} | ||||
|       displayCredits | ||||
|       displayThumbnailHeader | ||||
|       displayToc | ||||
|       {...props} | ||||
|     /> | ||||
|   ); | ||||
| }; | ||||
| export default LibrarySlug; | ||||
| 
 | ||||
| /* | ||||
|  | ||||
| @ -10,7 +10,6 @@ import { | ||||
| } from "components/Panels/ContentPanel"; | ||||
| import { SubPanel } from "components/Panels/SubPanel"; | ||||
| import { GetPostsPreviewQuery } from "graphql/generated"; | ||||
| import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { getReadySdk } from "graphql/sdk"; | ||||
| import { prettySlug } from "helpers/formatters"; | ||||
| import { Icon } from "components/Ico"; | ||||
| @ -26,6 +25,8 @@ import { TranslatedPreviewCard } from "components/PreviewCard"; | ||||
| import { HorizontalLine } from "components/HorizontalLine"; | ||||
| import { cIf } from "helpers/className"; | ||||
| import { useIsContentPanelAtLeast } from "hooks/useContainerQuery"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| import { getLangui } from "graphql/fetchLocalData"; | ||||
| 
 | ||||
| /* | ||||
|  *                                         ╭─────────────╮ | ||||
| @ -42,12 +43,13 @@ const DEFAULT_FILTERS_STATE = { | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps, AppLayoutRequired { | ||||
| interface Props extends AppLayoutRequired { | ||||
|   posts: NonNullable<GetPostsPreviewQuery["posts"]>["data"]; | ||||
| } | ||||
| 
 | ||||
| const News = ({ langui, posts, ...otherProps }: Props): JSX.Element => { | ||||
| const News = ({ posts, ...otherProps }: Props): JSX.Element => { | ||||
|   const isContentPanelAtLeast4xl = useIsContentPanelAtLeast("4xl"); | ||||
|   const { langui } = useAppLayout(); | ||||
|   const hoverable = useDeviceSupportsHover(); | ||||
|   const [searchName, setSearchName] = useState( | ||||
|     DEFAULT_FILTERS_STATE.searchName | ||||
| @ -109,7 +111,6 @@ const News = ({ langui, posts, ...otherProps }: Props): JSX.Element => { | ||||
|         <SmartList | ||||
|           items={filterHasAttributes(posts, ["attributes", "id"] as const)} | ||||
|           getItemId={(post) => post.id} | ||||
|           langui={langui} | ||||
|           renderItem={({ item: post }) => ( | ||||
|             <TranslatedPreviewCard | ||||
|               href={`/news/${post.attributes.slug}`} | ||||
| @ -150,7 +151,7 @@ const News = ({ langui, posts, ...otherProps }: Props): JSX.Element => { | ||||
|         /> | ||||
|       </ContentPanel> | ||||
|     ), | ||||
|     [keepInfoVisible, langui, posts, searchName, isContentPanelAtLeast4xl] | ||||
|     [keepInfoVisible, posts, searchName, isContentPanelAtLeast4xl] | ||||
|   ); | ||||
| 
 | ||||
|   return ( | ||||
| @ -158,7 +159,6 @@ const News = ({ langui, posts, ...otherProps }: Props): JSX.Element => { | ||||
|       subPanel={subPanel} | ||||
|       contentPanel={contentPanel} | ||||
|       subPanelIcon={Icon.Search} | ||||
|       langui={langui} | ||||
|       {...otherProps} | ||||
|     /> | ||||
|   ); | ||||
| @ -172,16 +172,13 @@ export default News; | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const sdk = getReadySdk(); | ||||
|   const langui = getLangui(context.locale); | ||||
|   const posts = await sdk.getPostsPreview(); | ||||
|   if (!posts.posts) return { notFound: true }; | ||||
|   const appStaticProps = await getAppStaticProps(context); | ||||
| 
 | ||||
|   const props: Props = { | ||||
|     ...appStaticProps, | ||||
|     posts: sortPosts(posts.posts.data), | ||||
|     openGraph: getOpenGraph( | ||||
|       appStaticProps.langui, | ||||
|       appStaticProps.langui.news ?? "News" | ||||
|     ), | ||||
|     openGraph: getOpenGraph(langui, langui.news ?? "News"), | ||||
|   }; | ||||
|   return { | ||||
|     props: props, | ||||
|  | ||||
| @ -11,7 +11,6 @@ import { | ||||
| } from "components/Panels/ContentPanel"; | ||||
| import { SubPanel } from "components/Panels/SubPanel"; | ||||
| import DefinitionCard from "components/Wiki/DefinitionCard"; | ||||
| import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { getReadySdk } from "graphql/sdk"; | ||||
| import { | ||||
|   filterHasAttributes, | ||||
| @ -31,26 +30,23 @@ import { | ||||
| import { getDescription } from "helpers/description"; | ||||
| import { cIf, cJoin } from "helpers/className"; | ||||
| import { useIs3ColumnsLayout } from "hooks/useContainerQuery"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| import { getLangui } from "graphql/fetchLocalData"; | ||||
| 
 | ||||
| /* | ||||
|  *                                           ╭────────╮ | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps, AppLayoutRequired { | ||||
| interface Props extends AppLayoutRequired { | ||||
|   page: WikiPageWithTranslations; | ||||
| } | ||||
| 
 | ||||
| const WikiPage = ({ | ||||
|   page, | ||||
|   langui, | ||||
|   languages, | ||||
|   ...otherProps | ||||
| }: Props): JSX.Element => { | ||||
| const WikiPage = ({ page, ...otherProps }: Props): JSX.Element => { | ||||
|   const { langui } = useAppLayout(); | ||||
|   const [selectedTranslation, LanguageSwitcher, languageSwitcherProps] = | ||||
|     useSmartLanguage({ | ||||
|       items: page.translations, | ||||
|       languages: languages, | ||||
|       languageExtractor: useCallback( | ||||
|         (item: NonNullable<Props["page"]["translations"][number]>) => | ||||
|           item.language?.data?.attributes?.code, | ||||
| @ -67,7 +63,6 @@ const WikiPage = ({ | ||||
|         <ReturnButton | ||||
|           href={`/wiki`} | ||||
|           title={langui.wiki} | ||||
|           langui={langui} | ||||
|           displayOnlyOn={"3ColumnsLayout"} | ||||
|         /> | ||||
|       </SubPanel> | ||||
| @ -83,7 +78,6 @@ const WikiPage = ({ | ||||
|         <ReturnButton | ||||
|           href={`/wiki`} | ||||
|           title={langui.wiki} | ||||
|           langui={langui} | ||||
|           displayOnlyOn={"1ColumnLayout"} | ||||
|           className="mb-10" | ||||
|         /> | ||||
| @ -200,8 +194,6 @@ const WikiPage = ({ | ||||
|                       }) | ||||
|                     )} | ||||
|                     index={index + 1} | ||||
|                     languages={languages} | ||||
|                     langui={langui} | ||||
|                     categories={filterHasAttributes( | ||||
|                       definition.categories?.data, | ||||
|                       ["attributes"] as const | ||||
| @ -219,7 +211,6 @@ const WikiPage = ({ | ||||
|       LightBox, | ||||
|       is3ColumnsLayout, | ||||
|       languageSwitcherProps, | ||||
|       languages, | ||||
|       langui, | ||||
|       openLightBox, | ||||
|       page.categories?.data, | ||||
| @ -234,8 +225,6 @@ const WikiPage = ({ | ||||
|     <AppLayout | ||||
|       subPanel={subPanel} | ||||
|       contentPanel={contentPanel} | ||||
|       languages={languages} | ||||
|       langui={langui} | ||||
|       {...otherProps} | ||||
|     /> | ||||
|   ); | ||||
| @ -249,6 +238,7 @@ export default WikiPage; | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const sdk = getReadySdk(); | ||||
|   const langui = getLangui(context.locale); | ||||
|   const slug = | ||||
|     context.params && isDefined(context.params.slug) | ||||
|       ? context.params.slug.toString() | ||||
| @ -259,18 +249,17 @@ export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   }); | ||||
|   if (!page.wikiPages?.data[0].attributes?.translations) | ||||
|     return { notFound: true }; | ||||
|   const appStaticProps = await getAppStaticProps(context); | ||||
| 
 | ||||
|   const { title, description } = (() => { | ||||
|     const chipsGroups = { | ||||
|       [appStaticProps.langui.tags ?? "Tags"]: filterHasAttributes( | ||||
|       [langui.tags ?? "Tags"]: filterHasAttributes( | ||||
|         page.wikiPages.data[0].attributes.tags?.data, | ||||
|         ["attributes"] as const | ||||
|       ).map( | ||||
|         (tag) => | ||||
|           tag.attributes.titles?.[0]?.title ?? prettySlug(tag.attributes.slug) | ||||
|       ), | ||||
|       [appStaticProps.langui.categories ?? "Categories"]: filterHasAttributes( | ||||
|       [langui.categories ?? "Categories"]: filterHasAttributes( | ||||
|         page.wikiPages.data[0].attributes.categories?.data, | ||||
|         ["attributes"] as const | ||||
|       ).map((category) => category.attributes.short), | ||||
| @ -303,14 +292,8 @@ export const getStaticProps: GetStaticProps = async (context) => { | ||||
|     page.wikiPages.data[0].attributes.thumbnail?.data?.attributes; | ||||
| 
 | ||||
|   const props: Props = { | ||||
|     ...appStaticProps, | ||||
|     page: page.wikiPages.data[0].attributes as WikiPageWithTranslations, | ||||
|     openGraph: getOpenGraph( | ||||
|       appStaticProps.langui, | ||||
|       title, | ||||
|       description, | ||||
|       thumbnail | ||||
|     ), | ||||
|     openGraph: getOpenGraph(langui, title, description, thumbnail), | ||||
|   }; | ||||
|   return { | ||||
|     props: props, | ||||
|  | ||||
| @ -11,7 +11,6 @@ import { | ||||
|   GetChronologyItemsQuery, | ||||
|   GetErasQuery, | ||||
| } from "graphql/generated"; | ||||
| import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps"; | ||||
| import { getReadySdk } from "graphql/sdk"; | ||||
| import { prettySlug } from "helpers/formatters"; | ||||
| import { | ||||
| @ -31,13 +30,15 @@ import { TranslatedProps } from "helpers/types/TranslatedProps"; | ||||
| import { TranslatedNavOption } from "components/PanelComponents/NavOption"; | ||||
| import { useIntersectionList } from "hooks/useIntersectionList"; | ||||
| import { HorizontalLine } from "components/HorizontalLine"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| import { getLangui } from "graphql/fetchLocalData"; | ||||
| 
 | ||||
| /* | ||||
|  *                                           ╭────────╮ | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps, AppLayoutRequired { | ||||
| interface Props extends AppLayoutRequired { | ||||
|   chronologyItems: NonNullable< | ||||
|     GetChronologyItemsQuery["chronologyItems"] | ||||
|   >["data"]; | ||||
| @ -47,10 +48,9 @@ interface Props extends AppStaticProps, AppLayoutRequired { | ||||
| const Chronology = ({ | ||||
|   chronologyItems, | ||||
|   chronologyEras, | ||||
|   langui, | ||||
|   languages, | ||||
|   ...otherProps | ||||
| }: Props): JSX.Element => { | ||||
|   const { langui } = useAppLayout(); | ||||
|   const ids = useMemo( | ||||
|     () => | ||||
|       filterHasAttributes(chronologyEras, ["attributes"] as const).map( | ||||
| @ -67,7 +67,6 @@ const Chronology = ({ | ||||
|         <ReturnButton | ||||
|           href="/wiki" | ||||
|           title={langui.wiki} | ||||
|           langui={langui} | ||||
|           displayOnlyOn="3ColumnsLayout" | ||||
|         /> | ||||
| 
 | ||||
| @ -106,7 +105,6 @@ const Chronology = ({ | ||||
|         <ReturnButton | ||||
|           href="/wiki" | ||||
|           title={langui.wiki} | ||||
|           langui={langui} | ||||
|           displayOnlyOn="1ColumnLayout" | ||||
|           className="mb-10" | ||||
|         /> | ||||
| @ -131,22 +129,18 @@ const Chronology = ({ | ||||
|                   item.attributes.year >= era.attributes.starting_year && | ||||
|                   item.attributes.year < era.attributes.ending_year | ||||
|               )} | ||||
|               langui={langui} | ||||
|               languages={languages} | ||||
|             /> | ||||
|           ) | ||||
|         )} | ||||
|       </ContentPanel> | ||||
|     ), | ||||
|     [chronologyEras, chronologyItems, languages, langui] | ||||
|     [chronologyEras, chronologyItems, langui] | ||||
|   ); | ||||
| 
 | ||||
|   return ( | ||||
|     <AppLayout | ||||
|       contentPanel={contentPanel} | ||||
|       subPanel={subPanel} | ||||
|       langui={langui} | ||||
|       languages={languages} | ||||
|       {...otherProps} | ||||
|     /> | ||||
|   ); | ||||
| @ -160,19 +154,16 @@ export default Chronology; | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const sdk = getReadySdk(); | ||||
|   const langui = getLangui(context.locale); | ||||
|   const chronologyItems = await sdk.getChronologyItems(); | ||||
|   const chronologyEras = await sdk.getEras(); | ||||
|   if (!chronologyItems.chronologyItems || !chronologyEras.chronologyEras) | ||||
|     return { notFound: true }; | ||||
|   const appStaticProps = await getAppStaticProps(context); | ||||
| 
 | ||||
|   const props: Props = { | ||||
|     ...appStaticProps, | ||||
|     chronologyItems: chronologyItems.chronologyItems.data, | ||||
|     chronologyEras: chronologyEras.chronologyEras.data, | ||||
|     openGraph: getOpenGraph( | ||||
|       appStaticProps.langui, | ||||
|       appStaticProps.langui.chronology ?? "Chronology" | ||||
|     ), | ||||
|     openGraph: getOpenGraph(langui, langui.chronology ?? "Chronology"), | ||||
|   }; | ||||
|   return { | ||||
|     props: props, | ||||
| @ -189,8 +180,6 @@ interface ChronologyEraProps { | ||||
|   title: string; | ||||
|   description?: string | null | undefined; | ||||
|   chronologyItems: Props["chronologyItems"]; | ||||
|   langui: AppStaticProps["langui"]; | ||||
|   languages: AppStaticProps["languages"]; | ||||
| } | ||||
| 
 | ||||
| const ChronologyEra = ({ | ||||
| @ -198,8 +187,6 @@ const ChronologyEra = ({ | ||||
|   title, | ||||
|   description, | ||||
|   chronologyItems, | ||||
|   langui, | ||||
|   languages, | ||||
| }: ChronologyEraProps) => { | ||||
|   const yearGroups = useMemo(() => { | ||||
|     const memo: Props["chronologyItems"][] = []; | ||||
| @ -222,7 +209,7 @@ const ChronologyEra = ({ | ||||
|       <InsetBox className="my-8 grid gap-4 text-center"> | ||||
|         <h2 className="flex place-content-center gap-3 text-2xl"> | ||||
|           {title} | ||||
|           <AnchorShare id={id} langui={langui} /> | ||||
|           <AnchorShare id={id} /> | ||||
|         </h2> | ||||
| 
 | ||||
|         {isDefinedAndNotEmpty(description) && ( | ||||
| @ -231,12 +218,7 @@ const ChronologyEra = ({ | ||||
|       </InsetBox> | ||||
|       <div> | ||||
|         {yearGroups.map((item, index) => ( | ||||
|           <ChronologyYear | ||||
|             key={index} | ||||
|             items={item} | ||||
|             langui={langui} | ||||
|             languages={languages} | ||||
|           /> | ||||
|           <ChronologyYear key={index} items={item} /> | ||||
|         ))} | ||||
|       </div> | ||||
|     </div> | ||||
| @ -271,11 +253,9 @@ const TranslatedChronologyEra = ({ | ||||
| 
 | ||||
| interface ChronologyYearProps { | ||||
|   items: NonNullable<Props["chronologyItems"]>; | ||||
|   langui: AppStaticProps["langui"]; | ||||
|   languages: AppStaticProps["languages"]; | ||||
| } | ||||
| 
 | ||||
| const ChronologyYear = ({ items, langui, languages }: ChronologyYearProps) => ( | ||||
| const ChronologyYear = ({ items }: ChronologyYearProps) => ( | ||||
|   <div | ||||
|     className="rounded-2xl target:my-4 target:bg-mid target:py-4" | ||||
|     id={generateAnchor(items[0].attributes?.year)} | ||||
| @ -284,8 +264,6 @@ const ChronologyYear = ({ items, langui, languages }: ChronologyYearProps) => ( | ||||
|       (item, index) => ( | ||||
|         <ChronologyDate | ||||
|           key={index} | ||||
|           langui={langui} | ||||
|           languages={languages} | ||||
|           date={{ | ||||
|             year: item.attributes.year, | ||||
|             month: item.attributes.month, | ||||
| @ -315,15 +293,11 @@ interface ChronologyDateProps { | ||||
|       NonNullable<Props["chronologyItems"]>[number]["attributes"] | ||||
|     >["events"] | ||||
|   >; | ||||
|   langui: AppStaticProps["langui"]; | ||||
|   languages: AppStaticProps["languages"]; | ||||
| } | ||||
| 
 | ||||
| export const ChronologyDate = ({ | ||||
|   date, | ||||
|   events, | ||||
|   langui, | ||||
|   languages, | ||||
| }: ChronologyDateProps): JSX.Element => { | ||||
|   const router = useRouter(); | ||||
|   return ( | ||||
| @ -368,8 +342,6 @@ export const ChronologyDate = ({ | ||||
|               id={generateAnchor(date.year, date.month, date.day)} | ||||
|               key={event.id} | ||||
|               event={event} | ||||
|               langui={langui} | ||||
|               languages={languages} | ||||
|             /> | ||||
|           ) | ||||
|         )} | ||||
| @ -388,17 +360,15 @@ interface ChronologyEventProps { | ||||
|       >["events"] | ||||
|     >[number] | ||||
|   >; | ||||
|   langui: AppStaticProps["langui"]; | ||||
|   languages: AppStaticProps["languages"]; | ||||
| 
 | ||||
|   id: string; | ||||
| } | ||||
| 
 | ||||
| export const ChronologyEvent = ({ | ||||
|   event, | ||||
|   langui, | ||||
|   languages, | ||||
|   id, | ||||
| }: ChronologyEventProps): JSX.Element => { | ||||
|   const { langui } = useAppLayout(); | ||||
|   const [selectedTranslation, LanguageSwitcher, languageSwitcherProps] = | ||||
|     useSmartLanguage({ | ||||
|       items: event.translations ?? [], | ||||
| @ -410,7 +380,6 @@ export const ChronologyEvent = ({ | ||||
|         ) => item?.language?.data?.attributes?.code, | ||||
|         [] | ||||
|       ), | ||||
|       languages: languages, | ||||
|     }); | ||||
| 
 | ||||
|   return ( | ||||
| @ -449,7 +418,7 @@ export const ChronologyEvent = ({ | ||||
|             </p> | ||||
| 
 | ||||
|             <span className="flex-shrink"> | ||||
|               <AnchorShare id={id} langui={langui} /> | ||||
|               <AnchorShare id={id} /> | ||||
|             </span> | ||||
|           </div> | ||||
| 
 | ||||
|  | ||||
| @ -5,7 +5,6 @@ import { AppLayout, AppLayoutRequired } from "components/AppLayout"; | ||||
| import { NavOption } from "components/PanelComponents/NavOption"; | ||||
| 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 { GetWikiPageQuery, GetWikiPagesPreviewsQuery } from "graphql/generated"; | ||||
| @ -28,6 +27,8 @@ import { getOpenGraph } from "helpers/openGraph"; | ||||
| import { TranslatedPreviewCard } from "components/PreviewCard"; | ||||
| import { useIsContentPanelAtLeast } from "hooks/useContainerQuery"; | ||||
| import { cIf } from "helpers/className"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| import { getLangui } from "graphql/fetchLocalData"; | ||||
| 
 | ||||
| /* | ||||
|  *                                         ╭─────────────╮ | ||||
| @ -45,12 +46,13 @@ const DEFAULT_FILTERS_STATE = { | ||||
|  * ──────────────────────────────────────────╯  PAGE  ╰───────────────────────────────────────────── | ||||
|  */ | ||||
| 
 | ||||
| interface Props extends AppStaticProps, AppLayoutRequired { | ||||
| interface Props extends AppLayoutRequired { | ||||
|   pages: NonNullable<GetWikiPagesPreviewsQuery["wikiPages"]>["data"]; | ||||
| } | ||||
| 
 | ||||
| const Wiki = ({ langui, pages, ...otherProps }: Props): JSX.Element => { | ||||
| const Wiki = ({ pages, ...otherProps }: Props): JSX.Element => { | ||||
|   const hoverable = useDeviceSupportsHover(); | ||||
|   const { langui } = useAppLayout(); | ||||
|   const isContentPanelAtLeast4xl = useIsContentPanelAtLeast("4xl"); | ||||
| 
 | ||||
|   const [searchName, setSearchName] = useState( | ||||
| @ -198,7 +200,6 @@ const Wiki = ({ langui, pages, ...otherProps }: Props): JSX.Element => { | ||||
|               ).map((category) => category.attributes.short)} | ||||
|             /> | ||||
|           )} | ||||
|           langui={langui} | ||||
|           className={cIf( | ||||
|             isContentPanelAtLeast4xl, | ||||
|             "grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))] gap-x-6 gap-y-8", | ||||
| @ -223,7 +224,6 @@ const Wiki = ({ langui, pages, ...otherProps }: Props): JSX.Element => { | ||||
|     [ | ||||
|       groupingFunction, | ||||
|       keepInfoVisible, | ||||
|       langui, | ||||
|       pages, | ||||
|       searchName, | ||||
|       isContentPanelAtLeast4xl, | ||||
| @ -235,7 +235,6 @@ const Wiki = ({ langui, pages, ...otherProps }: Props): JSX.Element => { | ||||
|       subPanel={subPanel} | ||||
|       contentPanel={contentPanel} | ||||
|       subPanelIcon={Icon.Search} | ||||
|       langui={langui} | ||||
|       {...otherProps} | ||||
|     /> | ||||
|   ); | ||||
| @ -249,18 +248,15 @@ export default Wiki; | ||||
| 
 | ||||
| export const getStaticProps: GetStaticProps = async (context) => { | ||||
|   const sdk = getReadySdk(); | ||||
|   const langui = getLangui(context.locale); | ||||
|   const pages = await sdk.getWikiPagesPreviews({ | ||||
|     language_code: context.locale ?? "en", | ||||
|   }); | ||||
|   if (!pages.wikiPages?.data) return { notFound: true }; | ||||
|   const appStaticProps = await getAppStaticProps(context); | ||||
| 
 | ||||
|   const props: Props = { | ||||
|     ...appStaticProps, | ||||
|     pages: sortPages(pages.wikiPages.data), | ||||
|     openGraph: getOpenGraph( | ||||
|       appStaticProps.langui, | ||||
|       appStaticProps.langui.wiki ?? "Wiki" | ||||
|     ), | ||||
|     openGraph: getOpenGraph(langui, langui.wiki ?? "Wiki"), | ||||
|   }; | ||||
|   return { | ||||
|     props: props, | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user