Linting! #17
							
								
								
									
										2
									
								
								.eslintignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.eslintignore
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
			
		||||
*.js
 | 
			
		||||
*.ts
 | 
			
		||||
							
								
								
									
										214
									
								
								.eslintrc.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										214
									
								
								.eslintrc.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,214 @@
 | 
			
		||||
module.exports = {
 | 
			
		||||
  parser: "@typescript-eslint/parser",
 | 
			
		||||
  parserOptions: {
 | 
			
		||||
    project: `./tsconfig.json`,
 | 
			
		||||
  },
 | 
			
		||||
  plugins: ["@typescript-eslint"],
 | 
			
		||||
  extends: [
 | 
			
		||||
    "eslint:recommended",
 | 
			
		||||
    "plugin:@typescript-eslint/recommended",
 | 
			
		||||
    "next/core-web-vitals",
 | 
			
		||||
  ],
 | 
			
		||||
  rules: {
 | 
			
		||||
    /* POSSIBLES PROBLEMS */
 | 
			
		||||
 | 
			
		||||
    // "array-callback-return": "error",
 | 
			
		||||
    "no-await-in-loop": "error",
 | 
			
		||||
    "no-constructor-return": "error",
 | 
			
		||||
    "no-promise-executor-return": "error",
 | 
			
		||||
    "no-self-compare": "error",
 | 
			
		||||
    "no-template-curly-in-string": "error",
 | 
			
		||||
    "no-unmodified-loop-condition": "error",
 | 
			
		||||
    "no-unreachable-loop": "error",
 | 
			
		||||
    "no-unused-private-class-members": "error",
 | 
			
		||||
    // "no-use-before-define": "error",
 | 
			
		||||
    "require-atomic-updates": "error",
 | 
			
		||||
 | 
			
		||||
    /* SUGGESTIONS */
 | 
			
		||||
 | 
			
		||||
    "accessor-pairs": "warn",
 | 
			
		||||
    "arrow-body-style": "warn",
 | 
			
		||||
    "block-scoped-var": "warn",
 | 
			
		||||
    // camelcase: "warn",
 | 
			
		||||
    // "capitalized-comments": "warn",
 | 
			
		||||
    // "class-methods-use-this": "warn",
 | 
			
		||||
    // complexity: "warn",
 | 
			
		||||
    "consistent-return": "warn",
 | 
			
		||||
    "consistent-this": "warn",
 | 
			
		||||
    // curly: "warn",
 | 
			
		||||
    "default-case": "warn",
 | 
			
		||||
    "default-case-last": "warn",
 | 
			
		||||
    eqeqeq: "error",
 | 
			
		||||
    "func-name-matching": "warn",
 | 
			
		||||
    "func-names": "warn",
 | 
			
		||||
    "func-style": ["warn", "declaration"],
 | 
			
		||||
    "grouped-accessor-pairs": "warn",
 | 
			
		||||
    "guard-for-in": "warn",
 | 
			
		||||
    "id-denylist": ["error", "data", "err", "e", "cb", "callback", "i"],
 | 
			
		||||
    // "id-length": "warn",
 | 
			
		||||
    "id-match": "warn",
 | 
			
		||||
    "max-classes-per-file": ["error", 1],
 | 
			
		||||
    // "max-depth": ["warn", 4],
 | 
			
		||||
    // "max-lines": "warn",
 | 
			
		||||
    // "max-lines-per-function": "warn",
 | 
			
		||||
    // "max-nested-callbacks": "warn",
 | 
			
		||||
    // "max-params": "warn",
 | 
			
		||||
    // "max-statements": "warn",
 | 
			
		||||
    "multiline-comment-style": "warn",
 | 
			
		||||
    "new-cap": "warn",
 | 
			
		||||
    "no-alert": "warn",
 | 
			
		||||
    "no-bitwise": "warn",
 | 
			
		||||
    "no-caller": "warn",
 | 
			
		||||
    "no-confusing-arrow": "warn",
 | 
			
		||||
    "no-continue": "warn",
 | 
			
		||||
    "no-else-return": "warn",
 | 
			
		||||
    "no-eq-null": "warn",
 | 
			
		||||
    "no-eval": "warn",
 | 
			
		||||
    "no-extend-native": "warn",
 | 
			
		||||
    "no-extra-bind": "warn",
 | 
			
		||||
    "no-floating-decimal": "warn",
 | 
			
		||||
    "no-implicit-coercion": "warn",
 | 
			
		||||
    "no-implicit-globals": "warn",
 | 
			
		||||
    "no-inline-comments": "warn",
 | 
			
		||||
    "no-iterator": "warn",
 | 
			
		||||
    "no-label-var": "warn",
 | 
			
		||||
    "no-labels": "warn",
 | 
			
		||||
    "no-lone-blocks": "warn",
 | 
			
		||||
    "no-lonely-if": "warn",
 | 
			
		||||
    // "no-magic-numbers": "warn",
 | 
			
		||||
    "no-mixed-operators": "warn",
 | 
			
		||||
    "no-multi-assign": "warn",
 | 
			
		||||
    "no-multi-str": "warn",
 | 
			
		||||
    "no-negated-condition": "warn",
 | 
			
		||||
    // "no-nested-ternary": "warn",
 | 
			
		||||
    "no-new": "warn",
 | 
			
		||||
    "no-new-func": "warn",
 | 
			
		||||
    "no-new-object": "warn",
 | 
			
		||||
    "no-new-wrappers": "warn",
 | 
			
		||||
    "no-octal-escape": "warn",
 | 
			
		||||
    "no-param-reassign": "warn",
 | 
			
		||||
    "no-plusplus": "warn",
 | 
			
		||||
    "no-proto": "warn",
 | 
			
		||||
    "no-restricted-exports": "warn",
 | 
			
		||||
    "no-restricted-globals": "warn",
 | 
			
		||||
    "no-restricted-imports": "warn",
 | 
			
		||||
    "no-restricted-properties": "warn",
 | 
			
		||||
    "no-restricted-syntax": "warn",
 | 
			
		||||
    "no-return-assign": "warn",
 | 
			
		||||
    // "no-return-await": "warn",
 | 
			
		||||
    "no-script-url": "warn",
 | 
			
		||||
    "no-sequences": "warn",
 | 
			
		||||
    // "no-ternary": "off",
 | 
			
		||||
    "no-throw-literal": "warn",
 | 
			
		||||
    "no-undef": "off",
 | 
			
		||||
    "no-undef-init": "warn",
 | 
			
		||||
    // "no-undefined": "warn",
 | 
			
		||||
    // "no-underscore-dangle": "warn",
 | 
			
		||||
    "no-unneeded-ternary": "warn",
 | 
			
		||||
    "no-useless-call": "warn",
 | 
			
		||||
    "no-useless-computed-key": "warn",
 | 
			
		||||
    "no-useless-concat": "warn",
 | 
			
		||||
    "no-useless-rename": "warn",
 | 
			
		||||
    "no-useless-return": "warn",
 | 
			
		||||
    "no-var": "warn",
 | 
			
		||||
    "no-void": "warn",
 | 
			
		||||
    "no-warning-comments": "warn",
 | 
			
		||||
    // "object-shorthand": "warn",
 | 
			
		||||
    "operator-assignment": "warn",
 | 
			
		||||
    "prefer-arrow-callback": "warn",
 | 
			
		||||
    "prefer-const": "warn",
 | 
			
		||||
    "prefer-destructuring": ["warn", { array: false, object: true }],
 | 
			
		||||
    "prefer-exponentiation-operator": "warn",
 | 
			
		||||
    "prefer-named-capture-group": "warn",
 | 
			
		||||
    "prefer-numeric-literals": "warn",
 | 
			
		||||
    // "prefer-object-has-own": "warn",
 | 
			
		||||
    "prefer-object-spread": "warn",
 | 
			
		||||
    "prefer-promise-reject-errors": "warn",
 | 
			
		||||
    "prefer-regex-literals": "warn",
 | 
			
		||||
    "prefer-rest-params": "warn",
 | 
			
		||||
    "prefer-spread": "warn",
 | 
			
		||||
    "prefer-template": "warn",
 | 
			
		||||
    // "quote-props": "warn",
 | 
			
		||||
    radix: "warn",
 | 
			
		||||
    "require-unicode-regexp": "warn",
 | 
			
		||||
    // "sort-imports": "warn",
 | 
			
		||||
    // "sort-keys": "warn",
 | 
			
		||||
    "sort-vars": "warn",
 | 
			
		||||
    "spaced-comment": "warn",
 | 
			
		||||
    strict: "warn",
 | 
			
		||||
    "symbol-description": "warn",
 | 
			
		||||
    "vars-on-top": "warn",
 | 
			
		||||
    yoda: "warn",
 | 
			
		||||
 | 
			
		||||
    /* TYPESCRIPT */
 | 
			
		||||
 | 
			
		||||
    "@typescript-eslint/array-type": "warn",
 | 
			
		||||
    "@typescript-eslint/ban-tslint-comment": "warn",
 | 
			
		||||
    "@typescript-eslint/class-literal-property-style": "warn",
 | 
			
		||||
    "@typescript-eslint/consistent-indexed-object-style": "warn",
 | 
			
		||||
    "@typescript-eslint/consistent-type-assertions": [
 | 
			
		||||
      "warn",
 | 
			
		||||
      { assertionStyle: "as" },
 | 
			
		||||
    ],
 | 
			
		||||
    "@typescript-eslint/consistent-type-exports": "error",
 | 
			
		||||
    "@typescript-eslint/explicit-module-boundary-types": "warn",
 | 
			
		||||
    "@typescript-eslint/method-signature-style": ["error", "property"],
 | 
			
		||||
    "@typescript-eslint/no-base-to-string": "warn",
 | 
			
		||||
    "@typescript-eslint/no-confusing-non-null-assertion": "warn",
 | 
			
		||||
    "@typescript-eslint/no-confusing-void-expression": [
 | 
			
		||||
      "error",
 | 
			
		||||
      { ignoreArrowShorthand: true },
 | 
			
		||||
    ],
 | 
			
		||||
    "@typescript-eslint/no-dynamic-delete": "error",
 | 
			
		||||
    "@typescript-eslint/no-empty-interface": [
 | 
			
		||||
      "error",
 | 
			
		||||
      { allowSingleExtends: true },
 | 
			
		||||
    ],
 | 
			
		||||
    "@typescript-eslint/no-invalid-void-type": "error",
 | 
			
		||||
    "@typescript-eslint/no-meaningless-void-operator": "error",
 | 
			
		||||
    "@typescript-eslint/no-non-null-asserted-nullish-coalescing": "error",
 | 
			
		||||
    "@typescript-eslint/no-parameter-properties": "error",
 | 
			
		||||
    "@typescript-eslint/no-require-imports": "error",
 | 
			
		||||
    // "@typescript-eslint/no-type-alias": "warn",
 | 
			
		||||
    "@typescript-eslint/no-unnecessary-boolean-literal-compare": "warn",
 | 
			
		||||
    // "@typescript-eslint/no-unnecessary-condition": "warn",
 | 
			
		||||
    "@typescript-eslint/no-unnecessary-qualifier": "warn",
 | 
			
		||||
    "@typescript-eslint/no-unnecessary-type-arguments": "warn",
 | 
			
		||||
    "@typescript-eslint/prefer-enum-initializers": "error",
 | 
			
		||||
    "@typescript-eslint/prefer-for-of": "error",
 | 
			
		||||
    "@typescript-eslint/prefer-includes": "error",
 | 
			
		||||
    "@typescript-eslint/prefer-literal-enum-member": "error",
 | 
			
		||||
    "@typescript-eslint/prefer-nullish-coalescing": "warn",
 | 
			
		||||
    "@typescript-eslint/prefer-optional-chain": "warn",
 | 
			
		||||
    "@typescript-eslint/prefer-readonly": "warn",
 | 
			
		||||
    // "@typescript-eslint/prefer-readonly-parameter-types": "warn",
 | 
			
		||||
    "@typescript-eslint/prefer-reduce-type-parameter": "warn",
 | 
			
		||||
    // "@typescript-eslint/prefer-regexp-exec": "warn",
 | 
			
		||||
    "@typescript-eslint/prefer-return-this-type": "warn",
 | 
			
		||||
    "@typescript-eslint/prefer-string-starts-ends-with": "error",
 | 
			
		||||
    "@typescript-eslint/promise-function-async": "error",
 | 
			
		||||
    "@typescript-eslint/require-array-sort-compare": "error",
 | 
			
		||||
    "@typescript-eslint/sort-type-union-intersection-members": "warn",
 | 
			
		||||
    // "@typescript-eslint/strict-boolean-expressions": "error",
 | 
			
		||||
    "@typescript-eslint/switch-exhaustiveness-check": "error",
 | 
			
		||||
    "@typescript-eslint/typedef": "error",
 | 
			
		||||
    "@typescript-eslint/unified-signatures": "error",
 | 
			
		||||
 | 
			
		||||
    /* EXTENSION OF ESLINT */
 | 
			
		||||
    "@typescript-eslint/no-duplicate-imports": "error",
 | 
			
		||||
    "@typescript-eslint/default-param-last": "warn",
 | 
			
		||||
    "@typescript-eslint/dot-notation": "warn",
 | 
			
		||||
    "@typescript-eslint/init-declarations": "warn",
 | 
			
		||||
    "@typescript-eslint/no-array-constructor": "warn",
 | 
			
		||||
    "@typescript-eslint/no-implied-eval": "warn",
 | 
			
		||||
    "@typescript-eslint/no-invalid-this": "warn",
 | 
			
		||||
    "@typescript-eslint/no-loop-func": "warn",
 | 
			
		||||
    "@typescript-eslint/no-shadow": "warn",
 | 
			
		||||
    "@typescript-eslint/no-unused-expressions": "warn",
 | 
			
		||||
    "@typescript-eslint/no-useless-constructor": "warn",
 | 
			
		||||
    "@typescript-eslint/require-await": "warn",
 | 
			
		||||
 | 
			
		||||
    /* NEXTJS */
 | 
			
		||||
    "@next/next/no-img-element": "off",
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
@ -1,3 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "extends": "next/core-web-vitals"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								.hintrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								.hintrc
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
{
 | 
			
		||||
  "extends": ["development"],
 | 
			
		||||
  "hints": {
 | 
			
		||||
    "no-inline-styles": "off",
 | 
			
		||||
    "apple-touch-icons": "off",
 | 
			
		||||
    "compat-api/html": "off",
 | 
			
		||||
    "axe/text-alternatives": "off",
 | 
			
		||||
    "axe/parsing": "off"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										337
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										337
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -26,10 +26,14 @@
 | 
			
		||||
        "@types/nodemailer": "^6.4.4",
 | 
			
		||||
        "@types/react": "17.0.40",
 | 
			
		||||
        "@types/react-dom": "^17.0.13",
 | 
			
		||||
        "eslint": "8.10.0",
 | 
			
		||||
        "@types/turndown": "^5.0.1",
 | 
			
		||||
        "@typescript-eslint/eslint-plugin": "^5.16.0",
 | 
			
		||||
        "@typescript-eslint/parser": "^5.16.0",
 | 
			
		||||
        "eslint": "^8.10.0",
 | 
			
		||||
        "eslint-config-next": "12.1.0",
 | 
			
		||||
        "prettier-plugin-organize-imports": "^2.3.4",
 | 
			
		||||
        "tailwindcss": "^3.0.23",
 | 
			
		||||
        "typescript": "4.6.2"
 | 
			
		||||
        "typescript": "^4.6.2"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@babel/code-frame": {
 | 
			
		||||
@ -479,6 +483,12 @@
 | 
			
		||||
        "react-dom": ">=16.8"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@types/json-schema": {
 | 
			
		||||
      "version": "7.0.11",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
 | 
			
		||||
      "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@types/json5": {
 | 
			
		||||
      "version": "0.0.29",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
 | 
			
		||||
@ -538,15 +548,54 @@
 | 
			
		||||
      "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@typescript-eslint/parser": {
 | 
			
		||||
      "version": "5.12.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.12.0.tgz",
 | 
			
		||||
      "integrity": "sha512-MfSwg9JMBojMUoGjUmX+D2stoQj1CBYTCP0qnnVtu9A+YQXVKNtLjasYh+jozOcrb/wau8TCfWOkQTiOAruBog==",
 | 
			
		||||
    "node_modules/@types/turndown": {
 | 
			
		||||
      "version": "5.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@types/turndown/-/turndown-5.0.1.tgz",
 | 
			
		||||
      "integrity": "sha512-N8Ad4e3oJxh9n9BiZx9cbe/0M3kqDpOTm2wzj13wdDUxDPjfjloWIJaquZzWE1cYTAHpjOH3rcTnXQdpEfS/SQ==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@typescript-eslint/eslint-plugin": {
 | 
			
		||||
      "version": "5.16.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.16.0.tgz",
 | 
			
		||||
      "integrity": "sha512-SJoba1edXvQRMmNI505Uo4XmGbxCK9ARQpkvOd00anxzri9RNQk0DDCxD+LIl+jYhkzOJiOMMKYEHnHEODjdCw==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@typescript-eslint/scope-manager": "5.12.0",
 | 
			
		||||
        "@typescript-eslint/types": "5.12.0",
 | 
			
		||||
        "@typescript-eslint/typescript-estree": "5.12.0",
 | 
			
		||||
        "@typescript-eslint/scope-manager": "5.16.0",
 | 
			
		||||
        "@typescript-eslint/type-utils": "5.16.0",
 | 
			
		||||
        "@typescript-eslint/utils": "5.16.0",
 | 
			
		||||
        "debug": "^4.3.2",
 | 
			
		||||
        "functional-red-black-tree": "^1.0.1",
 | 
			
		||||
        "ignore": "^5.1.8",
 | 
			
		||||
        "regexpp": "^3.2.0",
 | 
			
		||||
        "semver": "^7.3.5",
 | 
			
		||||
        "tsutils": "^3.21.0"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "funding": {
 | 
			
		||||
        "type": "opencollective",
 | 
			
		||||
        "url": "https://opencollective.com/typescript-eslint"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependencies": {
 | 
			
		||||
        "@typescript-eslint/parser": "^5.0.0",
 | 
			
		||||
        "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependenciesMeta": {
 | 
			
		||||
        "typescript": {
 | 
			
		||||
          "optional": true
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@typescript-eslint/parser": {
 | 
			
		||||
      "version": "5.16.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.16.0.tgz",
 | 
			
		||||
      "integrity": "sha512-fkDq86F0zl8FicnJtdXakFs4lnuebH6ZADDw6CYQv0UZeIjHvmEw87m9/29nk2Dv5Lmdp0zQ3zDQhiMWQf/GbA==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@typescript-eslint/scope-manager": "5.16.0",
 | 
			
		||||
        "@typescript-eslint/types": "5.16.0",
 | 
			
		||||
        "@typescript-eslint/typescript-estree": "5.16.0",
 | 
			
		||||
        "debug": "^4.3.2"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
@ -566,13 +615,13 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@typescript-eslint/scope-manager": {
 | 
			
		||||
      "version": "5.12.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.12.0.tgz",
 | 
			
		||||
      "integrity": "sha512-GAMobtIJI8FGf1sLlUWNUm2IOkIjvn7laFWyRx7CLrv6nLBI7su+B7lbStqVlK5NdLvHRFiJo2HhiDF7Ki01WQ==",
 | 
			
		||||
      "version": "5.16.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.16.0.tgz",
 | 
			
		||||
      "integrity": "sha512-P+Yab2Hovg8NekLIR/mOElCDPyGgFZKhGoZA901Yax6WR6HVeGLbsqJkZ+Cvk5nts/dAlFKm8PfL43UZnWdpIQ==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@typescript-eslint/types": "5.12.0",
 | 
			
		||||
        "@typescript-eslint/visitor-keys": "5.12.0"
 | 
			
		||||
        "@typescript-eslint/types": "5.16.0",
 | 
			
		||||
        "@typescript-eslint/visitor-keys": "5.16.0"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
 | 
			
		||||
@ -582,10 +631,36 @@
 | 
			
		||||
        "url": "https://opencollective.com/typescript-eslint"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@typescript-eslint/type-utils": {
 | 
			
		||||
      "version": "5.16.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.16.0.tgz",
 | 
			
		||||
      "integrity": "sha512-SKygICv54CCRl1Vq5ewwQUJV/8padIWvPgCxlWPGO/OgQLCijY9G7lDu6H+mqfQtbzDNlVjzVWQmeqbLMBLEwQ==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@typescript-eslint/utils": "5.16.0",
 | 
			
		||||
        "debug": "^4.3.2",
 | 
			
		||||
        "tsutils": "^3.21.0"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "funding": {
 | 
			
		||||
        "type": "opencollective",
 | 
			
		||||
        "url": "https://opencollective.com/typescript-eslint"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependencies": {
 | 
			
		||||
        "eslint": "*"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependenciesMeta": {
 | 
			
		||||
        "typescript": {
 | 
			
		||||
          "optional": true
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@typescript-eslint/types": {
 | 
			
		||||
      "version": "5.12.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.12.0.tgz",
 | 
			
		||||
      "integrity": "sha512-JowqbwPf93nvf8fZn5XrPGFBdIK8+yx5UEGs2QFAYFI8IWYfrzz+6zqlurGr2ctShMaJxqwsqmra3WXWjH1nRQ==",
 | 
			
		||||
      "version": "5.16.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.16.0.tgz",
 | 
			
		||||
      "integrity": "sha512-oUorOwLj/3/3p/HFwrp6m/J2VfbLC8gjW5X3awpQJ/bSG+YRGFS4dpsvtQ8T2VNveV+LflQHjlLvB6v0R87z4g==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
 | 
			
		||||
@ -596,13 +671,13 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@typescript-eslint/typescript-estree": {
 | 
			
		||||
      "version": "5.12.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.12.0.tgz",
 | 
			
		||||
      "integrity": "sha512-Dd9gVeOqt38QHR0BEA8oRaT65WYqPYbIc5tRFQPkfLquVEFPD1HAtbZT98TLBkEcCkvwDYOAvuSvAD9DnQhMfQ==",
 | 
			
		||||
      "version": "5.16.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.16.0.tgz",
 | 
			
		||||
      "integrity": "sha512-SE4VfbLWUZl9MR+ngLSARptUv2E8brY0luCdgmUevU6arZRY/KxYoLI/3V/yxaURR8tLRN7bmZtJdgmzLHI6pQ==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@typescript-eslint/types": "5.12.0",
 | 
			
		||||
        "@typescript-eslint/visitor-keys": "5.12.0",
 | 
			
		||||
        "@typescript-eslint/types": "5.16.0",
 | 
			
		||||
        "@typescript-eslint/visitor-keys": "5.16.0",
 | 
			
		||||
        "debug": "^4.3.2",
 | 
			
		||||
        "globby": "^11.0.4",
 | 
			
		||||
        "is-glob": "^4.0.3",
 | 
			
		||||
@ -622,13 +697,59 @@
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@typescript-eslint/visitor-keys": {
 | 
			
		||||
      "version": "5.12.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.12.0.tgz",
 | 
			
		||||
      "integrity": "sha512-cFwTlgnMV6TgezQynx2c/4/tx9Tufbuo9LPzmWqyRC3QC4qTGkAG1C6pBr0/4I10PAI/FlYunI3vJjIcu+ZHMg==",
 | 
			
		||||
    "node_modules/@typescript-eslint/utils": {
 | 
			
		||||
      "version": "5.16.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.16.0.tgz",
 | 
			
		||||
      "integrity": "sha512-iYej2ER6AwmejLWMWzJIHy3nPJeGDuCqf8Jnb+jAQVoPpmWzwQOfa9hWVB8GIQE5gsCv/rfN4T+AYb/V06WseQ==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@typescript-eslint/types": "5.12.0",
 | 
			
		||||
        "@types/json-schema": "^7.0.9",
 | 
			
		||||
        "@typescript-eslint/scope-manager": "5.16.0",
 | 
			
		||||
        "@typescript-eslint/types": "5.16.0",
 | 
			
		||||
        "@typescript-eslint/typescript-estree": "5.16.0",
 | 
			
		||||
        "eslint-scope": "^5.1.1",
 | 
			
		||||
        "eslint-utils": "^3.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "funding": {
 | 
			
		||||
        "type": "opencollective",
 | 
			
		||||
        "url": "https://opencollective.com/typescript-eslint"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependencies": {
 | 
			
		||||
        "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": {
 | 
			
		||||
      "version": "5.1.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
 | 
			
		||||
      "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "esrecurse": "^4.3.0",
 | 
			
		||||
        "estraverse": "^4.1.1"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=8.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@typescript-eslint/utils/node_modules/estraverse": {
 | 
			
		||||
      "version": "4.3.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
 | 
			
		||||
      "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=4.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@typescript-eslint/visitor-keys": {
 | 
			
		||||
      "version": "5.16.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.16.0.tgz",
 | 
			
		||||
      "integrity": "sha512-jqxO8msp5vZDhikTwq9ubyMHqZ67UIvawohr4qF3KhlpL7gzSjOd+8471H3nh5LyABkaI85laEKKU8SnGUK5/g==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@typescript-eslint/types": "5.16.0",
 | 
			
		||||
        "eslint-visitor-keys": "^3.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
@ -3003,6 +3124,32 @@
 | 
			
		||||
        "node": ">= 0.8.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/prettier": {
 | 
			
		||||
      "version": "2.6.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.1.tgz",
 | 
			
		||||
      "integrity": "sha512-8UVbTBYGwN37Bs9LERmxCPjdvPxlEowx2urIL6urHzdb3SDq4B/Z6xLFCblrSnE4iKWcS6ziJ3aOYrc1kz/E2A==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "peer": true,
 | 
			
		||||
      "bin": {
 | 
			
		||||
        "prettier": "bin-prettier.js"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=10.13.0"
 | 
			
		||||
      },
 | 
			
		||||
      "funding": {
 | 
			
		||||
        "url": "https://github.com/prettier/prettier?sponsor=1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/prettier-plugin-organize-imports": {
 | 
			
		||||
      "version": "2.3.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-2.3.4.tgz",
 | 
			
		||||
      "integrity": "sha512-R8o23sf5iVL/U71h9SFUdhdOEPsi3nm42FD/oDYIZ2PQa4TNWWuWecxln6jlIQzpZTDMUeO1NicJP6lLn2TtRw==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "peerDependencies": {
 | 
			
		||||
        "prettier": ">=2.0",
 | 
			
		||||
        "typescript": ">=2.9"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/prop-types": {
 | 
			
		||||
      "version": "15.8.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
 | 
			
		||||
@ -4011,6 +4158,12 @@
 | 
			
		||||
        "tippy.js": "^6.3.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "@types/json-schema": {
 | 
			
		||||
      "version": "7.0.11",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
 | 
			
		||||
      "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "@types/json5": {
 | 
			
		||||
      "version": "0.0.29",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
 | 
			
		||||
@ -4070,42 +4223,76 @@
 | 
			
		||||
      "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "@typescript-eslint/parser": {
 | 
			
		||||
      "version": "5.12.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.12.0.tgz",
 | 
			
		||||
      "integrity": "sha512-MfSwg9JMBojMUoGjUmX+D2stoQj1CBYTCP0qnnVtu9A+YQXVKNtLjasYh+jozOcrb/wau8TCfWOkQTiOAruBog==",
 | 
			
		||||
    "@types/turndown": {
 | 
			
		||||
      "version": "5.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@types/turndown/-/turndown-5.0.1.tgz",
 | 
			
		||||
      "integrity": "sha512-N8Ad4e3oJxh9n9BiZx9cbe/0M3kqDpOTm2wzj13wdDUxDPjfjloWIJaquZzWE1cYTAHpjOH3rcTnXQdpEfS/SQ==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "@typescript-eslint/eslint-plugin": {
 | 
			
		||||
      "version": "5.16.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.16.0.tgz",
 | 
			
		||||
      "integrity": "sha512-SJoba1edXvQRMmNI505Uo4XmGbxCK9ARQpkvOd00anxzri9RNQk0DDCxD+LIl+jYhkzOJiOMMKYEHnHEODjdCw==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "@typescript-eslint/scope-manager": "5.12.0",
 | 
			
		||||
        "@typescript-eslint/types": "5.12.0",
 | 
			
		||||
        "@typescript-eslint/typescript-estree": "5.12.0",
 | 
			
		||||
        "@typescript-eslint/scope-manager": "5.16.0",
 | 
			
		||||
        "@typescript-eslint/type-utils": "5.16.0",
 | 
			
		||||
        "@typescript-eslint/utils": "5.16.0",
 | 
			
		||||
        "debug": "^4.3.2",
 | 
			
		||||
        "functional-red-black-tree": "^1.0.1",
 | 
			
		||||
        "ignore": "^5.1.8",
 | 
			
		||||
        "regexpp": "^3.2.0",
 | 
			
		||||
        "semver": "^7.3.5",
 | 
			
		||||
        "tsutils": "^3.21.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "@typescript-eslint/parser": {
 | 
			
		||||
      "version": "5.16.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.16.0.tgz",
 | 
			
		||||
      "integrity": "sha512-fkDq86F0zl8FicnJtdXakFs4lnuebH6ZADDw6CYQv0UZeIjHvmEw87m9/29nk2Dv5Lmdp0zQ3zDQhiMWQf/GbA==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "@typescript-eslint/scope-manager": "5.16.0",
 | 
			
		||||
        "@typescript-eslint/types": "5.16.0",
 | 
			
		||||
        "@typescript-eslint/typescript-estree": "5.16.0",
 | 
			
		||||
        "debug": "^4.3.2"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "@typescript-eslint/scope-manager": {
 | 
			
		||||
      "version": "5.12.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.12.0.tgz",
 | 
			
		||||
      "integrity": "sha512-GAMobtIJI8FGf1sLlUWNUm2IOkIjvn7laFWyRx7CLrv6nLBI7su+B7lbStqVlK5NdLvHRFiJo2HhiDF7Ki01WQ==",
 | 
			
		||||
      "version": "5.16.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.16.0.tgz",
 | 
			
		||||
      "integrity": "sha512-P+Yab2Hovg8NekLIR/mOElCDPyGgFZKhGoZA901Yax6WR6HVeGLbsqJkZ+Cvk5nts/dAlFKm8PfL43UZnWdpIQ==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "@typescript-eslint/types": "5.12.0",
 | 
			
		||||
        "@typescript-eslint/visitor-keys": "5.12.0"
 | 
			
		||||
        "@typescript-eslint/types": "5.16.0",
 | 
			
		||||
        "@typescript-eslint/visitor-keys": "5.16.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "@typescript-eslint/type-utils": {
 | 
			
		||||
      "version": "5.16.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.16.0.tgz",
 | 
			
		||||
      "integrity": "sha512-SKygICv54CCRl1Vq5ewwQUJV/8padIWvPgCxlWPGO/OgQLCijY9G7lDu6H+mqfQtbzDNlVjzVWQmeqbLMBLEwQ==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "@typescript-eslint/utils": "5.16.0",
 | 
			
		||||
        "debug": "^4.3.2",
 | 
			
		||||
        "tsutils": "^3.21.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "@typescript-eslint/types": {
 | 
			
		||||
      "version": "5.12.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.12.0.tgz",
 | 
			
		||||
      "integrity": "sha512-JowqbwPf93nvf8fZn5XrPGFBdIK8+yx5UEGs2QFAYFI8IWYfrzz+6zqlurGr2ctShMaJxqwsqmra3WXWjH1nRQ==",
 | 
			
		||||
      "version": "5.16.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.16.0.tgz",
 | 
			
		||||
      "integrity": "sha512-oUorOwLj/3/3p/HFwrp6m/J2VfbLC8gjW5X3awpQJ/bSG+YRGFS4dpsvtQ8T2VNveV+LflQHjlLvB6v0R87z4g==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "@typescript-eslint/typescript-estree": {
 | 
			
		||||
      "version": "5.12.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.12.0.tgz",
 | 
			
		||||
      "integrity": "sha512-Dd9gVeOqt38QHR0BEA8oRaT65WYqPYbIc5tRFQPkfLquVEFPD1HAtbZT98TLBkEcCkvwDYOAvuSvAD9DnQhMfQ==",
 | 
			
		||||
      "version": "5.16.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.16.0.tgz",
 | 
			
		||||
      "integrity": "sha512-SE4VfbLWUZl9MR+ngLSARptUv2E8brY0luCdgmUevU6arZRY/KxYoLI/3V/yxaURR8tLRN7bmZtJdgmzLHI6pQ==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "@typescript-eslint/types": "5.12.0",
 | 
			
		||||
        "@typescript-eslint/visitor-keys": "5.12.0",
 | 
			
		||||
        "@typescript-eslint/types": "5.16.0",
 | 
			
		||||
        "@typescript-eslint/visitor-keys": "5.16.0",
 | 
			
		||||
        "debug": "^4.3.2",
 | 
			
		||||
        "globby": "^11.0.4",
 | 
			
		||||
        "is-glob": "^4.0.3",
 | 
			
		||||
@ -4113,13 +4300,45 @@
 | 
			
		||||
        "tsutils": "^3.21.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "@typescript-eslint/visitor-keys": {
 | 
			
		||||
      "version": "5.12.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.12.0.tgz",
 | 
			
		||||
      "integrity": "sha512-cFwTlgnMV6TgezQynx2c/4/tx9Tufbuo9LPzmWqyRC3QC4qTGkAG1C6pBr0/4I10PAI/FlYunI3vJjIcu+ZHMg==",
 | 
			
		||||
    "@typescript-eslint/utils": {
 | 
			
		||||
      "version": "5.16.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.16.0.tgz",
 | 
			
		||||
      "integrity": "sha512-iYej2ER6AwmejLWMWzJIHy3nPJeGDuCqf8Jnb+jAQVoPpmWzwQOfa9hWVB8GIQE5gsCv/rfN4T+AYb/V06WseQ==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "@typescript-eslint/types": "5.12.0",
 | 
			
		||||
        "@types/json-schema": "^7.0.9",
 | 
			
		||||
        "@typescript-eslint/scope-manager": "5.16.0",
 | 
			
		||||
        "@typescript-eslint/types": "5.16.0",
 | 
			
		||||
        "@typescript-eslint/typescript-estree": "5.16.0",
 | 
			
		||||
        "eslint-scope": "^5.1.1",
 | 
			
		||||
        "eslint-utils": "^3.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "eslint-scope": {
 | 
			
		||||
          "version": "5.1.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
 | 
			
		||||
          "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "esrecurse": "^4.3.0",
 | 
			
		||||
            "estraverse": "^4.1.1"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "estraverse": {
 | 
			
		||||
          "version": "4.3.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
 | 
			
		||||
          "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
 | 
			
		||||
          "dev": true
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "@typescript-eslint/visitor-keys": {
 | 
			
		||||
      "version": "5.16.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.16.0.tgz",
 | 
			
		||||
      "integrity": "sha512-jqxO8msp5vZDhikTwq9ubyMHqZ67UIvawohr4qF3KhlpL7gzSjOd+8471H3nh5LyABkaI85laEKKU8SnGUK5/g==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "@typescript-eslint/types": "5.16.0",
 | 
			
		||||
        "eslint-visitor-keys": "^3.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
@ -5843,6 +6062,20 @@
 | 
			
		||||
      "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "prettier": {
 | 
			
		||||
      "version": "2.6.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.1.tgz",
 | 
			
		||||
      "integrity": "sha512-8UVbTBYGwN37Bs9LERmxCPjdvPxlEowx2urIL6urHzdb3SDq4B/Z6xLFCblrSnE4iKWcS6ziJ3aOYrc1kz/E2A==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "peer": true
 | 
			
		||||
    },
 | 
			
		||||
    "prettier-plugin-organize-imports": {
 | 
			
		||||
      "version": "2.3.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-2.3.4.tgz",
 | 
			
		||||
      "integrity": "sha512-R8o23sf5iVL/U71h9SFUdhdOEPsi3nm42FD/oDYIZ2PQa4TNWWuWecxln6jlIQzpZTDMUeO1NicJP6lLn2TtRw==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {}
 | 
			
		||||
    },
 | 
			
		||||
    "prop-types": {
 | 
			
		||||
      "version": "15.8.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
 | 
			
		||||
 | 
			
		||||
@ -28,9 +28,13 @@
 | 
			
		||||
    "@types/nodemailer": "^6.4.4",
 | 
			
		||||
    "@types/react": "17.0.40",
 | 
			
		||||
    "@types/react-dom": "^17.0.13",
 | 
			
		||||
    "eslint": "8.10.0",
 | 
			
		||||
    "@types/turndown": "^5.0.1",
 | 
			
		||||
    "@typescript-eslint/eslint-plugin": "^5.16.0",
 | 
			
		||||
    "@typescript-eslint/parser": "^5.16.0",
 | 
			
		||||
    "eslint": "^8.10.0",
 | 
			
		||||
    "eslint-config-next": "12.1.0",
 | 
			
		||||
    "prettier-plugin-organize-imports": "^2.3.4",
 | 
			
		||||
    "tailwindcss": "^3.0.23",
 | 
			
		||||
    "typescript": "4.6.2"
 | 
			
		||||
    "typescript": "^4.6.2"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,17 +1,17 @@
 | 
			
		||||
import { StrapiImage } from "graphql/operations-types";
 | 
			
		||||
import MainPanel from "./Panels/MainPanel";
 | 
			
		||||
import Head from "next/head";
 | 
			
		||||
import { useSwipeable } from "react-swipeable";
 | 
			
		||||
import { useRouter } from "next/router";
 | 
			
		||||
import Button from "components/Button";
 | 
			
		||||
import { getOgImage, OgImage } from "queries/helpers";
 | 
			
		||||
import { useMediaCoarse, useMediaMobile } from "hooks/useMediaQuery";
 | 
			
		||||
import { useAppLayout } from "contexts/AppLayoutContext";
 | 
			
		||||
import { ImageQuality } from "./Img";
 | 
			
		||||
import Popup from "./Popup";
 | 
			
		||||
import { useEffect, useState } from "react";
 | 
			
		||||
import Select from "./Select";
 | 
			
		||||
import { StrapiImage } from "graphql/operations-types";
 | 
			
		||||
import { useMediaMobile } from "hooks/useMediaQuery";
 | 
			
		||||
import Head from "next/head";
 | 
			
		||||
import { useRouter } from "next/router";
 | 
			
		||||
import { AppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
import { getOgImage, OgImage } from "queries/helpers";
 | 
			
		||||
import { useEffect, useState } from "react";
 | 
			
		||||
import { useSwipeable } from "react-swipeable";
 | 
			
		||||
import { ImageQuality } from "./Img";
 | 
			
		||||
import MainPanel from "./Panels/MainPanel";
 | 
			
		||||
import Popup from "./Popup";
 | 
			
		||||
import Select from "./Select";
 | 
			
		||||
 | 
			
		||||
interface AppLayoutProps extends AppStaticProps {
 | 
			
		||||
  subPanel?: React.ReactNode;
 | 
			
		||||
@ -27,7 +27,6 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
 | 
			
		||||
  const { langui, currencies, languages, subPanel, contentPanel } = props;
 | 
			
		||||
  const router = useRouter();
 | 
			
		||||
  const isMobile = useMediaMobile();
 | 
			
		||||
  const isCoarse = useMediaCoarse();
 | 
			
		||||
  const appLayout = useAppLayout();
 | 
			
		||||
 | 
			
		||||
  const sensibilitySwipe = 1.1;
 | 
			
		||||
@ -70,23 +69,23 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    document.getElementsByTagName("html")[0].style.fontSize = `${
 | 
			
		||||
      (appLayout.fontSize || 1) * 100
 | 
			
		||||
      (appLayout.fontSize ?? 1) * 100
 | 
			
		||||
    }%`;
 | 
			
		||||
  }, [appLayout.fontSize]);
 | 
			
		||||
 | 
			
		||||
  const currencyOptions = currencies.map((currency) => {
 | 
			
		||||
    return currency.attributes.code;
 | 
			
		||||
  });
 | 
			
		||||
  const currencyOptions = currencies.map(
 | 
			
		||||
    (currency) => currency.attributes.code
 | 
			
		||||
  );
 | 
			
		||||
  const [currencySelect, setCurrencySelect] = useState<number>(-1);
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    appLayout.currency &&
 | 
			
		||||
    if (appLayout.currency)
 | 
			
		||||
      setCurrencySelect(currencyOptions.indexOf(appLayout.currency));
 | 
			
		||||
    // eslint-disable-next-line react-hooks/exhaustive-deps
 | 
			
		||||
  }, [appLayout.currency]);
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    currencySelect >= 0 &&
 | 
			
		||||
    if (currencySelect >= 0)
 | 
			
		||||
      appLayout.setCurrency(currencyOptions[currencySelect]);
 | 
			
		||||
    // eslint-disable-next-line react-hooks/exhaustive-deps
 | 
			
		||||
  }, [currencySelect]);
 | 
			
		||||
@ -98,12 +97,10 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
 | 
			
		||||
    } else {
 | 
			
		||||
      gridCol = "grid-cols-[20rem_20rem_1fr]";
 | 
			
		||||
    }
 | 
			
		||||
  } else if (appLayout.mainPanelReduced) {
 | 
			
		||||
    gridCol = "grid-cols-[6rem_0px_1fr]";
 | 
			
		||||
  } else {
 | 
			
		||||
    if (appLayout.mainPanelReduced) {
 | 
			
		||||
      gridCol = "grid-cols-[6rem_0px_1fr]";
 | 
			
		||||
    } else {
 | 
			
		||||
      gridCol = "grid-cols-[20rem_0px_1fr]";
 | 
			
		||||
    }
 | 
			
		||||
    gridCol = "grid-cols-[20rem_0px_1fr]";
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
@ -152,7 +149,7 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
 | 
			
		||||
        {/* Background when navbar is opened */}
 | 
			
		||||
        <div
 | 
			
		||||
          className={`[grid-area:content] mobile:z-10 absolute inset-0 transition-[backdrop-filter] duration-500 ${
 | 
			
		||||
            (appLayout.mainPanelOpen || appLayout.subPanelOpen) && isMobile
 | 
			
		||||
            (appLayout.mainPanelOpen ?? appLayout.subPanelOpen) && isMobile
 | 
			
		||||
              ? "[backdrop-filter:blur(2px)]"
 | 
			
		||||
              : "pointer-events-none touch-none "
 | 
			
		||||
          }`}
 | 
			
		||||
@ -161,7 +158,7 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
 | 
			
		||||
            className={`absolute bg-shade inset-0 transition-opacity duration-500 
 | 
			
		||||
        ${turnSubIntoContent ? "" : ""}
 | 
			
		||||
        ${
 | 
			
		||||
          (appLayout.mainPanelOpen || appLayout.subPanelOpen) && isMobile
 | 
			
		||||
          (appLayout.mainPanelOpen ?? appLayout.subPanelOpen) && isMobile
 | 
			
		||||
            ? "opacity-60"
 | 
			
		||||
            : "opacity-0"
 | 
			
		||||
        }`}
 | 
			
		||||
@ -195,9 +192,7 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
 | 
			
		||||
          ${
 | 
			
		||||
            turnSubIntoContent
 | 
			
		||||
              ? "mobile:border-l-0 mobile:w-full"
 | 
			
		||||
              : !appLayout.subPanelOpen
 | 
			
		||||
              ? "mobile:translate-x-[100vw]"
 | 
			
		||||
              : ""
 | 
			
		||||
              : !appLayout.subPanelOpen && "mobile:translate-x-[100vw]"
 | 
			
		||||
          }`}
 | 
			
		||||
          >
 | 
			
		||||
            {subPanel}
 | 
			
		||||
@ -338,7 +333,7 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
 | 
			
		||||
                  className="rounded-l-none rounded-r-none border-x-0"
 | 
			
		||||
                  onClick={() => appLayout.setFontSize(1)}
 | 
			
		||||
                >
 | 
			
		||||
                  {((appLayout.fontSize || 1) * 100).toLocaleString(undefined, {
 | 
			
		||||
                  {((appLayout.fontSize ?? 1) * 100).toLocaleString(undefined, {
 | 
			
		||||
                    maximumFractionDigits: 0,
 | 
			
		||||
                  })}
 | 
			
		||||
                  %
 | 
			
		||||
@ -382,8 +377,10 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
 | 
			
		||||
                type="text"
 | 
			
		||||
                placeholder="<player>"
 | 
			
		||||
                className="w-48"
 | 
			
		||||
                onInput={(e) =>
 | 
			
		||||
                  appLayout.setPlayerName((e.target as HTMLInputElement).value)
 | 
			
		||||
                onInput={(event) =>
 | 
			
		||||
                  appLayout.setPlayerName(
 | 
			
		||||
                    (event.target as HTMLInputElement).value
 | 
			
		||||
                  )
 | 
			
		||||
                }
 | 
			
		||||
              />
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,3 @@
 | 
			
		||||
import { MouseEventHandler } from "react";
 | 
			
		||||
 | 
			
		||||
type ChipProps = {
 | 
			
		||||
  className?: string;
 | 
			
		||||
  children: React.ReactNode;
 | 
			
		||||
 | 
			
		||||
@ -19,23 +19,22 @@ export default function ChronologyItemComponent(
 | 
			
		||||
  const { langui } = props;
 | 
			
		||||
 | 
			
		||||
  function generateAnchor(year: number, month: number, day: number): string {
 | 
			
		||||
    let result: string = "";
 | 
			
		||||
    let result = "";
 | 
			
		||||
    result += year;
 | 
			
		||||
    if (month) result += "-" + month.toString().padStart(2, "0");
 | 
			
		||||
    if (day) result += "-" + day.toString().padStart(2, "0");
 | 
			
		||||
    if (month) result += `- ${month.toString().padStart(2, "0")}`;
 | 
			
		||||
    if (day) result += `- ${day.toString().padStart(2, "0")}`;
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function generateYear(displayed_date: string, year: number): string {
 | 
			
		||||
    if (displayed_date) {
 | 
			
		||||
      return displayed_date;
 | 
			
		||||
    } else {
 | 
			
		||||
      return year.toString();
 | 
			
		||||
    }
 | 
			
		||||
    return year.toString();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function generateDate(month: number, day: number): string {
 | 
			
		||||
    let lut = [
 | 
			
		||||
    const lut = [
 | 
			
		||||
      "Jan",
 | 
			
		||||
      "Feb",
 | 
			
		||||
      "Mar",
 | 
			
		||||
@ -50,11 +49,11 @@ export default function ChronologyItemComponent(
 | 
			
		||||
      "Dec",
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    let result: string = "";
 | 
			
		||||
    let result = "";
 | 
			
		||||
    if (month) {
 | 
			
		||||
      result += lut[month - 1];
 | 
			
		||||
      if (day) {
 | 
			
		||||
        result += " " + day;
 | 
			
		||||
        result += ` ${day}`;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -113,7 +112,7 @@ export default function ChronologyItemComponent(
 | 
			
		||||
                  </p>
 | 
			
		||||
                )}
 | 
			
		||||
                {translation.note ? (
 | 
			
		||||
                  <em>{"Notes: " + translation.note}</em>
 | 
			
		||||
                  <em>{`Notes: ${translation.note}`}</em>
 | 
			
		||||
                ) : (
 | 
			
		||||
                  ""
 | 
			
		||||
                )}
 | 
			
		||||
@ -122,7 +121,7 @@ export default function ChronologyItemComponent(
 | 
			
		||||
 | 
			
		||||
            <p className="text-dark text-xs grid place-self-start grid-flow-col gap-1 mt-1">
 | 
			
		||||
              {event.source.data ? (
 | 
			
		||||
                "(" + event.source.data.attributes.name + ")"
 | 
			
		||||
                `(${event.source.data.attributes.name})`
 | 
			
		||||
              ) : (
 | 
			
		||||
                <>
 | 
			
		||||
                  <span className="material-icons !text-sm">warning</span>No
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,11 @@
 | 
			
		||||
import Chip from "components/Chip";
 | 
			
		||||
import Img, { ImageQuality } from "components/Img";
 | 
			
		||||
import InsetBox from "components/InsetBox";
 | 
			
		||||
import {
 | 
			
		||||
  GetContentQuery,
 | 
			
		||||
  GetWebsiteInterfaceQuery,
 | 
			
		||||
} from "graphql/operations-types";
 | 
			
		||||
import { prettyinlineTitle, prettySlug, slugify } from "queries/helpers";
 | 
			
		||||
import Img, { ImageQuality } from "components/Img";
 | 
			
		||||
import InsetBox from "components/InsetBox";
 | 
			
		||||
import Chip from "components/Chip";
 | 
			
		||||
 | 
			
		||||
export type ThumbnailHeaderProps = {
 | 
			
		||||
  pre_title?: string;
 | 
			
		||||
@ -49,7 +49,7 @@ export default function ThumbnailHeader(
 | 
			
		||||
        </div>
 | 
			
		||||
        <div
 | 
			
		||||
          id={slugify(
 | 
			
		||||
            prettyinlineTitle(pre_title || "", title, subtitle || "")
 | 
			
		||||
            prettyinlineTitle(pre_title ?? "", title, subtitle ?? "")
 | 
			
		||||
          )}
 | 
			
		||||
          className="grid place-items-center text-center"
 | 
			
		||||
        >
 | 
			
		||||
@ -60,7 +60,7 @@ export default function ThumbnailHeader(
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <div className="grid grid-flow-col gap-8">
 | 
			
		||||
        {type && type.data && (
 | 
			
		||||
        {type?.data && (
 | 
			
		||||
          <div className="flex flex-col place-items-center gap-2">
 | 
			
		||||
            <h3 className="text-xl">{langui.type}</h3>
 | 
			
		||||
            <div className="flex flex-row flex-wrap">
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,5 @@
 | 
			
		||||
import { StrapiImage } from "graphql/operations-types";
 | 
			
		||||
import { ImageProps } from "next/image";
 | 
			
		||||
import Image from "next/image";
 | 
			
		||||
import Image, { ImageProps } from "next/image";
 | 
			
		||||
 | 
			
		||||
export enum ImageQuality {
 | 
			
		||||
  Small = "small",
 | 
			
		||||
@ -10,11 +9,12 @@ export enum ImageQuality {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function getAssetURL(url: string, quality: ImageQuality): string {
 | 
			
		||||
  url = url.replace(/^\/uploads/, "/" + quality);
 | 
			
		||||
  url = url.replace(/.jpg$/, ".webp");
 | 
			
		||||
  url = url.replace(/.png$/, ".webp");
 | 
			
		||||
  if (quality === ImageQuality.Og) url = url.replace(/.webp$/, ".jpg");
 | 
			
		||||
  return process.env.NEXT_PUBLIC_URL_IMG + url;
 | 
			
		||||
  let newUrl = url;
 | 
			
		||||
  newUrl = newUrl.replace(/^\/uploads/u, `/${quality}`);
 | 
			
		||||
  newUrl = newUrl.replace(/.jpg$/u, ".webp");
 | 
			
		||||
  newUrl = newUrl.replace(/.png$/u, ".webp");
 | 
			
		||||
  if (quality === ImageQuality.Og) newUrl = newUrl.replace(/.webp$/u, ".jpg");
 | 
			
		||||
  return process.env.NEXT_PUBLIC_URL_IMG + newUrl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function getImgSizesByMaxSize(
 | 
			
		||||
@ -25,10 +25,9 @@ export function getImgSizesByMaxSize(
 | 
			
		||||
  if (width > height) {
 | 
			
		||||
    if (width < maxSize) return { width: width, height: height };
 | 
			
		||||
    return { width: maxSize, height: (height / width) * maxSize };
 | 
			
		||||
  } else {
 | 
			
		||||
    if (height < maxSize) return { width: width, height: height };
 | 
			
		||||
    return { width: (width / height) * maxSize, height: maxSize };
 | 
			
		||||
  }
 | 
			
		||||
  if (height < maxSize) return { width: width, height: height };
 | 
			
		||||
  return { width: (width / height) * maxSize, height: maxSize };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function getImgSizesByQuality(
 | 
			
		||||
@ -45,6 +44,8 @@ export function getImgSizesByQuality(
 | 
			
		||||
      return getImgSizesByMaxSize(width, height, 1024);
 | 
			
		||||
    case ImageQuality.Large:
 | 
			
		||||
      return getImgSizesByMaxSize(width, height, 2048);
 | 
			
		||||
    default:
 | 
			
		||||
      return { width: 0, height: 0 };
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -81,25 +82,23 @@ export default function Img(props: ImgProps): JSX.Element {
 | 
			
		||||
          height={imgSize.height}
 | 
			
		||||
        />
 | 
			
		||||
      );
 | 
			
		||||
    } else {
 | 
			
		||||
      return (
 | 
			
		||||
        <Image
 | 
			
		||||
          className={props.className}
 | 
			
		||||
          src={getAssetURL(
 | 
			
		||||
            props.image.url,
 | 
			
		||||
            props.quality ? props.quality : ImageQuality.Small
 | 
			
		||||
          )}
 | 
			
		||||
          alt={props.alt ? props.alt : props.image.alternativeText}
 | 
			
		||||
          width={props.layout === "fill" ? undefined : imgSize.width}
 | 
			
		||||
          height={props.layout === "fill" ? undefined : imgSize.height}
 | 
			
		||||
          layout={props.layout}
 | 
			
		||||
          objectFit={props.objectFit}
 | 
			
		||||
          priority={props.priority}
 | 
			
		||||
          unoptimized
 | 
			
		||||
        />
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    return <></>;
 | 
			
		||||
    return (
 | 
			
		||||
      <Image
 | 
			
		||||
        className={props.className}
 | 
			
		||||
        src={getAssetURL(
 | 
			
		||||
          props.image.url,
 | 
			
		||||
          props.quality ? props.quality : ImageQuality.Small
 | 
			
		||||
        )}
 | 
			
		||||
        alt={props.alt ? props.alt : props.image.alternativeText}
 | 
			
		||||
        width={props.layout === "fill" ? undefined : imgSize.width}
 | 
			
		||||
        height={props.layout === "fill" ? undefined : imgSize.height}
 | 
			
		||||
        layout={props.layout}
 | 
			
		||||
        objectFit={props.objectFit}
 | 
			
		||||
        priority={props.priority}
 | 
			
		||||
        unoptimized
 | 
			
		||||
      />
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
  return <></>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -16,8 +16,7 @@ type ContentTOCLineProps = {
 | 
			
		||||
export default function ContentTOCLine(
 | 
			
		||||
  props: ContentTOCLineProps
 | 
			
		||||
): JSX.Element {
 | 
			
		||||
  const content = props.content;
 | 
			
		||||
  const langui = props.langui;
 | 
			
		||||
  const { content, langui } = props;
 | 
			
		||||
 | 
			
		||||
  const [opened, setOpened] = useState(false);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
import Link from "next/link";
 | 
			
		||||
import { GetContentsQuery } from "graphql/operations-types";
 | 
			
		||||
import { prettySlug } from "queries/helpers";
 | 
			
		||||
import Chip from "components/Chip";
 | 
			
		||||
import Img, { ImageQuality } from "components/Img";
 | 
			
		||||
import { GetContentsQuery } from "graphql/operations-types";
 | 
			
		||||
import Link from "next/link";
 | 
			
		||||
import { prettySlug } from "queries/helpers";
 | 
			
		||||
 | 
			
		||||
export type LibraryContentPreviewProps = {
 | 
			
		||||
  item: {
 | 
			
		||||
@ -17,10 +17,10 @@ export type LibraryContentPreviewProps = {
 | 
			
		||||
export default function LibraryContentPreview(
 | 
			
		||||
  props: LibraryContentPreviewProps
 | 
			
		||||
): JSX.Element {
 | 
			
		||||
  const item = props.item;
 | 
			
		||||
  const { item } = props;
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Link href={"/contents/" + item.slug} passHref>
 | 
			
		||||
    <Link href={`/contents/${item.slug}`} passHref>
 | 
			
		||||
      <div className="drop-shadow-shade-xl cursor-pointer grid items-end fine:[--cover-opacity:0] hover:[--cover-opacity:1] hover:scale-[1.02] transition-transform">
 | 
			
		||||
        {item.thumbnail.data ? (
 | 
			
		||||
          <Img
 | 
			
		||||
 | 
			
		||||
@ -1,12 +1,12 @@
 | 
			
		||||
import Link from "next/link";
 | 
			
		||||
import Chip from "components/Chip";
 | 
			
		||||
import Img, { ImageQuality } from "components/Img";
 | 
			
		||||
import { useAppLayout } from "contexts/AppLayoutContext";
 | 
			
		||||
import {
 | 
			
		||||
  GetCurrenciesQuery,
 | 
			
		||||
  GetLibraryItemsPreviewQuery,
 | 
			
		||||
} from "graphql/operations-types";
 | 
			
		||||
import { prettyDate, prettyPrice, prettyItemSubType } from "queries/helpers";
 | 
			
		||||
import Chip from "components/Chip";
 | 
			
		||||
import Img, { ImageQuality } from "components/Img";
 | 
			
		||||
import { useAppLayout } from "contexts/AppLayoutContext";
 | 
			
		||||
import Link from "next/link";
 | 
			
		||||
import { prettyDate, prettyItemSubType, prettyPrice } from "queries/helpers";
 | 
			
		||||
 | 
			
		||||
export type LibraryItemsPreviewProps = {
 | 
			
		||||
  className?: string;
 | 
			
		||||
@ -26,11 +26,11 @@ export type LibraryItemsPreviewProps = {
 | 
			
		||||
export default function LibraryItemsPreview(
 | 
			
		||||
  props: LibraryItemsPreviewProps
 | 
			
		||||
): JSX.Element {
 | 
			
		||||
  const item = props.item;
 | 
			
		||||
  const { item } = props;
 | 
			
		||||
  const appLayout = useAppLayout();
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Link href={"/library/" + item.slug} passHref>
 | 
			
		||||
    <Link href={`/library/${item.slug}`} passHref>
 | 
			
		||||
      <div
 | 
			
		||||
        className={`drop-shadow-shade-xl cursor-pointer grid items-end hover:rounded-3xl fine:[--cover-opacity:0] hover:[--cover-opacity:1] hover:scale-[1.02] transition-transform ${props.className}`}
 | 
			
		||||
      >
 | 
			
		||||
@ -63,7 +63,7 @@ export default function LibraryItemsPreview(
 | 
			
		||||
            ))}
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
          {(item.release_date || item.price) && (
 | 
			
		||||
          {(item.release_date ?? item.price) && (
 | 
			
		||||
            <div className="grid grid-flow-col w-full">
 | 
			
		||||
              {item.release_date && (
 | 
			
		||||
                <p className="mobile:text-xs text-sm">
 | 
			
		||||
 | 
			
		||||
@ -4,8 +4,8 @@ import Lightbox from "react-image-lightbox";
 | 
			
		||||
 | 
			
		||||
export type LightBoxProps = {
 | 
			
		||||
  setState:
 | 
			
		||||
    | Dispatch<SetStateAction<boolean>>
 | 
			
		||||
    | Dispatch<SetStateAction<boolean | undefined>>;
 | 
			
		||||
    | Dispatch<SetStateAction<boolean | undefined>>
 | 
			
		||||
    | Dispatch<SetStateAction<boolean>>;
 | 
			
		||||
  state: boolean;
 | 
			
		||||
  images: string[];
 | 
			
		||||
  index: number;
 | 
			
		||||
 | 
			
		||||
@ -8,6 +8,7 @@ import Markdown from "markdown-to-jsx";
 | 
			
		||||
import { NextRouter } from "next/router";
 | 
			
		||||
import { slugify } from "queries/helpers";
 | 
			
		||||
import React, { useState } from "react";
 | 
			
		||||
import ReactDOMServer from "react-dom/server";
 | 
			
		||||
 | 
			
		||||
type MarkdawnProps = {
 | 
			
		||||
  className?: string;
 | 
			
		||||
@ -41,264 +42,233 @@ export default function Markdawn(props: MarkdawnProps): JSX.Element {
 | 
			
		||||
            slugify: slugify,
 | 
			
		||||
            overrides: {
 | 
			
		||||
              h1: {
 | 
			
		||||
                component: (props: {
 | 
			
		||||
                component: (compProps: {
 | 
			
		||||
                  id: string;
 | 
			
		||||
                  style: React.CSSProperties;
 | 
			
		||||
                  children: React.ReactNode;
 | 
			
		||||
                }) => {
 | 
			
		||||
                  return (
 | 
			
		||||
                    <h1 id={props.id} style={props.style}>
 | 
			
		||||
                      {props.children}
 | 
			
		||||
                      <HeaderToolTip id={props.id} />
 | 
			
		||||
                    </h1>
 | 
			
		||||
                  );
 | 
			
		||||
                },
 | 
			
		||||
                }) => (
 | 
			
		||||
                  <h1 id={compProps.id} style={compProps.style}>
 | 
			
		||||
                    {compProps.children}
 | 
			
		||||
                    <HeaderToolTip id={compProps.id} />
 | 
			
		||||
                  </h1>
 | 
			
		||||
                ),
 | 
			
		||||
              },
 | 
			
		||||
              h2: {
 | 
			
		||||
                component: (props: {
 | 
			
		||||
                component: (compProps: {
 | 
			
		||||
                  id: string;
 | 
			
		||||
                  style: React.CSSProperties;
 | 
			
		||||
                  children: React.ReactNode;
 | 
			
		||||
                }) => {
 | 
			
		||||
                  return (
 | 
			
		||||
                    <h2 id={props.id} style={props.style}>
 | 
			
		||||
                      {props.children}
 | 
			
		||||
                      <HeaderToolTip id={props.id} />
 | 
			
		||||
                    </h2>
 | 
			
		||||
                  );
 | 
			
		||||
                },
 | 
			
		||||
                }) => (
 | 
			
		||||
                  <h2 id={compProps.id} style={compProps.style}>
 | 
			
		||||
                    {compProps.children}
 | 
			
		||||
                    <HeaderToolTip id={compProps.id} />
 | 
			
		||||
                  </h2>
 | 
			
		||||
                ),
 | 
			
		||||
              },
 | 
			
		||||
              h3: {
 | 
			
		||||
                component: (props: {
 | 
			
		||||
                component: (compProps: {
 | 
			
		||||
                  id: string;
 | 
			
		||||
                  style: React.CSSProperties;
 | 
			
		||||
                  children: React.ReactNode;
 | 
			
		||||
                }) => {
 | 
			
		||||
                  return (
 | 
			
		||||
                    <h3 id={props.id} style={props.style}>
 | 
			
		||||
                      {props.children}
 | 
			
		||||
                      <HeaderToolTip id={props.id} />
 | 
			
		||||
                    </h3>
 | 
			
		||||
                  );
 | 
			
		||||
                },
 | 
			
		||||
                }) => (
 | 
			
		||||
                  <h3 id={compProps.id} style={compProps.style}>
 | 
			
		||||
                    {compProps.children}
 | 
			
		||||
                    <HeaderToolTip id={compProps.id} />
 | 
			
		||||
                  </h3>
 | 
			
		||||
                ),
 | 
			
		||||
              },
 | 
			
		||||
              h4: {
 | 
			
		||||
                component: (props: {
 | 
			
		||||
                component: (compProps: {
 | 
			
		||||
                  id: string;
 | 
			
		||||
                  style: React.CSSProperties;
 | 
			
		||||
                  children: React.ReactNode;
 | 
			
		||||
                }) => {
 | 
			
		||||
                  return (
 | 
			
		||||
                    <h4 id={props.id} style={props.style}>
 | 
			
		||||
                      {props.children}
 | 
			
		||||
                      <HeaderToolTip id={props.id} />
 | 
			
		||||
                    </h4>
 | 
			
		||||
                  );
 | 
			
		||||
                },
 | 
			
		||||
                }) => (
 | 
			
		||||
                  <h4 id={compProps.id} style={compProps.style}>
 | 
			
		||||
                    {compProps.children}
 | 
			
		||||
                    <HeaderToolTip id={compProps.id} />
 | 
			
		||||
                  </h4>
 | 
			
		||||
                ),
 | 
			
		||||
              },
 | 
			
		||||
              h5: {
 | 
			
		||||
                component: (props: {
 | 
			
		||||
                component: (compProps: {
 | 
			
		||||
                  id: string;
 | 
			
		||||
                  style: React.CSSProperties;
 | 
			
		||||
                  children: React.ReactNode;
 | 
			
		||||
                }) => {
 | 
			
		||||
                  return (
 | 
			
		||||
                    <h5 id={props.id} style={props.style}>
 | 
			
		||||
                      {props.children}
 | 
			
		||||
                      <HeaderToolTip id={props.id} />
 | 
			
		||||
                    </h5>
 | 
			
		||||
                  );
 | 
			
		||||
                },
 | 
			
		||||
                }) => (
 | 
			
		||||
                  <h5 id={compProps.id} style={compProps.style}>
 | 
			
		||||
                    {compProps.children}
 | 
			
		||||
                    <HeaderToolTip id={compProps.id} />
 | 
			
		||||
                  </h5>
 | 
			
		||||
                ),
 | 
			
		||||
              },
 | 
			
		||||
              h6: {
 | 
			
		||||
                component: (props: {
 | 
			
		||||
                component: (compProps: {
 | 
			
		||||
                  id: string;
 | 
			
		||||
                  style: React.CSSProperties;
 | 
			
		||||
                  children: React.ReactNode;
 | 
			
		||||
                }) => {
 | 
			
		||||
                  return (
 | 
			
		||||
                    <h6 id={props.id} style={props.style}>
 | 
			
		||||
                      {props.children}
 | 
			
		||||
                      <HeaderToolTip id={props.id} />
 | 
			
		||||
                    </h6>
 | 
			
		||||
                  );
 | 
			
		||||
                },
 | 
			
		||||
                }) => (
 | 
			
		||||
                  <h6 id={compProps.id} style={compProps.style}>
 | 
			
		||||
                    {compProps.children}
 | 
			
		||||
                    <HeaderToolTip id={compProps.id} />
 | 
			
		||||
                  </h6>
 | 
			
		||||
                ),
 | 
			
		||||
              },
 | 
			
		||||
              Sep: {
 | 
			
		||||
                component: () => {
 | 
			
		||||
                  return <div className="my-24"></div>;
 | 
			
		||||
                },
 | 
			
		||||
                component: () => <div className="my-24"></div>,
 | 
			
		||||
              },
 | 
			
		||||
              SceneBreak: {
 | 
			
		||||
                component: (props: { id: string }) => {
 | 
			
		||||
                  return (
 | 
			
		||||
                    <div
 | 
			
		||||
                      id={props.id}
 | 
			
		||||
                      className={
 | 
			
		||||
                        "h-0 text-center text-3xl text-dark mt-16 mb-20"
 | 
			
		||||
                      }
 | 
			
		||||
                    >
 | 
			
		||||
                      * * *
 | 
			
		||||
                    </div>
 | 
			
		||||
                  );
 | 
			
		||||
                },
 | 
			
		||||
                component: (compProps: { id: string }) => (
 | 
			
		||||
                  <div
 | 
			
		||||
                    id={compProps.id}
 | 
			
		||||
                    className={"h-0 text-center text-3xl text-dark mt-16 mb-20"}
 | 
			
		||||
                  >
 | 
			
		||||
                    * * *
 | 
			
		||||
                  </div>
 | 
			
		||||
                ),
 | 
			
		||||
              },
 | 
			
		||||
              IntraLink: {
 | 
			
		||||
                component: (props: {
 | 
			
		||||
                component: (compProps: {
 | 
			
		||||
                  children: React.ReactNode;
 | 
			
		||||
                  target?: string;
 | 
			
		||||
                  page?: string;
 | 
			
		||||
                }) => {
 | 
			
		||||
                  const slug = props.target
 | 
			
		||||
                    ? slugify(props.target)
 | 
			
		||||
                    : slugify(props.children?.toString());
 | 
			
		||||
                  const slug = compProps.target
 | 
			
		||||
                    ? slugify(compProps.target)
 | 
			
		||||
                    : slugify(compProps.children?.toString());
 | 
			
		||||
                  return (
 | 
			
		||||
                    <a
 | 
			
		||||
                      onClick={() =>
 | 
			
		||||
                      onClick={async () =>
 | 
			
		||||
                        router.replace(
 | 
			
		||||
                          `${props.page ? props.page : ""}#${slug}`
 | 
			
		||||
                          `${compProps.page ? compProps.page : ""}#${slug}`
 | 
			
		||||
                        )
 | 
			
		||||
                      }
 | 
			
		||||
                    >
 | 
			
		||||
                      {props.children}
 | 
			
		||||
                      {compProps.children}
 | 
			
		||||
                    </a>
 | 
			
		||||
                  );
 | 
			
		||||
                },
 | 
			
		||||
              },
 | 
			
		||||
              player: {
 | 
			
		||||
                component: () => {
 | 
			
		||||
                  return (
 | 
			
		||||
                    <span className="text-dark opacity-70">
 | 
			
		||||
                      {appLayout.playerName ? appLayout.playerName : "<player>"}
 | 
			
		||||
                    </span>
 | 
			
		||||
                  );
 | 
			
		||||
                },
 | 
			
		||||
                component: () => (
 | 
			
		||||
                  <span className="text-dark opacity-70">
 | 
			
		||||
                    {appLayout.playerName ? appLayout.playerName : "<player>"}
 | 
			
		||||
                  </span>
 | 
			
		||||
                ),
 | 
			
		||||
              },
 | 
			
		||||
              Transcript: {
 | 
			
		||||
                component: (props) => {
 | 
			
		||||
                  return (
 | 
			
		||||
                    <div className="grid grid-cols-[auto_1fr] mobile:grid-cols-1 gap-x-6 gap-y-2">
 | 
			
		||||
                      {props.children}
 | 
			
		||||
                    </div>
 | 
			
		||||
                  );
 | 
			
		||||
                },
 | 
			
		||||
                component: (compProps) => (
 | 
			
		||||
                  <div className="grid grid-cols-[auto_1fr] mobile:grid-cols-1 gap-x-6 gap-y-2">
 | 
			
		||||
                    {compProps.children}
 | 
			
		||||
                  </div>
 | 
			
		||||
                ),
 | 
			
		||||
              },
 | 
			
		||||
              Line: {
 | 
			
		||||
                component: (props) => {
 | 
			
		||||
                  return (
 | 
			
		||||
                    <>
 | 
			
		||||
                      <strong className="text-dark opacity-60 mobile:!-mb-4">
 | 
			
		||||
                        {props.name}
 | 
			
		||||
                      </strong>
 | 
			
		||||
                      <p className="whitespace-pre-line">{props.children}</p>
 | 
			
		||||
                    </>
 | 
			
		||||
                  );
 | 
			
		||||
                },
 | 
			
		||||
                component: (compProps) => (
 | 
			
		||||
                  <>
 | 
			
		||||
                    <strong className="text-dark opacity-60 mobile:!-mb-4">
 | 
			
		||||
                      {compProps.name}
 | 
			
		||||
                    </strong>
 | 
			
		||||
                    <p className="whitespace-pre-line">{compProps.children}</p>
 | 
			
		||||
                  </>
 | 
			
		||||
                ),
 | 
			
		||||
              },
 | 
			
		||||
              InsetBox: {
 | 
			
		||||
                component: (props) => {
 | 
			
		||||
                  return (
 | 
			
		||||
                    <InsetBox className="my-12">{props.children}</InsetBox>
 | 
			
		||||
                  );
 | 
			
		||||
                },
 | 
			
		||||
                component: (compProps) => (
 | 
			
		||||
                  <InsetBox className="my-12">{compProps.children}</InsetBox>
 | 
			
		||||
                ),
 | 
			
		||||
              },
 | 
			
		||||
              li: {
 | 
			
		||||
                component: (props: { children: React.ReactNode }) => {
 | 
			
		||||
                  return (
 | 
			
		||||
                    <li
 | 
			
		||||
                      className={
 | 
			
		||||
                        props.children &&
 | 
			
		||||
                        props.children?.toString().length > 100
 | 
			
		||||
                          ? "my-4"
 | 
			
		||||
                          : ""
 | 
			
		||||
                      }
 | 
			
		||||
                    >
 | 
			
		||||
                      {props.children}
 | 
			
		||||
                    </li>
 | 
			
		||||
                  );
 | 
			
		||||
                },
 | 
			
		||||
                component: (compProps: { children: React.ReactNode }) => (
 | 
			
		||||
                  <li
 | 
			
		||||
                    className={
 | 
			
		||||
                      compProps.children &&
 | 
			
		||||
                      ReactDOMServer.renderToStaticMarkup(
 | 
			
		||||
                        <>{compProps.children}</>
 | 
			
		||||
                      ).length > 100
 | 
			
		||||
                        ? "my-4"
 | 
			
		||||
                        : ""
 | 
			
		||||
                    }
 | 
			
		||||
                  >
 | 
			
		||||
                    {compProps.children}
 | 
			
		||||
                  </li>
 | 
			
		||||
                ),
 | 
			
		||||
              },
 | 
			
		||||
              Highlight: {
 | 
			
		||||
                component: (props: { children: React.ReactNode }) => {
 | 
			
		||||
                  return <mark>{props.children}</mark>;
 | 
			
		||||
                },
 | 
			
		||||
                component: (compProps: { children: React.ReactNode }) => (
 | 
			
		||||
                  <mark>{compProps.children}</mark>
 | 
			
		||||
                ),
 | 
			
		||||
              },
 | 
			
		||||
              footer: {
 | 
			
		||||
                component: (props: { children: React.ReactNode }) => {
 | 
			
		||||
                  return (
 | 
			
		||||
                    <>
 | 
			
		||||
                      <HorizontalLine />
 | 
			
		||||
                      <div>{props.children}</div>
 | 
			
		||||
                    </>
 | 
			
		||||
                  );
 | 
			
		||||
                },
 | 
			
		||||
                component: (compProps: { children: React.ReactNode }) => (
 | 
			
		||||
                  <>
 | 
			
		||||
                    <HorizontalLine />
 | 
			
		||||
                    <div>{compProps.children}</div>
 | 
			
		||||
                  </>
 | 
			
		||||
                ),
 | 
			
		||||
              },
 | 
			
		||||
              blockquote: {
 | 
			
		||||
                component: (props: {
 | 
			
		||||
                component: (compProps: {
 | 
			
		||||
                  children: React.ReactNode;
 | 
			
		||||
                  cite?: string;
 | 
			
		||||
                }) => {
 | 
			
		||||
                  return (
 | 
			
		||||
                    <blockquote>
 | 
			
		||||
                      {props.cite ? (
 | 
			
		||||
                        <>
 | 
			
		||||
                          “{props.children}”
 | 
			
		||||
                          <cite>— {props.cite}</cite>
 | 
			
		||||
                        </>
 | 
			
		||||
                      ) : (
 | 
			
		||||
                        props.children
 | 
			
		||||
                      )}
 | 
			
		||||
                    </blockquote>
 | 
			
		||||
                  );
 | 
			
		||||
                },
 | 
			
		||||
                }) => (
 | 
			
		||||
                  <blockquote>
 | 
			
		||||
                    {compProps.cite ? (
 | 
			
		||||
                      <>
 | 
			
		||||
                        “{compProps.children}”
 | 
			
		||||
                        <cite>— {compProps.cite}</cite>
 | 
			
		||||
                      </>
 | 
			
		||||
                    ) : (
 | 
			
		||||
                      compProps.children
 | 
			
		||||
                    )}
 | 
			
		||||
                  </blockquote>
 | 
			
		||||
                ),
 | 
			
		||||
              },
 | 
			
		||||
              img: {
 | 
			
		||||
                component: (props: {
 | 
			
		||||
                component: (compProps: {
 | 
			
		||||
                  alt: string;
 | 
			
		||||
                  src: string;
 | 
			
		||||
                  width?: number;
 | 
			
		||||
                  height?: number;
 | 
			
		||||
                  caption?: string;
 | 
			
		||||
                  name?: string;
 | 
			
		||||
                }) => {
 | 
			
		||||
                  return (
 | 
			
		||||
                    <div
 | 
			
		||||
                      className="my-8 cursor-pointer"
 | 
			
		||||
                      onClick={() => {
 | 
			
		||||
                        setLightboxOpen(true);
 | 
			
		||||
                        setLightboxImages([
 | 
			
		||||
                          props.src.startsWith("/uploads/")
 | 
			
		||||
                            ? getAssetURL(props.src, ImageQuality.Large)
 | 
			
		||||
                            : props.src,
 | 
			
		||||
                        ]);
 | 
			
		||||
                        setLightboxIndex(0);
 | 
			
		||||
                      }}
 | 
			
		||||
                    >
 | 
			
		||||
                      {props.src.startsWith("/uploads/") ? (
 | 
			
		||||
                        <div className="relative w-full aspect-video">
 | 
			
		||||
                          <Img
 | 
			
		||||
                            image={{
 | 
			
		||||
                              __typename: "UploadFile",
 | 
			
		||||
                              alternativeText: props.alt,
 | 
			
		||||
                              url: props.src,
 | 
			
		||||
                              width: props.width || 1500,
 | 
			
		||||
                              height: props.height || 1000,
 | 
			
		||||
                              caption: props.caption || "",
 | 
			
		||||
                              name: props.name || "",
 | 
			
		||||
                            }}
 | 
			
		||||
                            layout="fill"
 | 
			
		||||
                            objectFit="contain"
 | 
			
		||||
                            quality={ImageQuality.Medium}
 | 
			
		||||
                          ></Img>
 | 
			
		||||
                        </div>
 | 
			
		||||
                      ) : (
 | 
			
		||||
                        <div className="grid place-content-center">
 | 
			
		||||
                          <img {...props} className="max-h-[50vh] " />
 | 
			
		||||
                        </div>
 | 
			
		||||
                      )}
 | 
			
		||||
                    </div>
 | 
			
		||||
                  );
 | 
			
		||||
                },
 | 
			
		||||
                }) => (
 | 
			
		||||
                  <div
 | 
			
		||||
                    className="my-8 cursor-pointer"
 | 
			
		||||
                    onClick={() => {
 | 
			
		||||
                      setLightboxOpen(true);
 | 
			
		||||
                      setLightboxImages([
 | 
			
		||||
                        compProps.src.startsWith("/uploads/")
 | 
			
		||||
                          ? getAssetURL(compProps.src, ImageQuality.Large)
 | 
			
		||||
                          : compProps.src,
 | 
			
		||||
                      ]);
 | 
			
		||||
                      setLightboxIndex(0);
 | 
			
		||||
                    }}
 | 
			
		||||
                  >
 | 
			
		||||
                    {compProps.src.startsWith("/uploads/") ? (
 | 
			
		||||
                      <div className="relative w-full aspect-video">
 | 
			
		||||
                        <Img
 | 
			
		||||
                          image={{
 | 
			
		||||
                            __typename: "UploadFile",
 | 
			
		||||
                            alternativeText: compProps.alt,
 | 
			
		||||
                            url: compProps.src,
 | 
			
		||||
                            width: compProps.width ?? 1500,
 | 
			
		||||
                            height: compProps.height ?? 1000,
 | 
			
		||||
                            caption: compProps.caption ?? "",
 | 
			
		||||
                            name: compProps.name ?? "",
 | 
			
		||||
                          }}
 | 
			
		||||
                          layout="fill"
 | 
			
		||||
                          objectFit="contain"
 | 
			
		||||
                          quality={ImageQuality.Medium}
 | 
			
		||||
                        ></Img>
 | 
			
		||||
                      </div>
 | 
			
		||||
                    ) : (
 | 
			
		||||
                      <div className="grid place-content-center">
 | 
			
		||||
                        {/* eslint-disable-next-line jsx-a11y/alt-text */}
 | 
			
		||||
                        <img {...compProps} className="max-h-[50vh] " />
 | 
			
		||||
                      </div>
 | 
			
		||||
                    )}
 | 
			
		||||
                  </div>
 | 
			
		||||
                ),
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          }}
 | 
			
		||||
@ -323,10 +293,9 @@ function HeaderToolTip(props: { id: string }) {
 | 
			
		||||
          className="material-icons transition-color hover:text-dark cursor-pointer"
 | 
			
		||||
          onClick={() => {
 | 
			
		||||
            navigator.clipboard.writeText(
 | 
			
		||||
              process.env.NEXT_PUBLIC_URL_SELF +
 | 
			
		||||
                window.location.pathname +
 | 
			
		||||
                "#" +
 | 
			
		||||
              `${process.env.NEXT_PUBLIC_URL_SELF + window.location.pathname}#${
 | 
			
		||||
                props.id
 | 
			
		||||
              }`
 | 
			
		||||
            );
 | 
			
		||||
          }}
 | 
			
		||||
        >
 | 
			
		||||
@ -344,8 +313,8 @@ export function preprocessMarkDawn(text: string): string {
 | 
			
		||||
  const visitedSlugs: string[] = [];
 | 
			
		||||
 | 
			
		||||
  const result = text.split("\n").map((line) => {
 | 
			
		||||
    if (line === "* * *" || line === "---") {
 | 
			
		||||
      scenebreakIndex++;
 | 
			
		||||
    if (line === "* * *" ?? line === "---") {
 | 
			
		||||
      scenebreakIndex += 1;
 | 
			
		||||
      return `<SceneBreak id="scene-break-${scenebreakIndex}">`;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -393,16 +362,13 @@ function markdawnHeadersParser(
 | 
			
		||||
  visitedSlugs: string[]
 | 
			
		||||
): string {
 | 
			
		||||
  const lineText = line.slice(headerLevel + 1);
 | 
			
		||||
  let slug = slugify(lineText);
 | 
			
		||||
  const slug = slugify(lineText);
 | 
			
		||||
  let newSlug = slug;
 | 
			
		||||
  let index = 2;
 | 
			
		||||
  while (visitedSlugs.includes(newSlug)) {
 | 
			
		||||
    newSlug = `${slug}-${index}`;
 | 
			
		||||
    index++;
 | 
			
		||||
    index += 1;
 | 
			
		||||
  }
 | 
			
		||||
  visitedSlugs.push(newSlug);
 | 
			
		||||
  return `<${headerLevels[headerLevel]} id="${newSlug}">${lineText}</${headerLevels[headerLevel]}>`;
 | 
			
		||||
}
 | 
			
		||||
function getAssetUrl(): React.SetStateAction<string[]> {
 | 
			
		||||
  throw new Error("Function not implemented.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,7 @@ type TOCProps = {
 | 
			
		||||
  router: NextRouter;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default function TOC(props: TOCProps): JSX.Element {
 | 
			
		||||
export default function TOCComponent(props: TOCProps): JSX.Element {
 | 
			
		||||
  const { router, text, title } = props;
 | 
			
		||||
  const toc = getTocFromMarkdawn(preprocessMarkDawn(text), title);
 | 
			
		||||
 | 
			
		||||
@ -17,7 +17,7 @@ export default function TOC(props: TOCProps): JSX.Element {
 | 
			
		||||
      <h3 className="text-xl">Table of content</h3>
 | 
			
		||||
      <div className="text-left max-w-[14.5rem]">
 | 
			
		||||
        <p className="my-2 overflow-x-hidden relative text-ellipsis whitespace-nowrap text-left">
 | 
			
		||||
          <a className="" onClick={() => router.replace(`#${toc.slug}`)}>
 | 
			
		||||
          <a className="" onClick={async () => router.replace(`#${toc.slug}`)}>
 | 
			
		||||
            {<abbr title={toc.title}>{toc.title}</abbr>}
 | 
			
		||||
          </a>
 | 
			
		||||
        </p>
 | 
			
		||||
@ -50,7 +50,7 @@ function TOCLevel(props: TOCLevelProps): JSX.Element {
 | 
			
		||||
            <span className="text-dark">{`${parentNumbering}${
 | 
			
		||||
              childIndex + 1
 | 
			
		||||
            }.`}</span>{" "}
 | 
			
		||||
            <a onClick={() => router.replace(`#${child.slug}`)}>
 | 
			
		||||
            <a onClick={async () => router.replace(`#${child.slug}`)}>
 | 
			
		||||
              {<abbr title={child.title}>{child.title}</abbr>}
 | 
			
		||||
            </a>
 | 
			
		||||
          </li>
 | 
			
		||||
@ -72,8 +72,11 @@ export type TOC = {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function getTocFromMarkdawn(text: string, title?: string): TOC {
 | 
			
		||||
  if (!title) title = "Return to top";
 | 
			
		||||
  let toc: TOC = { title: title, slug: slugify(title) || "", children: [] };
 | 
			
		||||
  const toc: TOC = {
 | 
			
		||||
    title: title ?? "Return to top",
 | 
			
		||||
    slug: slugify(title) ?? "",
 | 
			
		||||
    children: [],
 | 
			
		||||
  };
 | 
			
		||||
  let h2 = -1;
 | 
			
		||||
  let h3 = -1;
 | 
			
		||||
  let h4 = -1;
 | 
			
		||||
@ -99,7 +102,7 @@ export function getTocFromMarkdawn(text: string, title?: string): TOC {
 | 
			
		||||
        slug: getSlug(line),
 | 
			
		||||
        children: [],
 | 
			
		||||
      });
 | 
			
		||||
      h2++;
 | 
			
		||||
      h2 += 1;
 | 
			
		||||
      h3 = -1;
 | 
			
		||||
      h4 = -1;
 | 
			
		||||
      h5 = -1;
 | 
			
		||||
@ -110,7 +113,7 @@ export function getTocFromMarkdawn(text: string, title?: string): TOC {
 | 
			
		||||
        slug: getSlug(line),
 | 
			
		||||
        children: [],
 | 
			
		||||
      });
 | 
			
		||||
      h3++;
 | 
			
		||||
      h3 += 1;
 | 
			
		||||
      h4 = -1;
 | 
			
		||||
      h5 = -1;
 | 
			
		||||
      scenebreak = 0;
 | 
			
		||||
@ -120,7 +123,7 @@ export function getTocFromMarkdawn(text: string, title?: string): TOC {
 | 
			
		||||
        slug: getSlug(line),
 | 
			
		||||
        children: [],
 | 
			
		||||
      });
 | 
			
		||||
      h4++;
 | 
			
		||||
      h4 += 1;
 | 
			
		||||
      h5 = -1;
 | 
			
		||||
      scenebreak = 0;
 | 
			
		||||
    } else if (line.startsWith("<h5 id=")) {
 | 
			
		||||
@ -129,7 +132,7 @@ export function getTocFromMarkdawn(text: string, title?: string): TOC {
 | 
			
		||||
        slug: getSlug(line),
 | 
			
		||||
        children: [],
 | 
			
		||||
      });
 | 
			
		||||
      h5++;
 | 
			
		||||
      h5 += 1;
 | 
			
		||||
      scenebreak = 0;
 | 
			
		||||
    } else if (line.startsWith("<h6 id=")) {
 | 
			
		||||
      toc.children[h2].children[h3].children[h4].children[h5].children.push({
 | 
			
		||||
@ -138,8 +141,8 @@ export function getTocFromMarkdawn(text: string, title?: string): TOC {
 | 
			
		||||
        children: [],
 | 
			
		||||
      });
 | 
			
		||||
    } else if (line.startsWith(`<SceneBreak`)) {
 | 
			
		||||
      scenebreak++;
 | 
			
		||||
      scenebreakIndex++;
 | 
			
		||||
      scenebreak += 1;
 | 
			
		||||
      scenebreakIndex += 1;
 | 
			
		||||
 | 
			
		||||
      const child = {
 | 
			
		||||
        title: `Scene break ${scenebreak}`,
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
import Link from "next/link";
 | 
			
		||||
import { prettyDate, prettySlug } from "queries/helpers";
 | 
			
		||||
import Chip from "components/Chip";
 | 
			
		||||
import Img, { ImageQuality } from "components/Img";
 | 
			
		||||
import { GetPostsPreviewQuery } from "graphql/operations-types";
 | 
			
		||||
import Link from "next/link";
 | 
			
		||||
import { prettyDate, prettySlug } from "queries/helpers";
 | 
			
		||||
 | 
			
		||||
export type PostPreviewProps = {
 | 
			
		||||
  post: {
 | 
			
		||||
@ -15,10 +15,10 @@ export type PostPreviewProps = {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default function PostPreview(props: PostPreviewProps): JSX.Element {
 | 
			
		||||
  const post = props.post;
 | 
			
		||||
  const { post } = props;
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Link href={"/news/" + post.slug} passHref>
 | 
			
		||||
    <Link href={`/news/${post.slug}`} passHref>
 | 
			
		||||
      <div className="drop-shadow-shade-xl cursor-pointer grid items-end hover:scale-[1.02] transition-transform">
 | 
			
		||||
        {post.thumbnail.data ? (
 | 
			
		||||
          <Img
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
import { useRouter } from "next/router";
 | 
			
		||||
import Link from "next/link";
 | 
			
		||||
import { MouseEventHandler } from "react";
 | 
			
		||||
import ToolTip from "components/ToolTip";
 | 
			
		||||
import Link from "next/link";
 | 
			
		||||
import { useRouter } from "next/router";
 | 
			
		||||
import { MouseEventHandler } from "react";
 | 
			
		||||
 | 
			
		||||
type NavOptionProps = {
 | 
			
		||||
  url: string;
 | 
			
		||||
 | 
			
		||||
@ -13,9 +13,9 @@ type ReturnButtonProps = {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export enum ReturnButtonType {
 | 
			
		||||
  Mobile,
 | 
			
		||||
  Desktop,
 | 
			
		||||
  Both,
 | 
			
		||||
  mobile = "mobile",
 | 
			
		||||
  desktop = "desktop",
 | 
			
		||||
  both = "both",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default function ReturnButton(props: ReturnButtonProps): JSX.Element {
 | 
			
		||||
@ -24,9 +24,9 @@ export default function ReturnButton(props: ReturnButtonProps): JSX.Element {
 | 
			
		||||
  return (
 | 
			
		||||
    <div
 | 
			
		||||
      className={`${
 | 
			
		||||
        props.displayOn === ReturnButtonType.Mobile
 | 
			
		||||
        props.displayOn === ReturnButtonType.mobile
 | 
			
		||||
          ? "desktop:hidden"
 | 
			
		||||
          : props.displayOn === ReturnButtonType.Desktop
 | 
			
		||||
          : props.displayOn === ReturnButtonType.desktop
 | 
			
		||||
          ? "mobile:hidden"
 | 
			
		||||
          : ""
 | 
			
		||||
      } ${props.className}`}
 | 
			
		||||
 | 
			
		||||
@ -5,8 +5,8 @@ type ContentPanelProps = {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export enum ContentPanelWidthSizes {
 | 
			
		||||
  default,
 | 
			
		||||
  large,
 | 
			
		||||
  default = "default",
 | 
			
		||||
  large = "large",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default function ContentPanel(props: ContentPanelProps): JSX.Element {
 | 
			
		||||
 | 
			
		||||
@ -1,20 +1,20 @@
 | 
			
		||||
import Link from "next/link";
 | 
			
		||||
import NavOption from "components/PanelComponents/NavOption";
 | 
			
		||||
import { useRouter } from "next/router";
 | 
			
		||||
import Button from "components/Button";
 | 
			
		||||
import HorizontalLine from "components/HorizontalLine";
 | 
			
		||||
import { GetWebsiteInterfaceQuery } from "graphql/operations-types";
 | 
			
		||||
import Markdown from "markdown-to-jsx";
 | 
			
		||||
import { useMediaDesktop } from "hooks/useMediaQuery";
 | 
			
		||||
import { useAppLayout } from "contexts/AppLayoutContext";
 | 
			
		||||
import NavOption from "components/PanelComponents/NavOption";
 | 
			
		||||
import ToolTip from "components/ToolTip";
 | 
			
		||||
import { useAppLayout } from "contexts/AppLayoutContext";
 | 
			
		||||
import { GetWebsiteInterfaceQuery } from "graphql/operations-types";
 | 
			
		||||
import { useMediaDesktop } from "hooks/useMediaQuery";
 | 
			
		||||
import Markdown from "markdown-to-jsx";
 | 
			
		||||
import Link from "next/link";
 | 
			
		||||
import { useRouter } from "next/router";
 | 
			
		||||
 | 
			
		||||
type MainPanelProps = {
 | 
			
		||||
  langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default function MainPanel(props: MainPanelProps): JSX.Element {
 | 
			
		||||
  const langui = props.langui;
 | 
			
		||||
  const { langui } = props;
 | 
			
		||||
  const router = useRouter();
 | 
			
		||||
  const isDesktop = useMediaDesktop();
 | 
			
		||||
  const appLayout = useAppLayout();
 | 
			
		||||
 | 
			
		||||
@ -3,8 +3,8 @@ import Button from "./Button";
 | 
			
		||||
 | 
			
		||||
export type PopupProps = {
 | 
			
		||||
  setState:
 | 
			
		||||
    | Dispatch<SetStateAction<boolean>>
 | 
			
		||||
    | Dispatch<SetStateAction<boolean | undefined>>;
 | 
			
		||||
    | Dispatch<SetStateAction<boolean | undefined>>
 | 
			
		||||
    | Dispatch<SetStateAction<boolean>>;
 | 
			
		||||
  state?: boolean;
 | 
			
		||||
  children: React.ReactNode;
 | 
			
		||||
  fillViewport?: boolean;
 | 
			
		||||
@ -19,8 +19,8 @@ export default function Popup(props: PopupProps): JSX.Element {
 | 
			
		||||
          ? "[backdrop-filter:blur(2px)]"
 | 
			
		||||
          : "pointer-events-none touch-none"
 | 
			
		||||
      }`}
 | 
			
		||||
      onKeyUp={(e) => {
 | 
			
		||||
        if (e.key.match("Escape")) props.setState(false);
 | 
			
		||||
      onKeyUp={(event) => {
 | 
			
		||||
        if (event.key.match("Escape")) props.setState(false);
 | 
			
		||||
      }}
 | 
			
		||||
      tabIndex={0}
 | 
			
		||||
    >
 | 
			
		||||
 | 
			
		||||
@ -14,8 +14,7 @@ type RecorderChipProps = {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default function RecorderChip(props: RecorderChipProps): JSX.Element {
 | 
			
		||||
  const recorder = props.recorder;
 | 
			
		||||
  const langui = props.langui;
 | 
			
		||||
  const { recorder, langui } = props;
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <ToolTip
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,6 @@ export type SelectProps = {
 | 
			
		||||
  selected?: number;
 | 
			
		||||
  allowEmpty?: boolean;
 | 
			
		||||
  className?: string;
 | 
			
		||||
  onChange?: Function;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default function Select(props: SelectProps): JSX.Element {
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@ import "tippy.js/animations/scale-subtle.css";
 | 
			
		||||
interface ToolTipProps extends TippyProps {}
 | 
			
		||||
 | 
			
		||||
export default function ToolTip(props: ToolTipProps): JSX.Element {
 | 
			
		||||
  let newProps = { ...props };
 | 
			
		||||
  const newProps = { ...props };
 | 
			
		||||
 | 
			
		||||
  // Set defaults
 | 
			
		||||
  if (newProps.delay === undefined) newProps.delay = [150, 0];
 | 
			
		||||
 | 
			
		||||
@ -33,6 +33,7 @@ export interface AppLayoutState {
 | 
			
		||||
  setPlayerName: React.Dispatch<React.SetStateAction<string | undefined>>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* eslint-disable @typescript-eslint/no-empty-function */
 | 
			
		||||
const initialState: AppLayoutState = {
 | 
			
		||||
  subPanelOpen: false,
 | 
			
		||||
  languagePanelOpen: false,
 | 
			
		||||
@ -57,12 +58,13 @@ const initialState: AppLayoutState = {
 | 
			
		||||
  setCurrency: () => {},
 | 
			
		||||
  setPlayerName: () => {},
 | 
			
		||||
};
 | 
			
		||||
/* eslint-enable @typescript-eslint/no-empty-function */
 | 
			
		||||
 | 
			
		||||
const AppContext = React.createContext<AppLayoutState>(initialState);
 | 
			
		||||
 | 
			
		||||
export default AppContext;
 | 
			
		||||
 | 
			
		||||
export function useAppLayout() {
 | 
			
		||||
export function useAppLayout(): AppLayoutState {
 | 
			
		||||
  return useContext(AppContext);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -70,7 +72,7 @@ type Props = {
 | 
			
		||||
  children: ReactNode;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const AppContextProvider = (props: Props) => {
 | 
			
		||||
export function AppContextProvider(props: Props): JSX.Element {
 | 
			
		||||
  const [subPanelOpen, setSubPanelOpen] = useStateWithLocalStorage<
 | 
			
		||||
    boolean | undefined
 | 
			
		||||
  >("subPanelOpen", initialState.subPanelOpen);
 | 
			
		||||
@ -143,4 +145,4 @@ export const AppContextProvider = (props: Props) => {
 | 
			
		||||
      {props.children}
 | 
			
		||||
    </AppContext.Provider>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,7 @@
 | 
			
		||||
/* eslint-disable @typescript-eslint/consistent-indexed-object-style */
 | 
			
		||||
/* eslint-disable @typescript-eslint/array-type */
 | 
			
		||||
/* eslint-disable no-shadow */
 | 
			
		||||
/* eslint-disable id-denylist */
 | 
			
		||||
export type Exact<T> = T;
 | 
			
		||||
export type InputMaybe<T> = T;
 | 
			
		||||
export type Scalars = {
 | 
			
		||||
@ -6,30 +10,31 @@ export type Scalars = {
 | 
			
		||||
  Boolean: boolean;
 | 
			
		||||
  Int: number;
 | 
			
		||||
  Float: number;
 | 
			
		||||
  JSON: any;
 | 
			
		||||
  DateTime: any;
 | 
			
		||||
  Time: any;
 | 
			
		||||
  Upload: any;
 | 
			
		||||
  LibraryContentRangeDynamicZoneInput: any;
 | 
			
		||||
  LibraryItemMetadataDynamicZoneInput: any;
 | 
			
		||||
  SourceSourceDynamicZoneInput: any;
 | 
			
		||||
  JSON: unknown;
 | 
			
		||||
  DateTime: unknown;
 | 
			
		||||
  Time: unknown;
 | 
			
		||||
  Upload: unknown;
 | 
			
		||||
  LibraryContentRangeDynamicZoneInput: unknown;
 | 
			
		||||
  LibraryItemMetadataDynamicZoneInput: unknown;
 | 
			
		||||
  SourceSourceDynamicZoneInput: unknown;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  The following is generated using https://www.graphql-code-generator.com/
 | 
			
		||||
  With the following codegen.yml:
 | 
			
		||||
 | 
			
		||||
  generates:
 | 
			
		||||
  operations-types.ts:
 | 
			
		||||
    plugins:
 | 
			
		||||
      - typescript-operations
 | 
			
		||||
 | 
			
		||||
  And the schema.graphql and operation.graphql files from this folder.
 | 
			
		||||
  
 | 
			
		||||
  But to make the type easier to work with, it went through the following transformation:
 | 
			
		||||
    - Removed ?
 | 
			
		||||
    - Removed | null
 | 
			
		||||
*/
 | 
			
		||||
 * The following is generated using https://www.graphql-code-generator.com/
 | 
			
		||||
 * With the following codegen.yml:
 | 
			
		||||
 *
 | 
			
		||||
 * generates:
 | 
			
		||||
 * operations-types.ts:
 | 
			
		||||
 *   plugins:
 | 
			
		||||
 *     - typescript-operations
 | 
			
		||||
 *
 | 
			
		||||
 * And the schema.graphql and operation.graphql files from this folder.
 | 
			
		||||
 *
 | 
			
		||||
 * But to make the type easier to work with, it went through the following transformation:
 | 
			
		||||
 *   - Removed ?
 | 
			
		||||
 *   - Removed | null
 | 
			
		||||
 *   - Replaced any by unknown
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
export enum Enum_Componentmetadatabooks_Binding_Type {
 | 
			
		||||
  Paperback = "Paperback",
 | 
			
		||||
@ -939,8 +944,8 @@ export type GetLibraryItemQuery = {
 | 
			
		||||
                  }
 | 
			
		||||
                | {
 | 
			
		||||
                    __typename: "ComponentRangeTimeRange";
 | 
			
		||||
                    starting_time: any;
 | 
			
		||||
                    ending_time: any;
 | 
			
		||||
                    starting_time: unknown;
 | 
			
		||||
                    ending_time: unknown;
 | 
			
		||||
                  }
 | 
			
		||||
                | { __typename: "ComponentRangeOther" }
 | 
			
		||||
                | { __typename: "Error" }
 | 
			
		||||
@ -1571,7 +1576,7 @@ export type GetPostQuery = {
 | 
			
		||||
      attributes: {
 | 
			
		||||
        __typename: "Post";
 | 
			
		||||
        slug: string;
 | 
			
		||||
        updatedAt: any;
 | 
			
		||||
        updatedAt: unknown;
 | 
			
		||||
        date: {
 | 
			
		||||
          __typename: "ComponentBasicsDatepicker";
 | 
			
		||||
          year: number;
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,4 @@
 | 
			
		||||
import { readFileSync } from "fs";
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
  GetChronologyItemsQuery,
 | 
			
		||||
  GetChronologyItemsQueryVariables,
 | 
			
		||||
@ -37,7 +36,7 @@ import {
 | 
			
		||||
  GetWebsiteInterfaceQueryVariables,
 | 
			
		||||
} from "graphql/operations-types";
 | 
			
		||||
 | 
			
		||||
const graphQL = async (query: string, variables?: string) => {
 | 
			
		||||
async function graphQL(query: string, variables?: string) {
 | 
			
		||||
  const res = await fetch(`${process.env.URL_GRAPHQL}`, {
 | 
			
		||||
    method: "POST",
 | 
			
		||||
    body: JSON.stringify({
 | 
			
		||||
@ -46,11 +45,11 @@ const graphQL = async (query: string, variables?: string) => {
 | 
			
		||||
    }),
 | 
			
		||||
    headers: {
 | 
			
		||||
      "content-type": "application/json",
 | 
			
		||||
      Authorization: "Bearer " + process.env.ACCESS_TOKEN,
 | 
			
		||||
      Authorization: `Bearer ${process.env.ACCESS_TOKEN}`,
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
  return (await res.json()).data;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getQueryFromOperations(queryName: string): string {
 | 
			
		||||
  const operations = readFileSync("./src/graphql/operation.graphql", "utf8");
 | 
			
		||||
 | 
			
		||||
@ -1,13 +1,13 @@
 | 
			
		||||
import { useEffect, useState } from "react";
 | 
			
		||||
 | 
			
		||||
export default function useMediaQuery(query: string): boolean {
 | 
			
		||||
  const getMatches = (query: string): boolean => {
 | 
			
		||||
  function getMatches(query: string): boolean {
 | 
			
		||||
    // Prevents SSR issues
 | 
			
		||||
    if (typeof window !== "undefined") {
 | 
			
		||||
      return window.matchMedia(query).matches;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const [matches, setMatches] = useState<boolean>(getMatches(query));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,9 @@
 | 
			
		||||
import ContentPanel from "components/Panels/ContentPanel";
 | 
			
		||||
import { GetStaticProps } from "next";
 | 
			
		||||
import AppLayout from "components/AppLayout";
 | 
			
		||||
import ReturnButton, {
 | 
			
		||||
  ReturnButtonType,
 | 
			
		||||
} from "components/PanelComponents/ReturnButton";
 | 
			
		||||
import ContentPanel from "components/Panels/ContentPanel";
 | 
			
		||||
import { GetStaticPropsContext } from "next";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
 | 
			
		||||
interface FourOhFourProps extends AppStaticProps {}
 | 
			
		||||
@ -17,18 +17,20 @@ export default function FourOhFour(props: FourOhFourProps): JSX.Element {
 | 
			
		||||
        href="/"
 | 
			
		||||
        title="Home"
 | 
			
		||||
        langui={langui}
 | 
			
		||||
        displayOn={ReturnButtonType.Both}
 | 
			
		||||
        displayOn={ReturnButtonType.both}
 | 
			
		||||
      />
 | 
			
		||||
    </ContentPanel>
 | 
			
		||||
  );
 | 
			
		||||
  return <AppLayout navTitle="404" contentPanel={contentPanel} {...props} />;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
export async function getStaticProps(
 | 
			
		||||
  context: GetStaticPropsContext
 | 
			
		||||
): Promise<{ props: FourOhFourProps }> {
 | 
			
		||||
  const props: FourOhFourProps = {
 | 
			
		||||
    ...(await getAppStaticProps(context)),
 | 
			
		||||
  };
 | 
			
		||||
  return {
 | 
			
		||||
    props: props,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,15 +1,14 @@
 | 
			
		||||
import type { AppProps } from "next/app";
 | 
			
		||||
import "tailwind.css";
 | 
			
		||||
import "@fontsource/zen-maru-gothic/500.css";
 | 
			
		||||
import "@fontsource/zen-maru-gothic/900.css";
 | 
			
		||||
import "@fontsource/vollkorn/700.css";
 | 
			
		||||
import "@fontsource/material-icons";
 | 
			
		||||
import "@fontsource/opendyslexic/400.css";
 | 
			
		||||
import "@fontsource/opendyslexic/700.css";
 | 
			
		||||
import "@fontsource/material-icons";
 | 
			
		||||
 | 
			
		||||
import "@fontsource/vollkorn/700.css";
 | 
			
		||||
import "@fontsource/zen-maru-gothic/500.css";
 | 
			
		||||
import "@fontsource/zen-maru-gothic/900.css";
 | 
			
		||||
import { AppContextProvider } from "contexts/AppLayoutContext";
 | 
			
		||||
import type { AppProps } from "next/app";
 | 
			
		||||
import "tailwind.css";
 | 
			
		||||
 | 
			
		||||
export default function AccordsLibraryApp(props: AppProps) {
 | 
			
		||||
export default function AccordsLibraryApp(props: AppProps): JSX.Element {
 | 
			
		||||
  return (
 | 
			
		||||
    <AppContextProvider>
 | 
			
		||||
      <props.Component {...props.pageProps} />
 | 
			
		||||
 | 
			
		||||
@ -1,18 +1,19 @@
 | 
			
		||||
import Document, {
 | 
			
		||||
  Html,
 | 
			
		||||
  DocumentContext,
 | 
			
		||||
  Head,
 | 
			
		||||
  Html,
 | 
			
		||||
  Main,
 | 
			
		||||
  NextScript,
 | 
			
		||||
  DocumentContext,
 | 
			
		||||
} from "next/document";
 | 
			
		||||
 | 
			
		||||
class MyDocument extends Document {
 | 
			
		||||
  // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
 | 
			
		||||
  static async getInitialProps(ctx: DocumentContext) {
 | 
			
		||||
    const initialProps = await Document.getInitialProps(ctx);
 | 
			
		||||
    return { ...initialProps };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  render() {
 | 
			
		||||
  render(): JSX.Element {
 | 
			
		||||
    return (
 | 
			
		||||
      <Html>
 | 
			
		||||
        <Head>
 | 
			
		||||
 | 
			
		||||
@ -9,7 +9,7 @@ import ContentPanel from "components/Panels/ContentPanel";
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import { getPost, getPostLanguages } from "graphql/operations";
 | 
			
		||||
import { GetPostQuery } from "graphql/operations-types";
 | 
			
		||||
import { GetStaticProps } from "next";
 | 
			
		||||
import { GetStaticPropsContext } from "next";
 | 
			
		||||
import { useRouter } from "next/router";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
import { prettySlug } from "queries/helpers";
 | 
			
		||||
@ -29,7 +29,7 @@ export default function AccordsHandbook(
 | 
			
		||||
    <SubPanel>
 | 
			
		||||
      <ReturnButton
 | 
			
		||||
        href="/about-us"
 | 
			
		||||
        displayOn={ReturnButtonType.Desktop}
 | 
			
		||||
        displayOn={ReturnButtonType.desktop}
 | 
			
		||||
        langui={langui}
 | 
			
		||||
        title={langui.about_us}
 | 
			
		||||
        horizontalLine
 | 
			
		||||
@ -48,12 +48,12 @@ export default function AccordsHandbook(
 | 
			
		||||
    <ContentPanel>
 | 
			
		||||
      <ReturnButton
 | 
			
		||||
        href="/about-us"
 | 
			
		||||
        displayOn={ReturnButtonType.Mobile}
 | 
			
		||||
        displayOn={ReturnButtonType.mobile}
 | 
			
		||||
        langui={langui}
 | 
			
		||||
        title={langui.about_us}
 | 
			
		||||
        className="mb-10"
 | 
			
		||||
      />
 | 
			
		||||
      {locales.includes(router.locale || "en") ? (
 | 
			
		||||
      {locales.includes(router.locale ?? "en") ? (
 | 
			
		||||
        <Markdawn router={router} text={post.translations[0].body} />
 | 
			
		||||
      ) : (
 | 
			
		||||
        <LanguageSwitcher
 | 
			
		||||
@ -80,23 +80,25 @@ export default function AccordsHandbook(
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
export async function getStaticProps(
 | 
			
		||||
  context: GetStaticPropsContext
 | 
			
		||||
): Promise<{ props: AccordsHandbookProps }> {
 | 
			
		||||
  const slug = "accords-handbook";
 | 
			
		||||
  const props: AccordsHandbookProps = {
 | 
			
		||||
    ...(await getAppStaticProps(context)),
 | 
			
		||||
    post: (
 | 
			
		||||
      await getPost({
 | 
			
		||||
        slug: slug,
 | 
			
		||||
        language_code: context.locale || "en",
 | 
			
		||||
        language_code: context.locale ?? "en",
 | 
			
		||||
      })
 | 
			
		||||
    ).posts.data[0].attributes,
 | 
			
		||||
    locales: (
 | 
			
		||||
      await getPostLanguages({ slug: slug })
 | 
			
		||||
    ).posts.data[0].attributes.translations.map((translation) => {
 | 
			
		||||
      return translation.language.data.attributes.code;
 | 
			
		||||
    }),
 | 
			
		||||
    ).posts.data[0].attributes.translations.map(
 | 
			
		||||
      (translation) => translation.language.data.attributes.code
 | 
			
		||||
    ),
 | 
			
		||||
  };
 | 
			
		||||
  return {
 | 
			
		||||
    props: props,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,21 +1,21 @@
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
import AppLayout from "components/AppLayout";
 | 
			
		||||
import InsetBox from "components/InsetBox";
 | 
			
		||||
import LanguageSwitcher from "components/LanguageSwitcher";
 | 
			
		||||
import Markdawn from "components/Markdown/Markdawn";
 | 
			
		||||
import TOC from "components/Markdown/TOC";
 | 
			
		||||
import ReturnButton, {
 | 
			
		||||
  ReturnButtonType,
 | 
			
		||||
} from "components/PanelComponents/ReturnButton";
 | 
			
		||||
import AppLayout from "components/AppLayout";
 | 
			
		||||
import ContentPanel from "components/Panels/ContentPanel";
 | 
			
		||||
import { GetStaticProps } from "next";
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import { getPost, getPostLanguages } from "graphql/operations";
 | 
			
		||||
import { GetPostQuery } from "graphql/operations-types";
 | 
			
		||||
import { GetStaticPropsContext } from "next";
 | 
			
		||||
import { useRouter } from "next/router";
 | 
			
		||||
import LanguageSwitcher from "components/LanguageSwitcher";
 | 
			
		||||
import Markdawn from "components/Markdown/Markdawn";
 | 
			
		||||
import { RequestMailProps, ResponseMailProps } from "pages/api/mail";
 | 
			
		||||
import { useState } from "react";
 | 
			
		||||
import InsetBox from "components/InsetBox";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
import { randomInt } from "queries/helpers";
 | 
			
		||||
import TOC from "components/Markdown/TOC";
 | 
			
		||||
import { useState } from "react";
 | 
			
		||||
 | 
			
		||||
interface ContactProps extends AppStaticProps {
 | 
			
		||||
  post: GetPostQuery["posts"]["data"][number]["attributes"];
 | 
			
		||||
@ -26,18 +26,18 @@ export default function AboutUs(props: ContactProps): JSX.Element {
 | 
			
		||||
  const { langui, post, locales } = props;
 | 
			
		||||
  const router = useRouter();
 | 
			
		||||
  const [formResponse, setFormResponse] = useState("");
 | 
			
		||||
  const [formState, setFormState] = useState<"stale" | "ongoing" | "completed">(
 | 
			
		||||
  const [formState, setFormState] = useState<"completed" | "ongoing" | "stale">(
 | 
			
		||||
    "stale"
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  const random1 = randomInt(0, 10);
 | 
			
		||||
  const random2 = randomInt(0, 10);
 | 
			
		||||
  const [randomNumber1, setRandomNumber1] = useState(randomInt(0, 10));
 | 
			
		||||
  const [randomNumber2, setRandomNumber2] = useState(randomInt(0, 10));
 | 
			
		||||
 | 
			
		||||
  const subPanel = (
 | 
			
		||||
    <SubPanel>
 | 
			
		||||
      <ReturnButton
 | 
			
		||||
        href="/about-us"
 | 
			
		||||
        displayOn={ReturnButtonType.Desktop}
 | 
			
		||||
        displayOn={ReturnButtonType.desktop}
 | 
			
		||||
        langui={langui}
 | 
			
		||||
        title={langui.about_us}
 | 
			
		||||
        horizontalLine
 | 
			
		||||
@ -56,12 +56,12 @@ export default function AboutUs(props: ContactProps): JSX.Element {
 | 
			
		||||
    <ContentPanel>
 | 
			
		||||
      <ReturnButton
 | 
			
		||||
        href="/about-us"
 | 
			
		||||
        displayOn={ReturnButtonType.Mobile}
 | 
			
		||||
        displayOn={ReturnButtonType.mobile}
 | 
			
		||||
        langui={langui}
 | 
			
		||||
        title={langui.about_us}
 | 
			
		||||
        className="mb-10"
 | 
			
		||||
      />
 | 
			
		||||
      {locales.includes(router.locale || "en") ? (
 | 
			
		||||
      {locales.includes(router.locale ?? "en") ? (
 | 
			
		||||
        <Markdawn router={router} text={post.translations[0].body} />
 | 
			
		||||
      ) : (
 | 
			
		||||
        <LanguageSwitcher
 | 
			
		||||
@ -78,10 +78,10 @@ export default function AboutUs(props: ContactProps): JSX.Element {
 | 
			
		||||
            formState !== "stale" &&
 | 
			
		||||
            "opacity-60 cursor-not-allowed touch-none pointer-events-none"
 | 
			
		||||
          }`}
 | 
			
		||||
          onSubmit={(e) => {
 | 
			
		||||
            e.preventDefault();
 | 
			
		||||
          onSubmit={(event) => {
 | 
			
		||||
            event.preventDefault();
 | 
			
		||||
 | 
			
		||||
            const fields = e.target as unknown as {
 | 
			
		||||
            const fields = event.target as unknown as {
 | 
			
		||||
              verif: HTMLInputElement;
 | 
			
		||||
              name: HTMLInputElement;
 | 
			
		||||
              email: HTMLInputElement;
 | 
			
		||||
@ -91,7 +91,8 @@ export default function AboutUs(props: ContactProps): JSX.Element {
 | 
			
		||||
            setFormState("ongoing");
 | 
			
		||||
 | 
			
		||||
            if (
 | 
			
		||||
              parseInt(fields.verif.value) == random1 + random2 &&
 | 
			
		||||
              parseInt(fields.verif.value, 10) ===
 | 
			
		||||
                randomNumber1 + randomNumber2 &&
 | 
			
		||||
              formState !== "completed"
 | 
			
		||||
            ) {
 | 
			
		||||
              const content: RequestMailProps = {
 | 
			
		||||
@ -107,9 +108,9 @@ export default function AboutUs(props: ContactProps): JSX.Element {
 | 
			
		||||
                  "Content-type": "application/json; charset=UTF-8",
 | 
			
		||||
                },
 | 
			
		||||
              })
 | 
			
		||||
                .then((response) => response.json())
 | 
			
		||||
                .then((data: ResponseMailProps) => {
 | 
			
		||||
                  switch (data.code) {
 | 
			
		||||
                .then(async (responseJson) => responseJson.json())
 | 
			
		||||
                .then((response: ResponseMailProps) => {
 | 
			
		||||
                  switch (response.code) {
 | 
			
		||||
                    case "OKAY":
 | 
			
		||||
                      setFormResponse(langui.response_email_success);
 | 
			
		||||
                      setFormState("completed");
 | 
			
		||||
@ -122,7 +123,7 @@ export default function AboutUs(props: ContactProps): JSX.Element {
 | 
			
		||||
                      break;
 | 
			
		||||
 | 
			
		||||
                    default:
 | 
			
		||||
                      setFormResponse(data.message || "");
 | 
			
		||||
                      setFormResponse(response.message ?? "");
 | 
			
		||||
                      setFormState("stale");
 | 
			
		||||
                      break;
 | 
			
		||||
                  }
 | 
			
		||||
@ -130,6 +131,8 @@ export default function AboutUs(props: ContactProps): JSX.Element {
 | 
			
		||||
            } else {
 | 
			
		||||
              setFormResponse(langui.response_invalid_code);
 | 
			
		||||
              setFormState("stale");
 | 
			
		||||
              setRandomNumber1(randomInt(0, 10));
 | 
			
		||||
              setRandomNumber2(randomInt(0, 10));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            router.replace("#send-response");
 | 
			
		||||
@ -180,7 +183,7 @@ export default function AboutUs(props: ContactProps): JSX.Element {
 | 
			
		||||
              <label
 | 
			
		||||
                className="flex-shrink-0"
 | 
			
		||||
                htmlFor="verif"
 | 
			
		||||
              >{`${random1} + ${random2} =`}</label>
 | 
			
		||||
              >{`${randomNumber1} + ${randomNumber2} =`}</label>
 | 
			
		||||
              <input
 | 
			
		||||
                className="w-24"
 | 
			
		||||
                type="number"
 | 
			
		||||
@ -221,23 +224,25 @@ export default function AboutUs(props: ContactProps): JSX.Element {
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
export async function getStaticProps(
 | 
			
		||||
  context: GetStaticPropsContext
 | 
			
		||||
): Promise<{ props: ContactProps }> {
 | 
			
		||||
  const slug = "contact";
 | 
			
		||||
  const props: ContactProps = {
 | 
			
		||||
    ...(await getAppStaticProps(context)),
 | 
			
		||||
    post: (
 | 
			
		||||
      await getPost({
 | 
			
		||||
        slug: slug,
 | 
			
		||||
        language_code: context.locale || "en",
 | 
			
		||||
        language_code: context.locale ?? "en",
 | 
			
		||||
      })
 | 
			
		||||
    ).posts.data[0].attributes,
 | 
			
		||||
    locales: (
 | 
			
		||||
      await getPostLanguages({ slug: slug })
 | 
			
		||||
    ).posts.data[0].attributes.translations.map((translation) => {
 | 
			
		||||
      return translation.language.data.attributes.code;
 | 
			
		||||
    }),
 | 
			
		||||
    ).posts.data[0].attributes.translations.map(
 | 
			
		||||
      (translation) => translation.language.data.attributes.code
 | 
			
		||||
    ),
 | 
			
		||||
  };
 | 
			
		||||
  return {
 | 
			
		||||
    props: props,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,9 @@
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import PanelHeader from "components/PanelComponents/PanelHeader";
 | 
			
		||||
import { GetStaticProps } from "next";
 | 
			
		||||
import AppLayout from "components/AppLayout";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
import NavOption from "components/PanelComponents/NavOption";
 | 
			
		||||
import PanelHeader from "components/PanelComponents/PanelHeader";
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import { GetStaticPropsContext } from "next";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
 | 
			
		||||
interface AboutUsProps extends AppStaticProps {}
 | 
			
		||||
 | 
			
		||||
@ -36,11 +36,13 @@ export default function AboutUs(props: AboutUsProps): JSX.Element {
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
export async function getStaticProps(
 | 
			
		||||
  context: GetStaticPropsContext
 | 
			
		||||
): Promise<{ props: AboutUsProps }> {
 | 
			
		||||
  const props: AboutUsProps = {
 | 
			
		||||
    ...(await getAppStaticProps(context)),
 | 
			
		||||
  };
 | 
			
		||||
  return {
 | 
			
		||||
    props: props,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -9,7 +9,7 @@ import ContentPanel from "components/Panels/ContentPanel";
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import { getPost, getPostLanguages } from "graphql/operations";
 | 
			
		||||
import { GetPostQuery } from "graphql/operations-types";
 | 
			
		||||
import { GetStaticProps } from "next";
 | 
			
		||||
import { GetStaticPropsContext } from "next";
 | 
			
		||||
import { useRouter } from "next/router";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
import { prettySlug } from "queries/helpers";
 | 
			
		||||
@ -27,7 +27,7 @@ export default function SiteInformation(props: SiteInfoProps): JSX.Element {
 | 
			
		||||
    <SubPanel>
 | 
			
		||||
      <ReturnButton
 | 
			
		||||
        href="/about-us"
 | 
			
		||||
        displayOn={ReturnButtonType.Desktop}
 | 
			
		||||
        displayOn={ReturnButtonType.desktop}
 | 
			
		||||
        langui={langui}
 | 
			
		||||
        title={langui.about_us}
 | 
			
		||||
        horizontalLine
 | 
			
		||||
@ -46,12 +46,12 @@ export default function SiteInformation(props: SiteInfoProps): JSX.Element {
 | 
			
		||||
    <ContentPanel>
 | 
			
		||||
      <ReturnButton
 | 
			
		||||
        href="/about-us"
 | 
			
		||||
        displayOn={ReturnButtonType.Mobile}
 | 
			
		||||
        displayOn={ReturnButtonType.mobile}
 | 
			
		||||
        langui={langui}
 | 
			
		||||
        title={langui.about_us}
 | 
			
		||||
        className="mb-10"
 | 
			
		||||
      />
 | 
			
		||||
      {locales.includes(router.locale || "en") ? (
 | 
			
		||||
      {locales.includes(router.locale ?? "en") ? (
 | 
			
		||||
        <Markdawn router={router} text={post.translations[0].body} />
 | 
			
		||||
      ) : (
 | 
			
		||||
        <LanguageSwitcher
 | 
			
		||||
@ -78,23 +78,25 @@ export default function SiteInformation(props: SiteInfoProps): JSX.Element {
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
export async function getStaticProps(
 | 
			
		||||
  context: GetStaticPropsContext
 | 
			
		||||
): Promise<{ props: SiteInfoProps }> {
 | 
			
		||||
  const slug = "legality";
 | 
			
		||||
  const props: SiteInfoProps = {
 | 
			
		||||
    ...(await getAppStaticProps(context)),
 | 
			
		||||
    post: (
 | 
			
		||||
      await getPost({
 | 
			
		||||
        slug: slug,
 | 
			
		||||
        language_code: context.locale || "en",
 | 
			
		||||
        language_code: context.locale ?? "en",
 | 
			
		||||
      })
 | 
			
		||||
    ).posts.data[0].attributes,
 | 
			
		||||
    locales: (
 | 
			
		||||
      await getPostLanguages({ slug: slug })
 | 
			
		||||
    ).posts.data[0].attributes.translations.map((translation) => {
 | 
			
		||||
      return translation.language.data.attributes.code;
 | 
			
		||||
    }),
 | 
			
		||||
    ).posts.data[0].attributes.translations.map(
 | 
			
		||||
      (translation) => translation.language.data.attributes.code
 | 
			
		||||
    ),
 | 
			
		||||
  };
 | 
			
		||||
  return {
 | 
			
		||||
    props: props,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -9,7 +9,7 @@ import ContentPanel from "components/Panels/ContentPanel";
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import { getPost, getPostLanguages } from "graphql/operations";
 | 
			
		||||
import { GetPostQuery } from "graphql/operations-types";
 | 
			
		||||
import { GetStaticProps } from "next";
 | 
			
		||||
import { GetStaticPropsContext } from "next";
 | 
			
		||||
import { useRouter } from "next/router";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
import { prettySlug } from "queries/helpers";
 | 
			
		||||
@ -27,7 +27,7 @@ export default function SharingPolicy(props: SharingPolicyProps): JSX.Element {
 | 
			
		||||
    <SubPanel>
 | 
			
		||||
      <ReturnButton
 | 
			
		||||
        href="/about-us"
 | 
			
		||||
        displayOn={ReturnButtonType.Desktop}
 | 
			
		||||
        displayOn={ReturnButtonType.desktop}
 | 
			
		||||
        langui={langui}
 | 
			
		||||
        title={langui.about_us}
 | 
			
		||||
        horizontalLine
 | 
			
		||||
@ -46,12 +46,12 @@ export default function SharingPolicy(props: SharingPolicyProps): JSX.Element {
 | 
			
		||||
    <ContentPanel>
 | 
			
		||||
      <ReturnButton
 | 
			
		||||
        href="/about-us"
 | 
			
		||||
        displayOn={ReturnButtonType.Mobile}
 | 
			
		||||
        displayOn={ReturnButtonType.mobile}
 | 
			
		||||
        langui={langui}
 | 
			
		||||
        title={langui.about_us}
 | 
			
		||||
        className="mb-10"
 | 
			
		||||
      />
 | 
			
		||||
      {locales.includes(router.locale || "en") ? (
 | 
			
		||||
      {locales.includes(router.locale ?? "en") ? (
 | 
			
		||||
        <Markdawn router={router} text={post.translations[0].body} />
 | 
			
		||||
      ) : (
 | 
			
		||||
        <LanguageSwitcher
 | 
			
		||||
@ -78,23 +78,25 @@ export default function SharingPolicy(props: SharingPolicyProps): JSX.Element {
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
export async function getStaticProps(
 | 
			
		||||
  context: GetStaticPropsContext
 | 
			
		||||
): Promise<{ props: SharingPolicyProps }> {
 | 
			
		||||
  const slug = "sharing-policy";
 | 
			
		||||
  const props: SharingPolicyProps = {
 | 
			
		||||
    ...(await getAppStaticProps(context)),
 | 
			
		||||
    post: (
 | 
			
		||||
      await getPost({
 | 
			
		||||
        slug: slug,
 | 
			
		||||
        language_code: context.locale || "en",
 | 
			
		||||
        language_code: context.locale ?? "en",
 | 
			
		||||
      })
 | 
			
		||||
    ).posts.data[0].attributes,
 | 
			
		||||
    locales: (
 | 
			
		||||
      await getPostLanguages({ slug: slug })
 | 
			
		||||
    ).posts.data[0].attributes.translations.map((translation) => {
 | 
			
		||||
      return translation.language.data.attributes.code;
 | 
			
		||||
    }),
 | 
			
		||||
    ).posts.data[0].attributes.translations.map(
 | 
			
		||||
      (translation) => translation.language.data.attributes.code
 | 
			
		||||
    ),
 | 
			
		||||
  };
 | 
			
		||||
  return {
 | 
			
		||||
    props: props,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -21,10 +21,10 @@ export default async function Mail(
 | 
			
		||||
  if (req.method === "POST") {
 | 
			
		||||
    const body = req.body as RequestMailProps;
 | 
			
		||||
 | 
			
		||||
    let transporter = nodemailer.createTransport({
 | 
			
		||||
    const transporter = nodemailer.createTransport({
 | 
			
		||||
      host: process.env.SMTP_HOST,
 | 
			
		||||
      port: 587,
 | 
			
		||||
      secure: false, // true for 465, false for other ports
 | 
			
		||||
      secure: false,
 | 
			
		||||
      auth: {
 | 
			
		||||
        user: process.env.SMTP_USER,
 | 
			
		||||
        pass: process.env.SMTP_PASSWORD,
 | 
			
		||||
@ -32,7 +32,7 @@ export default async function Mail(
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // send mail with defined transport object
 | 
			
		||||
    let info = await transporter
 | 
			
		||||
    await transporter
 | 
			
		||||
      .sendMail({
 | 
			
		||||
        from: `"${body.name}" <${body.email}>`,
 | 
			
		||||
        to: "contact@accords-library.com",
 | 
			
		||||
@ -40,7 +40,7 @@ export default async function Mail(
 | 
			
		||||
        text: body.message,
 | 
			
		||||
      })
 | 
			
		||||
      .catch((reason: SMTPError) => {
 | 
			
		||||
        res.status(reason.responseCode || 500).json({
 | 
			
		||||
        res.status(reason.responseCode ?? 500).json({
 | 
			
		||||
          code: reason.code,
 | 
			
		||||
          message: reason.response,
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import PanelHeader from "components/PanelComponents/PanelHeader";
 | 
			
		||||
import { GetStaticProps } from "next";
 | 
			
		||||
import AppLayout from "components/AppLayout";
 | 
			
		||||
import PanelHeader from "components/PanelComponents/PanelHeader";
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import { GetStaticPropsContext } from "next";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
 | 
			
		||||
interface ArchivesProps extends AppStaticProps {}
 | 
			
		||||
@ -22,11 +22,13 @@ export default function Archives(props: ArchivesProps): JSX.Element {
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
export async function getStaticProps(
 | 
			
		||||
  context: GetStaticPropsContext
 | 
			
		||||
): Promise<{ props: ArchivesProps }> {
 | 
			
		||||
  const props: ArchivesProps = {
 | 
			
		||||
    ...(await getAppStaticProps(context)),
 | 
			
		||||
  };
 | 
			
		||||
  return {
 | 
			
		||||
    props: props,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import PanelHeader from "components/PanelComponents/PanelHeader";
 | 
			
		||||
import { GetStaticProps } from "next";
 | 
			
		||||
import AppLayout from "components/AppLayout";
 | 
			
		||||
import PanelHeader from "components/PanelComponents/PanelHeader";
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import { GetStaticPropsContext } from "next";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
 | 
			
		||||
interface ChroniclesProps extends AppStaticProps {}
 | 
			
		||||
@ -22,11 +22,13 @@ export default function Chronicles(props: ChroniclesProps): JSX.Element {
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
export async function getStaticProps(context: GetStaticPropsContext): Promise<{
 | 
			
		||||
  props: ChroniclesProps;
 | 
			
		||||
}> {
 | 
			
		||||
  const props: ChroniclesProps = {
 | 
			
		||||
    ...(await getAppStaticProps(context)),
 | 
			
		||||
  };
 | 
			
		||||
  return {
 | 
			
		||||
    props: props,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,17 +1,21 @@
 | 
			
		||||
import { GetStaticPaths, GetStaticProps } from "next";
 | 
			
		||||
import { getContent, getContentsSlugs } from "graphql/operations";
 | 
			
		||||
import { GetContentQuery } from "graphql/operations-types";
 | 
			
		||||
import ContentPanel from "components/Panels/ContentPanel";
 | 
			
		||||
import Button from "components/Button";
 | 
			
		||||
import HorizontalLine from "components/HorizontalLine";
 | 
			
		||||
import ThumbnailHeader from "components/Content/ThumbnailHeader";
 | 
			
		||||
import AppLayout from "components/AppLayout";
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import Button from "components/Button";
 | 
			
		||||
import ThumbnailHeader from "components/Content/ThumbnailHeader";
 | 
			
		||||
import HorizontalLine from "components/HorizontalLine";
 | 
			
		||||
import ReturnButton, {
 | 
			
		||||
  ReturnButtonType,
 | 
			
		||||
} from "components/PanelComponents/ReturnButton";
 | 
			
		||||
import { prettyinlineTitle, prettySlug } from "queries/helpers";
 | 
			
		||||
import ContentPanel from "components/Panels/ContentPanel";
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import { getContent, getContentsSlugs } from "graphql/operations";
 | 
			
		||||
import { GetContentQuery } from "graphql/operations-types";
 | 
			
		||||
import {
 | 
			
		||||
  GetStaticPathsContext,
 | 
			
		||||
  GetStaticPathsResult,
 | 
			
		||||
  GetStaticPropsContext,
 | 
			
		||||
} from "next";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
import { prettyinlineTitle, prettySlug } from "queries/helpers";
 | 
			
		||||
 | 
			
		||||
interface ContentIndexProps extends AppStaticProps {
 | 
			
		||||
  content: GetContentQuery["contents"]["data"][number]["attributes"];
 | 
			
		||||
@ -25,7 +29,7 @@ export default function ContentIndex(props: ContentIndexProps): JSX.Element {
 | 
			
		||||
        href="/contents"
 | 
			
		||||
        title={"Contents"}
 | 
			
		||||
        langui={langui}
 | 
			
		||||
        displayOn={ReturnButtonType.Desktop}
 | 
			
		||||
        displayOn={ReturnButtonType.desktop}
 | 
			
		||||
        horizontalLine
 | 
			
		||||
      />
 | 
			
		||||
    </SubPanel>
 | 
			
		||||
@ -36,7 +40,7 @@ export default function ContentIndex(props: ContentIndexProps): JSX.Element {
 | 
			
		||||
        href="/contents"
 | 
			
		||||
        title={"Contents"}
 | 
			
		||||
        langui={langui}
 | 
			
		||||
        displayOn={ReturnButtonType.Mobile}
 | 
			
		||||
        displayOn={ReturnButtonType.mobile}
 | 
			
		||||
        className="mb-10"
 | 
			
		||||
      />
 | 
			
		||||
      <div className="grid place-items-center">
 | 
			
		||||
@ -99,9 +103,7 @@ export default function ContentIndex(props: ContentIndexProps): JSX.Element {
 | 
			
		||||
  if (content.categories.data.length > 0) {
 | 
			
		||||
    description += `${langui.categories}: `;
 | 
			
		||||
    description += content.categories.data
 | 
			
		||||
      .map((category) => {
 | 
			
		||||
        return category.attributes.short;
 | 
			
		||||
      })
 | 
			
		||||
      .map((category) => category.attributes.short)
 | 
			
		||||
      .join(" | ");
 | 
			
		||||
    description += "\n";
 | 
			
		||||
  }
 | 
			
		||||
@ -132,27 +134,29 @@ export default function ContentIndex(props: ContentIndexProps): JSX.Element {
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
export async function getStaticProps(context: GetStaticPropsContext): Promise<{
 | 
			
		||||
  props: ContentIndexProps;
 | 
			
		||||
}> {
 | 
			
		||||
  const props: ContentIndexProps = {
 | 
			
		||||
    ...(await getAppStaticProps(context)),
 | 
			
		||||
    content: (
 | 
			
		||||
      await getContent({
 | 
			
		||||
        slug: context.params?.slug?.toString() || "",
 | 
			
		||||
        language_code: context.locale || "en",
 | 
			
		||||
        slug: context.params?.slug?.toString() ?? "",
 | 
			
		||||
        language_code: context.locale ?? "en",
 | 
			
		||||
      })
 | 
			
		||||
    ).contents.data[0].attributes,
 | 
			
		||||
  };
 | 
			
		||||
  return {
 | 
			
		||||
    props: props,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getStaticPaths: GetStaticPaths = async (context) => {
 | 
			
		||||
  type Path = { params: { slug: string }; locale: string };
 | 
			
		||||
 | 
			
		||||
  const data = await getContentsSlugs({});
 | 
			
		||||
  const paths: Path[] = [];
 | 
			
		||||
  data.contents.data.map((item) => {
 | 
			
		||||
export async function getStaticPaths(
 | 
			
		||||
  context: GetStaticPathsContext
 | 
			
		||||
): Promise<GetStaticPathsResult> {
 | 
			
		||||
  const contents = await getContentsSlugs({});
 | 
			
		||||
  const paths: GetStaticPathsResult["paths"] = [];
 | 
			
		||||
  contents.contents.data.map((item) => {
 | 
			
		||||
    context.locales?.map((local) => {
 | 
			
		||||
      paths.push({ params: { slug: item.attributes.slug }, locale: local });
 | 
			
		||||
    });
 | 
			
		||||
@ -161,4 +165,4 @@ export const getStaticPaths: GetStaticPaths = async (context) => {
 | 
			
		||||
    paths,
 | 
			
		||||
    fallback: false,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,19 +1,31 @@
 | 
			
		||||
import { GetStaticPaths, GetStaticProps } from "next";
 | 
			
		||||
import AppLayout from "components/AppLayout";
 | 
			
		||||
import Button from "components/Button";
 | 
			
		||||
import Chip from "components/Chip";
 | 
			
		||||
import ThumbnailHeader from "components/Content/ThumbnailHeader";
 | 
			
		||||
import HorizontalLine from "components/HorizontalLine";
 | 
			
		||||
import LanguageSwitcher from "components/LanguageSwitcher";
 | 
			
		||||
import Markdawn from "components/Markdown/Markdawn";
 | 
			
		||||
import TOC from "components/Markdown/TOC";
 | 
			
		||||
import ReturnButton, {
 | 
			
		||||
  ReturnButtonType,
 | 
			
		||||
} from "components/PanelComponents/ReturnButton";
 | 
			
		||||
import ContentPanel from "components/Panels/ContentPanel";
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import RecorderChip from "components/RecorderChip";
 | 
			
		||||
import ToolTip from "components/ToolTip";
 | 
			
		||||
import {
 | 
			
		||||
  getContentLanguages,
 | 
			
		||||
  getContentsSlugs,
 | 
			
		||||
  getContentText,
 | 
			
		||||
} from "graphql/operations";
 | 
			
		||||
import { GetContentTextQuery } from "graphql/operations-types";
 | 
			
		||||
import ContentPanel from "components/Panels/ContentPanel";
 | 
			
		||||
import HorizontalLine from "components/HorizontalLine";
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import ReturnButton, {
 | 
			
		||||
  ReturnButtonType,
 | 
			
		||||
} from "components/PanelComponents/ReturnButton";
 | 
			
		||||
import ThumbnailHeader from "components/Content/ThumbnailHeader";
 | 
			
		||||
import AppLayout from "components/AppLayout";
 | 
			
		||||
import Markdawn from "components/Markdown/Markdawn";
 | 
			
		||||
import {
 | 
			
		||||
  GetStaticPathsContext,
 | 
			
		||||
  GetStaticPathsResult,
 | 
			
		||||
  GetStaticPropsContext,
 | 
			
		||||
} from "next";
 | 
			
		||||
import { useRouter } from "next/router";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
import {
 | 
			
		||||
  getStatusDescription,
 | 
			
		||||
  prettyinlineTitle,
 | 
			
		||||
@ -22,14 +34,6 @@ import {
 | 
			
		||||
  prettyTestError,
 | 
			
		||||
  prettyTestWarning,
 | 
			
		||||
} from "queries/helpers";
 | 
			
		||||
import Button from "components/Button";
 | 
			
		||||
import { useRouter } from "next/router";
 | 
			
		||||
import Chip from "components/Chip";
 | 
			
		||||
import RecorderChip from "components/RecorderChip";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
import TOC from "components/Markdown/TOC";
 | 
			
		||||
import ToolTip from "components/ToolTip";
 | 
			
		||||
import LanguageSwitcher from "components/LanguageSwitcher";
 | 
			
		||||
 | 
			
		||||
interface ContentReadProps extends AppStaticProps {
 | 
			
		||||
  content: GetContentTextQuery["contents"]["data"][number]["attributes"];
 | 
			
		||||
@ -48,7 +52,7 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
 | 
			
		||||
        href={`/contents/${content.slug}`}
 | 
			
		||||
        title={"Content"}
 | 
			
		||||
        langui={langui}
 | 
			
		||||
        displayOn={ReturnButtonType.Desktop}
 | 
			
		||||
        displayOn={ReturnButtonType.desktop}
 | 
			
		||||
        horizontalLine
 | 
			
		||||
      />
 | 
			
		||||
 | 
			
		||||
@ -163,7 +167,7 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
 | 
			
		||||
        href={`/contents/${content.slug}`}
 | 
			
		||||
        title={langui.content}
 | 
			
		||||
        langui={langui}
 | 
			
		||||
        displayOn={ReturnButtonType.Mobile}
 | 
			
		||||
        displayOn={ReturnButtonType.mobile}
 | 
			
		||||
        className="mb-10"
 | 
			
		||||
      />
 | 
			
		||||
      <div className="grid place-items-center">
 | 
			
		||||
@ -192,7 +196,7 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
 | 
			
		||||
 | 
			
		||||
        <HorizontalLine />
 | 
			
		||||
 | 
			
		||||
        {locales.includes(router.locale || "en") ? (
 | 
			
		||||
        {locales.includes(router.locale ?? "en") ? (
 | 
			
		||||
          <Markdawn router={router} text={content.text_set[0].text} />
 | 
			
		||||
        ) : (
 | 
			
		||||
          <LanguageSwitcher
 | 
			
		||||
@ -219,9 +223,7 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
 | 
			
		||||
  if (content.categories.data.length > 0) {
 | 
			
		||||
    description += `${langui.categories}: `;
 | 
			
		||||
    description += content.categories.data
 | 
			
		||||
      .map((category) => {
 | 
			
		||||
        return category.attributes.short;
 | 
			
		||||
      })
 | 
			
		||||
      .map((category) => category.attributes.short)
 | 
			
		||||
      .join(" | ");
 | 
			
		||||
    description += "\n";
 | 
			
		||||
  }
 | 
			
		||||
@ -247,12 +249,14 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
  const slug = context.params?.slug?.toString() || "";
 | 
			
		||||
export async function getStaticProps(
 | 
			
		||||
  context: GetStaticPropsContext
 | 
			
		||||
): Promise<{ props: ContentReadProps }> {
 | 
			
		||||
  const slug = context.params?.slug?.toString() ?? "";
 | 
			
		||||
  const content = (
 | 
			
		||||
    await getContentText({
 | 
			
		||||
      slug: slug,
 | 
			
		||||
      language_code: context.locale || "en",
 | 
			
		||||
      language_code: context.locale ?? "en",
 | 
			
		||||
    })
 | 
			
		||||
  ).contents.data[0];
 | 
			
		||||
  const props: ContentReadProps = {
 | 
			
		||||
@ -261,26 +265,21 @@ export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
    contentId: content.id,
 | 
			
		||||
    locales: (
 | 
			
		||||
      await getContentLanguages({ slug: slug })
 | 
			
		||||
    ).contents.data[0].attributes.text_set.map((translation) => {
 | 
			
		||||
      return translation.language.data.attributes.code;
 | 
			
		||||
    }),
 | 
			
		||||
    ).contents.data[0].attributes.text_set.map(
 | 
			
		||||
      (translation) => translation.language.data.attributes.code
 | 
			
		||||
    ),
 | 
			
		||||
  };
 | 
			
		||||
  return {
 | 
			
		||||
    props: props,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getStaticPaths: GetStaticPaths = async (context) => {
 | 
			
		||||
  type Path = {
 | 
			
		||||
    params: {
 | 
			
		||||
      slug: string;
 | 
			
		||||
    };
 | 
			
		||||
    locale: string;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const data = await getContentsSlugs({});
 | 
			
		||||
  const paths: Path[] = [];
 | 
			
		||||
  data.contents.data.map((item) => {
 | 
			
		||||
export async function getStaticPaths(
 | 
			
		||||
  context: GetStaticPathsContext
 | 
			
		||||
): Promise<GetStaticPathsResult> {
 | 
			
		||||
  const contents = await getContentsSlugs({});
 | 
			
		||||
  const paths: GetStaticPathsResult["paths"] = [];
 | 
			
		||||
  contents.contents.data.map((item) => {
 | 
			
		||||
    context.locales?.map((local) => {
 | 
			
		||||
      paths.push({ params: { slug: item.attributes.slug }, locale: local });
 | 
			
		||||
    });
 | 
			
		||||
@ -289,14 +288,13 @@ export const getStaticPaths: GetStaticPaths = async (context) => {
 | 
			
		||||
    paths,
 | 
			
		||||
    fallback: false,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function useTesting(props: ContentReadProps) {
 | 
			
		||||
function useTesting(props: ContentReadProps) {
 | 
			
		||||
  const router = useRouter();
 | 
			
		||||
  const { content, contentId } = props;
 | 
			
		||||
 | 
			
		||||
  const contentURL =
 | 
			
		||||
    "/admin/content-manager/collectionType/api::content.content/" + contentId;
 | 
			
		||||
  const contentURL = `/admin/content-manager/collectionType/api::content.content/${contentId}`;
 | 
			
		||||
 | 
			
		||||
  if (router.locale === "en") {
 | 
			
		||||
    if (content.categories.data.length === 0) {
 | 
			
		||||
@ -323,18 +321,17 @@ export function useTesting(props: ContentReadProps) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (content.text_set.length > 1) {
 | 
			
		||||
    console.warn(
 | 
			
		||||
      prettyTestError(
 | 
			
		||||
        router,
 | 
			
		||||
        "More than one textset for this language",
 | 
			
		||||
        ["content", "text_set"],
 | 
			
		||||
        contentURL
 | 
			
		||||
      )
 | 
			
		||||
    prettyTestError(
 | 
			
		||||
      router,
 | 
			
		||||
      "More than one textset for this language",
 | 
			
		||||
      ["content", "text_set"],
 | 
			
		||||
      contentURL
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (content.text_set.length === 1) {
 | 
			
		||||
    const textset = content.text_set[0];
 | 
			
		||||
 | 
			
		||||
    if (!textset.text) {
 | 
			
		||||
      prettyTestError(
 | 
			
		||||
        router,
 | 
			
		||||
@ -350,43 +347,41 @@ export function useTesting(props: ContentReadProps) {
 | 
			
		||||
        ["content", "text_set"],
 | 
			
		||||
        contentURL
 | 
			
		||||
      );
 | 
			
		||||
    } else if (textset.source_language.data.attributes.code === router.locale) {
 | 
			
		||||
      // This is a transcript
 | 
			
		||||
      if (textset.transcribers.data.length === 0) {
 | 
			
		||||
        prettyTestError(
 | 
			
		||||
          router,
 | 
			
		||||
          "Missing transcribers attribution",
 | 
			
		||||
          ["content", "text_set"],
 | 
			
		||||
          contentURL
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
      if (textset.translators.data.length > 0) {
 | 
			
		||||
        prettyTestError(
 | 
			
		||||
          router,
 | 
			
		||||
          "Transcripts shouldn't have translators",
 | 
			
		||||
          ["content", "text_set"],
 | 
			
		||||
          contentURL
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      if (textset.source_language.data.attributes.code === router.locale) {
 | 
			
		||||
        // This is a transcript
 | 
			
		||||
        if (textset.transcribers.data.length === 0) {
 | 
			
		||||
          prettyTestError(
 | 
			
		||||
            router,
 | 
			
		||||
            "Missing transcribers attribution",
 | 
			
		||||
            ["content", "text_set"],
 | 
			
		||||
            contentURL
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
        if (textset.translators.data.length > 0) {
 | 
			
		||||
          prettyTestError(
 | 
			
		||||
            router,
 | 
			
		||||
            "Transcripts shouldn't have translators",
 | 
			
		||||
            ["content", "text_set"],
 | 
			
		||||
            contentURL
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        // This is a translation
 | 
			
		||||
        if (textset.translators.data.length === 0) {
 | 
			
		||||
          prettyTestError(
 | 
			
		||||
            router,
 | 
			
		||||
            "Missing translators attribution",
 | 
			
		||||
            ["content", "text_set"],
 | 
			
		||||
            contentURL
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
        if (textset.transcribers.data.length > 0) {
 | 
			
		||||
          prettyTestError(
 | 
			
		||||
            router,
 | 
			
		||||
            "Translations shouldn't have transcribers",
 | 
			
		||||
            ["content", "text_set"],
 | 
			
		||||
            contentURL
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
      // This is a translation
 | 
			
		||||
      if (textset.translators.data.length === 0) {
 | 
			
		||||
        prettyTestError(
 | 
			
		||||
          router,
 | 
			
		||||
          "Missing translators attribution",
 | 
			
		||||
          ["content", "text_set"],
 | 
			
		||||
          contentURL
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
      if (textset.transcribers.data.length > 0) {
 | 
			
		||||
        prettyTestError(
 | 
			
		||||
          router,
 | 
			
		||||
          "Translations shouldn't have transcribers",
 | 
			
		||||
          ["content", "text_set"],
 | 
			
		||||
          contentURL
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -1,21 +1,21 @@
 | 
			
		||||
import { GetStaticProps } from "next";
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import AppLayout from "components/AppLayout";
 | 
			
		||||
import Chip from "components/Chip";
 | 
			
		||||
import LibraryContentPreview from "components/Library/LibraryContentPreview";
 | 
			
		||||
import PanelHeader from "components/PanelComponents/PanelHeader";
 | 
			
		||||
import ContentPanel, {
 | 
			
		||||
  ContentPanelWidthSizes,
 | 
			
		||||
} from "components/Panels/ContentPanel";
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import Select from "components/Select";
 | 
			
		||||
import { getContents } from "graphql/operations";
 | 
			
		||||
import {
 | 
			
		||||
  GetContentsQuery,
 | 
			
		||||
  GetWebsiteInterfaceQuery,
 | 
			
		||||
} from "graphql/operations-types";
 | 
			
		||||
import { getContents } from "graphql/operations";
 | 
			
		||||
import PanelHeader from "components/PanelComponents/PanelHeader";
 | 
			
		||||
import AppLayout from "components/AppLayout";
 | 
			
		||||
import LibraryContentPreview from "components/Library/LibraryContentPreview";
 | 
			
		||||
import { prettyinlineTitle, prettySlug } from "queries/helpers";
 | 
			
		||||
import { GetStaticPropsContext } from "next";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
import Select from "components/Select";
 | 
			
		||||
import { prettyinlineTitle, prettySlug } from "queries/helpers";
 | 
			
		||||
import { useEffect, useState } from "react";
 | 
			
		||||
import Chip from "components/Chip";
 | 
			
		||||
 | 
			
		||||
interface ContentsProps extends AppStaticProps {
 | 
			
		||||
  contents: GetContentsQuery["contents"]["data"];
 | 
			
		||||
@ -64,7 +64,7 @@ export default function Contents(props: ContentsProps): JSX.Element {
 | 
			
		||||
            <>
 | 
			
		||||
              {name && (
 | 
			
		||||
                <h2
 | 
			
		||||
                  key={"h2" + name}
 | 
			
		||||
                  key={`h2${name}`}
 | 
			
		||||
                  className="text-2xl pb-2 pt-10 first-of-type:pt-0 flex flex-row place-items-center gap-2"
 | 
			
		||||
                >
 | 
			
		||||
                  {name}
 | 
			
		||||
@ -76,7 +76,7 @@ export default function Contents(props: ContentsProps): JSX.Element {
 | 
			
		||||
                </h2>
 | 
			
		||||
              )}
 | 
			
		||||
              <div
 | 
			
		||||
                key={"items" + name}
 | 
			
		||||
                key={`items${name}`}
 | 
			
		||||
                className="grid gap-8 items-end grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))]"
 | 
			
		||||
              >
 | 
			
		||||
                {items.map((item) => (
 | 
			
		||||
@ -99,10 +99,12 @@ export default function Contents(props: ContentsProps): JSX.Element {
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
export async function getStaticProps(
 | 
			
		||||
  context: GetStaticPropsContext
 | 
			
		||||
): Promise<{ props: ContentsProps }> {
 | 
			
		||||
  const contents = (
 | 
			
		||||
    await getContents({
 | 
			
		||||
      language_code: context.locale || "en",
 | 
			
		||||
      language_code: context.locale ?? "en",
 | 
			
		||||
    })
 | 
			
		||||
  ).contents.data;
 | 
			
		||||
 | 
			
		||||
@ -133,7 +135,7 @@ export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
  return {
 | 
			
		||||
    props: props,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getGroups(
 | 
			
		||||
  langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"],
 | 
			
		||||
@ -141,55 +143,58 @@ function getGroups(
 | 
			
		||||
  items: ContentsProps["contents"]
 | 
			
		||||
): GroupContentItems {
 | 
			
		||||
  switch (groupByType) {
 | 
			
		||||
    case 0:
 | 
			
		||||
      const typeGroup = new Map();
 | 
			
		||||
      typeGroup.set("Drakengard 1", []);
 | 
			
		||||
      typeGroup.set("Drakengard 1.3", []);
 | 
			
		||||
      typeGroup.set("Drakengard 2", []);
 | 
			
		||||
      typeGroup.set("Drakengard 3", []);
 | 
			
		||||
      typeGroup.set("Drakengard 4", []);
 | 
			
		||||
      typeGroup.set("NieR Gestalt", []);
 | 
			
		||||
      typeGroup.set("NieR Replicant", []);
 | 
			
		||||
      typeGroup.set("NieR Replicant ver.1.22474487139...", []);
 | 
			
		||||
      typeGroup.set("NieR:Automata", []);
 | 
			
		||||
      typeGroup.set("NieR Re[in]carnation", []);
 | 
			
		||||
      typeGroup.set("SINoALICE", []);
 | 
			
		||||
      typeGroup.set("Voice of Cards", []);
 | 
			
		||||
      typeGroup.set("Final Fantasy XIV", []);
 | 
			
		||||
      typeGroup.set("Thou Shalt Not Die", []);
 | 
			
		||||
      typeGroup.set("Bakuken", []);
 | 
			
		||||
      typeGroup.set("YoRHa", []);
 | 
			
		||||
      typeGroup.set("YoRHa Boys", []);
 | 
			
		||||
      typeGroup.set(langui.no_category, []);
 | 
			
		||||
    case 0: {
 | 
			
		||||
      const group = new Map();
 | 
			
		||||
      group.set("Drakengard 1", []);
 | 
			
		||||
      group.set("Drakengard 1.3", []);
 | 
			
		||||
      group.set("Drakengard 2", []);
 | 
			
		||||
      group.set("Drakengard 3", []);
 | 
			
		||||
      group.set("Drakengard 4", []);
 | 
			
		||||
      group.set("NieR Gestalt", []);
 | 
			
		||||
      group.set("NieR Replicant", []);
 | 
			
		||||
      group.set("NieR Replicant ver.1.22474487139...", []);
 | 
			
		||||
      group.set("NieR:Automata", []);
 | 
			
		||||
      group.set("NieR Re[in]carnation", []);
 | 
			
		||||
      group.set("SINoALICE", []);
 | 
			
		||||
      group.set("Voice of Cards", []);
 | 
			
		||||
      group.set("Final Fantasy XIV", []);
 | 
			
		||||
      group.set("Thou Shalt Not Die", []);
 | 
			
		||||
      group.set("Bakuken", []);
 | 
			
		||||
      group.set("YoRHa", []);
 | 
			
		||||
      group.set("YoRHa Boys", []);
 | 
			
		||||
      group.set(langui.no_category, []);
 | 
			
		||||
 | 
			
		||||
      items.map((item) => {
 | 
			
		||||
        if (item.attributes.categories.data.length === 0) {
 | 
			
		||||
          typeGroup.get(langui.no_category)?.push(item);
 | 
			
		||||
          group.get(langui.no_category)?.push(item);
 | 
			
		||||
        } else {
 | 
			
		||||
          item.attributes.categories.data.map((category) => {
 | 
			
		||||
            typeGroup.get(category.attributes.name)?.push(item);
 | 
			
		||||
            group.get(category.attributes.name)?.push(item);
 | 
			
		||||
          });
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
      return typeGroup;
 | 
			
		||||
      return group;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    case 1:
 | 
			
		||||
      const groupType: GroupContentItems = new Map();
 | 
			
		||||
    case 1: {
 | 
			
		||||
      const group: GroupContentItems = new Map();
 | 
			
		||||
      items.map((item) => {
 | 
			
		||||
        const type =
 | 
			
		||||
          item.attributes.type.data.attributes.titles.length > 0
 | 
			
		||||
            ? item.attributes.type.data.attributes.titles[0].title
 | 
			
		||||
            : prettySlug(item.attributes.type.data.attributes.slug);
 | 
			
		||||
 | 
			
		||||
        if (!groupType.has(type)) groupType.set(type, []);
 | 
			
		||||
        groupType.get(type)?.push(item);
 | 
			
		||||
        if (!group.has(type)) group.set(type, []);
 | 
			
		||||
        group.get(type)?.push(item);
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      return groupType;
 | 
			
		||||
      return group;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
      const groupDefault: GroupContentItems = new Map();
 | 
			
		||||
      groupDefault.set("", items);
 | 
			
		||||
      return groupDefault;
 | 
			
		||||
    default: {
 | 
			
		||||
      const group: GroupContentItems = new Map();
 | 
			
		||||
      group.set("", items);
 | 
			
		||||
      return group;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,22 +1,22 @@
 | 
			
		||||
import AppLayout from "components/AppLayout";
 | 
			
		||||
import Markdawn from "components/Markdown/Markdawn";
 | 
			
		||||
import ContentPanel, {
 | 
			
		||||
  ContentPanelWidthSizes,
 | 
			
		||||
} from "components/Panels/ContentPanel";
 | 
			
		||||
import { GetStaticProps } from "next";
 | 
			
		||||
import AppLayout from "components/AppLayout";
 | 
			
		||||
import { useCallback, useState } from "react";
 | 
			
		||||
import Markdawn from "components/Markdown/Markdawn";
 | 
			
		||||
import { GetStaticPropsContext } from "next";
 | 
			
		||||
import { useRouter } from "next/router";
 | 
			
		||||
import Script from "next/script";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
import { useRouter } from "next/router";
 | 
			
		||||
import { useCallback, useState } from "react";
 | 
			
		||||
import { default as TurndownService } from "turndown";
 | 
			
		||||
 | 
			
		||||
interface EditorProps extends AppStaticProps {}
 | 
			
		||||
 | 
			
		||||
export default function Editor(props: EditorProps): JSX.Element {
 | 
			
		||||
  const { langui } = props;
 | 
			
		||||
  const router = useRouter();
 | 
			
		||||
 | 
			
		||||
  const handleInput = useCallback((e) => {
 | 
			
		||||
    setMarkdown(e.target.value);
 | 
			
		||||
  const handleInput = useCallback((event) => {
 | 
			
		||||
    setMarkdown(event.target.value);
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  const [markdown, setMarkdown] = useState("");
 | 
			
		||||
@ -53,7 +53,6 @@ export default function Editor(props: EditorProps): JSX.Element {
 | 
			
		||||
            id="htmlMdTextArea"
 | 
			
		||||
            title="Ouput textarea"
 | 
			
		||||
            onPaste={(event) => {
 | 
			
		||||
              const TurndownService = require("turndown").default;
 | 
			
		||||
              const turndownService = new TurndownService({
 | 
			
		||||
                headingStyle: "atx",
 | 
			
		||||
                codeBlockStyle: "fenced",
 | 
			
		||||
@ -63,9 +62,9 @@ export default function Editor(props: EditorProps): JSX.Element {
 | 
			
		||||
              });
 | 
			
		||||
 | 
			
		||||
              let paste = event.clipboardData.getData("text/html");
 | 
			
		||||
              paste = paste.replace(/<\!--.*?-->/g, "");
 | 
			
		||||
              paste = paste.replace(/<!--.*?-->/u, "");
 | 
			
		||||
              paste = turndownService.turndown(paste);
 | 
			
		||||
              paste = paste.replace(/<\!--.*?-->/g, "");
 | 
			
		||||
              paste = paste.replace(/<!--.*?-->/u, "");
 | 
			
		||||
 | 
			
		||||
              const target = event.target as HTMLTextAreaElement;
 | 
			
		||||
              target.value = paste;
 | 
			
		||||
@ -93,11 +92,13 @@ export default function Editor(props: EditorProps): JSX.Element {
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
export async function getStaticProps(
 | 
			
		||||
  context: GetStaticPropsContext
 | 
			
		||||
): Promise<{ props: EditorProps }> {
 | 
			
		||||
  const props: EditorProps = {
 | 
			
		||||
    ...(await getAppStaticProps(context)),
 | 
			
		||||
  };
 | 
			
		||||
  return {
 | 
			
		||||
    props: props,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
import AppLayout from "components/AppLayout";
 | 
			
		||||
import { GetStaticProps } from "next";
 | 
			
		||||
import { GetStaticPropsContext } from "next";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
 | 
			
		||||
interface GalleryProps extends AppStaticProps {}
 | 
			
		||||
@ -22,11 +22,13 @@ export default function Gallery(props: GalleryProps): JSX.Element {
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
export async function getStaticProps(
 | 
			
		||||
  context: GetStaticPropsContext
 | 
			
		||||
): Promise<{ props: GalleryProps }> {
 | 
			
		||||
  const props: GalleryProps = {
 | 
			
		||||
    ...(await getAppStaticProps(context)),
 | 
			
		||||
  };
 | 
			
		||||
  return {
 | 
			
		||||
    props: props,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@ import Markdawn from "components/Markdown/Markdawn";
 | 
			
		||||
import ContentPanel from "components/Panels/ContentPanel";
 | 
			
		||||
import { getPost, getPostLanguages } from "graphql/operations";
 | 
			
		||||
import { GetPostQuery } from "graphql/operations-types";
 | 
			
		||||
import { GetStaticProps } from "next";
 | 
			
		||||
import { GetStaticPropsContext } from "next";
 | 
			
		||||
import { useRouter } from "next/router";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
import { prettySlug } from "queries/helpers";
 | 
			
		||||
@ -27,7 +27,7 @@ export default function Home(props: HomeProps): JSX.Element {
 | 
			
		||||
          Discover • Analyse • Translate • Archive
 | 
			
		||||
        </h2>
 | 
			
		||||
      </div>
 | 
			
		||||
      {locales.includes(router.locale || "en") ? (
 | 
			
		||||
      {locales.includes(router.locale ?? "en") ? (
 | 
			
		||||
        <Markdawn router={router} text={post.translations[0].body} />
 | 
			
		||||
      ) : (
 | 
			
		||||
        <LanguageSwitcher
 | 
			
		||||
@ -53,23 +53,25 @@ export default function Home(props: HomeProps): JSX.Element {
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
export async function getStaticProps(
 | 
			
		||||
  context: GetStaticPropsContext
 | 
			
		||||
): Promise<{ props: HomeProps }> {
 | 
			
		||||
  const slug = "home";
 | 
			
		||||
  const props: HomeProps = {
 | 
			
		||||
    ...(await getAppStaticProps(context)),
 | 
			
		||||
    post: (
 | 
			
		||||
      await getPost({
 | 
			
		||||
        slug: slug,
 | 
			
		||||
        language_code: context.locale || "en",
 | 
			
		||||
        language_code: context.locale ?? "en",
 | 
			
		||||
      })
 | 
			
		||||
    ).posts.data[0].attributes,
 | 
			
		||||
    locales: (
 | 
			
		||||
      await getPostLanguages({ slug: slug })
 | 
			
		||||
    ).posts.data[0].attributes.translations.map((translation) => {
 | 
			
		||||
      return translation.language.data.attributes.code;
 | 
			
		||||
    }),
 | 
			
		||||
    ).posts.data[0].attributes.translations.map(
 | 
			
		||||
      (translation) => translation.language.data.attributes.code
 | 
			
		||||
    ),
 | 
			
		||||
  };
 | 
			
		||||
  return {
 | 
			
		||||
    props: props,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,41 +1,45 @@
 | 
			
		||||
import AppLayout from "components/AppLayout";
 | 
			
		||||
import Button from "components/Button";
 | 
			
		||||
import Chip from "components/Chip";
 | 
			
		||||
import Img, { getAssetURL, ImageQuality } from "components/Img";
 | 
			
		||||
import InsetBox from "components/InsetBox";
 | 
			
		||||
import ContentTOCLine from "components/Library/ContentTOCLine";
 | 
			
		||||
import LibraryItemsPreview from "components/Library/LibraryItemsPreview";
 | 
			
		||||
import LightBox from "components/LightBox";
 | 
			
		||||
import NavOption from "components/PanelComponents/NavOption";
 | 
			
		||||
import ReturnButton, {
 | 
			
		||||
  ReturnButtonType,
 | 
			
		||||
} from "components/PanelComponents/ReturnButton";
 | 
			
		||||
import ContentPanel, {
 | 
			
		||||
  ContentPanelWidthSizes,
 | 
			
		||||
} from "components/Panels/ContentPanel";
 | 
			
		||||
import { GetStaticPaths, GetStaticProps } from "next";
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import { useAppLayout } from "contexts/AppLayoutContext";
 | 
			
		||||
import { getLibraryItem, getLibraryItemsSlugs } from "graphql/operations";
 | 
			
		||||
import {
 | 
			
		||||
  Enum_Componentmetadatabooks_Binding_Type,
 | 
			
		||||
  Enum_Componentmetadatabooks_Page_Order,
 | 
			
		||||
  GetLibraryItemQuery,
 | 
			
		||||
} from "graphql/operations-types";
 | 
			
		||||
import {
 | 
			
		||||
  GetStaticPathsContext,
 | 
			
		||||
  GetStaticPathsResult,
 | 
			
		||||
  GetStaticPropsContext,
 | 
			
		||||
} from "next";
 | 
			
		||||
import { useRouter } from "next/router";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
import {
 | 
			
		||||
  convertMmToInch,
 | 
			
		||||
  prettyDate,
 | 
			
		||||
  prettyinlineTitle,
 | 
			
		||||
  prettyItemType,
 | 
			
		||||
  prettyItemSubType,
 | 
			
		||||
  prettyItemType,
 | 
			
		||||
  prettyPrice,
 | 
			
		||||
  prettyTestError,
 | 
			
		||||
  prettyTestWarning,
 | 
			
		||||
  sortContent,
 | 
			
		||||
} from "queries/helpers";
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import ReturnButton, {
 | 
			
		||||
  ReturnButtonType,
 | 
			
		||||
} from "components/PanelComponents/ReturnButton";
 | 
			
		||||
import NavOption from "components/PanelComponents/NavOption";
 | 
			
		||||
import Chip from "components/Chip";
 | 
			
		||||
import Button from "components/Button";
 | 
			
		||||
import AppLayout from "components/AppLayout";
 | 
			
		||||
import LibraryItemsPreview from "components/Library/LibraryItemsPreview";
 | 
			
		||||
import InsetBox from "components/InsetBox";
 | 
			
		||||
import Img, { getAssetURL, ImageQuality } from "components/Img";
 | 
			
		||||
import { useAppLayout } from "contexts/AppLayoutContext";
 | 
			
		||||
import { useRouter } from "next/router";
 | 
			
		||||
import ContentTOCLine from "components/Library/ContentTOCLine";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
import { useState } from "react";
 | 
			
		||||
import LightBox from "components/LightBox";
 | 
			
		||||
 | 
			
		||||
interface LibrarySlugProps extends AppStaticProps {
 | 
			
		||||
  item: GetLibraryItemQuery["libraryItems"]["data"][number]["attributes"];
 | 
			
		||||
@ -64,7 +68,7 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
 | 
			
		||||
        href="/library/"
 | 
			
		||||
        title={langui.library}
 | 
			
		||||
        langui={langui}
 | 
			
		||||
        displayOn={ReturnButtonType.Desktop}
 | 
			
		||||
        displayOn={ReturnButtonType.desktop}
 | 
			
		||||
        horizontalLine
 | 
			
		||||
      />
 | 
			
		||||
 | 
			
		||||
@ -122,7 +126,7 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
 | 
			
		||||
        href="/library/"
 | 
			
		||||
        title={langui.library}
 | 
			
		||||
        langui={langui}
 | 
			
		||||
        displayOn={ReturnButtonType.Mobile}
 | 
			
		||||
        displayOn={ReturnButtonType.mobile}
 | 
			
		||||
        className="mb-10"
 | 
			
		||||
      />
 | 
			
		||||
      <div className="grid place-items-center gap-12">
 | 
			
		||||
@ -189,12 +193,9 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
 | 
			
		||||
                  onClick={() => {
 | 
			
		||||
                    setLightboxOpen(true);
 | 
			
		||||
                    setLightboxImages(
 | 
			
		||||
                      item.gallery.data.map((image) => {
 | 
			
		||||
                        return getAssetURL(
 | 
			
		||||
                          image.attributes.url,
 | 
			
		||||
                          ImageQuality.Large
 | 
			
		||||
                        );
 | 
			
		||||
                      })
 | 
			
		||||
                      item.gallery.data.map((image) =>
 | 
			
		||||
                        getAssetURL(image.attributes.url, ImageQuality.Large)
 | 
			
		||||
                      )
 | 
			
		||||
                    );
 | 
			
		||||
                    setLightboxIndex(index);
 | 
			
		||||
                  }}
 | 
			
		||||
@ -408,11 +409,13 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
export async function getStaticProps(
 | 
			
		||||
  context: GetStaticPropsContext
 | 
			
		||||
): Promise<{ props: LibrarySlugProps }> {
 | 
			
		||||
  const item = (
 | 
			
		||||
    await getLibraryItem({
 | 
			
		||||
      slug: context.params?.slug?.toString() || "",
 | 
			
		||||
      language_code: context.locale || "en",
 | 
			
		||||
      slug: context.params?.slug?.toString() ?? "",
 | 
			
		||||
      language_code: context.locale ?? "en",
 | 
			
		||||
    })
 | 
			
		||||
  ).libraryItems.data[0];
 | 
			
		||||
  const props: LibrarySlugProps = {
 | 
			
		||||
@ -423,19 +426,14 @@ export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
  return {
 | 
			
		||||
    props: props,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getStaticPaths: GetStaticPaths = async (context) => {
 | 
			
		||||
  type Path = {
 | 
			
		||||
    params: {
 | 
			
		||||
      slug: string;
 | 
			
		||||
    };
 | 
			
		||||
    locale: string;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const data = await getLibraryItemsSlugs({});
 | 
			
		||||
  const paths: Path[] = [];
 | 
			
		||||
  data.libraryItems.data.map((item) => {
 | 
			
		||||
export async function getStaticPaths(
 | 
			
		||||
  context: GetStaticPathsContext
 | 
			
		||||
): Promise<GetStaticPathsResult> {
 | 
			
		||||
  const libraryItems = await getLibraryItemsSlugs({});
 | 
			
		||||
  const paths: GetStaticPathsResult["paths"] = [];
 | 
			
		||||
  libraryItems.libraryItems.data.map((item) => {
 | 
			
		||||
    context.locales?.map((local) => {
 | 
			
		||||
      paths.push({ params: { slug: item.attributes.slug }, locale: local });
 | 
			
		||||
    });
 | 
			
		||||
@ -444,15 +442,13 @@ export const getStaticPaths: GetStaticPaths = async (context) => {
 | 
			
		||||
    paths,
 | 
			
		||||
    fallback: false,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function useTesting(props: LibrarySlugProps) {
 | 
			
		||||
  const { item, itemId } = props;
 | 
			
		||||
  const router = useRouter();
 | 
			
		||||
 | 
			
		||||
  const libraryItemURL =
 | 
			
		||||
    "/admin/content-manager/collectionType/api::library-item.library-item/" +
 | 
			
		||||
    itemId;
 | 
			
		||||
  const libraryItemURL = `/admin/content-manager/collectionType/api::library-item.library-item/${itemId}`;
 | 
			
		||||
 | 
			
		||||
  sortContent(item.contents);
 | 
			
		||||
 | 
			
		||||
@ -472,269 +468,264 @@ function useTesting(props: LibrarySlugProps) {
 | 
			
		||||
        ["libraryItem"],
 | 
			
		||||
        libraryItemURL
 | 
			
		||||
      );
 | 
			
		||||
    } else if (
 | 
			
		||||
      item.metadata[0].__typename === "ComponentMetadataGroup" &&
 | 
			
		||||
      (item.metadata[0].subtype.data.attributes.slug === "relation-set" ||
 | 
			
		||||
        item.metadata[0].subtype.data.attributes.slug === "variant-set")
 | 
			
		||||
    ) {
 | 
			
		||||
      // This is a group type item
 | 
			
		||||
      if (item.price) {
 | 
			
		||||
        prettyTestError(
 | 
			
		||||
          router,
 | 
			
		||||
          "Group-type items shouldn't have price",
 | 
			
		||||
          ["libraryItem"],
 | 
			
		||||
          libraryItemURL
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
      if (item.size) {
 | 
			
		||||
        prettyTestError(
 | 
			
		||||
          router,
 | 
			
		||||
          "Group-type items shouldn't have size",
 | 
			
		||||
          ["libraryItem"],
 | 
			
		||||
          libraryItemURL
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
      if (item.release_date) {
 | 
			
		||||
        prettyTestError(
 | 
			
		||||
          router,
 | 
			
		||||
          "Group-type items shouldn't have release_date",
 | 
			
		||||
          ["libraryItem"],
 | 
			
		||||
          libraryItemURL
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
      if (item.contents.data.length > 0) {
 | 
			
		||||
        prettyTestError(
 | 
			
		||||
          router,
 | 
			
		||||
          "Group-type items shouldn't have contents",
 | 
			
		||||
          ["libraryItem"],
 | 
			
		||||
          libraryItemURL
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
      if (item.subitems.data.length === 0) {
 | 
			
		||||
        prettyTestError(
 | 
			
		||||
          router,
 | 
			
		||||
          "Group-type items should have subitems",
 | 
			
		||||
          ["libraryItem"],
 | 
			
		||||
          libraryItemURL
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      if (
 | 
			
		||||
        item.metadata[0].__typename === "ComponentMetadataGroup" &&
 | 
			
		||||
        (item.metadata[0].subtype.data.attributes.slug === "relation-set" ||
 | 
			
		||||
          item.metadata[0].subtype.data.attributes.slug === "variant-set")
 | 
			
		||||
      ) {
 | 
			
		||||
        // This is a group type item
 | 
			
		||||
        if (item.price) {
 | 
			
		||||
          prettyTestError(
 | 
			
		||||
            router,
 | 
			
		||||
            "Group-type items shouldn't have price",
 | 
			
		||||
            ["libraryItem"],
 | 
			
		||||
            libraryItemURL
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
        if (item.size) {
 | 
			
		||||
          prettyTestError(
 | 
			
		||||
            router,
 | 
			
		||||
            "Group-type items shouldn't have size",
 | 
			
		||||
            ["libraryItem"],
 | 
			
		||||
            libraryItemURL
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
        if (item.release_date) {
 | 
			
		||||
          prettyTestError(
 | 
			
		||||
            router,
 | 
			
		||||
            "Group-type items shouldn't have release_date",
 | 
			
		||||
            ["libraryItem"],
 | 
			
		||||
            libraryItemURL
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
        if (item.contents.data.length > 0) {
 | 
			
		||||
          prettyTestError(
 | 
			
		||||
            router,
 | 
			
		||||
            "Group-type items shouldn't have contents",
 | 
			
		||||
            ["libraryItem"],
 | 
			
		||||
            libraryItemURL
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
      // This is a normal item
 | 
			
		||||
 | 
			
		||||
      if (item.metadata[0].__typename === "ComponentMetadataGroup") {
 | 
			
		||||
        if (item.subitems.data.length === 0) {
 | 
			
		||||
          prettyTestError(
 | 
			
		||||
            router,
 | 
			
		||||
            "Group-type items should have subitems",
 | 
			
		||||
            "Group-type item should have subitems",
 | 
			
		||||
            ["libraryItem"],
 | 
			
		||||
            libraryItemURL
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (item.price) {
 | 
			
		||||
        if (!item.price.amount) {
 | 
			
		||||
          prettyTestError(
 | 
			
		||||
            router,
 | 
			
		||||
            "Missing amount",
 | 
			
		||||
            ["libraryItem", "price"],
 | 
			
		||||
            libraryItemURL
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
        if (!item.price.currency) {
 | 
			
		||||
          prettyTestError(
 | 
			
		||||
            router,
 | 
			
		||||
            "Missing currency",
 | 
			
		||||
            ["libraryItem", "price"],
 | 
			
		||||
            libraryItemURL
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        // This is a normal item
 | 
			
		||||
        prettyTestWarning(
 | 
			
		||||
          router,
 | 
			
		||||
          "Missing price",
 | 
			
		||||
          ["libraryItem"],
 | 
			
		||||
          libraryItemURL
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
        if (item.metadata[0].__typename === "ComponentMetadataGroup") {
 | 
			
		||||
          if (item.subitems.data.length === 0) {
 | 
			
		||||
            prettyTestError(
 | 
			
		||||
              router,
 | 
			
		||||
              "Group-type item should have subitems",
 | 
			
		||||
              ["libraryItem"],
 | 
			
		||||
              libraryItemURL
 | 
			
		||||
            );
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!item.price) {
 | 
			
		||||
          prettyTestWarning(
 | 
			
		||||
            router,
 | 
			
		||||
            "Missing price",
 | 
			
		||||
            ["libraryItem"],
 | 
			
		||||
            libraryItemURL
 | 
			
		||||
          );
 | 
			
		||||
        } else {
 | 
			
		||||
          if (!item.price.amount) {
 | 
			
		||||
            prettyTestError(
 | 
			
		||||
              router,
 | 
			
		||||
              "Missing amount",
 | 
			
		||||
              ["libraryItem", "price"],
 | 
			
		||||
              libraryItemURL
 | 
			
		||||
            );
 | 
			
		||||
          }
 | 
			
		||||
          if (!item.price.currency) {
 | 
			
		||||
            prettyTestError(
 | 
			
		||||
              router,
 | 
			
		||||
              "Missing currency",
 | 
			
		||||
              ["libraryItem", "price"],
 | 
			
		||||
              libraryItemURL
 | 
			
		||||
            );
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!item.digital) {
 | 
			
		||||
          if (!item.size) {
 | 
			
		||||
      if (!item.digital) {
 | 
			
		||||
        if (item.size) {
 | 
			
		||||
          if (!item.size.width) {
 | 
			
		||||
            prettyTestWarning(
 | 
			
		||||
              router,
 | 
			
		||||
              "Missing size",
 | 
			
		||||
              ["libraryItem"],
 | 
			
		||||
              "Missing width",
 | 
			
		||||
              ["libraryItem", "size"],
 | 
			
		||||
              libraryItemURL
 | 
			
		||||
            );
 | 
			
		||||
          } else {
 | 
			
		||||
            if (!item.size.width) {
 | 
			
		||||
              prettyTestWarning(
 | 
			
		||||
                router,
 | 
			
		||||
                "Missing width",
 | 
			
		||||
                ["libraryItem", "size"],
 | 
			
		||||
                libraryItemURL
 | 
			
		||||
              );
 | 
			
		||||
            }
 | 
			
		||||
            if (!item.size.height) {
 | 
			
		||||
              prettyTestWarning(
 | 
			
		||||
                router,
 | 
			
		||||
                "Missing height",
 | 
			
		||||
                ["libraryItem", "size"],
 | 
			
		||||
                libraryItemURL
 | 
			
		||||
              );
 | 
			
		||||
            }
 | 
			
		||||
            if (!item.size.thickness) {
 | 
			
		||||
              prettyTestWarning(
 | 
			
		||||
                router,
 | 
			
		||||
                "Missing thickness",
 | 
			
		||||
                ["libraryItem", "size"],
 | 
			
		||||
                libraryItemURL
 | 
			
		||||
              );
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!item.release_date) {
 | 
			
		||||
          if (!item.size.height) {
 | 
			
		||||
            prettyTestWarning(
 | 
			
		||||
              router,
 | 
			
		||||
              "Missing height",
 | 
			
		||||
              ["libraryItem", "size"],
 | 
			
		||||
              libraryItemURL
 | 
			
		||||
            );
 | 
			
		||||
          }
 | 
			
		||||
          if (!item.size.thickness) {
 | 
			
		||||
            prettyTestWarning(
 | 
			
		||||
              router,
 | 
			
		||||
              "Missing thickness",
 | 
			
		||||
              ["libraryItem", "size"],
 | 
			
		||||
              libraryItemURL
 | 
			
		||||
            );
 | 
			
		||||
          }
 | 
			
		||||
        } else {
 | 
			
		||||
          prettyTestWarning(
 | 
			
		||||
            router,
 | 
			
		||||
            "Missing release_date",
 | 
			
		||||
            "Missing size",
 | 
			
		||||
            ["libraryItem"],
 | 
			
		||||
            libraryItemURL
 | 
			
		||||
          );
 | 
			
		||||
        } else {
 | 
			
		||||
          if (!item.release_date.year) {
 | 
			
		||||
            prettyTestError(
 | 
			
		||||
              router,
 | 
			
		||||
              "Missing year",
 | 
			
		||||
              ["libraryItem", "release_date"],
 | 
			
		||||
              libraryItemURL
 | 
			
		||||
            );
 | 
			
		||||
          }
 | 
			
		||||
          if (!item.release_date.month) {
 | 
			
		||||
            prettyTestError(
 | 
			
		||||
              router,
 | 
			
		||||
              "Missing month",
 | 
			
		||||
              ["libraryItem", "release_date"],
 | 
			
		||||
              libraryItemURL
 | 
			
		||||
            );
 | 
			
		||||
          }
 | 
			
		||||
          if (!item.release_date.day) {
 | 
			
		||||
            prettyTestError(
 | 
			
		||||
              router,
 | 
			
		||||
              "Missing day",
 | 
			
		||||
              ["libraryItem", "release_date"],
 | 
			
		||||
              libraryItemURL
 | 
			
		||||
            );
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
        if (item.contents.data.length === 0) {
 | 
			
		||||
          prettyTestWarning(
 | 
			
		||||
      if (item.release_date) {
 | 
			
		||||
        if (!item.release_date.year) {
 | 
			
		||||
          prettyTestError(
 | 
			
		||||
            router,
 | 
			
		||||
            "Missing contents",
 | 
			
		||||
            ["libraryItem"],
 | 
			
		||||
            "Missing year",
 | 
			
		||||
            ["libraryItem", "release_date"],
 | 
			
		||||
            libraryItemURL
 | 
			
		||||
          );
 | 
			
		||||
        } else {
 | 
			
		||||
          let currentRangePage = 0;
 | 
			
		||||
          item.contents.data.map((content) => {
 | 
			
		||||
            const contentURL =
 | 
			
		||||
              "/admin/content-manager/collectionType/api::content.content/" +
 | 
			
		||||
              content.id;
 | 
			
		||||
        }
 | 
			
		||||
        if (!item.release_date.month) {
 | 
			
		||||
          prettyTestError(
 | 
			
		||||
            router,
 | 
			
		||||
            "Missing month",
 | 
			
		||||
            ["libraryItem", "release_date"],
 | 
			
		||||
            libraryItemURL
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
        if (!item.release_date.day) {
 | 
			
		||||
          prettyTestError(
 | 
			
		||||
            router,
 | 
			
		||||
            "Missing day",
 | 
			
		||||
            ["libraryItem", "release_date"],
 | 
			
		||||
            libraryItemURL
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        prettyTestWarning(
 | 
			
		||||
          router,
 | 
			
		||||
          "Missing release_date",
 | 
			
		||||
          ["libraryItem"],
 | 
			
		||||
          libraryItemURL
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
            if (content.attributes.scan_set.length === 0) {
 | 
			
		||||
              prettyTestWarning(
 | 
			
		||||
      if (item.contents.data.length === 0) {
 | 
			
		||||
        prettyTestWarning(
 | 
			
		||||
          router,
 | 
			
		||||
          "Missing contents",
 | 
			
		||||
          ["libraryItem"],
 | 
			
		||||
          libraryItemURL
 | 
			
		||||
        );
 | 
			
		||||
      } else {
 | 
			
		||||
        let currentRangePage = 0;
 | 
			
		||||
        item.contents.data.map((content) => {
 | 
			
		||||
          const contentURL = `/admin/content-manager/collectionType/api::content.content/${content.id}`;
 | 
			
		||||
 | 
			
		||||
          if (content.attributes.scan_set.length === 0) {
 | 
			
		||||
            prettyTestWarning(
 | 
			
		||||
              router,
 | 
			
		||||
              "Missing scan_set",
 | 
			
		||||
              ["libraryItem", "content", content.id],
 | 
			
		||||
              contentURL
 | 
			
		||||
            );
 | 
			
		||||
          }
 | 
			
		||||
          if (content.attributes.range.length === 0) {
 | 
			
		||||
            prettyTestWarning(
 | 
			
		||||
              router,
 | 
			
		||||
              "Missing range",
 | 
			
		||||
              ["libraryItem", "content", content.id],
 | 
			
		||||
              contentURL
 | 
			
		||||
            );
 | 
			
		||||
          } else if (
 | 
			
		||||
            content.attributes.range[0].__typename === "ComponentRangePageRange"
 | 
			
		||||
          ) {
 | 
			
		||||
            if (
 | 
			
		||||
              content.attributes.range[0].starting_page <
 | 
			
		||||
              currentRangePage + 1
 | 
			
		||||
            ) {
 | 
			
		||||
              prettyTestError(
 | 
			
		||||
                router,
 | 
			
		||||
                "Missing scan_set",
 | 
			
		||||
                ["libraryItem", "content", content.id],
 | 
			
		||||
                contentURL
 | 
			
		||||
              );
 | 
			
		||||
            }
 | 
			
		||||
            if (content.attributes.range.length === 0) {
 | 
			
		||||
              prettyTestWarning(
 | 
			
		||||
                router,
 | 
			
		||||
                "Missing range",
 | 
			
		||||
                ["libraryItem", "content", content.id],
 | 
			
		||||
                contentURL
 | 
			
		||||
                `Overlapping pages ${content.attributes.range[0].starting_page} to ${currentRangePage}`,
 | 
			
		||||
                ["libraryItem", "content", content.id, "range"],
 | 
			
		||||
                libraryItemURL
 | 
			
		||||
              );
 | 
			
		||||
            } else if (
 | 
			
		||||
              content.attributes.range[0].__typename ===
 | 
			
		||||
              "ComponentRangePageRange"
 | 
			
		||||
              content.attributes.range[0].starting_page >
 | 
			
		||||
              currentRangePage + 1
 | 
			
		||||
            ) {
 | 
			
		||||
              if (
 | 
			
		||||
                content.attributes.range[0].starting_page <
 | 
			
		||||
                currentRangePage + 1
 | 
			
		||||
              ) {
 | 
			
		||||
                prettyTestError(
 | 
			
		||||
                  router,
 | 
			
		||||
                  `Overlapping pages ${content.attributes.range[0].starting_page} to ${currentRangePage}`,
 | 
			
		||||
                  ["libraryItem", "content", content.id, "range"],
 | 
			
		||||
                  libraryItemURL
 | 
			
		||||
                );
 | 
			
		||||
              } else if (
 | 
			
		||||
                content.attributes.range[0].starting_page >
 | 
			
		||||
                currentRangePage + 1
 | 
			
		||||
              ) {
 | 
			
		||||
                prettyTestError(
 | 
			
		||||
                  router,
 | 
			
		||||
                  `Missing pages ${currentRangePage + 1} to ${
 | 
			
		||||
                    content.attributes.range[0].starting_page - 1
 | 
			
		||||
                  }`,
 | 
			
		||||
                  ["libraryItem", "content", content.id, "range"],
 | 
			
		||||
                  libraryItemURL
 | 
			
		||||
                );
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              if (!content.attributes.content.data) {
 | 
			
		||||
                prettyTestWarning(
 | 
			
		||||
                  router,
 | 
			
		||||
                  "Missing content",
 | 
			
		||||
                  ["libraryItem", "content", content.id, "range"],
 | 
			
		||||
                  libraryItemURL
 | 
			
		||||
                );
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              currentRangePage = content.attributes.range[0].ending_page;
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
 | 
			
		||||
          if (item.metadata[0].__typename === "ComponentMetadataBooks") {
 | 
			
		||||
            if (currentRangePage < item.metadata[0].page_count) {
 | 
			
		||||
              prettyTestError(
 | 
			
		||||
                router,
 | 
			
		||||
                `Missing pages ${currentRangePage + 1} to ${
 | 
			
		||||
                  item.metadata[0].page_count
 | 
			
		||||
                  content.attributes.range[0].starting_page - 1
 | 
			
		||||
                }`,
 | 
			
		||||
                ["libraryItem", "content"],
 | 
			
		||||
                libraryItemURL
 | 
			
		||||
              );
 | 
			
		||||
            } else if (currentRangePage > item.metadata[0].page_count) {
 | 
			
		||||
              prettyTestError(
 | 
			
		||||
                router,
 | 
			
		||||
                `Page overflow, content references pages up to ${currentRangePage} when the highest expected was ${item.metadata[0].page_count}`,
 | 
			
		||||
                ["libraryItem", "content"],
 | 
			
		||||
                ["libraryItem", "content", content.id, "range"],
 | 
			
		||||
                libraryItemURL
 | 
			
		||||
              );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (item.metadata[0].languages.data.length === 0) {
 | 
			
		||||
            if (!content.attributes.content.data) {
 | 
			
		||||
              prettyTestWarning(
 | 
			
		||||
                router,
 | 
			
		||||
                "Missing language",
 | 
			
		||||
                ["libraryItem", "metadata"],
 | 
			
		||||
                "Missing content",
 | 
			
		||||
                ["libraryItem", "content", content.id, "range"],
 | 
			
		||||
                libraryItemURL
 | 
			
		||||
              );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!item.metadata[0].page_count) {
 | 
			
		||||
              prettyTestWarning(
 | 
			
		||||
                router,
 | 
			
		||||
                "Missing page_count",
 | 
			
		||||
                ["libraryItem", "metadata"],
 | 
			
		||||
                libraryItemURL
 | 
			
		||||
              );
 | 
			
		||||
            }
 | 
			
		||||
            currentRangePage = content.attributes.range[0].ending_page;
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        if (item.metadata[0].__typename === "ComponentMetadataBooks") {
 | 
			
		||||
          if (currentRangePage < item.metadata[0].page_count) {
 | 
			
		||||
            prettyTestError(
 | 
			
		||||
              router,
 | 
			
		||||
              `Missing pages ${currentRangePage + 1} to ${
 | 
			
		||||
                item.metadata[0].page_count
 | 
			
		||||
              }`,
 | 
			
		||||
              ["libraryItem", "content"],
 | 
			
		||||
              libraryItemURL
 | 
			
		||||
            );
 | 
			
		||||
          } else if (currentRangePage > item.metadata[0].page_count) {
 | 
			
		||||
            prettyTestError(
 | 
			
		||||
              router,
 | 
			
		||||
              `Page overflow, content references pages up to ${currentRangePage} when the highest expected was ${item.metadata[0].page_count}`,
 | 
			
		||||
              ["libraryItem", "content"],
 | 
			
		||||
              libraryItemURL
 | 
			
		||||
            );
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          if (item.metadata[0].languages.data.length === 0) {
 | 
			
		||||
            prettyTestWarning(
 | 
			
		||||
              router,
 | 
			
		||||
              "Missing language",
 | 
			
		||||
              ["libraryItem", "metadata"],
 | 
			
		||||
              libraryItemURL
 | 
			
		||||
            );
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          if (!item.metadata[0].page_count) {
 | 
			
		||||
            prettyTestWarning(
 | 
			
		||||
              router,
 | 
			
		||||
              "Missing page_count",
 | 
			
		||||
              ["libraryItem", "metadata"],
 | 
			
		||||
              libraryItemURL
 | 
			
		||||
            );
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
@ -1,23 +1,23 @@
 | 
			
		||||
import { GetStaticProps } from "next";
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import AppLayout from "components/AppLayout";
 | 
			
		||||
import Chip from "components/Chip";
 | 
			
		||||
import LibraryItemsPreview from "components/Library/LibraryItemsPreview";
 | 
			
		||||
import PanelHeader from "components/PanelComponents/PanelHeader";
 | 
			
		||||
import ContentPanel, {
 | 
			
		||||
  ContentPanelWidthSizes,
 | 
			
		||||
} from "components/Panels/ContentPanel";
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import Select from "components/Select";
 | 
			
		||||
import Switch from "components/Switch";
 | 
			
		||||
import { getLibraryItemsPreview } from "graphql/operations";
 | 
			
		||||
import {
 | 
			
		||||
  GetCurrenciesQuery,
 | 
			
		||||
  GetLibraryItemsPreviewQuery,
 | 
			
		||||
  GetWebsiteInterfaceQuery,
 | 
			
		||||
} from "graphql/operations-types";
 | 
			
		||||
import { getLibraryItemsPreview } from "graphql/operations";
 | 
			
		||||
import PanelHeader from "components/PanelComponents/PanelHeader";
 | 
			
		||||
import AppLayout from "components/AppLayout";
 | 
			
		||||
import LibraryItemsPreview from "components/Library/LibraryItemsPreview";
 | 
			
		||||
import Select from "components/Select";
 | 
			
		||||
import { useEffect, useState } from "react";
 | 
			
		||||
import { convertPrice, prettyDate, prettyinlineTitle } from "queries/helpers";
 | 
			
		||||
import Switch from "components/Switch";
 | 
			
		||||
import { GetStaticPropsContext } from "next";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
import Chip from "components/Chip";
 | 
			
		||||
import { convertPrice, prettyDate, prettyinlineTitle } from "queries/helpers";
 | 
			
		||||
import { useEffect, useState } from "react";
 | 
			
		||||
 | 
			
		||||
interface LibraryProps extends AppStaticProps {
 | 
			
		||||
  items: GetLibraryItemsPreviewQuery["libraryItems"]["data"];
 | 
			
		||||
@ -29,7 +29,7 @@ type GroupLibraryItems = Map<
 | 
			
		||||
>;
 | 
			
		||||
 | 
			
		||||
export default function Library(props: LibraryProps): JSX.Element {
 | 
			
		||||
  const { langui, items, currencies } = props;
 | 
			
		||||
  const { langui, items: libraryItems, currencies } = props;
 | 
			
		||||
 | 
			
		||||
  const [showSubitems, setShowSubitems] = useState<boolean>(false);
 | 
			
		||||
  const [showPrimaryItems, setShowPrimaryItems] = useState<boolean>(true);
 | 
			
		||||
@ -38,7 +38,12 @@ export default function Library(props: LibraryProps): JSX.Element {
 | 
			
		||||
  const [groupingMethod, setGroupingMethod] = useState<number>(-1);
 | 
			
		||||
 | 
			
		||||
  const [filteredItems, setFilteredItems] = useState<LibraryProps["items"]>(
 | 
			
		||||
    filterItems(showSubitems, showPrimaryItems, showSecondaryItems, items)
 | 
			
		||||
    filterItems(
 | 
			
		||||
      showSubitems,
 | 
			
		||||
      showPrimaryItems,
 | 
			
		||||
      showSecondaryItems,
 | 
			
		||||
      libraryItems
 | 
			
		||||
    )
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  const [sortedItems, setSortedItem] = useState<LibraryProps["items"]>(
 | 
			
		||||
@ -51,9 +56,14 @@ export default function Library(props: LibraryProps): JSX.Element {
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    setFilteredItems(
 | 
			
		||||
      filterItems(showSubitems, showPrimaryItems, showSecondaryItems, items)
 | 
			
		||||
      filterItems(
 | 
			
		||||
        showSubitems,
 | 
			
		||||
        showPrimaryItems,
 | 
			
		||||
        showSecondaryItems,
 | 
			
		||||
        libraryItems
 | 
			
		||||
      )
 | 
			
		||||
    );
 | 
			
		||||
  }, [showSubitems, items, showPrimaryItems, showSecondaryItems]);
 | 
			
		||||
  }, [showSubitems, libraryItems, showPrimaryItems, showSecondaryItems]);
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    setSortedItem(sortBy(sortingMethod, filteredItems, currencies));
 | 
			
		||||
@ -116,7 +126,7 @@ export default function Library(props: LibraryProps): JSX.Element {
 | 
			
		||||
            <>
 | 
			
		||||
              {name && (
 | 
			
		||||
                <h2
 | 
			
		||||
                  key={"h2" + name}
 | 
			
		||||
                  key={`h2${name}`}
 | 
			
		||||
                  className="text-2xl pb-2 pt-10 first-of-type:pt-0 flex flex-row place-items-center gap-2"
 | 
			
		||||
                >
 | 
			
		||||
                  {name}
 | 
			
		||||
@ -128,7 +138,7 @@ export default function Library(props: LibraryProps): JSX.Element {
 | 
			
		||||
                </h2>
 | 
			
		||||
              )}
 | 
			
		||||
              <div
 | 
			
		||||
                key={"items" + name}
 | 
			
		||||
                key={`items${name}`}
 | 
			
		||||
                className="grid gap-8 items-end mobile:grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(13rem,1fr))] pb-12 border-b-[3px] border-dotted last-of-type:border-0"
 | 
			
		||||
              >
 | 
			
		||||
                {items.map((item) => (
 | 
			
		||||
@ -155,19 +165,21 @@ export default function Library(props: LibraryProps): JSX.Element {
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
export async function getStaticProps(
 | 
			
		||||
  context: GetStaticPropsContext
 | 
			
		||||
): Promise<{ props: LibraryProps }> {
 | 
			
		||||
  const props: LibraryProps = {
 | 
			
		||||
    ...(await getAppStaticProps(context)),
 | 
			
		||||
    items: (
 | 
			
		||||
      await getLibraryItemsPreview({
 | 
			
		||||
        language_code: context.locale || "en",
 | 
			
		||||
        language_code: context.locale ?? "en",
 | 
			
		||||
      })
 | 
			
		||||
    ).libraryItems.data,
 | 
			
		||||
  };
 | 
			
		||||
  return {
 | 
			
		||||
    props: props,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getGroups(
 | 
			
		||||
  langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"],
 | 
			
		||||
@ -175,7 +187,7 @@ function getGroups(
 | 
			
		||||
  items: LibraryProps["items"]
 | 
			
		||||
): GroupLibraryItems {
 | 
			
		||||
  switch (groupByType) {
 | 
			
		||||
    case 0:
 | 
			
		||||
    case 0: {
 | 
			
		||||
      const typeGroup = new Map();
 | 
			
		||||
      typeGroup.set("Drakengard 1", []);
 | 
			
		||||
      typeGroup.set("Drakengard 1.3", []);
 | 
			
		||||
@ -207,63 +219,73 @@ function getGroups(
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      return typeGroup;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    case 1:
 | 
			
		||||
      const groupType: GroupLibraryItems = new Map();
 | 
			
		||||
      groupType.set(langui.audio, []);
 | 
			
		||||
      groupType.set(langui.game, []);
 | 
			
		||||
      groupType.set(langui.textual, []);
 | 
			
		||||
      groupType.set(langui.video, []);
 | 
			
		||||
      groupType.set(langui.other, []);
 | 
			
		||||
      groupType.set(langui.group, []);
 | 
			
		||||
      groupType.set(langui.no_type, []);
 | 
			
		||||
    case 1: {
 | 
			
		||||
      const group: GroupLibraryItems = new Map();
 | 
			
		||||
      group.set(langui.audio, []);
 | 
			
		||||
      group.set(langui.game, []);
 | 
			
		||||
      group.set(langui.textual, []);
 | 
			
		||||
      group.set(langui.video, []);
 | 
			
		||||
      group.set(langui.other, []);
 | 
			
		||||
      group.set(langui.group, []);
 | 
			
		||||
      group.set(langui.no_type, []);
 | 
			
		||||
      items.map((item) => {
 | 
			
		||||
        if (item.attributes.metadata.length > 0) {
 | 
			
		||||
          switch (item.attributes.metadata[0].__typename) {
 | 
			
		||||
            case "ComponentMetadataAudio":
 | 
			
		||||
              groupType.get(langui.audio)?.push(item);
 | 
			
		||||
              group.get(langui.audio)?.push(item);
 | 
			
		||||
              break;
 | 
			
		||||
            case "ComponentMetadataGame":
 | 
			
		||||
              groupType.get(langui.game)?.push(item);
 | 
			
		||||
              group.get(langui.game)?.push(item);
 | 
			
		||||
              break;
 | 
			
		||||
            case "ComponentMetadataBooks":
 | 
			
		||||
              groupType.get(langui.textual)?.push(item);
 | 
			
		||||
              group.get(langui.textual)?.push(item);
 | 
			
		||||
              break;
 | 
			
		||||
            case "ComponentMetadataVideo":
 | 
			
		||||
              groupType.get(langui.video)?.push(item);
 | 
			
		||||
              group.get(langui.video)?.push(item);
 | 
			
		||||
              break;
 | 
			
		||||
            case "ComponentMetadataOther":
 | 
			
		||||
              groupType.get(langui.other)?.push(item);
 | 
			
		||||
              group.get(langui.other)?.push(item);
 | 
			
		||||
              break;
 | 
			
		||||
            case "ComponentMetadataGroup":
 | 
			
		||||
              switch (
 | 
			
		||||
                item.attributes.metadata[0].subitems_type.data.attributes.slug
 | 
			
		||||
              ) {
 | 
			
		||||
                case "audio":
 | 
			
		||||
                  groupType.get(langui.audio)?.push(item);
 | 
			
		||||
                  group.get(langui.audio)?.push(item);
 | 
			
		||||
                  break;
 | 
			
		||||
                case "video":
 | 
			
		||||
                  groupType.get(langui.video)?.push(item);
 | 
			
		||||
                  group.get(langui.video)?.push(item);
 | 
			
		||||
                  break;
 | 
			
		||||
                case "game":
 | 
			
		||||
                  groupType.get(langui.game)?.push(item);
 | 
			
		||||
                  group.get(langui.game)?.push(item);
 | 
			
		||||
                  break;
 | 
			
		||||
                case "textual":
 | 
			
		||||
                  groupType.get(langui.textual)?.push(item);
 | 
			
		||||
                  group.get(langui.textual)?.push(item);
 | 
			
		||||
                  break;
 | 
			
		||||
                case "mixed":
 | 
			
		||||
                  groupType.get(langui.group)?.push(item);
 | 
			
		||||
                  group.get(langui.group)?.push(item);
 | 
			
		||||
                  break;
 | 
			
		||||
                default: {
 | 
			
		||||
                  throw new Error(
 | 
			
		||||
                    "An unexpected subtype of group-metadata was given"
 | 
			
		||||
                  );
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
              break;
 | 
			
		||||
            default: {
 | 
			
		||||
              throw new Error("An unexpected type of metadata was given");
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        } else {
 | 
			
		||||
          groupType.get(langui.no_type)?.push(item);
 | 
			
		||||
          group.get(langui.no_type)?.push(item);
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
      return groupType;
 | 
			
		||||
      return group;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    case 2:
 | 
			
		||||
    case 2: {
 | 
			
		||||
      const years: number[] = [];
 | 
			
		||||
      items.map((item) => {
 | 
			
		||||
        if (item.attributes.release_date) {
 | 
			
		||||
@ -271,28 +293,28 @@ function getGroups(
 | 
			
		||||
            years.push(item.attributes.release_date.year);
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
      const groupYear: GroupLibraryItems = new Map();
 | 
			
		||||
      years.sort();
 | 
			
		||||
      const group: GroupLibraryItems = new Map();
 | 
			
		||||
      years.sort((a, b) => a - b);
 | 
			
		||||
      years.map((year) => {
 | 
			
		||||
        groupYear.set(year.toString(), []);
 | 
			
		||||
        group.set(year.toString(), []);
 | 
			
		||||
      });
 | 
			
		||||
      groupYear.set(langui.no_year, []);
 | 
			
		||||
      group.set(langui.no_year, []);
 | 
			
		||||
      items.map((item) => {
 | 
			
		||||
        if (item.attributes.release_date) {
 | 
			
		||||
          groupYear
 | 
			
		||||
            .get(item.attributes.release_date.year.toString())
 | 
			
		||||
            ?.push(item);
 | 
			
		||||
          group.get(item.attributes.release_date.year.toString())?.push(item);
 | 
			
		||||
        } else {
 | 
			
		||||
          groupYear.get(langui.no_year)?.push(item);
 | 
			
		||||
          group.get(langui.no_year)?.push(item);
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      return groupYear;
 | 
			
		||||
      return group;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
      const groupDefault: GroupLibraryItems = new Map();
 | 
			
		||||
      groupDefault.set("", items);
 | 
			
		||||
      return groupDefault;
 | 
			
		||||
    default: {
 | 
			
		||||
      const group: GroupLibraryItems = new Map();
 | 
			
		||||
      group.set("", items);
 | 
			
		||||
      return group;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -353,13 +375,13 @@ function sortBy(
 | 
			
		||||
    case 2:
 | 
			
		||||
      return [...items].sort((a, b) => {
 | 
			
		||||
        const dateA =
 | 
			
		||||
          a.attributes.release_date !== null
 | 
			
		||||
            ? prettyDate(a.attributes.release_date)
 | 
			
		||||
            : "9999";
 | 
			
		||||
          a.attributes.release_date === null
 | 
			
		||||
            ? "9999"
 | 
			
		||||
            : prettyDate(a.attributes.release_date);
 | 
			
		||||
        const dateB =
 | 
			
		||||
          b.attributes.release_date !== null
 | 
			
		||||
            ? prettyDate(b.attributes.release_date)
 | 
			
		||||
            : "9999";
 | 
			
		||||
          b.attributes.release_date === null
 | 
			
		||||
            ? "9999"
 | 
			
		||||
            : prettyDate(b.attributes.release_date);
 | 
			
		||||
        return dateA.localeCompare(dateB);
 | 
			
		||||
      });
 | 
			
		||||
    default:
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import PanelHeader from "components/PanelComponents/PanelHeader";
 | 
			
		||||
import { GetStaticProps } from "next";
 | 
			
		||||
import AppLayout from "components/AppLayout";
 | 
			
		||||
import PanelHeader from "components/PanelComponents/PanelHeader";
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import { GetStaticPropsContext } from "next";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
 | 
			
		||||
interface MerchProps extends AppStaticProps {}
 | 
			
		||||
@ -20,11 +20,13 @@ export default function Merch(props: MerchProps): JSX.Element {
 | 
			
		||||
  return <AppLayout navTitle={langui.merch} subPanel={subPanel} {...props} />;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
export async function getStaticProps(
 | 
			
		||||
  context: GetStaticPropsContext
 | 
			
		||||
): Promise<{ props: MerchProps }> {
 | 
			
		||||
  const props: MerchProps = {
 | 
			
		||||
    ...(await getAppStaticProps(context)),
 | 
			
		||||
  };
 | 
			
		||||
  return {
 | 
			
		||||
    props: props,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -14,10 +14,14 @@ import RecorderChip from "components/RecorderChip";
 | 
			
		||||
import ToolTip from "components/ToolTip";
 | 
			
		||||
import { getPost, getPostLanguages, getPostsSlugs } from "graphql/operations";
 | 
			
		||||
import { GetPostQuery, StrapiImage } from "graphql/operations-types";
 | 
			
		||||
import { GetStaticPaths, GetStaticProps } from "next";
 | 
			
		||||
import {
 | 
			
		||||
  GetStaticPathsContext,
 | 
			
		||||
  GetStaticPathsResult,
 | 
			
		||||
  GetStaticPropsContext,
 | 
			
		||||
} from "next";
 | 
			
		||||
import { useRouter } from "next/router";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
import { prettySlug, getStatusDescription } from "queries/helpers";
 | 
			
		||||
import { getStatusDescription, prettySlug } from "queries/helpers";
 | 
			
		||||
 | 
			
		||||
interface PostProps extends AppStaticProps {
 | 
			
		||||
  post: GetPostQuery["posts"]["data"][number]["attributes"];
 | 
			
		||||
@ -42,7 +46,7 @@ export default function LibrarySlug(props: PostProps): JSX.Element {
 | 
			
		||||
        href="/news"
 | 
			
		||||
        title={langui.news}
 | 
			
		||||
        langui={langui}
 | 
			
		||||
        displayOn={ReturnButtonType.Desktop}
 | 
			
		||||
        displayOn={ReturnButtonType.desktop}
 | 
			
		||||
        horizontalLine
 | 
			
		||||
      />
 | 
			
		||||
 | 
			
		||||
@ -87,7 +91,7 @@ export default function LibrarySlug(props: PostProps): JSX.Element {
 | 
			
		||||
        href="/news"
 | 
			
		||||
        title={langui.news}
 | 
			
		||||
        langui={langui}
 | 
			
		||||
        displayOn={ReturnButtonType.Mobile}
 | 
			
		||||
        displayOn={ReturnButtonType.mobile}
 | 
			
		||||
        className="mb-10"
 | 
			
		||||
      />
 | 
			
		||||
 | 
			
		||||
@ -109,7 +113,7 @@ export default function LibrarySlug(props: PostProps): JSX.Element {
 | 
			
		||||
 | 
			
		||||
      <HorizontalLine />
 | 
			
		||||
 | 
			
		||||
      {locales.includes(router.locale || "en") ? (
 | 
			
		||||
      {locales.includes(router.locale ?? "en") ? (
 | 
			
		||||
        <Markdawn router={router} text={post.translations[0].body} />
 | 
			
		||||
      ) : (
 | 
			
		||||
        <LanguageSwitcher
 | 
			
		||||
@ -138,12 +142,14 @@ export default function LibrarySlug(props: PostProps): JSX.Element {
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
  const slug = context.params?.slug?.toString() || "";
 | 
			
		||||
export async function getStaticProps(
 | 
			
		||||
  context: GetStaticPropsContext
 | 
			
		||||
): Promise<{ props: PostProps }> {
 | 
			
		||||
  const slug = context.params?.slug?.toString() ?? "";
 | 
			
		||||
  const post = (
 | 
			
		||||
    await getPost({
 | 
			
		||||
      slug: slug,
 | 
			
		||||
      language_code: context.locale || "en",
 | 
			
		||||
      language_code: context.locale ?? "en",
 | 
			
		||||
    })
 | 
			
		||||
  ).posts.data[0];
 | 
			
		||||
  const props: PostProps = {
 | 
			
		||||
@ -152,26 +158,21 @@ export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
    postId: post.id,
 | 
			
		||||
    locales: (
 | 
			
		||||
      await getPostLanguages({ slug: slug })
 | 
			
		||||
    ).posts.data[0].attributes.translations.map((translation) => {
 | 
			
		||||
      return translation.language.data.attributes.code;
 | 
			
		||||
    }),
 | 
			
		||||
    ).posts.data[0].attributes.translations.map(
 | 
			
		||||
      (translation) => translation.language.data.attributes.code
 | 
			
		||||
    ),
 | 
			
		||||
  };
 | 
			
		||||
  return {
 | 
			
		||||
    props: props,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getStaticPaths: GetStaticPaths = async (context) => {
 | 
			
		||||
  type Path = {
 | 
			
		||||
    params: {
 | 
			
		||||
      slug: string;
 | 
			
		||||
    };
 | 
			
		||||
    locale: string;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const data = await getPostsSlugs({});
 | 
			
		||||
  const paths: Path[] = [];
 | 
			
		||||
  data.posts.data.map((item) => {
 | 
			
		||||
export async function getStaticPaths(
 | 
			
		||||
  context: GetStaticPathsContext
 | 
			
		||||
): Promise<GetStaticPathsResult> {
 | 
			
		||||
  const posts = await getPostsSlugs({});
 | 
			
		||||
  const paths: GetStaticPathsResult["paths"] = [];
 | 
			
		||||
  posts.posts.data.map((item) => {
 | 
			
		||||
    context.locales?.map((local) => {
 | 
			
		||||
      paths.push({ params: { slug: item.attributes.slug }, locale: local });
 | 
			
		||||
    });
 | 
			
		||||
@ -180,4 +181,4 @@ export const getStaticPaths: GetStaticPaths = async (context) => {
 | 
			
		||||
    paths,
 | 
			
		||||
    fallback: false,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,14 +1,14 @@
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import PanelHeader from "components/PanelComponents/PanelHeader";
 | 
			
		||||
import { GetStaticProps } from "next";
 | 
			
		||||
import AppLayout from "components/AppLayout";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
import { GetPostsPreviewQuery } from "graphql/operations-types";
 | 
			
		||||
import { getPostsPreview } from "graphql/operations";
 | 
			
		||||
import PostsPreview from "components/News/PostsPreview";
 | 
			
		||||
import PanelHeader from "components/PanelComponents/PanelHeader";
 | 
			
		||||
import ContentPanel, {
 | 
			
		||||
  ContentPanelWidthSizes,
 | 
			
		||||
} from "components/Panels/ContentPanel";
 | 
			
		||||
import PostsPreview from "components/News/PostsPreview";
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import { getPostsPreview } from "graphql/operations";
 | 
			
		||||
import { GetPostsPreviewQuery } from "graphql/operations-types";
 | 
			
		||||
import { GetStaticPropsContext } from "next";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
 | 
			
		||||
interface NewsProps extends AppStaticProps {
 | 
			
		||||
  posts: GetPostsPreviewQuery["posts"]["data"];
 | 
			
		||||
@ -46,14 +46,16 @@ export default function News(props: NewsProps): JSX.Element {
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
export async function getStaticProps(
 | 
			
		||||
  context: GetStaticPropsContext
 | 
			
		||||
): Promise<{ props: NewsProps }> {
 | 
			
		||||
  const props: NewsProps = {
 | 
			
		||||
    ...(await getAppStaticProps(context)),
 | 
			
		||||
    posts: await (
 | 
			
		||||
      await getPostsPreview({ language_code: context.locale || "en" })
 | 
			
		||||
      await getPostsPreview({ language_code: context.locale ?? "en" })
 | 
			
		||||
    ).posts.data,
 | 
			
		||||
  };
 | 
			
		||||
  return {
 | 
			
		||||
    props: props,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,25 +1,25 @@
 | 
			
		||||
import { GetStaticProps } from "next";
 | 
			
		||||
import AppLayout from "components/AppLayout";
 | 
			
		||||
import ChronologyYearComponent from "components/Chronology/ChronologyYearComponent";
 | 
			
		||||
import InsetBox from "components/InsetBox";
 | 
			
		||||
import NavOption from "components/PanelComponents/NavOption";
 | 
			
		||||
import ReturnButton, {
 | 
			
		||||
  ReturnButtonType,
 | 
			
		||||
} from "components/PanelComponents/ReturnButton";
 | 
			
		||||
import ContentPanel from "components/Panels/ContentPanel";
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import ChronologyYearComponent from "components/Chronology/ChronologyYearComponent";
 | 
			
		||||
import { getChronologyItems, getEras } from "graphql/operations";
 | 
			
		||||
import {
 | 
			
		||||
  GetChronologyItemsQuery,
 | 
			
		||||
  GetErasQuery,
 | 
			
		||||
} from "graphql/operations-types";
 | 
			
		||||
import { getEras, getChronologyItems } from "graphql/operations";
 | 
			
		||||
import NavOption from "components/PanelComponents/NavOption";
 | 
			
		||||
import AppLayout from "components/AppLayout";
 | 
			
		||||
import { GetStaticPropsContext } from "next";
 | 
			
		||||
import { useRouter } from "next/router";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
import {
 | 
			
		||||
  prettySlug,
 | 
			
		||||
  prettyTestError,
 | 
			
		||||
  prettyTestWarning,
 | 
			
		||||
} from "queries/helpers";
 | 
			
		||||
import InsetBox from "components/InsetBox";
 | 
			
		||||
import { useRouter } from "next/router";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
import ReturnButton, {
 | 
			
		||||
  ReturnButtonType,
 | 
			
		||||
} from "components/PanelComponents/ReturnButton";
 | 
			
		||||
 | 
			
		||||
interface ChronologyProps extends AppStaticProps {
 | 
			
		||||
  chronologyItems: GetChronologyItemsQuery["chronologyItems"]["data"];
 | 
			
		||||
@ -31,7 +31,7 @@ export default function Chronology(props: ChronologyProps): JSX.Element {
 | 
			
		||||
  const { chronologyItems, chronologyEras, langui } = props;
 | 
			
		||||
 | 
			
		||||
  // Group by year the Chronology items
 | 
			
		||||
  let chronologyItemYearGroups: GetChronologyItemsQuery["chronologyItems"]["data"][number][][][] =
 | 
			
		||||
  const chronologyItemYearGroups: GetChronologyItemsQuery["chronologyItems"]["data"][number][][][] =
 | 
			
		||||
    [];
 | 
			
		||||
 | 
			
		||||
  chronologyEras.map(() => {
 | 
			
		||||
@ -44,20 +44,21 @@ export default function Chronology(props: ChronologyProps): JSX.Element {
 | 
			
		||||
      item.attributes.year >
 | 
			
		||||
      chronologyEras[currentChronologyEraIndex].attributes.ending_year
 | 
			
		||||
    ) {
 | 
			
		||||
      currentChronologyEraIndex++;
 | 
			
		||||
      currentChronologyEraIndex += 1;
 | 
			
		||||
    }
 | 
			
		||||
    if (
 | 
			
		||||
      !chronologyItemYearGroups[currentChronologyEraIndex].hasOwnProperty(
 | 
			
		||||
      Object.prototype.hasOwnProperty.call(
 | 
			
		||||
        chronologyItemYearGroups[currentChronologyEraIndex],
 | 
			
		||||
        item.attributes.year
 | 
			
		||||
      )
 | 
			
		||||
    ) {
 | 
			
		||||
      chronologyItemYearGroups[currentChronologyEraIndex][
 | 
			
		||||
        item.attributes.year
 | 
			
		||||
      ] = [item];
 | 
			
		||||
      ].push(item);
 | 
			
		||||
    } else {
 | 
			
		||||
      chronologyItemYearGroups[currentChronologyEraIndex][
 | 
			
		||||
        item.attributes.year
 | 
			
		||||
      ].push(item);
 | 
			
		||||
      ] = [item];
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
@ -67,22 +68,20 @@ export default function Chronology(props: ChronologyProps): JSX.Element {
 | 
			
		||||
        href="/wiki"
 | 
			
		||||
        title={langui.wiki}
 | 
			
		||||
        langui={langui}
 | 
			
		||||
        displayOn={ReturnButtonType.Desktop}
 | 
			
		||||
        displayOn={ReturnButtonType.desktop}
 | 
			
		||||
        horizontalLine
 | 
			
		||||
      />
 | 
			
		||||
 | 
			
		||||
      {chronologyEras.map((era) => (
 | 
			
		||||
        <NavOption
 | 
			
		||||
          key={era.id}
 | 
			
		||||
          url={"#" + era.attributes.slug}
 | 
			
		||||
          url={`#${era.attributes.slug}`}
 | 
			
		||||
          title={
 | 
			
		||||
            era.attributes.title.length > 0
 | 
			
		||||
              ? era.attributes.title[0].title
 | 
			
		||||
              : prettySlug(era.attributes.slug)
 | 
			
		||||
          }
 | 
			
		||||
          subtitle={
 | 
			
		||||
            era.attributes.starting_year + " → " + era.attributes.ending_year
 | 
			
		||||
          }
 | 
			
		||||
          subtitle={`${era.attributes.starting_year} → ${era.attributes.ending_year}`}
 | 
			
		||||
          border
 | 
			
		||||
        />
 | 
			
		||||
      ))}
 | 
			
		||||
@ -95,7 +94,7 @@ export default function Chronology(props: ChronologyProps): JSX.Element {
 | 
			
		||||
        href="/wiki"
 | 
			
		||||
        title={langui.wiki}
 | 
			
		||||
        langui={langui}
 | 
			
		||||
        displayOn={ReturnButtonType.Mobile}
 | 
			
		||||
        displayOn={ReturnButtonType.mobile}
 | 
			
		||||
        className="mb-10"
 | 
			
		||||
      />
 | 
			
		||||
 | 
			
		||||
@ -139,29 +138,29 @@ export default function Chronology(props: ChronologyProps): JSX.Element {
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
export async function getStaticProps(
 | 
			
		||||
  context: GetStaticPropsContext
 | 
			
		||||
): Promise<{ props: ChronologyProps }> {
 | 
			
		||||
  const props: ChronologyProps = {
 | 
			
		||||
    ...(await getAppStaticProps(context)),
 | 
			
		||||
    chronologyItems: (
 | 
			
		||||
      await getChronologyItems({
 | 
			
		||||
        language_code: context.locale || "en",
 | 
			
		||||
        language_code: context.locale ?? "en",
 | 
			
		||||
      })
 | 
			
		||||
    ).chronologyItems.data,
 | 
			
		||||
    chronologyEras: (await getEras({ language_code: context.locale || "en" }))
 | 
			
		||||
    chronologyEras: (await getEras({ language_code: context.locale ?? "en" }))
 | 
			
		||||
      .chronologyEras.data,
 | 
			
		||||
  };
 | 
			
		||||
  return {
 | 
			
		||||
    props: props,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function useTesting(props: ChronologyProps) {
 | 
			
		||||
  const router = useRouter();
 | 
			
		||||
  const { chronologyItems, chronologyEras } = props;
 | 
			
		||||
  chronologyEras.map((era) => {
 | 
			
		||||
    const chronologyErasURL =
 | 
			
		||||
      "/admin/content-manager/collectionType/api::chronology-era.chronology-era/" +
 | 
			
		||||
      chronologyItems[0].id;
 | 
			
		||||
    const chronologyErasURL = `/admin/content-manager/collectionType/api::chronology-era.chronology-era/${chronologyItems[0].id}`;
 | 
			
		||||
 | 
			
		||||
    if (era.attributes.title.length === 0) {
 | 
			
		||||
      prettyTestError(
 | 
			
		||||
@ -196,20 +195,11 @@ function useTesting(props: ChronologyProps) {
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  chronologyItems.map((item) => {
 | 
			
		||||
    const chronologyItemsURL =
 | 
			
		||||
      "/admin/content-manager/collectionType/api::chronology-item.chronology-item/" +
 | 
			
		||||
      chronologyItems[0].id;
 | 
			
		||||
    const chronologyItemsURL = `/admin/content-manager/collectionType/api::chronology-item.chronology-item/${chronologyItems[0].id}`;
 | 
			
		||||
 | 
			
		||||
    const date = `${item.attributes.year}/${item.attributes.month}/${item.attributes.day}`;
 | 
			
		||||
 | 
			
		||||
    if (!(item.attributes.events.length > 0)) {
 | 
			
		||||
      prettyTestError(
 | 
			
		||||
        router,
 | 
			
		||||
        "No events for this date",
 | 
			
		||||
        ["chronologyItems", date],
 | 
			
		||||
        chronologyItemsURL
 | 
			
		||||
      );
 | 
			
		||||
    } else {
 | 
			
		||||
    if (item.attributes.events.length > 0) {
 | 
			
		||||
      item.attributes.events.map((event) => {
 | 
			
		||||
        if (!event.source.data) {
 | 
			
		||||
          prettyTestError(
 | 
			
		||||
@ -228,6 +218,13 @@ function useTesting(props: ChronologyProps) {
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    } else {
 | 
			
		||||
      prettyTestError(
 | 
			
		||||
        router,
 | 
			
		||||
        "No events for this date",
 | 
			
		||||
        ["chronologyItems", date],
 | 
			
		||||
        chronologyItemsURL
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,9 @@
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import PanelHeader from "components/PanelComponents/PanelHeader";
 | 
			
		||||
import { GetStaticProps } from "next";
 | 
			
		||||
import AppLayout from "components/AppLayout";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
import HorizontalLine from "components/HorizontalLine";
 | 
			
		||||
import NavOption from "components/PanelComponents/NavOption";
 | 
			
		||||
import PanelHeader from "components/PanelComponents/PanelHeader";
 | 
			
		||||
import SubPanel from "components/Panels/SubPanel";
 | 
			
		||||
import { GetStaticPropsContext } from "next";
 | 
			
		||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
 | 
			
		||||
 | 
			
		||||
interface WikiProps extends AppStaticProps {}
 | 
			
		||||
 | 
			
		||||
@ -24,11 +23,13 @@ export default function Wiki(props: WikiProps): JSX.Element {
 | 
			
		||||
  return <AppLayout navTitle={langui.wiki} subPanel={subPanel} {...props} />;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getStaticProps: GetStaticProps = async (context) => {
 | 
			
		||||
export async function getStaticProps(
 | 
			
		||||
  context: GetStaticPropsContext
 | 
			
		||||
): Promise<{ props: WikiProps }> {
 | 
			
		||||
  const props: WikiProps = {
 | 
			
		||||
    ...(await getAppStaticProps(context)),
 | 
			
		||||
  };
 | 
			
		||||
  return {
 | 
			
		||||
    props: props,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -8,8 +8,7 @@ import {
 | 
			
		||||
  GetLanguagesQuery,
 | 
			
		||||
  GetWebsiteInterfaceQuery,
 | 
			
		||||
} from "graphql/operations-types";
 | 
			
		||||
import { GetStaticPropsContext, PreviewData } from "next";
 | 
			
		||||
import { ParsedUrlQuery } from "querystring";
 | 
			
		||||
import { GetStaticPropsContext } from "next";
 | 
			
		||||
 | 
			
		||||
export interface AppStaticProps {
 | 
			
		||||
  langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"];
 | 
			
		||||
@ -18,24 +17,20 @@ export interface AppStaticProps {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function getAppStaticProps(
 | 
			
		||||
  context: GetStaticPropsContext<ParsedUrlQuery, PreviewData>
 | 
			
		||||
  context: GetStaticPropsContext
 | 
			
		||||
): Promise<AppStaticProps> {
 | 
			
		||||
  const languages = (await getLanguages({})).languages.data;
 | 
			
		||||
  languages.sort((a, b) => {
 | 
			
		||||
    return a.attributes.localized_name.localeCompare(
 | 
			
		||||
      b.attributes.localized_name
 | 
			
		||||
    );
 | 
			
		||||
  });
 | 
			
		||||
  languages.sort((a, b) =>
 | 
			
		||||
    a.attributes.localized_name.localeCompare(b.attributes.localized_name)
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  const currencies = (await getCurrencies({})).currencies.data;
 | 
			
		||||
  currencies.sort((a, b) => {
 | 
			
		||||
    return a.attributes.code.localeCompare(b.attributes.code);
 | 
			
		||||
  });
 | 
			
		||||
  currencies.sort((a, b) => a.attributes.code.localeCompare(b.attributes.code));
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    langui: (
 | 
			
		||||
      await getWebsiteInterface({
 | 
			
		||||
        language_code: context.locale || "en",
 | 
			
		||||
        language_code: context.locale ?? "en",
 | 
			
		||||
      })
 | 
			
		||||
    ).websiteInterfaces.data[0].attributes,
 | 
			
		||||
    currencies: currencies,
 | 
			
		||||
 | 
			
		||||
@ -17,13 +17,9 @@ import { NextRouter } from "next/router";
 | 
			
		||||
export function prettyDate(
 | 
			
		||||
  datePicker: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["release_date"]
 | 
			
		||||
): string {
 | 
			
		||||
  return (
 | 
			
		||||
    datePicker.year +
 | 
			
		||||
    "/" +
 | 
			
		||||
    datePicker.month.toString().padStart(2, "0") +
 | 
			
		||||
    "/" +
 | 
			
		||||
    datePicker.day.toString().padStart(2, "0")
 | 
			
		||||
  );
 | 
			
		||||
  return `${datePicker.year}/${datePicker.month
 | 
			
		||||
    .toString()
 | 
			
		||||
    .padStart(2, "0")}/${datePicker.day.toString().padStart(2, "0")}`;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function prettyPrice(
 | 
			
		||||
@ -74,9 +70,9 @@ export function prettyinlineTitle(
 | 
			
		||||
  subtitle: string
 | 
			
		||||
): string {
 | 
			
		||||
  let result = "";
 | 
			
		||||
  if (pretitle) result += pretitle + ": ";
 | 
			
		||||
  if (pretitle) result += `${pretitle}: `;
 | 
			
		||||
  result += title;
 | 
			
		||||
  if (subtitle) result += " - " + subtitle;
 | 
			
		||||
  if (subtitle) result += ` - ${subtitle}`;
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -86,7 +82,6 @@ export function prettyItemType(
 | 
			
		||||
  },
 | 
			
		||||
  langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"]
 | 
			
		||||
): string {
 | 
			
		||||
  const type = metadata.__typename;
 | 
			
		||||
  switch (metadata.__typename) {
 | 
			
		||||
    case "ComponentMetadataAudio":
 | 
			
		||||
      return langui.audio;
 | 
			
		||||
@ -106,6 +101,7 @@ export function prettyItemType(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function prettyItemSubType(metadata: {
 | 
			
		||||
  /* eslint-disable @typescript-eslint/no-explicit-any */
 | 
			
		||||
  __typename: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["metadata"][number]["__typename"];
 | 
			
		||||
  subtype?: any;
 | 
			
		||||
  platforms?: any;
 | 
			
		||||
@ -138,6 +134,7 @@ export function prettyItemSubType(metadata: {
 | 
			
		||||
    default:
 | 
			
		||||
      return "";
 | 
			
		||||
  }
 | 
			
		||||
  /* eslint-enable @typescript-eslint/no-explicit-any */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function prettyLanguage(
 | 
			
		||||
@ -184,7 +181,7 @@ function prettyTestWritter(
 | 
			
		||||
): void {
 | 
			
		||||
  const line = [
 | 
			
		||||
    level,
 | 
			
		||||
    process.env.NEXT_PUBLIC_URL_SELF + "/" + locale + asPath,
 | 
			
		||||
    `${process.env.NEXT_PUBLIC_URL_SELF}/${locale}${asPath}`,
 | 
			
		||||
    locale,
 | 
			
		||||
    subCategory?.join(" -> "),
 | 
			
		||||
    message,
 | 
			
		||||
@ -206,7 +203,7 @@ export function capitalizeString(string: string): string {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  let words = string.split(" ");
 | 
			
		||||
  words = words.map((word) => (word = capitalizeWord(word)));
 | 
			
		||||
  words = words.map((word) => capitalizeWord(word));
 | 
			
		||||
  return words.join(" ");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -275,20 +272,22 @@ export function getStatusDescription(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function slugify(string: string | undefined): string {
 | 
			
		||||
  if (!string) return "";
 | 
			
		||||
  if (!string) {
 | 
			
		||||
    return "";
 | 
			
		||||
  }
 | 
			
		||||
  return string
 | 
			
		||||
    .replace(/[ÀÁÂÃÄÅàáâãä忯]/g, "a")
 | 
			
		||||
    .replace(/[çÇ]/g, "c")
 | 
			
		||||
    .replace(/[ðÐ]/g, "d")
 | 
			
		||||
    .replace(/[ÈÉÊËéèêë]/g, "e")
 | 
			
		||||
    .replace(/[ÏïÎîÍíÌì]/g, "i")
 | 
			
		||||
    .replace(/[Ññ]/g, "n")
 | 
			
		||||
    .replace(/[øØœŒÕõÔôÓóÒò]/g, "o")
 | 
			
		||||
    .replace(/[ÜüÛûÚúÙù]/g, "u")
 | 
			
		||||
    .replace(/[ŸÿÝý]/g, "y")
 | 
			
		||||
    .replace(/[^a-z0-9- ]/gi, "")
 | 
			
		||||
    .replace(/[ÀÁÂÃÄÅàáâãä忯]/u, "a")
 | 
			
		||||
    .replace(/[çÇ]/u, "c")
 | 
			
		||||
    .replace(/[ðÐ]/u, "d")
 | 
			
		||||
    .replace(/[ÈÉÊËéèêë]/u, "e")
 | 
			
		||||
    .replace(/[ÏïÎîÍíÌì]/u, "i")
 | 
			
		||||
    .replace(/[Ññ]/u, "n")
 | 
			
		||||
    .replace(/[øØœŒÕõÔôÓóÒò]/u, "o")
 | 
			
		||||
    .replace(/[ÜüÛûÚúÙù]/u, "u")
 | 
			
		||||
    .replace(/[ŸÿÝý]/u, "y")
 | 
			
		||||
    .replace(/[^a-z0-9- ]/iu, "")
 | 
			
		||||
    .trim()
 | 
			
		||||
    .replace(/ /gi, "-")
 | 
			
		||||
    .replace(/ /iu, "-")
 | 
			
		||||
    .toLowerCase();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										314
									
								
								src/tailwind.css
									
									
									
									
									
								
							
							
						
						
									
										314
									
								
								src/tailwind.css
									
									
									
									
									
								
							@ -2,167 +2,163 @@
 | 
			
		||||
@tailwind components;
 | 
			
		||||
@tailwind utilities;
 | 
			
		||||
 | 
			
		||||
@layer base {
 | 
			
		||||
  * {
 | 
			
		||||
    @apply box-border font-body font-medium scroll-smooth scroll-m-8;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  h1,
 | 
			
		||||
  h2,
 | 
			
		||||
  h3,
 | 
			
		||||
  h4,
 | 
			
		||||
  h5,
 | 
			
		||||
  h6 {
 | 
			
		||||
    @apply font-headers font-black;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  a {
 | 
			
		||||
    @apply transition-colors underline-offset-2 decoration-dotted underline decoration-dark hover:text-dark cursor-pointer;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  *::selection {
 | 
			
		||||
    @apply bg-dark text-light;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  mark {
 | 
			
		||||
    @apply bg-mid px-2;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* SCROLLBARS STYLING */
 | 
			
		||||
 | 
			
		||||
  * {
 | 
			
		||||
    @apply [scrollbar-color:theme(colors.dark)_transparent] [scrollbar-width:thin];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  *::-webkit-scrollbar {
 | 
			
		||||
    @apply w-3 mobile:w-0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  *::-webkit-scrollbar-track {
 | 
			
		||||
    @apply bg-light;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  *::-webkit-scrollbar-thumb {
 | 
			
		||||
    @apply bg-dark rounded-full border-[3px] border-solid border-light;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* CHANGE FORMATTED DEFAULTS */
 | 
			
		||||
 | 
			
		||||
  .formatted h1,
 | 
			
		||||
  .formatted h2,
 | 
			
		||||
  .formatted h3,
 | 
			
		||||
  .formatted h4,
 | 
			
		||||
  .formatted h5,
 | 
			
		||||
  .formatted h6 {
 | 
			
		||||
    @apply text-center flex gap-3 justify-center;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .formatted h1 {
 | 
			
		||||
    @apply text-4xl my-16;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .formatted h1 + h2 {
 | 
			
		||||
    @apply -mt-10;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .formatted h2 {
 | 
			
		||||
    @apply text-3xl my-12;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .formatted h2 + h3 {
 | 
			
		||||
    @apply -mt-8;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .formatted h3 {
 | 
			
		||||
    @apply text-2xl my-8;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .formatted h3 + h4 {
 | 
			
		||||
    @apply -mt-6;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .formatted h4 {
 | 
			
		||||
    @apply text-xl my-6;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .formatted h5 {
 | 
			
		||||
    @apply text-lg my-4;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .formatted p,
 | 
			
		||||
  .formatted strong {
 | 
			
		||||
    @apply my-2 text-justify;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .formatted strong {
 | 
			
		||||
    @apply font-black;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .formatted footer {
 | 
			
		||||
    @apply border-t-[3px] border-dotted pt-6;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .formatted footer > div {
 | 
			
		||||
    @apply my-2 px-6 py-4 rounded-xl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .formatted footer > div:target {
 | 
			
		||||
    @apply bg-mid shadow-inner-sm shadow-shade;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .formatted li::marker {
 | 
			
		||||
    @apply text-dark;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .formatted blockquote {
 | 
			
		||||
    @apply border-l-dark;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .formatted ul {
 | 
			
		||||
    @apply list-disc pl-4;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .formatted ol {
 | 
			
		||||
    @apply list-decimal pl-4;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .formatted blockquote {
 | 
			
		||||
    @apply border-2 border-mid rounded-lg p-5 text-center my-8;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .formatted blockquote cite {
 | 
			
		||||
    @apply text-dark block;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* INPUT */
 | 
			
		||||
 | 
			
		||||
  input,
 | 
			
		||||
  textarea {
 | 
			
		||||
    @apply rounded-full p-2 text-center bg-light outline outline-mid outline-2 outline-offset-[-2px] hover:outline-[transparent] text-dark hover:bg-mid transition-all placeholder:text-dark placeholder:opacity-60;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  input::placeholder {
 | 
			
		||||
    @apply text-dark opacity-60;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  input:focus-visible,
 | 
			
		||||
  textarea:focus-within {
 | 
			
		||||
    @apply outline-none bg-mid shadow-inner-sm shadow-shade;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  textarea {
 | 
			
		||||
    @apply rounded-2xl text-left p-6;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  input[type="submit"] {
 | 
			
		||||
    @apply grid place-content-center place-items-center border-[1px] border-dark text-dark rounded-full px-4 pt-[0.4rem] pb-[0.5rem] transition-all cursor-pointer hover:text-light hover:bg-dark hover:drop-shadow-shade-lg active:bg-black active:text-light active:drop-shadow-black-lg active:border-black;
 | 
			
		||||
  }
 | 
			
		||||
* {
 | 
			
		||||
  @apply box-border font-body font-medium scroll-smooth scroll-m-8;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@layer components {
 | 
			
		||||
  .texture-paper-dots {
 | 
			
		||||
    @apply [background-image:var(--theme-texture-dots)] [background-blend-mode:var(--theme-texture-dots-blend)] bg-local bg-[length:10cm];
 | 
			
		||||
  }
 | 
			
		||||
h1,
 | 
			
		||||
h2,
 | 
			
		||||
h3,
 | 
			
		||||
h4,
 | 
			
		||||
h5,
 | 
			
		||||
h6 {
 | 
			
		||||
  @apply font-headers font-black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
a {
 | 
			
		||||
  @apply transition-colors underline-offset-2 decoration-dotted underline decoration-dark hover:text-dark cursor-pointer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
*::selection {
 | 
			
		||||
  @apply bg-dark text-light;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
mark {
 | 
			
		||||
  @apply bg-mid px-2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* SCROLLBARS STYLING */
 | 
			
		||||
 | 
			
		||||
* {
 | 
			
		||||
  @apply [scrollbar-color:theme(colors.dark)_transparent] [scrollbar-width:thin];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
*::-webkit-scrollbar {
 | 
			
		||||
  @apply w-3 mobile:w-0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
*::-webkit-scrollbar-track {
 | 
			
		||||
  @apply bg-light;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
*::-webkit-scrollbar-thumb {
 | 
			
		||||
  @apply bg-dark rounded-full border-[3px] border-solid border-light;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* CHANGE FORMATTED DEFAULTS */
 | 
			
		||||
 | 
			
		||||
.formatted h1,
 | 
			
		||||
.formatted h2,
 | 
			
		||||
.formatted h3,
 | 
			
		||||
.formatted h4,
 | 
			
		||||
.formatted h5,
 | 
			
		||||
.formatted h6 {
 | 
			
		||||
  @apply text-center flex gap-3 justify-center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formatted h1 {
 | 
			
		||||
  @apply text-4xl my-16;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formatted h1 + h2 {
 | 
			
		||||
  @apply -mt-10;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formatted h2 {
 | 
			
		||||
  @apply text-3xl my-12;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formatted h2 + h3 {
 | 
			
		||||
  @apply -mt-8;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formatted h3 {
 | 
			
		||||
  @apply text-2xl my-8;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formatted h3 + h4 {
 | 
			
		||||
  @apply -mt-6;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formatted h4 {
 | 
			
		||||
  @apply text-xl my-6;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formatted h5 {
 | 
			
		||||
  @apply text-lg my-4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formatted p,
 | 
			
		||||
.formatted strong {
 | 
			
		||||
  @apply my-2 text-justify;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formatted strong {
 | 
			
		||||
  @apply font-black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formatted footer {
 | 
			
		||||
  @apply border-t-[3px] border-dotted pt-6;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formatted footer > div {
 | 
			
		||||
  @apply my-2 px-6 py-4 rounded-xl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formatted footer > div:target {
 | 
			
		||||
  @apply bg-mid shadow-inner-sm shadow-shade;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formatted li::marker {
 | 
			
		||||
  @apply text-dark;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formatted blockquote {
 | 
			
		||||
  @apply border-l-dark;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formatted ul {
 | 
			
		||||
  @apply list-disc pl-4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formatted ol {
 | 
			
		||||
  @apply list-decimal pl-4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formatted blockquote {
 | 
			
		||||
  @apply border-2 border-mid rounded-lg p-5 text-center my-8;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formatted blockquote cite {
 | 
			
		||||
  @apply text-dark block;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* INPUT */
 | 
			
		||||
 | 
			
		||||
input,
 | 
			
		||||
textarea {
 | 
			
		||||
  @apply rounded-full p-2 text-center bg-light outline outline-mid outline-2 outline-offset-[-2px] hover:outline-[transparent] text-dark hover:bg-mid transition-all placeholder:text-dark placeholder:opacity-60;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
input::placeholder {
 | 
			
		||||
  @apply text-dark opacity-60;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
input:focus-visible,
 | 
			
		||||
textarea:focus-within {
 | 
			
		||||
  @apply outline-none bg-mid shadow-inner-sm shadow-shade;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
textarea {
 | 
			
		||||
  @apply rounded-2xl text-left p-6;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
input[type="submit"] {
 | 
			
		||||
  @apply grid place-content-center place-items-center border-[1px] border-dark text-dark rounded-full px-4 pt-[0.4rem] pb-[0.5rem] transition-all cursor-pointer hover:text-light hover:bg-dark hover:drop-shadow-shade-lg active:bg-black active:text-light active:drop-shadow-black-lg active:border-black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.texture-paper-dots {
 | 
			
		||||
  @apply [background-image:var(--theme-texture-dots)] [background-blend-mode:var(--theme-texture-dots-blend)] bg-local bg-[length:10cm];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* TIPPY */
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user