From eae19bb1b047b3568e7a9a624b50e80886e56331 Mon Sep 17 00:00:00 2001 From: Arda Serdar Pektezol <1669855+pektezol@users.noreply.github.com> Date: Mon, 4 Nov 2024 13:47:50 +0300 Subject: feat/frontend: optimizing imports, file extensions (#230) Co-authored-by: FifthWit --- frontend/craco.config.js | 14 ++ frontend/package-lock.json | 297 ++++++++++++++++++++++++++ frontend/package.json | 10 +- frontend/src/App.tsx | 22 +- frontend/src/api/Api.ts | 56 +++++ frontend/src/api/Api.tsx | 56 ----- frontend/src/api/Auth.ts | 14 ++ frontend/src/api/Auth.tsx | 14 -- frontend/src/api/Games.ts | 31 +++ frontend/src/api/Games.tsx | 31 --- frontend/src/api/Maps.ts | 106 +++++++++ frontend/src/api/Maps.tsx | 106 --------- frontend/src/api/Mod.ts | 58 +++++ frontend/src/api/Mod.tsx | 58 ----- frontend/src/api/Rankings.ts | 13 ++ frontend/src/api/Rankings.tsx | 13 -- frontend/src/api/User.ts | 25 +++ frontend/src/api/User.tsx | 25 --- frontend/src/components/ConfirmDialog.tsx | 2 +- frontend/src/components/Discussions.tsx | 12 +- frontend/src/components/GameCategory.tsx | 4 +- frontend/src/components/GameEntry.tsx | 6 +- frontend/src/components/Leaderboards.tsx | 10 +- frontend/src/components/Login.tsx | 8 +- frontend/src/components/MessageDialog.tsx | 2 +- frontend/src/components/MessageDialogLoad.tsx | 2 +- frontend/src/components/ModMenu.tsx | 10 +- frontend/src/components/RankingEntry.tsx | 2 +- frontend/src/components/Sidebar.tsx | 12 +- frontend/src/components/Summary.tsx | 4 +- frontend/src/components/UploadRunDialog.tsx | 16 +- frontend/src/hooks/UseConfirm.tsx | 2 +- frontend/src/hooks/UseMessage.tsx | 2 +- frontend/src/hooks/UseMessageLoad.tsx | 2 +- frontend/src/pages/About.tsx | 2 +- frontend/src/pages/Games.tsx | 6 +- frontend/src/pages/Homepage.tsx | 1 - frontend/src/pages/Maplist.tsx | 9 +- frontend/src/pages/Maps.tsx | 16 +- frontend/src/pages/Profile.tsx | 24 +-- frontend/src/pages/Rankings.tsx | 8 +- frontend/src/pages/Rules.tsx | 2 +- frontend/src/pages/User.tsx | 16 +- frontend/src/types/Chapters.ts | 19 ++ frontend/src/types/Chapters.tsx | 19 -- frontend/src/types/Content.ts | 24 +++ frontend/src/types/Content.tsx | 24 --- frontend/src/types/Game.ts | 37 ++++ frontend/src/types/Game.tsx | 37 ---- frontend/src/types/Map.ts | 108 ++++++++++ frontend/src/types/Map.tsx | 108 ---------- frontend/src/types/Pagination.ts | 6 + frontend/src/types/Pagination.tsx | 6 - frontend/src/types/Profile.ts | 63 ++++++ frontend/src/types/Profile.tsx | 63 ------ frontend/src/types/Ranking.ts | 31 +++ frontend/src/types/Ranking.tsx | 31 --- frontend/src/types/Search.ts | 13 ++ frontend/src/types/Search.tsx | 13 -- frontend/src/utils/Jwt.ts | 44 ++++ frontend/src/utils/Jwt.tsx | 44 ---- frontend/src/utils/Time.ts | 42 ++++ frontend/src/utils/Time.tsx | 42 ---- frontend/tsconfig.json | 3 +- frontend/tsconfig.paths.json | 16 ++ 65 files changed, 1126 insertions(+), 796 deletions(-) create mode 100644 frontend/craco.config.js create mode 100644 frontend/src/api/Api.ts delete mode 100644 frontend/src/api/Api.tsx create mode 100644 frontend/src/api/Auth.ts delete mode 100644 frontend/src/api/Auth.tsx create mode 100644 frontend/src/api/Games.ts delete mode 100644 frontend/src/api/Games.tsx create mode 100644 frontend/src/api/Maps.ts delete mode 100644 frontend/src/api/Maps.tsx create mode 100644 frontend/src/api/Mod.ts delete mode 100644 frontend/src/api/Mod.tsx create mode 100644 frontend/src/api/Rankings.ts delete mode 100644 frontend/src/api/Rankings.tsx create mode 100644 frontend/src/api/User.ts delete mode 100644 frontend/src/api/User.tsx create mode 100644 frontend/src/types/Chapters.ts delete mode 100644 frontend/src/types/Chapters.tsx create mode 100644 frontend/src/types/Content.ts delete mode 100644 frontend/src/types/Content.tsx create mode 100644 frontend/src/types/Game.ts delete mode 100644 frontend/src/types/Game.tsx create mode 100644 frontend/src/types/Map.ts delete mode 100644 frontend/src/types/Map.tsx create mode 100644 frontend/src/types/Pagination.ts delete mode 100644 frontend/src/types/Pagination.tsx create mode 100644 frontend/src/types/Profile.ts delete mode 100644 frontend/src/types/Profile.tsx create mode 100644 frontend/src/types/Ranking.ts delete mode 100644 frontend/src/types/Ranking.tsx create mode 100644 frontend/src/types/Search.ts delete mode 100644 frontend/src/types/Search.tsx create mode 100644 frontend/src/utils/Jwt.ts delete mode 100644 frontend/src/utils/Jwt.tsx create mode 100644 frontend/src/utils/Time.ts delete mode 100644 frontend/src/utils/Time.tsx create mode 100644 frontend/tsconfig.paths.json diff --git a/frontend/craco.config.js b/frontend/craco.config.js new file mode 100644 index 0000000..79037fa --- /dev/null +++ b/frontend/craco.config.js @@ -0,0 +1,14 @@ +const CracoAlias = require('craco-alias'); + +module.exports = { + plugins: [ + { + plugin: CracoAlias, + options: { + source: 'tsconfig', + baseUrl: './src', + tsConfigPath: './tsconfig.paths.json', + }, + }, + ], +}; \ No newline at end of file diff --git a/frontend/package-lock.json b/frontend/package-lock.json index a77d244..b342a9c 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -24,6 +24,10 @@ "react-scripts": "5.0.1", "typescript": "^4.9.5", "web-vitals": "^2.1.4" + }, + "devDependencies": { + "@craco/craco": "^7.1.0", + "craco-alias": "^3.0.1" } }, "node_modules/@adobe/css-tools": { @@ -2019,6 +2023,55 @@ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" }, + "node_modules/@craco/craco": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@craco/craco/-/craco-7.1.0.tgz", + "integrity": "sha512-oRAcPIKYrfPXp9rSzlsDNeOaVtDiKhoyqSXUoqiK24jCkHr4T8m/a2f74yXIzCbIheoUWDOIfWZyRgFgT+cpqA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "autoprefixer": "^10.4.12", + "cosmiconfig": "^7.0.1", + "cosmiconfig-typescript-loader": "^1.0.0", + "cross-spawn": "^7.0.3", + "lodash": "^4.17.21", + "semver": "^7.3.7", + "webpack-merge": "^5.8.0" + }, + "bin": { + "craco": "dist/bin/craco.js" + }, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "react-scripts": "^5.0.0" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@csstools/normalize.css": { "version": "12.1.1", "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-12.1.1.tgz", @@ -3932,6 +3985,34 @@ "node": ">=10.13.0" } }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "devOptional": true, + "license": "MIT" + }, "node_modules/@types/aria-query": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", @@ -5981,6 +6062,21 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -6225,6 +6321,41 @@ "node": ">=10" } }, + "node_modules/cosmiconfig-typescript-loader": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-1.0.9.tgz", + "integrity": "sha512-tRuMRhxN4m1Y8hP9SNYfz7jRwt8lZdWxdjg/ohg5esKmsndJIn4yT96oJVcf5x0eA11taXl+sIp+ielu529k6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "cosmiconfig": "^7", + "ts-node": "^10.7.0" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@types/node": "*", + "cosmiconfig": ">=7", + "typescript": ">=3" + } + }, + "node_modules/craco-alias": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/craco-alias/-/craco-alias-3.0.1.tgz", + "integrity": "sha512-N+Qaf/Gr/f3o5ZH2TQjMu5NhR9PnT1ZYsfejpNvZPpB0ujdrhsSr4Ct6GVjnV5ostCVquhTKJpIVBKyL9qDQYA==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "license": "MIT" + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "devOptional": true, + "license": "MIT" + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -6892,6 +7023,16 @@ "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "devOptional": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/diff-sequences": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", @@ -8401,6 +8542,16 @@ "node": ">=8" } }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, "node_modules/flat-cache": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", @@ -9831,6 +9982,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", @@ -10008,6 +10172,16 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", @@ -12500,6 +12674,13 @@ "semver": "bin/semver.js" } }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "devOptional": true, + "license": "ISC" + }, "node_modules/makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", @@ -16559,6 +16740,19 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -17683,6 +17877,70 @@ "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ts-node/node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "devOptional": true, + "license": "MIT" + }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", @@ -18142,6 +18400,13 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "devOptional": true, + "license": "MIT" + }, "node_modules/v8-to-istanbul": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", @@ -18436,6 +18701,21 @@ "node": ">=10.13.0" } }, + "node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/webpack-sources": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", @@ -18633,6 +18913,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true, + "license": "MIT" + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -19122,6 +19409,16 @@ "node": ">=10" } }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 57c92a7..c317b98 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -21,9 +21,9 @@ "web-vitals": "^2.1.4" }, "scripts": { - "start": "react-scripts start", - "build": "react-scripts build", - "test": "react-scripts test", + "start": "craco start", + "build": "craco build", + "test": "craco test", "eject": "react-scripts eject" }, "eslintConfig": { @@ -43,5 +43,9 @@ "last 1 firefox version", "last 1 safari version" ] + }, + "devDependencies": { + "@craco/craco": "^7.1.0", + "craco-alias": "^3.0.1" } } diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index c6952b1..e4bde75 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,22 +1,22 @@ import React from 'react'; import { Routes, Route } from "react-router-dom"; -import { UserProfile } from './types/Profile'; +import { UserProfile } from '@customTypes/Profile'; import Sidebar from './components/Sidebar'; import "./App.css"; -import Profile from './pages/Profile'; -import Games from './pages/Games'; -import Maps from './pages/Maps'; -import User from './pages/User'; -import Homepage from './pages/Homepage'; +import Profile from '@pages/Profile'; +import Games from '@pages/Games'; +import Maps from '@pages/Maps'; +import User from '@pages/User'; +import Homepage from '@pages/Homepage'; import UploadRunDialog from './components/UploadRunDialog'; -import Rules from './pages/Rules'; -import About from './pages/About'; -import { Game } from './types/Game'; +import Rules from '@pages/Rules'; +import About from '@pages/About'; +import { Game } from '@customTypes/Game'; import { API } from './api/Api'; -import Maplist from './pages/Maplist'; -import Rankings from './pages/Rankings'; +import Maplist from '@pages/Maplist'; +import Rankings from '@pages/Rankings'; import { get_user_id_from_token, get_user_mod_from_token } from './utils/Jwt'; const App: React.FC = () => { diff --git a/frontend/src/api/Api.ts b/frontend/src/api/Api.ts new file mode 100644 index 0000000..2e55ab4 --- /dev/null +++ b/frontend/src/api/Api.ts @@ -0,0 +1,56 @@ +import { MapDiscussionCommentContent, MapDiscussionContent, ModMenuContent } from '@customTypes/Content'; +import { delete_token, get_token } from '@api/Auth'; +import { get_user, get_profile, post_profile } from '@api/User'; +import { get_games, get_chapters, get_games_chapters, get_game_maps, get_search } from '@api/Games'; +import { get_official_rankings, get_unofficial_rankings } from '@api/Rankings'; +import { get_map_summary, get_map_leaderboard, get_map_discussions, get_map_discussion, post_map_discussion, post_map_discussion_comment, delete_map_discussion, post_record, delete_map_record } from '@api/Maps'; +import { delete_map_summary, post_map_summary, put_map_image, put_map_summary } from '@api/Mod'; +import { UploadRunContent } from '@customTypes/Content'; + +// add new api call function entries here +// example usage: API.get_games(); +export const API = { + // Auth + get_token: () => get_token(), + + delete_token: () => delete_token(), + // User + get_user: (user_id: string) => get_user(user_id), + get_profile: (token: string) => get_profile(token), + post_profile: (token: string) => post_profile(token), + // Games + get_games: () => get_games(), + get_chapters: (chapter_id: string) => get_chapters(chapter_id), + get_games_chapters: (game_id: string) => get_games_chapters(game_id), + get_game_maps: (game_id: string) => get_game_maps(game_id), + get_search: (q: string) => get_search(q), + // Rankings + get_official_rankings: () => get_official_rankings(), + get_unofficial_rankings: () => get_unofficial_rankings(), + // Maps + get_map_summary: (map_id: string) => get_map_summary(map_id), + get_map_leaderboard: (map_id: string) => get_map_leaderboard(map_id), + get_map_discussions: (map_id: string) => get_map_discussions(map_id), + get_map_discussion: (map_id: string, discussion_id: number) => get_map_discussion(map_id, discussion_id), + + post_map_discussion: (token: string, map_id: string, content: MapDiscussionContent) => post_map_discussion(token, map_id, content), + post_map_discussion_comment: (token: string, map_id: string, discussion_id: number, comment: string) => post_map_discussion_comment(token, map_id, discussion_id, comment), + post_record: (token: string, run: UploadRunContent) => post_record(token, run), + + delete_map_discussion: (token: string, map_id: string, discussion_id: number) => delete_map_discussion(token, map_id, discussion_id), + + delete_map_record: (token: string, map_id: number, record_id: number) => delete_map_record(token, map_id, record_id), + // Mod + post_map_summary: (token: string, map_id: string, content: ModMenuContent) => post_map_summary(token, map_id, content), + + put_map_image: (token: string, map_id: string, image: string) => put_map_image(token, map_id, image), + put_map_summary: (token: string, map_id: string, content: ModMenuContent) => put_map_summary(token, map_id, content), + + delete_map_summary: (token: string, map_id: string, route_id: number) => delete_map_summary(token, map_id, route_id), +}; + +const BASE_API_URL: string = "/api/v1/" + +export function url(path: string): string { + return BASE_API_URL + path; +}; diff --git a/frontend/src/api/Api.tsx b/frontend/src/api/Api.tsx deleted file mode 100644 index 053e920..0000000 --- a/frontend/src/api/Api.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { MapDiscussionCommentContent, MapDiscussionContent, ModMenuContent } from '../types/Content'; -import { delete_token, get_token } from './Auth'; -import { get_user, get_profile, post_profile } from './User'; -import { get_games, get_chapters, get_games_chapters, get_game_maps, get_search } from './Games'; -import { get_official_rankings, get_unofficial_rankings } from './Rankings'; -import { get_map_summary, get_map_leaderboard, get_map_discussions, get_map_discussion, post_map_discussion, post_map_discussion_comment, delete_map_discussion, post_record, delete_map_record } from './Maps'; -import { delete_map_summary, post_map_summary, put_map_image, put_map_summary } from './Mod'; -import { UploadRunContent } from '../types/Content'; - -// add new api call function entries here -// example usage: API.get_games(); -export const API = { - // Auth - get_token: () => get_token(), - - delete_token: () => delete_token(), - // User - get_user: (user_id: string) => get_user(user_id), - get_profile: (token: string) => get_profile(token), - post_profile: (token: string) => post_profile(token), - // Games - get_games: () => get_games(), - get_chapters: (chapter_id: string) => get_chapters(chapter_id), - get_games_chapters: (game_id: string) => get_games_chapters(game_id), - get_game_maps: (game_id: string) => get_game_maps(game_id), - get_search: (q: string) => get_search(q), - // Rankings - get_official_rankings: () => get_official_rankings(), - get_unofficial_rankings: () => get_unofficial_rankings(), - // Maps - get_map_summary: (map_id: string) => get_map_summary(map_id), - get_map_leaderboard: (map_id: string) => get_map_leaderboard(map_id), - get_map_discussions: (map_id: string) => get_map_discussions(map_id), - get_map_discussion: (map_id: string, discussion_id: number) => get_map_discussion(map_id, discussion_id), - - post_map_discussion: (token: string, map_id: string, content: MapDiscussionContent) => post_map_discussion(token, map_id, content), - post_map_discussion_comment: (token: string, map_id: string, discussion_id: number, comment: string) => post_map_discussion_comment(token, map_id, discussion_id, comment), - post_record: (token: string, run: UploadRunContent) => post_record(token, run), - - delete_map_discussion: (token: string, map_id: string, discussion_id: number) => delete_map_discussion(token, map_id, discussion_id), - - delete_map_record: (token: string, map_id: number, record_id: number) => delete_map_record(token, map_id, record_id), - // Mod - post_map_summary: (token: string, map_id: string, content: ModMenuContent) => post_map_summary(token, map_id, content), - - put_map_image: (token: string, map_id: string, image: string) => put_map_image(token, map_id, image), - put_map_summary: (token: string, map_id: string, content: ModMenuContent) => put_map_summary(token, map_id, content), - - delete_map_summary: (token: string, map_id: string, route_id: number) => delete_map_summary(token, map_id, route_id), -}; - -const BASE_API_URL: string = "/api/v1/" - -export function url(path: string): string { - return BASE_API_URL + path; -}; diff --git a/frontend/src/api/Auth.ts b/frontend/src/api/Auth.ts new file mode 100644 index 0000000..875c7e5 --- /dev/null +++ b/frontend/src/api/Auth.ts @@ -0,0 +1,14 @@ +import axios from "axios"; +import { url } from "@api/Api"; + +export const get_token = async (): Promise => { + const response = await axios.get(url(`token`)) + if (!response.data.success) { + return undefined; + } + return response.data.data.token; +}; + +export const delete_token = async () => { + await axios.delete(url("token")); +}; diff --git a/frontend/src/api/Auth.tsx b/frontend/src/api/Auth.tsx deleted file mode 100644 index 09269e6..0000000 --- a/frontend/src/api/Auth.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import axios from "axios"; -import { url } from "./Api"; - -export const get_token = async (): Promise => { - const response = await axios.get(url(`token`)) - if (!response.data.success) { - return undefined; - } - return response.data.data.token; -}; - -export const delete_token = async () => { - await axios.delete(url("token")); -}; diff --git a/frontend/src/api/Games.ts b/frontend/src/api/Games.ts new file mode 100644 index 0000000..72bb4b3 --- /dev/null +++ b/frontend/src/api/Games.ts @@ -0,0 +1,31 @@ +import axios from "axios"; +import { url } from "@api/Api"; +import { GameChapter, GamesChapters } from "@customTypes/Chapters"; +import { Game } from "@customTypes/Game"; +import { Map } from "@customTypes/Map"; +import { Search } from "@customTypes/Search"; + +export const get_games = async (): Promise => { + const response = await axios.get(url(`games`)) + return response.data.data; +}; + +export const get_chapters = async (chapter_id: string): Promise => { + const response = await axios.get(url(`chapters/${chapter_id}`)); + return response.data.data; +} + +export const get_games_chapters = async (game_id: string): Promise => { + const response = await axios.get(url(`games/${game_id}`)); + return response.data.data; +}; + +export const get_game_maps = async (game_id: string): Promise => { + const response = await axios.get(url(`games/${game_id}/maps`)) + return response.data.data.maps; +}; + +export const get_search = async (q: string): Promise => { + const response = await axios.get(url(`search?q=${q}`)) + return response.data.data; +}; diff --git a/frontend/src/api/Games.tsx b/frontend/src/api/Games.tsx deleted file mode 100644 index 84b5f74..0000000 --- a/frontend/src/api/Games.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import axios from "axios"; -import { url } from "./Api"; -import { GameChapter, GamesChapters } from "../types/Chapters"; -import { Game } from "../types/Game"; -import { Map } from "../types/Map"; -import { Search } from "../types/Search"; - -export const get_games = async (): Promise => { - const response = await axios.get(url(`games`)) - return response.data.data; -}; - -export const get_chapters = async (chapter_id: string): Promise => { - const response = await axios.get(url(`chapters/${chapter_id}`)); - return response.data.data; -} - -export const get_games_chapters = async (game_id: string): Promise => { - const response = await axios.get(url(`games/${game_id}`)); - return response.data.data; -}; - -export const get_game_maps = async (game_id: string): Promise => { - const response = await axios.get(url(`games/${game_id}/maps`)) - return response.data.data.maps; -}; - -export const get_search = async (q: string): Promise => { - const response = await axios.get(url(`search?q=${q}`)) - return response.data.data; -}; diff --git a/frontend/src/api/Maps.ts b/frontend/src/api/Maps.ts new file mode 100644 index 0000000..89657b5 --- /dev/null +++ b/frontend/src/api/Maps.ts @@ -0,0 +1,106 @@ +import axios from "axios"; +import { url } from "@api/Api"; +import { MapDiscussionContent, UploadRunContent } from "@customTypes/Content"; +import { MapSummary, MapLeaderboard, MapDiscussions, MapDiscussion } from "@customTypes/Map"; + +export const get_map_summary = async (map_id: string): Promise => { + const response = await axios.get(url(`maps/${map_id}/summary`)) + return response.data.data; +}; + +export const get_map_leaderboard = async (map_id: string): Promise => { + const response = await axios.get(url(`maps/${map_id}/leaderboards`)); + if (!response.data.success) { + return undefined; + } + const data = response.data.data; + // map the kind of leaderboard + data.records = data.records.map((record: any) => { + if (record.host && record.partner) { + return { ...record, kind: 'multiplayer' }; + } else { + return { ...record, kind: 'singleplayer' }; + } + }); + return data; +}; + +export const get_map_discussions = async (map_id: string): Promise => { + const response = await axios.get(url(`maps/${map_id}/discussions`)); + if (!response.data.data.discussions) { + return undefined; + } + return response.data.data; +}; + +export const get_map_discussion = async (map_id: string, discussion_id: number): Promise => { + const response = await axios.get(url(`maps/${map_id}/discussions/${discussion_id}`)); + if (!response.data.data.discussion) { + return undefined; + } + return response.data.data; +}; + +export const post_map_discussion = async (token: string, map_id: string, content: MapDiscussionContent): Promise => { + const response = await axios.post(url(`maps/${map_id}/discussions`), { + "title": content.title, + "content": content.content, + }, { + headers: { + "Authorization": token, + } + }); + return response.data.success; +}; + +export const post_map_discussion_comment = async (token: string, map_id: string, discussion_id: number, comment: string): Promise => { + const response = await axios.post(url(`maps/${map_id}/discussions/${discussion_id}`), { + "comment": comment, + }, { + headers: { + "Authorization": token, + } + }); + return response.data.success; +}; + +export const delete_map_discussion = async (token: string, map_id: string, discussion_id: number): Promise => { + const response = await axios.delete(url(`maps/${map_id}/discussions/${discussion_id}`), { + headers: { + "Authorization": token, + } + }); + return response.data.success; +}; + +export const post_record = async (token: string, run: UploadRunContent): Promise<[boolean, string]> => { + if (run.partner_demo) { + const response = await axios.postForm(url(`maps/${run.map_id}/record`), { + "host_demo": run.host_demo, + "partner_demo": run.partner_demo, + }, { + headers: { + "Authorization": token, + } + }); + return [ response.data.success, response.data.message ]; + } else { + const response = await axios.postForm(url(`maps/${run.map_id}/record`), { + "host_demo": run.host_demo, + }, { + headers: { + "Authorization": token, + } + }); + return [ response.data.success, response.data.message ]; + } +} + +export const delete_map_record = async (token: string, map_id: number, record_id: number): Promise => { + const response = await axios.delete(url(`maps/${map_id}/record/${record_id}`), { + headers: { + "Authorization": token, + } + }); + return response.data.success; +}; diff --git a/frontend/src/api/Maps.tsx b/frontend/src/api/Maps.tsx deleted file mode 100644 index fc50293..0000000 --- a/frontend/src/api/Maps.tsx +++ /dev/null @@ -1,106 +0,0 @@ -import axios from "axios"; -import { url } from "./Api"; -import { MapDiscussionContent, UploadRunContent } from "../types/Content"; -import { MapSummary, MapLeaderboard, MapDiscussions, MapDiscussion } from "../types/Map"; - -export const get_map_summary = async (map_id: string): Promise => { - const response = await axios.get(url(`maps/${map_id}/summary`)) - return response.data.data; -}; - -export const get_map_leaderboard = async (map_id: string): Promise => { - const response = await axios.get(url(`maps/${map_id}/leaderboards`)); - if (!response.data.success) { - return undefined; - } - const data = response.data.data; - // map the kind of leaderboard - data.records = data.records.map((record: any) => { - if (record.host && record.partner) { - return { ...record, kind: 'multiplayer' }; - } else { - return { ...record, kind: 'singleplayer' }; - } - }); - return data; -}; - -export const get_map_discussions = async (map_id: string): Promise => { - const response = await axios.get(url(`maps/${map_id}/discussions`)); - if (!response.data.data.discussions) { - return undefined; - } - return response.data.data; -}; - -export const get_map_discussion = async (map_id: string, discussion_id: number): Promise => { - const response = await axios.get(url(`maps/${map_id}/discussions/${discussion_id}`)); - if (!response.data.data.discussion) { - return undefined; - } - return response.data.data; -}; - -export const post_map_discussion = async (token: string, map_id: string, content: MapDiscussionContent): Promise => { - const response = await axios.post(url(`maps/${map_id}/discussions`), { - "title": content.title, - "content": content.content, - }, { - headers: { - "Authorization": token, - } - }); - return response.data.success; -}; - -export const post_map_discussion_comment = async (token: string, map_id: string, discussion_id: number, comment: string): Promise => { - const response = await axios.post(url(`maps/${map_id}/discussions/${discussion_id}`), { - "comment": comment, - }, { - headers: { - "Authorization": token, - } - }); - return response.data.success; -}; - -export const delete_map_discussion = async (token: string, map_id: string, discussion_id: number): Promise => { - const response = await axios.delete(url(`maps/${map_id}/discussions/${discussion_id}`), { - headers: { - "Authorization": token, - } - }); - return response.data.success; -}; - -export const post_record = async (token: string, run: UploadRunContent): Promise<[boolean, string]> => { - if (run.partner_demo) { - const response = await axios.postForm(url(`maps/${run.map_id}/record`), { - "host_demo": run.host_demo, - "partner_demo": run.partner_demo, - }, { - headers: { - "Authorization": token, - } - }); - return [ response.data.success, response.data.message ]; - } else { - const response = await axios.postForm(url(`maps/${run.map_id}/record`), { - "host_demo": run.host_demo, - }, { - headers: { - "Authorization": token, - } - }); - return [ response.data.success, response.data.message ]; - } -} - -export const delete_map_record = async (token: string, map_id: number, record_id: number): Promise => { - const response = await axios.delete(url(`maps/${map_id}/record/${record_id}`), { - headers: { - "Authorization": token, - } - }); - return response.data.success; -}; diff --git a/frontend/src/api/Mod.ts b/frontend/src/api/Mod.ts new file mode 100644 index 0000000..1511f8b --- /dev/null +++ b/frontend/src/api/Mod.ts @@ -0,0 +1,58 @@ +import axios from "axios"; +import { url } from "@api/Api"; +import { ModMenuContent } from "@customTypes/Content"; + +export const put_map_image = async (token: string, map_id: string, image: string): Promise => { + const response = await axios.put(url(`maps/${map_id}/image`), { + "image": image, + }, { + headers: { + "Authorization": token, + } + }); + return response.data.success; +}; + +export const post_map_summary = async (token: string, map_id: string, content: ModMenuContent): Promise => { + const response = await axios.post(url(`maps/${map_id}/summary`), { + "category_id": content.category_id, + "user_name": content.name, + "score_count": content.score, + "record_date": content.date, + "showcase": content.showcase, + "description": content.description, + }, { + headers: { + "Authorization": token, + } + }); + return response.data.success; +}; + +export const put_map_summary = async (token: string, map_id: string, content: ModMenuContent): Promise => { + const response = await axios.put(url(`maps/${map_id}/summary`), { + "route_id": content.id, + "user_name": content.name, + "score_count": content.score, + "record_date": content.date, + "showcase": content.showcase, + "description": content.description, + }, { + headers: { + "Authorization": token, + } + }); + return response.data.success; +}; + +export const delete_map_summary = async (token: string, map_id: string, route_id: number): Promise => { + const response = await axios.delete(url(`maps/${map_id}/summary`), { + data: { + "route_id": route_id, + }, + headers: { + "Authorization": token, + } + }); + return response.data.success; +}; diff --git a/frontend/src/api/Mod.tsx b/frontend/src/api/Mod.tsx deleted file mode 100644 index 9091379..0000000 --- a/frontend/src/api/Mod.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import axios from "axios"; -import { url } from "./Api"; -import { ModMenuContent } from "../types/Content"; - -export const put_map_image = async (token: string, map_id: string, image: string): Promise => { - const response = await axios.put(url(`maps/${map_id}/image`), { - "image": image, - }, { - headers: { - "Authorization": token, - } - }); - return response.data.success; -}; - -export const post_map_summary = async (token: string, map_id: string, content: ModMenuContent): Promise => { - const response = await axios.post(url(`maps/${map_id}/summary`), { - "category_id": content.category_id, - "user_name": content.name, - "score_count": content.score, - "record_date": content.date, - "showcase": content.showcase, - "description": content.description, - }, { - headers: { - "Authorization": token, - } - }); - return response.data.success; -}; - -export const put_map_summary = async (token: string, map_id: string, content: ModMenuContent): Promise => { - const response = await axios.put(url(`maps/${map_id}/summary`), { - "route_id": content.id, - "user_name": content.name, - "score_count": content.score, - "record_date": content.date, - "showcase": content.showcase, - "description": content.description, - }, { - headers: { - "Authorization": token, - } - }); - return response.data.success; -}; - -export const delete_map_summary = async (token: string, map_id: string, route_id: number): Promise => { - const response = await axios.delete(url(`maps/${map_id}/summary`), { - data: { - "route_id": route_id, - }, - headers: { - "Authorization": token, - } - }); - return response.data.success; -}; diff --git a/frontend/src/api/Rankings.ts b/frontend/src/api/Rankings.ts new file mode 100644 index 0000000..b8d9bec --- /dev/null +++ b/frontend/src/api/Rankings.ts @@ -0,0 +1,13 @@ +import axios from "axios"; +import { url } from "@api/Api"; +import { Ranking, SteamRanking } from "@customTypes/Ranking"; + +export const get_official_rankings = async (): Promise => { + const response = await axios.get(url(`rankings/lphub`)); + return response.data.data; +}; + +export const get_unofficial_rankings = async (): Promise => { + const response = await axios.get(url(`rankings/steam`)); + return response.data.data; +}; diff --git a/frontend/src/api/Rankings.tsx b/frontend/src/api/Rankings.tsx deleted file mode 100644 index 384f826..0000000 --- a/frontend/src/api/Rankings.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import axios from "axios"; -import { url } from "./Api"; -import { Ranking, SteamRanking } from "../types/Ranking"; - -export const get_official_rankings = async (): Promise => { - const response = await axios.get(url(`rankings/lphub`)); - return response.data.data; -}; - -export const get_unofficial_rankings = async (): Promise => { - const response = await axios.get(url(`rankings/steam`)); - return response.data.data; -}; diff --git a/frontend/src/api/User.ts b/frontend/src/api/User.ts new file mode 100644 index 0000000..88da0f2 --- /dev/null +++ b/frontend/src/api/User.ts @@ -0,0 +1,25 @@ +import axios from "axios"; +import { url } from "@api/Api"; +import { UserProfile } from "@customTypes/Profile"; + +export const get_user = async (user_id: string): Promise => { + const response = await axios.get(url(`users/${user_id}`)); + return response.data.data; +}; + +export const get_profile = async (token: string): Promise => { + const response = await axios.get(url(`profile`), { + headers: { + "Authorization": token, + } + }); + return response.data.data; +}; + +export const post_profile = async (token: string) => { + const _ = await axios.post(url(`profile`), {}, { + headers: { + "Authorization": token, + } + }); +}; diff --git a/frontend/src/api/User.tsx b/frontend/src/api/User.tsx deleted file mode 100644 index c4d1944..0000000 --- a/frontend/src/api/User.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import axios from "axios"; -import { url } from "./Api"; -import { UserProfile } from "../types/Profile"; - -export const get_user = async (user_id: string): Promise => { - const response = await axios.get(url(`users/${user_id}`)); - return response.data.data; -}; - -export const get_profile = async (token: string): Promise => { - const response = await axios.get(url(`profile`), { - headers: { - "Authorization": token, - } - }); - return response.data.data; -}; - -export const post_profile = async (token: string) => { - const _ = await axios.post(url(`profile`), {}, { - headers: { - "Authorization": token, - } - }); -}; diff --git a/frontend/src/components/ConfirmDialog.tsx b/frontend/src/components/ConfirmDialog.tsx index c4299fd..44a653b 100644 --- a/frontend/src/components/ConfirmDialog.tsx +++ b/frontend/src/components/ConfirmDialog.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import "../css/Dialog.css" +import "@css/Dialog.css" interface ConfirmDialogProps { title: string; diff --git a/frontend/src/components/Discussions.tsx b/frontend/src/components/Discussions.tsx index 0522910..17ae586 100644 --- a/frontend/src/components/Discussions.tsx +++ b/frontend/src/components/Discussions.tsx @@ -1,12 +1,12 @@ import React from 'react'; -import { MapDiscussion, MapDiscussions, MapDiscussionsDetail } from '../types/Map'; -import { MapDiscussionCommentContent, MapDiscussionContent } from '../types/Content'; -import { time_ago } from '../utils/Time'; -import { API } from '../api/Api'; -import "../css/Maps.css" +import { MapDiscussion, MapDiscussions, MapDiscussionsDetail } from '@customTypes/Map'; +import { MapDiscussionCommentContent, MapDiscussionContent } from '@customTypes/Content'; +import { time_ago } from '@utils/Time'; +import { API } from '@api/Api'; +import "@css/Maps.css" import { Link } from 'react-router-dom'; -import useConfirm from '../hooks/UseConfirm'; +import useConfirm from '@hooks/UseConfirm'; interface DiscussionsProps { token?: string diff --git a/frontend/src/components/GameCategory.tsx b/frontend/src/components/GameCategory.tsx index 3291e09..d8879ef 100644 --- a/frontend/src/components/GameCategory.tsx +++ b/frontend/src/components/GameCategory.tsx @@ -1,8 +1,8 @@ import React from 'react'; import { Link } from "react-router-dom"; -import { Game, GameCategoryPortals } from '../types/Game'; -import "../css/Games.css" +import { Game, GameCategoryPortals } from '@customTypes/Game'; +import "@css/Games.css" interface GameCategoryProps { game: Game; diff --git a/frontend/src/components/GameEntry.tsx b/frontend/src/components/GameEntry.tsx index ced40ee..3bd2842 100644 --- a/frontend/src/components/GameEntry.tsx +++ b/frontend/src/components/GameEntry.tsx @@ -1,10 +1,10 @@ import React from 'react'; import { Link } from "react-router-dom"; -import { Game, GameCategoryPortals } from '../types/Game'; -import "../css/Games.css" +import { Game, GameCategoryPortals } from '@customTypes/Game'; +import "@css/Games.css" -import GameCategory from './GameCategory'; +import GameCategory from '@components/GameCategory'; interface GameEntryProps { game: Game; diff --git a/frontend/src/components/Leaderboards.tsx b/frontend/src/components/Leaderboards.tsx index aaaee62..4a8b463 100644 --- a/frontend/src/components/Leaderboards.tsx +++ b/frontend/src/components/Leaderboards.tsx @@ -1,11 +1,11 @@ import React from 'react'; import { Link } from 'react-router-dom'; -import { DownloadIcon, ThreedotIcon } from '../images/Images'; -import { MapLeaderboard } from '../types/Map'; -import { ticks_to_time, time_ago } from '../utils/Time'; -import useMessage from "../hooks/UseMessage"; -import "../css/Maps.css" +import { DownloadIcon, ThreedotIcon } from '@images/Images'; +import { MapLeaderboard } from '@customTypes/Map'; +import { ticks_to_time, time_ago } from '@utils/Time'; +import useMessage from "@hooks/UseMessage"; +import "@css/Maps.css" interface LeaderboardsProps { data?: MapLeaderboard; diff --git a/frontend/src/components/Login.tsx b/frontend/src/components/Login.tsx index 545f724..f1628b2 100644 --- a/frontend/src/components/Login.tsx +++ b/frontend/src/components/Login.tsx @@ -1,10 +1,10 @@ import React from 'react'; import { Link, useNavigate } from 'react-router-dom'; -import { ExitIcon, UserIcon, LoginIcon } from '../images/Images'; -import { UserProfile } from '../types/Profile'; -import { API } from '../api/Api'; -import "../css/Login.css"; +import { ExitIcon, UserIcon, LoginIcon } from '@images/Images'; +import { UserProfile } from '@customTypes/Profile'; +import { API } from '@api/Api'; +import "@css/Login.css"; interface LoginProps { setToken: React.Dispatch>; diff --git a/frontend/src/components/MessageDialog.tsx b/frontend/src/components/MessageDialog.tsx index 17b1258..5c85189 100644 --- a/frontend/src/components/MessageDialog.tsx +++ b/frontend/src/components/MessageDialog.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import "../css/Dialog.css" +import "@css/Dialog.css" interface MessageDialogProps { title: string; diff --git a/frontend/src/components/MessageDialogLoad.tsx b/frontend/src/components/MessageDialogLoad.tsx index 381a4a4..966e064 100644 --- a/frontend/src/components/MessageDialogLoad.tsx +++ b/frontend/src/components/MessageDialogLoad.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import "../css/Dialog.css" +import "@css/Dialog.css" interface MessageDialogLoadProps { title: string; diff --git a/frontend/src/components/ModMenu.tsx b/frontend/src/components/ModMenu.tsx index 2fb1737..925b8a8 100644 --- a/frontend/src/components/ModMenu.tsx +++ b/frontend/src/components/ModMenu.tsx @@ -2,11 +2,11 @@ import React from 'react'; import ReactMarkdown from 'react-markdown'; import { useNavigate } from 'react-router-dom'; -import { MapSummary } from '../types/Map'; -import { ModMenuContent } from '../types/Content'; -import { API } from '../api/Api'; -import "../css/ModMenu.css" -import useConfirm from '../hooks/UseConfirm'; +import { MapSummary } from '@customTypes/Map'; +import { ModMenuContent } from '@customTypes/Content'; +import { API } from '@api/Api'; +import "@css/ModMenu.css" +import useConfirm from '@hooks/UseConfirm'; interface ModMenuProps { token?: string; diff --git a/frontend/src/components/RankingEntry.tsx b/frontend/src/components/RankingEntry.tsx index 25b0201..b899965 100644 --- a/frontend/src/components/RankingEntry.tsx +++ b/frontend/src/components/RankingEntry.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { Link } from "react-router-dom"; -import { RankingType, SteamRanking, SteamRankingType } from '../types/Ranking'; +import { RankingType, SteamRanking, SteamRankingType } from '@customTypes/Ranking'; enum RankingCategories { rankings_overall, diff --git a/frontend/src/components/Sidebar.tsx b/frontend/src/components/Sidebar.tsx index 5757183..67f7f3d 100644 --- a/frontend/src/components/Sidebar.tsx +++ b/frontend/src/components/Sidebar.tsx @@ -1,12 +1,12 @@ import React from 'react'; import { Link, useLocation } from 'react-router-dom'; -import { BookIcon, FlagIcon, HelpIcon, HomeIcon, LogoIcon, PortalIcon, SearchIcon, UploadIcon } from '../images/Images'; -import Login from './Login'; -import { UserProfile } from '../types/Profile'; -import { Search } from '../types/Search'; -import { API } from '../api/Api'; -import "../css/Sidebar.css"; +import { BookIcon, FlagIcon, HelpIcon, HomeIcon, LogoIcon, PortalIcon, SearchIcon, UploadIcon } from '@images/Images'; +import Login from '@components/Login'; +import { UserProfile } from '@customTypes/Profile'; +import { Search } from '@customTypes/Search'; +import { API } from '@api/Api'; +import "@css/Sidebar.css"; interface SidebarProps { setToken: React.Dispatch>; diff --git a/frontend/src/components/Summary.tsx b/frontend/src/components/Summary.tsx index 79e989f..14b02ac 100644 --- a/frontend/src/components/Summary.tsx +++ b/frontend/src/components/Summary.tsx @@ -1,8 +1,8 @@ import React from 'react'; import ReactMarkdown from 'react-markdown'; -import { MapSummary } from '../types/Map'; -import "../css/Maps.css" +import { MapSummary } from '@customTypes/Map'; +import "@css/Maps.css" interface SummaryProps { selectedRun: number diff --git a/frontend/src/components/UploadRunDialog.tsx b/frontend/src/components/UploadRunDialog.tsx index 0610377..118b589 100644 --- a/frontend/src/components/UploadRunDialog.tsx +++ b/frontend/src/components/UploadRunDialog.tsx @@ -1,15 +1,15 @@ import React from 'react'; -import { UploadRunContent } from '../types/Content'; +import { UploadRunContent } from '@customTypes/Content'; import { ScoreboardTempUpdate, SourceDemoParser, NetMessages } from '@nekz/sdp'; -import '../css/UploadRunDialog.css'; -import { Game } from '../types/Game'; -import { Map } from '../types/Map'; -import { API } from '../api/Api'; +import '@css/UploadRunDialog.css'; +import { Game } from '@customTypes/Game'; +import { Map } from '@customTypes/Map'; +import { API } from '@api/Api'; import { useNavigate } from 'react-router-dom'; -import useMessage from '../hooks/UseMessage'; -import useConfirm from '../hooks/UseConfirm'; -import useMessageLoad from "../hooks/UseMessageLoad"; +import useMessage from '@hooks/UseMessage'; +import useConfirm from '@hooks/UseConfirm'; +import useMessageLoad from "@hooks/UseMessageLoad"; interface UploadRunDialogProps { token?: string; diff --git a/frontend/src/hooks/UseConfirm.tsx b/frontend/src/hooks/UseConfirm.tsx index 0d64224..e86d70d 100644 --- a/frontend/src/hooks/UseConfirm.tsx +++ b/frontend/src/hooks/UseConfirm.tsx @@ -1,5 +1,5 @@ import React, { useState } from 'react'; -import ConfirmDialog from '../components/ConfirmDialog'; +import ConfirmDialog from '@components/ConfirmDialog'; const useConfirm = () => { const [isOpen, setIsOpen] = useState(false); diff --git a/frontend/src/hooks/UseMessage.tsx b/frontend/src/hooks/UseMessage.tsx index 13d8e4f..97ec746 100644 --- a/frontend/src/hooks/UseMessage.tsx +++ b/frontend/src/hooks/UseMessage.tsx @@ -1,5 +1,5 @@ import React, { useState } from 'react'; -import MessageDialog from "../components/MessageDialog"; +import MessageDialog from "@components/MessageDialog"; const useMessage = () => { const [isOpen, setIsOpen] = useState(false); diff --git a/frontend/src/hooks/UseMessageLoad.tsx b/frontend/src/hooks/UseMessageLoad.tsx index defd2b3..228c2b4 100644 --- a/frontend/src/hooks/UseMessageLoad.tsx +++ b/frontend/src/hooks/UseMessageLoad.tsx @@ -1,5 +1,5 @@ import React, { useState } from 'react'; -import MessageDialogLoad from "../components/MessageDialogLoad"; +import MessageDialogLoad from "@components/MessageDialogLoad"; const useMessageLoad = () => { const [isOpen, setIsOpen] = useState(false); diff --git a/frontend/src/pages/About.tsx b/frontend/src/pages/About.tsx index c0883eb..ded3461 100644 --- a/frontend/src/pages/About.tsx +++ b/frontend/src/pages/About.tsx @@ -1,7 +1,7 @@ import React from 'react'; import ReactMarkdown from 'react-markdown'; -import '../css/About.css'; +import '@css/About.css'; const About: React.FC = () => { diff --git a/frontend/src/pages/Games.tsx b/frontend/src/pages/Games.tsx index ea136c2..15105c9 100644 --- a/frontend/src/pages/Games.tsx +++ b/frontend/src/pages/Games.tsx @@ -1,8 +1,8 @@ import React from 'react'; -import GameEntry from '../components/GameEntry'; -import { Game } from '../types/Game'; -import "../css/Maps.css" +import GameEntry from '@components/GameEntry'; +import { Game } from '@customTypes/Game'; +import "@css/Maps.css" interface GamesProps { games: Game[]; diff --git a/frontend/src/pages/Homepage.tsx b/frontend/src/pages/Homepage.tsx index 8c1cd48..68562b6 100644 --- a/frontend/src/pages/Homepage.tsx +++ b/frontend/src/pages/Homepage.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import { PortalIcon } from '../images/Images'; const Homepage: React.FC = () => { diff --git a/frontend/src/pages/Maplist.tsx b/frontend/src/pages/Maplist.tsx index 4c1c172..8fc52b0 100644 --- a/frontend/src/pages/Maplist.tsx +++ b/frontend/src/pages/Maplist.tsx @@ -1,11 +1,10 @@ import React, { useEffect } from "react"; import { Link, useLocation, useNavigate, useParams } from "react-router-dom"; -import "../css/Maplist.css"; -import { API } from "../api/Api"; -import { Game, GameChapters } from "../types/Game"; -import { GameChapter, GamesChapters } from "../types/Chapters"; -import { Map } from "../types/Map"; +import "@css/Maplist.css"; +import { API } from "@api/Api"; +import { Game } from "@customTypes/Game"; +import { GameChapter, GamesChapters } from "@customTypes/Chapters"; const Maplist: React.FC = () => { const [game, setGame] = React.useState(null); diff --git a/frontend/src/pages/Maps.tsx b/frontend/src/pages/Maps.tsx index 915b5f8..f1daa36 100644 --- a/frontend/src/pages/Maps.tsx +++ b/frontend/src/pages/Maps.tsx @@ -1,14 +1,14 @@ import React from 'react'; import { Link, useLocation } from 'react-router-dom'; -import { PortalIcon, FlagIcon, ChatIcon } from '../images/Images'; -import Summary from '../components/Summary'; -import Leaderboards from '../components/Leaderboards'; -import Discussions from '../components/Discussions'; -import ModMenu from '../components/ModMenu'; -import { MapDiscussions, MapLeaderboard, MapSummary } from '../types/Map'; -import { API } from '../api/Api'; -import "../css/Maps.css"; +import { PortalIcon, FlagIcon, ChatIcon } from '@images/Images'; +import Summary from '@components/Summary'; +import Leaderboards from '@components/Leaderboards'; +import Discussions from '@components/Discussions'; +import ModMenu from '@components/ModMenu'; +import { MapDiscussions, MapLeaderboard, MapSummary } from '@customTypes/Map'; +import { API } from '@api/Api'; +import "@css/Maps.css"; interface MapProps { token?: string; diff --git a/frontend/src/pages/Profile.tsx b/frontend/src/pages/Profile.tsx index 590bb9b..f7134a7 100644 --- a/frontend/src/pages/Profile.tsx +++ b/frontend/src/pages/Profile.tsx @@ -1,16 +1,16 @@ import React from 'react'; -import { Link, useLocation, useNavigate } from 'react-router-dom'; - -import { SteamIcon, TwitchIcon, YouTubeIcon, PortalIcon, FlagIcon, StatisticsIcon, SortIcon, ThreedotIcon, DownloadIcon, HistoryIcon, DeleteIcon } from '../images/Images'; -import { UserProfile } from '../types/Profile'; -import { Game, GameChapters } from '../types/Game'; -import { Map } from '../types/Map'; -import { ticks_to_time } from '../utils/Time'; -import "../css/Profile.css"; -import { API } from '../api/Api'; -import useConfirm from '../hooks/UseConfirm'; -import useMessage from '../hooks/UseMessage'; -import useMessageLoad from "../hooks/UseMessageLoad"; +import { Link, useNavigate } from 'react-router-dom'; + +import { SteamIcon, TwitchIcon, YouTubeIcon, PortalIcon, FlagIcon, StatisticsIcon, SortIcon, ThreedotIcon, DownloadIcon, HistoryIcon, DeleteIcon } from '@images/Images'; +import { UserProfile } from '@customTypes/Profile'; +import { Game, GameChapters } from '@customTypes/Game'; +import { Map } from '@customTypes/Map'; +import { ticks_to_time } from '@utils/Time'; +import "@css/Profile.css"; +import { API } from '@api/Api'; +import useConfirm from '@hooks/UseConfirm'; +import useMessage from '@hooks/UseMessage'; +import useMessageLoad from "@hooks/UseMessageLoad"; interface ProfileProps { profile?: UserProfile; diff --git a/frontend/src/pages/Rankings.tsx b/frontend/src/pages/Rankings.tsx index 1830815..cdb87a8 100644 --- a/frontend/src/pages/Rankings.tsx +++ b/frontend/src/pages/Rankings.tsx @@ -1,10 +1,10 @@ import React, { useEffect } from "react"; -import RankingEntry from "../components/RankingEntry"; -import { Ranking, SteamRanking, RankingType, SteamRankingType } from "../types/Ranking"; -import { API } from "../api/Api"; +import RankingEntry from "@components/RankingEntry"; +import { Ranking, SteamRanking, RankingType, SteamRankingType } from "@customTypes/Ranking"; +import { API } from "@api/Api"; -import "../css/Rankings.css"; +import "@css/Rankings.css"; const Rankings: React.FC = () => { const [leaderboardData, setLeaderboardData] = React.useState(); diff --git a/frontend/src/pages/Rules.tsx b/frontend/src/pages/Rules.tsx index 340a9f6..b5625ce 100644 --- a/frontend/src/pages/Rules.tsx +++ b/frontend/src/pages/Rules.tsx @@ -1,7 +1,7 @@ import React from 'react'; import ReactMarkdown from 'react-markdown'; -import '../css/Rules.css'; +import '@css/Rules.css'; const Rules: React.FC = () => { diff --git a/frontend/src/pages/User.tsx b/frontend/src/pages/User.tsx index ad230bd..f90d1aa 100644 --- a/frontend/src/pages/User.tsx +++ b/frontend/src/pages/User.tsx @@ -1,14 +1,14 @@ import React from 'react'; import { Link, useLocation, useNavigate } from 'react-router-dom'; -import { SteamIcon, TwitchIcon, YouTubeIcon, PortalIcon, FlagIcon, StatisticsIcon, SortIcon, ThreedotIcon, DownloadIcon, HistoryIcon } from '../images/Images'; -import { UserProfile } from '../types/Profile'; -import { Game, GameChapters } from '../types/Game'; -import { Map } from '../types/Map'; -import { API } from '../api/Api'; -import { ticks_to_time } from '../utils/Time'; -import "../css/Profile.css"; -import useMessage from '../hooks/UseMessage'; +import { SteamIcon, TwitchIcon, YouTubeIcon, PortalIcon, FlagIcon, StatisticsIcon, SortIcon, ThreedotIcon, DownloadIcon, HistoryIcon } from '@images/Images'; +import { UserProfile } from '@customTypes/Profile'; +import { Game, GameChapters } from '@customTypes/Game'; +import { Map } from '@customTypes/Map'; +import { API } from '@api/Api'; +import { ticks_to_time } from '@utils/Time'; +import "@css/Profile.css"; +import useMessage from '@hooks/UseMessage'; interface UserProps { profile?: UserProfile; diff --git a/frontend/src/types/Chapters.ts b/frontend/src/types/Chapters.ts new file mode 100644 index 0000000..1d48306 --- /dev/null +++ b/frontend/src/types/Chapters.ts @@ -0,0 +1,19 @@ +import type { Game } from "@customTypes/Game"; +import type { Map } from "@customTypes/Map"; + +interface Chapter { + id: number; + name: string; + image: string; + is_disabled: boolean; +} + +export interface GameChapter { + chapter: Chapter; + maps: Map[]; +} + +export interface GamesChapters { + game: Game; + chapters: Chapter[]; +} \ No newline at end of file diff --git a/frontend/src/types/Chapters.tsx b/frontend/src/types/Chapters.tsx deleted file mode 100644 index 2c0afdd..0000000 --- a/frontend/src/types/Chapters.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { Game } from "./Game"; -import { Map } from "./Map"; - -interface Chapter { - id: number; - name: string; - image: string; - is_disabled: boolean; -} - -export interface GameChapter { - chapter: Chapter; - maps: Map[]; -} - -export interface GamesChapters { - game: Game; - chapters: Chapter[]; -} \ No newline at end of file diff --git a/frontend/src/types/Content.ts b/frontend/src/types/Content.ts new file mode 100644 index 0000000..42a6917 --- /dev/null +++ b/frontend/src/types/Content.ts @@ -0,0 +1,24 @@ +export interface ModMenuContent { + id: number; + name: string; + score: number; + date: string; + showcase: string; + description: string; + category_id: number; +}; + +export interface MapDiscussionContent { + title: string; + content: string; +}; + +export interface MapDiscussionCommentContent { + comment: string; +}; + +export interface UploadRunContent { + map_id: number; + host_demo: File | null; + partner_demo: File | null; +}; diff --git a/frontend/src/types/Content.tsx b/frontend/src/types/Content.tsx deleted file mode 100644 index 42a6917..0000000 --- a/frontend/src/types/Content.tsx +++ /dev/null @@ -1,24 +0,0 @@ -export interface ModMenuContent { - id: number; - name: string; - score: number; - date: string; - showcase: string; - description: string; - category_id: number; -}; - -export interface MapDiscussionContent { - title: string; - content: string; -}; - -export interface MapDiscussionCommentContent { - comment: string; -}; - -export interface UploadRunContent { - map_id: number; - host_demo: File | null; - partner_demo: File | null; -}; diff --git a/frontend/src/types/Game.ts b/frontend/src/types/Game.ts new file mode 100644 index 0000000..1a80341 --- /dev/null +++ b/frontend/src/types/Game.ts @@ -0,0 +1,37 @@ +import type { Map } from '@customTypes/Map'; + + +export interface Game { + id: number; + name: string; + image: string; + is_coop: boolean; + category_portals: GameCategoryPortals[]; +}; + +export interface GameChapters { + game: Game; + chapters: Chapter[]; +}; + +export interface GameMaps { + game: Game; + maps: Map[]; +}; + +export interface Category { + id: number; + name: string; +}; + +interface Chapter { + id: number; + name: string; + image: string; + is_disabled: boolean; +}; + +export interface GameCategoryPortals { + category: Category; + portal_count: number; +}; diff --git a/frontend/src/types/Game.tsx b/frontend/src/types/Game.tsx deleted file mode 100644 index eb435f6..0000000 --- a/frontend/src/types/Game.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { Map } from './Map'; - - -export interface Game { - id: number; - name: string; - image: string; - is_coop: boolean; - category_portals: GameCategoryPortals[]; -}; - -export interface GameChapters { - game: Game; - chapters: Chapter[]; -}; - -export interface GameMaps { - game: Game; - maps: Map[]; -}; - -export interface Category { - id: number; - name: string; -}; - -interface Chapter { - id: number; - name: string; - image: string; - is_disabled: boolean; -}; - -export interface GameCategoryPortals { - category: Category; - portal_count: number; -}; diff --git a/frontend/src/types/Map.ts b/frontend/src/types/Map.ts new file mode 100644 index 0000000..89c66d5 --- /dev/null +++ b/frontend/src/types/Map.ts @@ -0,0 +1,108 @@ +import type { Category, GameCategoryPortals } from '@customTypes/Game'; +import type { Pagination } from '@customTypes/Pagination'; +import type { UserShort } from '@customTypes/Profile'; + +export interface Map { + id: number; + name: string; + image: string; + is_disabled: boolean; + difficulty: number; + category_portals: GameCategoryPortals[]; +}; + +export interface MapDiscussion { + discussion: MapDiscussionsDetail; +}; + +export interface MapDiscussions { + discussions: MapDiscussionsDetail[]; +}; + +export interface MapDiscussionsDetail { + id: number; + title: string; + content: string; + creator: UserShort; + comments: MapDiscussionDetailComment[]; + created_at: string; + updated_at: string; +}; + +interface MapDiscussionDetailComment { + comment: string; + date: string; + user: UserShort; +}; + +export interface MapLeaderboard { + map: MapSummaryMap; + records: MapLeaderboardRecordSingleplayer[] | MapLeaderboardRecordMultiplayer[]; + pagination: Pagination; +}; + +export interface MapLeaderboardRecordSingleplayer { + kind: "singleplayer"; + placement: number; + record_id: number; + score_count: number; + score_time: number; + user: UserShort; + demo_id: string; + record_date: string; +}; + +export interface MapLeaderboardRecordMultiplayer { + kind: "multiplayer"; + placement: number; + record_id: number; + score_count: number; + score_time: number; + host: UserShort; + partner: UserShort; + host_demo_id: string; + partner_demo_id: string; + record_date: string; +}; + + +export interface MapSummary { + map: MapSummaryMap; + summary: MapSummaryDetails; +}; + +interface MapSummaryMap { + id: number; + image: string; + chapter_name: string; + game_name: string; + map_name: string; + is_coop: boolean; + is_disabled: boolean; +}; + +interface MapSummaryDetails { + routes: MapSummaryDetailsRoute[]; +}; + +interface MapSummaryDetailsRoute { + route_id: number; + category: Category; + history: MapSummaryDetailsRouteHistory; + rating: number; + completion_count: number; + description: string; + showcase: string; +}; + +interface MapSummaryDetailsRouteHistory { + runner_name: string; + score_count: number; + date: string; +}; + +export interface MapDeleteEndpoint { + map_id: number; + record_id: number; +} + diff --git a/frontend/src/types/Map.tsx b/frontend/src/types/Map.tsx deleted file mode 100644 index 4669e8b..0000000 --- a/frontend/src/types/Map.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import { Category, GameCategoryPortals } from './Game'; -import { Pagination } from './Pagination'; -import { UserShort } from './Profile'; - -export interface Map { - id: number; - name: string; - image: string; - is_disabled: boolean; - difficulty: number; - category_portals: GameCategoryPortals[]; -}; - -export interface MapDiscussion { - discussion: MapDiscussionsDetail; -}; - -export interface MapDiscussions { - discussions: MapDiscussionsDetail[]; -}; - -export interface MapDiscussionsDetail { - id: number; - title: string; - content: string; - creator: UserShort; - comments: MapDiscussionDetailComment[]; - created_at: string; - updated_at: string; -}; - -interface MapDiscussionDetailComment { - comment: string; - date: string; - user: UserShort; -}; - -export interface MapLeaderboard { - map: MapSummaryMap; - records: MapLeaderboardRecordSingleplayer[] | MapLeaderboardRecordMultiplayer[]; - pagination: Pagination; -}; - -export interface MapLeaderboardRecordSingleplayer { - kind: "singleplayer"; - placement: number; - record_id: number; - score_count: number; - score_time: number; - user: UserShort; - demo_id: string; - record_date: string; -}; - -export interface MapLeaderboardRecordMultiplayer { - kind: "multiplayer"; - placement: number; - record_id: number; - score_count: number; - score_time: number; - host: UserShort; - partner: UserShort; - host_demo_id: string; - partner_demo_id: string; - record_date: string; -}; - - -export interface MapSummary { - map: MapSummaryMap; - summary: MapSummaryDetails; -}; - -interface MapSummaryMap { - id: number; - image: string; - chapter_name: string; - game_name: string; - map_name: string; - is_coop: boolean; - is_disabled: boolean; -}; - -interface MapSummaryDetails { - routes: MapSummaryDetailsRoute[]; -}; - -interface MapSummaryDetailsRoute { - route_id: number; - category: Category; - history: MapSummaryDetailsRouteHistory; - rating: number; - completion_count: number; - description: string; - showcase: string; -}; - -interface MapSummaryDetailsRouteHistory { - runner_name: string; - score_count: number; - date: string; -}; - -export interface MapDeleteEndpoint { - map_id: number; - record_id: number; -} - diff --git a/frontend/src/types/Pagination.ts b/frontend/src/types/Pagination.ts new file mode 100644 index 0000000..ccff04b --- /dev/null +++ b/frontend/src/types/Pagination.ts @@ -0,0 +1,6 @@ +export interface Pagination { + total_records: number; + total_pages: number; + current_page: number; + page_size: number; +}; diff --git a/frontend/src/types/Pagination.tsx b/frontend/src/types/Pagination.tsx deleted file mode 100644 index ccff04b..0000000 --- a/frontend/src/types/Pagination.tsx +++ /dev/null @@ -1,6 +0,0 @@ -export interface Pagination { - total_records: number; - total_pages: number; - current_page: number; - page_size: number; -}; diff --git a/frontend/src/types/Profile.ts b/frontend/src/types/Profile.ts new file mode 100644 index 0000000..42e5c3e --- /dev/null +++ b/frontend/src/types/Profile.ts @@ -0,0 +1,63 @@ +import type { Pagination } from "@customTypes/Pagination"; + +export interface UserShort { + steam_id: string; + user_name: string; + avatar_link: string; +}; + +export interface UserProfile { + profile: boolean; + steam_id: string; + user_name: string; + avatar_link: string; + country_code: string; + titles: UserProfileTitles[]; + links: UserProfileLinks; + rankings: UserProfileRankings; + records: UserProfileRecords[]; + pagination: Pagination; +}; + +interface UserProfileTitles { + name: string; + color: string; +}; + +interface UserProfileLinks { + p2sr: string; + steam: string; + youtube: string; + twitch: string; +}; + +interface UserProfileRankings { + overall: UserProfileRankingsDetail; + singleplayer: UserProfileRankingsDetail; + cooperative: UserProfileRankingsDetail; +}; + +interface UserProfileRecords { + game_id: number; + category_id: number; + map_id: number; + map_name: string; + map_wr_count: number; + placement: number; + scores: UserProfileRecordsScores[] +}; + +interface UserProfileRecordsScores { + record_id: number; + demo_id: string; + score_count: number; + score_time: number; + date: string; +}; + +interface UserProfileRankingsDetail { + rank: number; + completion_count: number; + completion_total: number; +}; + diff --git a/frontend/src/types/Profile.tsx b/frontend/src/types/Profile.tsx deleted file mode 100644 index 2bb037c..0000000 --- a/frontend/src/types/Profile.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { Pagination } from "./Pagination"; - -export interface UserShort { - steam_id: string; - user_name: string; - avatar_link: string; -}; - -export interface UserProfile { - profile: boolean; - steam_id: string; - user_name: string; - avatar_link: string; - country_code: string; - titles: UserProfileTitles[]; - links: UserProfileLinks; - rankings: UserProfileRankings; - records: UserProfileRecords[]; - pagination: Pagination; -}; - -interface UserProfileTitles { - name: string; - color: string; -}; - -interface UserProfileLinks { - p2sr: string; - steam: string; - youtube: string; - twitch: string; -}; - -interface UserProfileRankings { - overall: UserProfileRankingsDetail; - singleplayer: UserProfileRankingsDetail; - cooperative: UserProfileRankingsDetail; -}; - -interface UserProfileRecords { - game_id: number; - category_id: number; - map_id: number; - map_name: string; - map_wr_count: number; - placement: number; - scores: UserProfileRecordsScores[] -}; - -interface UserProfileRecordsScores { - record_id: number; - demo_id: string; - score_count: number; - score_time: number; - date: string; -}; - -interface UserProfileRankingsDetail { - rank: number; - completion_count: number; - completion_total: number; -}; - diff --git a/frontend/src/types/Ranking.ts b/frontend/src/types/Ranking.ts new file mode 100644 index 0000000..a143355 --- /dev/null +++ b/frontend/src/types/Ranking.ts @@ -0,0 +1,31 @@ +import type { UserShort } from "@customTypes/Profile"; + +export interface RankingType { + placement: number; + user: UserShort; + total_score: number; +} + +export interface SteamRankingType { + user_name: string; + avatar_link: string; + steam_id: string; + sp_score: number; + mp_score: number; + overall_score: number; + sp_rank: number; + mp_rank: number; + overall_rank: number; +} + +export interface Ranking { + rankings_overall: RankingType[]; + rankings_singleplayer: RankingType[]; + rankings_multiplayer: RankingType[]; +} + +export interface SteamRanking { + rankings_overall: SteamRankingType[]; + rankings_singleplayer: SteamRankingType[]; + rankings_multiplayer: SteamRankingType[]; +} \ No newline at end of file diff --git a/frontend/src/types/Ranking.tsx b/frontend/src/types/Ranking.tsx deleted file mode 100644 index b3b26c6..0000000 --- a/frontend/src/types/Ranking.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { UserShort } from "./Profile"; - -export interface RankingType { - placement: number; - user: UserShort; - total_score: number; -} - -export interface SteamRankingType { - user_name: string; - avatar_link: string; - steam_id: string; - sp_score: number; - mp_score: number; - overall_score: number; - sp_rank: number; - mp_rank: number; - overall_rank: number; -} - -export interface Ranking { - rankings_overall: RankingType[]; - rankings_singleplayer: RankingType[]; - rankings_multiplayer: RankingType[]; -} - -export interface SteamRanking { - rankings_overall: SteamRankingType[]; - rankings_singleplayer: SteamRankingType[]; - rankings_multiplayer: SteamRankingType[]; -} \ No newline at end of file diff --git a/frontend/src/types/Search.ts b/frontend/src/types/Search.ts new file mode 100644 index 0000000..d218806 --- /dev/null +++ b/frontend/src/types/Search.ts @@ -0,0 +1,13 @@ +import type { UserShort } from "@customTypes/Profile"; + +export interface Search { + players: UserShort[]; + maps: SearchMap[]; +}; + +interface SearchMap { + id: number; + game: string; + chapter: string; + map: string; +}; diff --git a/frontend/src/types/Search.tsx b/frontend/src/types/Search.tsx deleted file mode 100644 index 766311a..0000000 --- a/frontend/src/types/Search.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { UserShort } from "./Profile"; - -export interface Search { - players: UserShort[]; - maps: SearchMap[]; -}; - -interface SearchMap { - id: number; - game: string; - chapter: string; - map: string; -}; diff --git a/frontend/src/utils/Jwt.ts b/frontend/src/utils/Jwt.ts new file mode 100644 index 0000000..ce351fb --- /dev/null +++ b/frontend/src/utils/Jwt.ts @@ -0,0 +1,44 @@ +// llm ahh funcs +export function get_user_id_from_token(token: string | undefined): string | undefined { + if (!token) { + return undefined; + } + const parts = token.split('.'); + if (parts.length !== 3) { + return undefined; + } + const base64Url = parts[1]; + const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); + + const jsonPayload = decodeURIComponent( + atob(base64) + .split('') + .map(function (c) { + return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); + }) + .join('') + ); + return JSON.parse(jsonPayload).sub; +}; + +export function get_user_mod_from_token(token: string | undefined): boolean | undefined { + if (!token) { + return undefined; + } + const parts = token.split('.'); + if (parts.length !== 3) { + return undefined; + } + const base64Url = parts[1]; + const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); + + const jsonPayload = decodeURIComponent( + atob(base64) + .split('') + .map(function (c) { + return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); + }) + .join('') + ); + return JSON.parse(jsonPayload).mod; +}; diff --git a/frontend/src/utils/Jwt.tsx b/frontend/src/utils/Jwt.tsx deleted file mode 100644 index ce351fb..0000000 --- a/frontend/src/utils/Jwt.tsx +++ /dev/null @@ -1,44 +0,0 @@ -// llm ahh funcs -export function get_user_id_from_token(token: string | undefined): string | undefined { - if (!token) { - return undefined; - } - const parts = token.split('.'); - if (parts.length !== 3) { - return undefined; - } - const base64Url = parts[1]; - const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); - - const jsonPayload = decodeURIComponent( - atob(base64) - .split('') - .map(function (c) { - return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); - }) - .join('') - ); - return JSON.parse(jsonPayload).sub; -}; - -export function get_user_mod_from_token(token: string | undefined): boolean | undefined { - if (!token) { - return undefined; - } - const parts = token.split('.'); - if (parts.length !== 3) { - return undefined; - } - const base64Url = parts[1]; - const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); - - const jsonPayload = decodeURIComponent( - atob(base64) - .split('') - .map(function (c) { - return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); - }) - .join('') - ); - return JSON.parse(jsonPayload).mod; -}; diff --git a/frontend/src/utils/Time.ts b/frontend/src/utils/Time.ts new file mode 100644 index 0000000..b83a7ed --- /dev/null +++ b/frontend/src/utils/Time.ts @@ -0,0 +1,42 @@ +export function time_ago(date: any) { + const now = new Date().getTime(); + + const localDate = new Date(date.getTime() - (date.getTimezoneOffset() * 60000)); + const seconds = Math.floor((now - localDate.getTime()) / 1000); + + let interval = Math.floor(seconds / 31536000); + if (interval === 1) {return interval + ' year ago';} + if (interval > 1) {return interval + ' years ago';} + + interval = Math.floor(seconds / 2592000); + if (interval === 1) {return interval + ' month ago';} + if (interval > 1) {return interval + ' months ago';} + + interval = Math.floor(seconds / 86400); + if (interval === 1) {return interval + ' day ago';} + if (interval > 1) {return interval + ' days ago';} + + interval = Math.floor(seconds / 3600); + if (interval === 1) {return interval + ' hour ago';} + if (interval > 1) {return interval + ' hours ago';} + + interval = Math.floor(seconds / 60); + if (interval === 1) {return interval + ' minute ago';} + if (interval > 1) {return interval + ' minutes ago';} + + if(seconds < 10) return 'just now'; + + return Math.floor(seconds) + ' seconds ago'; +}; + +export function ticks_to_time(ticks: number) { + let seconds = Math.floor(ticks / 60) + let minutes = Math.floor(seconds / 60) + let hours = Math.floor(minutes / 60) + + let milliseconds = Math.floor((ticks % 60) * 1000 / 60) + seconds = seconds % 60; + minutes = minutes % 60; + + return `${hours === 0 ? "" : hours + ":"}${minutes === 0 ? "" : hours > 0 ? minutes.toString().padStart(2, '0') + ":" : (minutes + ":")}${minutes > 0 ? seconds.toString().padStart(2, '0') : seconds}.${milliseconds.toString().padStart(3, '0')}`; +}; \ No newline at end of file diff --git a/frontend/src/utils/Time.tsx b/frontend/src/utils/Time.tsx deleted file mode 100644 index b83a7ed..0000000 --- a/frontend/src/utils/Time.tsx +++ /dev/null @@ -1,42 +0,0 @@ -export function time_ago(date: any) { - const now = new Date().getTime(); - - const localDate = new Date(date.getTime() - (date.getTimezoneOffset() * 60000)); - const seconds = Math.floor((now - localDate.getTime()) / 1000); - - let interval = Math.floor(seconds / 31536000); - if (interval === 1) {return interval + ' year ago';} - if (interval > 1) {return interval + ' years ago';} - - interval = Math.floor(seconds / 2592000); - if (interval === 1) {return interval + ' month ago';} - if (interval > 1) {return interval + ' months ago';} - - interval = Math.floor(seconds / 86400); - if (interval === 1) {return interval + ' day ago';} - if (interval > 1) {return interval + ' days ago';} - - interval = Math.floor(seconds / 3600); - if (interval === 1) {return interval + ' hour ago';} - if (interval > 1) {return interval + ' hours ago';} - - interval = Math.floor(seconds / 60); - if (interval === 1) {return interval + ' minute ago';} - if (interval > 1) {return interval + ' minutes ago';} - - if(seconds < 10) return 'just now'; - - return Math.floor(seconds) + ' seconds ago'; -}; - -export function ticks_to_time(ticks: number) { - let seconds = Math.floor(ticks / 60) - let minutes = Math.floor(seconds / 60) - let hours = Math.floor(minutes / 60) - - let milliseconds = Math.floor((ticks % 60) * 1000 / 60) - seconds = seconds % 60; - minutes = minutes % 60; - - return `${hours === 0 ? "" : hours + ":"}${minutes === 0 ? "" : hours > 0 ? minutes.toString().padStart(2, '0') + ":" : (minutes + ":")}${minutes > 0 ? seconds.toString().padStart(2, '0') : seconds}.${milliseconds.toString().padStart(3, '0')}`; -}; \ No newline at end of file diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index ab0af5e..813525a 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -1,4 +1,5 @@ { + "extends": "./tsconfig.paths.json", "compilerOptions": { "target": "es5", "lib": [ @@ -20,7 +21,7 @@ "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, - "jsx": "react-jsx" + "jsx": "react-jsx", }, "include": [ "src" diff --git a/frontend/tsconfig.paths.json b/frontend/tsconfig.paths.json new file mode 100644 index 0000000..2a33687 --- /dev/null +++ b/frontend/tsconfig.paths.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "baseUrl": "src", + "paths": { + "@api/*": ["api/*"], + "@components/*": ["components/*"], + "@css/*": ["css/*"], + "@fonts/*": ["fonts/*"], + "@hooks/*": ["hooks/*"], + "@images/*": ["images/*"], + "@pages/*": ["pages/*"], + "@customTypes/*": ["types/*"], + "@utils/*": ["utils/*"] + } + } + } \ No newline at end of file -- cgit v1.2.3