From 6a8b909afbe1560be95f7ad0a3e19cfe4717aec6 Mon Sep 17 00:00:00 2001 From: FifthWit Date: Thu, 14 Aug 2025 14:01:01 -0500 Subject: Switched to tailwind/vite --- frontend/index.html | 1 + frontend/package-lock.json | 701 +++++++++++++++++++++++++--- frontend/package.json | 3 + frontend/src/App.css | 229 ++++++++- frontend/src/api/Api.ts | 2 +- frontend/src/components/ConfirmDialog.tsx | 16 +- frontend/src/components/GameCategory.tsx | 15 +- frontend/src/components/GameEntry.tsx | 27 +- frontend/src/components/Leaderboards.tsx | 6 +- frontend/src/components/Login.tsx | 53 ++- frontend/src/components/ModMenu.tsx | 1 - frontend/src/components/Sidebar.tsx | 386 ++++++++------- frontend/src/components/Summary.tsx | 1 - frontend/src/components/UploadRunDialog.tsx | 1 - frontend/src/images/Images.tsx | 4 +- frontend/src/images/svgs/steam.tsx | 7 + frontend/src/pages/About.tsx | 4 +- frontend/src/pages/Games.tsx | 32 +- frontend/src/pages/Homepage.tsx | 12 +- frontend/src/pages/Maplist.tsx | 131 +++--- frontend/src/pages/Maps.tsx | 15 +- frontend/src/pages/Profile.tsx | 1 - frontend/src/pages/Rules.tsx | 4 +- frontend/src/pages/User.tsx | 1 - frontend/vite.config.ts | 5 +- 25 files changed, 1227 insertions(+), 431 deletions(-) create mode 100644 frontend/src/images/svgs/steam.tsx diff --git a/frontend/index.html b/frontend/index.html index 8578eba..7538ee9 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -7,6 +7,7 @@ + LPHUB diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 9bc560f..92fcc9b 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -9,6 +9,7 @@ "version": "0.1.0", "dependencies": { "@nekz/sdp": "^0.9.0", + "@tailwindcss/vite": "^4.1.11", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", @@ -21,6 +22,7 @@ "react-helmet": "^6.1.0", "react-markdown": "^9.0.1", "react-router-dom": "^6.26.1", + "tailwindcss": "^4.1.11", "typescript": "^4.9.5", "web-vitals": "^2.1.4" }, @@ -42,7 +44,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -348,7 +349,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -365,7 +365,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -382,7 +381,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -399,7 +397,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -416,7 +413,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -433,7 +429,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -450,7 +445,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -467,7 +461,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -484,7 +477,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -501,7 +493,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -518,7 +509,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -535,7 +525,6 @@ "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -552,7 +541,6 @@ "cpu": [ "mips64el" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -569,7 +557,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -586,7 +573,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -603,7 +589,6 @@ "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -620,7 +605,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -637,7 +621,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -654,7 +637,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -671,7 +653,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -688,7 +669,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -705,7 +685,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -722,7 +701,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -739,7 +717,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -756,7 +733,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -773,7 +749,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -783,11 +758,22 @@ "node": ">=18" } }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.12", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -798,7 +784,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -808,14 +793,12 @@ "version": "1.5.4", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", - "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.29", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -851,7 +834,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -865,7 +847,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -879,7 +860,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -893,7 +873,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -907,7 +886,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -921,7 +899,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -935,7 +912,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -949,7 +925,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -963,7 +938,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -977,7 +951,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -991,7 +964,6 @@ "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1005,7 +977,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1019,7 +990,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1033,7 +1003,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1047,7 +1016,6 @@ "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1061,7 +1029,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1075,7 +1042,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1089,7 +1055,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1103,7 +1068,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1117,13 +1081,274 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "win32" ] }, + "node_modules/@tailwindcss/node": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.11.tgz", + "integrity": "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q==", + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.3.0", + "enhanced-resolve": "^5.18.1", + "jiti": "^2.4.2", + "lightningcss": "1.30.1", + "magic-string": "^0.30.17", + "source-map-js": "^1.2.1", + "tailwindcss": "4.1.11" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.11.tgz", + "integrity": "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.4", + "tar": "^7.4.3" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.1.11", + "@tailwindcss/oxide-darwin-arm64": "4.1.11", + "@tailwindcss/oxide-darwin-x64": "4.1.11", + "@tailwindcss/oxide-freebsd-x64": "4.1.11", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.11", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.11", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.11", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.11", + "@tailwindcss/oxide-linux-x64-musl": "4.1.11", + "@tailwindcss/oxide-wasm32-wasi": "4.1.11", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.11", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.11" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.11.tgz", + "integrity": "sha512-3IfFuATVRUMZZprEIx9OGDjG3Ou3jG4xQzNTvjDoKmU9JdmoCohQJ83MYd0GPnQIu89YoJqvMM0G3uqLRFtetg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.11.tgz", + "integrity": "sha512-ESgStEOEsyg8J5YcMb1xl8WFOXfeBmrhAwGsFxxB2CxY9evy63+AtpbDLAyRkJnxLy2WsD1qF13E97uQyP1lfQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.11.tgz", + "integrity": "sha512-EgnK8kRchgmgzG6jE10UQNaH9Mwi2n+yw1jWmof9Vyg2lpKNX2ioe7CJdf9M5f8V9uaQxInenZkOxnTVL3fhAw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.11.tgz", + "integrity": "sha512-xdqKtbpHs7pQhIKmqVpxStnY1skuNh4CtbcyOHeX1YBE0hArj2romsFGb6yUmzkq/6M24nkxDqU8GYrKrz+UcA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.11.tgz", + "integrity": "sha512-ryHQK2eyDYYMwB5wZL46uoxz2zzDZsFBwfjssgB7pzytAeCCa6glsiJGjhTEddq/4OsIjsLNMAiMlHNYnkEEeg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.11.tgz", + "integrity": "sha512-mYwqheq4BXF83j/w75ewkPJmPZIqqP1nhoghS9D57CLjsh3Nfq0m4ftTotRYtGnZd3eCztgbSPJ9QhfC91gDZQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.11.tgz", + "integrity": "sha512-m/NVRFNGlEHJrNVk3O6I9ggVuNjXHIPoD6bqay/pubtYC9QIdAMpS+cswZQPBLvVvEF6GtSNONbDkZrjWZXYNQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.11.tgz", + "integrity": "sha512-YW6sblI7xukSD2TdbbaeQVDysIm/UPJtObHJHKxDEcW2exAtY47j52f8jZXkqE1krdnkhCMGqP3dbniu1Te2Fg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.11.tgz", + "integrity": "sha512-e3C/RRhGunWYNC3aSF7exsQkdXzQ/M+aYuZHKnw4U7KQwTJotnWsGOIVih0s2qQzmEzOFIJ3+xt7iq67K/p56Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.11.tgz", + "integrity": "sha512-Xo1+/GU0JEN/C/dvcammKHzeM6NqKovG+6921MR6oadee5XPBaKOumrJCXvopJ/Qb5TH7LX/UAywbqrP4lax0g==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@emnapi/wasi-threads": "^1.0.2", + "@napi-rs/wasm-runtime": "^0.2.11", + "@tybys/wasm-util": "^0.9.0", + "tslib": "^2.8.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz", + "integrity": "sha512-UgKYx5PwEKrac3GPNPf6HVMNhUIGuUh4wlDFR2jYYdkX6pL/rn73zTq/4pzUm8fOjAn5L8zDeHp9iXmUGOXZ+w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.11.tgz", + "integrity": "sha512-YfHoggn1j0LK7wR82TOucWc5LDCguHnoS879idHekmmiR7g9HUtMw9MI0NHatS28u/Xlkfi9w5RJWgz2Dl+5Qg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/vite": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.11.tgz", + "integrity": "sha512-RHYhrR3hku0MJFRV+fN2gNbDNEh3dwKvY8XJvTxCSXeMOsCRSr+uKvDWQcbizrHgjML6ZmTE5OwMrl5wKcujCw==", + "license": "MIT", + "dependencies": { + "@tailwindcss/node": "4.1.11", + "@tailwindcss/oxide": "4.1.11", + "tailwindcss": "4.1.11" + }, + "peerDependencies": { + "vite": "^5.2.0 || ^6 || ^7" + } + }, "node_modules/@testing-library/dom": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", @@ -1354,7 +1579,7 @@ "version": "20.19.9", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.9.tgz", "integrity": "sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -1695,6 +1920,15 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1868,6 +2102,15 @@ "node": ">=6" } }, + "node_modules/detect-libc": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, "node_modules/devlop": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", @@ -1917,6 +2160,19 @@ "dev": true, "license": "ISC" }, + "node_modules/enhanced-resolve": { + "version": "5.18.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", + "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -1986,7 +2242,6 @@ "version": "0.25.8", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.8.tgz", "integrity": "sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==", - "dev": true, "hasInstallScript": true, "license": "MIT", "bin": { @@ -2054,7 +2309,6 @@ "version": "6.4.6", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", - "dev": true, "license": "MIT", "peerDependencies": { "picomatch": "^3 || ^4" @@ -2120,7 +2374,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -2208,6 +2461,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, "node_modules/has-bigints": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", @@ -2686,6 +2945,15 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, + "node_modules/jiti": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", + "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2718,6 +2986,234 @@ "node": ">=6" } }, + "node_modules/lightningcss": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", + "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-darwin-arm64": "1.30.1", + "lightningcss-darwin-x64": "1.30.1", + "lightningcss-freebsd-x64": "1.30.1", + "lightningcss-linux-arm-gnueabihf": "1.30.1", + "lightningcss-linux-arm64-gnu": "1.30.1", + "lightningcss-linux-arm64-musl": "1.30.1", + "lightningcss-linux-x64-gnu": "1.30.1", + "lightningcss-linux-x64-musl": "1.30.1", + "lightningcss-win32-arm64-msvc": "1.30.1", + "lightningcss-win32-x64-msvc": "1.30.1" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", + "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", + "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", + "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", + "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", + "cpu": [ + "arm" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", + "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", + "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", + "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", + "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", + "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", + "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -2765,6 +3261,15 @@ "lz-string": "bin/bin.js" } }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -3399,6 +3904,42 @@ "node": ">=4" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", + "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -3409,7 +3950,6 @@ "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, "funding": [ { "type": "github", @@ -3532,7 +4072,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -3554,7 +4093,6 @@ "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, "funding": [ { "type": "opencollective", @@ -3853,7 +4391,6 @@ "version": "4.46.2", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.46.2.tgz", "integrity": "sha512-WMmLFI+Boh6xbop+OAGo9cQ3OgX9MIg7xOQjn+pTCwOkk+FNDAeAemXkJ3HzDJrVXleLOFVa1ipuc1AmEx1Dwg==", - "dev": true, "license": "MIT", "dependencies": { "@types/estree": "1.0.8" @@ -4033,7 +4570,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -4109,11 +4645,51 @@ "node": ">=8" } }, + "node_modules/tailwindcss": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.11.tgz", + "integrity": "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==", + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", + "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "license": "ISC", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, "node_modules/tinyglobby": { "version": "0.2.14", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", - "dev": true, "license": "MIT", "dependencies": { "fdir": "^6.4.4", @@ -4163,7 +4739,7 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/unified": { @@ -4316,7 +4892,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.1.tgz", "integrity": "sha512-yJ+Mp7OyV+4S+afWo+QyoL9jFWD11QFH0i5i7JypnfTcA1rmgxCbiA8WwAICDEtZ1Z1hzrVhN8R8rGTqkTY8ZQ==", - "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.25.0", diff --git a/frontend/package.json b/frontend/package.json index f9cab6b..e7b16f7 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,9 +1,11 @@ { "name": "frontend", "version": "0.1.0", + "type": "module", "private": true, "dependencies": { "@nekz/sdp": "^0.9.0", + "@tailwindcss/vite": "^4.1.11", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", @@ -16,6 +18,7 @@ "react-helmet": "^6.1.0", "react-markdown": "^9.0.1", "react-router-dom": "^6.26.1", + "tailwindcss": "^4.1.11", "typescript": "^4.9.5", "web-vitals": "^2.1.4" }, diff --git a/frontend/src/App.css b/frontend/src/App.css index 14a9972..a4c058b 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -1,3 +1,54 @@ +@import url('https://fonts.googleapis.com/css2?family=Barlow+Condensed:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Montserrat+Alternates:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap'); +@import "tailwindcss"; + +@theme { + --color-rosewater: #f2d5cf; + --color-flamingo: #eebebe; + --color-pink: #f4b8e4; + --color-mauve: #ca9ee6; + --color-red: #e78284; + --color-maroon: #ea999c; + --color-peach: #ef9f76; + --color-yellow: #e5c890; + --color-green: #a6d189; + --color-teal: #81c8be; + --color-sky: #99d1db; + --color-sapphire: #85c1dc; + --color-blue: #8caaee; + --color-lavender: #babbf1; + --color-text: #c6d0f5; + --color-subtext1: #b5bfe2; + --color-subtext0: #a5adce; + --color-overlay2: #949cbb; + --color-overlay1: #838ba7; + --color-overlay0: #737994; + --color-surface2: #626880; + --color-surface1: #51576d; + --color-surface0: #414559; + --color-base: #303446; + --color-mantle: #292c3c; + --color-crust: #232634; + + --color-primary: var(--color-mauve); + --color-secondary: var(--color-blue); + --color-accent: var(--color-peach); + --color-background: var(--color-base); + --color-surface: var(--color-surface0); + --color-muted: var(--color-overlay0); + --color-border: var(--color-surface2); + --color-input: var(--color-surface1); + --color-foreground: var(--color-text); + --color-success: var(--color-green); + --color-warning: var(--color-yellow); + --color-error: var(--color-red); + --color-info: var(--color-blue); + + --font-barlow-condensed-regular: 'BarlowCondensed-Regular'; + --font-barlow-condensed-bold: 'BarlowCondensed-Bold'; + --font-barlow-semicondensed-regular: 'BarlowSemiCondensed-Regular'; + --font-barlow-semicondensed-semibold: 'BarlowSemiCondensed-SemiBold'; +} + main { overflow: auto; overflow-x: hidden; @@ -10,33 +61,32 @@ main { padding-right: 30px; font-size: 40px; - font-family: BarlowSemiCondensed-Regular; - color: #cdcfdf; + font-family: var(--font-barlow-semicondensed-regular); + color: var(--color-text); } a { color: inherit; - width: fit-content; } body { overflow: hidden; - background-color: #141520; + background-color: var(--color-crust); margin: 0; } .loader { animation: loader 1.2s ease infinite; background-size: 400% 300%; - background-image: linear-gradient(-90deg, #202232 0%, #202232 25%, #2a2c41 50%, #202232 75%, #202232 100%); + background-image: linear-gradient(-90deg, var(--color-mantle) 0%, var(--color-mantle) 25%, var(--color-surface1) 50%, var(--color-mantle) 75%, var(--color-mantle) 100%); user-select: none; } .loader-text { animation: loader 1.2s ease infinite; background-size: 400% 300%; - background-image: linear-gradient(-90deg, #202232 0%, #202232 25%, #2a2c41 50%, #202232 75%, #202232 100%); + background-image: linear-gradient(-90deg, var(--color-mantle) 0%, var(--color-mantle) 25%, var(--color-surface1) 50%, var(--color-mantle) 75%, var(--color-mantle) 100%); user-select: none; color: #00000000; border-radius: 1000px; @@ -76,6 +126,173 @@ body { } } +/* Custom Tailwind utilities for Catppuccin Frappe theme */ +@layer utilities { + .bg-primary { + background-color: var(--color-primary); + } + + .bg-secondary { + background-color: var(--color-secondary); + } + + .bg-accent { + background-color: var(--color-accent); + } + + .bg-background { + background-color: var(--color-background); + } + + .bg-surface { + background-color: var(--color-surface); + } + + .bg-muted { + background-color: var(--color-muted); + } + + .text-primary { + color: var(--color-primary); + } + + .text-secondary { + color: var(--color-secondary); + } + + .text-accent { + color: var(--color-accent); + } + + .text-foreground { + color: var(--color-foreground); + } + + .text-muted { + color: var(--color-muted); + } + + .border-primary { + border-color: var(--color-primary); + } + + .border-secondary { + border-color: var(--color-secondary); + } + + .border-muted { + border-color: var(--color-border); + } + + .hover\:bg-primary:hover { + background-color: var(--color-primary); + } + + .hover\:bg-secondary:hover { + background-color: var(--color-secondary); + } + + .hover\:bg-surface:hover { + background-color: var(--color-surface); + } + + .hover\:text-primary:hover { + color: var(--color-primary); + } + + .focus\:ring-primary:focus { + --tw-ring-color: var(--color-primary); + } + + .triangle { + width: 0; + height: 0; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-bottom: 8px solid var(--color-foreground); + display: inline-block; + } + + .sidebar-button-selected { + background-color: var(--color-primary) !important; + color: var(--color-background) !important; + } + + .sidebar-button-deselected { + background-color: var(--color-surface) !important; + color: var(--color-foreground) !important; + } + + .profileboard-record { + background-color: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: 0.5rem; + padding: 0.75rem; + margin-bottom: 0.5rem; + transition: all 0.2s ease; + } + + .profileboard-record:hover { + background-color: var(--color-surface1); + } + + .difficulty-rating { + width: 20px; + height: 20px; + background-color: var(--color-muted); + border-radius: 50%; + margin: 0 2px; + display: inline-block; + } + + .nav-button { + background-color: var(--color-surface); + color: var(--color-foreground); + border: 1px solid var(--color-border); + border-radius: 0.5rem; + padding: 0.5rem 1rem; + transition: all 0.2s ease; + display: inline-flex; + align-items: center; + gap: 0.5rem; + text-decoration: none; + } + + .nav-button:hover { + background-color: var(--color-surface1); + } + + .record { + background-color: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: 0.5rem; + padding: 0.5rem; + margin: 0.25rem; + cursor: pointer; + transition: all 0.2s ease; + } + + .record:hover { + background-color: var(--color-surface1); + } + + .portal-count { + font-size: 3rem; + font-weight: bold; + color: var(--color-primary); + } + + .titles { + background-color: var(--color-accent); + color: var(--color-background); + padding: 0.25rem 0.5rem; + border-radius: 1rem; + font-size: 0.875rem; + margin-right: 0.5rem; + display: inline-block; + } +} + @font-face { font-family: 'BarlowCondensed-Bold'; src: local('BarlowCondensed-Bold'), url(./fonts/BarlowCondensed-Bold.ttf) format('truetype'); diff --git a/frontend/src/api/Api.ts b/frontend/src/api/Api.ts index 0e1658c..b782d17 100644 --- a/frontend/src/api/Api.ts +++ b/frontend/src/api/Api.ts @@ -91,7 +91,7 @@ export const API = { delete_map_summary(token, map_id, route_id), }; -const BASE_API_URL: string = "/api/v1/"; +const BASE_API_URL: string = "https://lp.portal2.sr/api/v1/" export function url(path: string): string { return BASE_API_URL + path; diff --git a/frontend/src/components/ConfirmDialog.tsx b/frontend/src/components/ConfirmDialog.tsx index c89d9ea..8f2ce7a 100644 --- a/frontend/src/components/ConfirmDialog.tsx +++ b/frontend/src/components/ConfirmDialog.tsx @@ -1,7 +1,5 @@ import React from "react"; -import "@css/Dialog.css"; - interface ConfirmDialogProps { title: string; subtitle: string; @@ -16,17 +14,17 @@ const ConfirmDialog: React.FC = ({ onCancel, }) => { return ( -
-
-
+
+
+
{title}
-
+
{subtitle}
-
- - +
+ +
diff --git a/frontend/src/components/GameCategory.tsx b/frontend/src/components/GameCategory.tsx index 2bb6d42..b18c9d9 100644 --- a/frontend/src/components/GameCategory.tsx +++ b/frontend/src/components/GameCategory.tsx @@ -2,7 +2,6 @@ import React from "react"; import { Link } from "react-router-dom"; import { Game, GameCategoryPortals } from "@customTypes/Game"; -import "@css/Games.css"; interface GameCategoryProps { game: Game; @@ -12,18 +11,12 @@ interface GameCategoryProps { const GameCategory: React.FC = ({ cat, game }) => { return ( - {cat.category.name} - -
- - {cat.portal_count} - -
+

{cat.category.name}

+
+

{cat.portal_count}

); }; diff --git a/frontend/src/components/GameEntry.tsx b/frontend/src/components/GameEntry.tsx index 04c3483..f8fd179 100644 --- a/frontend/src/components/GameEntry.tsx +++ b/frontend/src/components/GameEntry.tsx @@ -2,7 +2,6 @@ import React from "react"; import { Link } from "react-router-dom"; import { Game, GameCategoryPortals } from "@customTypes/Game"; -import "@css/Games.css"; import GameCategory from "@components/GameCategory"; @@ -18,23 +17,25 @@ const GameEntry: React.FC = ({ game }) => { }, [game.category_portals]); return ( - -
-
+ +
+
- - {game.name} + + {game.name}
-
- {catInfo.map((cat, index) => { - return ( - - ); - })} +
+
+ {catInfo.map((cat, index) => { + return ( + + ); + })} +
diff --git a/frontend/src/components/Leaderboards.tsx b/frontend/src/components/Leaderboards.tsx index b388aba..99481a2 100644 --- a/frontend/src/components/Leaderboards.tsx +++ b/frontend/src/components/Leaderboards.tsx @@ -36,7 +36,7 @@ const Leaderboards: React.FC = ({ mapID }) => { return (

- Map is not available for competitive boards. + Loading...

); @@ -195,6 +195,7 @@ const Leaderboards: React.FC = ({ mapID }) => { filter: "hue-rotate(160deg) contrast(60%) saturate(1000%)", }} + className="w-6 h-6 mx-4" /> @@ -227,7 +229,7 @@ const Leaderboards: React.FC = ({ mapID }) => { (window.location.href = `/api/v1/demos?uuid=${r.demo_id}`) } > - download + download ) diff --git a/frontend/src/components/Login.tsx b/frontend/src/components/Login.tsx index 1858c48..ba85aeb 100644 --- a/frontend/src/components/Login.tsx +++ b/frontend/src/components/Login.tsx @@ -1,18 +1,18 @@ import React from "react"; import { Link, useNavigate } from "react-router-dom"; -import { ExitIcon, UserIcon, LoginIcon } from "@images/Images"; +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>; profile?: UserProfile; setProfile: React.Dispatch>; + isOpen: boolean; } -const Login: React.FC = ({ setToken, profile, setProfile }) => { +const Login: React.FC = ({ setToken, profile, setProfile, isOpen }) => { const navigate = useNavigate(); const _login = () => { @@ -32,16 +32,16 @@ const Login: React.FC = ({ setToken, profile, setProfile }) => { <> {profile.profile ? ( <> - - - @@ -49,16 +49,16 @@ const Login: React.FC = ({ setToken, profile, setProfile }) => { ) : ( <> - - - @@ -67,11 +67,28 @@ const Login: React.FC = ({ setToken, profile, setProfile }) => { )} ) : ( - - diff --git a/frontend/src/components/ModMenu.tsx b/frontend/src/components/ModMenu.tsx index 618d1a7..a0d7eb7 100644 --- a/frontend/src/components/ModMenu.tsx +++ b/frontend/src/components/ModMenu.tsx @@ -5,7 +5,6 @@ import { useNavigate } from "react-router-dom"; 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 { diff --git a/frontend/src/components/Sidebar.tsx b/frontend/src/components/Sidebar.tsx index b55d56b..88a5297 100644 --- a/frontend/src/components/Sidebar.tsx +++ b/frontend/src/components/Sidebar.tsx @@ -1,4 +1,4 @@ -import React, { useCallback } from "react"; +import React, { useCallback, useRef } from "react"; import { Link, useLocation } from "react-router-dom"; import { @@ -10,12 +10,11 @@ import { PortalIcon, SearchIcon, UploadIcon, -} from "@images/Images"; +} 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>; @@ -24,6 +23,17 @@ interface SidebarProps { onUploadRun: () => void; } +function OpenSidebarIcon(){ + return ( + + ) +} + +function ClosedSidebarIcon(){ + return ( + ) +} + const Sidebar: React.FC = ({ setToken, profile, @@ -34,100 +44,38 @@ const Sidebar: React.FC = ({ undefined ); const [isSidebarLocked, setIsSidebarLocked] = React.useState(false); - const [isSidebarOpen, setSidebarOpen] = React.useState(true); + const [isSidebarOpen, setSidebarOpen] = React.useState(false); + const [selectedButtonIndex, setSelectedButtonIndex] = React.useState(1); const location = useLocation(); const path = location.pathname; - const _handle_sidebar_hide = useCallback(() => { - var btn = document.querySelectorAll( - "button.sidebar-button" - ) as NodeListOf; - const span = document.querySelectorAll( - "button.sidebar-button>span" - ) as NodeListOf; - const side = document.querySelector("#sidebar-list") as HTMLElement; - const searchbar = document.querySelector("#searchbar") as HTMLInputElement; - const uploadRunBtn = document.querySelector( - "#upload-run" - ) as HTMLInputElement; - const uploadRunSpan = document.querySelector( - "#upload-run>span" - ) as HTMLInputElement; + const sidebarRef = useRef(null); + const searchbarRef = useRef(null); + const uploadRunRef = useRef(null); + const sidebarButtonRefs = useRef<(HTMLButtonElement | null)[]>([]); + + const _handle_sidebar_toggle = useCallback(() => { + if (!sidebarRef.current) return; if (isSidebarOpen) { - if (profile) { - const login = document.querySelectorAll( - ".login>button" - )[1] as HTMLElement; - login.style.opacity = "1"; - uploadRunBtn.style.width = "310px"; - uploadRunBtn.style.padding = "0.4em 0 0 11px"; - uploadRunSpan.style.opacity = "0"; - setTimeout(() => { - uploadRunSpan.style.opacity = "1"; - }, 100); - } setSidebarOpen(false); - side.style.width = "320px"; - btn.forEach((e, i) => { - e.style.width = "310px"; - e.style.padding = "0.4em 0 0 11px"; - setTimeout(() => { - span[i].style.opacity = "1"; - }, 100); - }); - side.style.zIndex = "2"; } else { - if (profile) { - const login = document.querySelectorAll( - ".login>button" - )[1] as HTMLElement; - login.style.opacity = "0"; - uploadRunBtn.style.width = "40px"; - uploadRunBtn.style.padding = "0.4em 0 0 5px"; - uploadRunSpan.style.opacity = "0"; - } setSidebarOpen(true); - side.style.width = "40px"; - searchbar.focus(); - btn.forEach((e, i) => { - e.style.width = "40px"; - e.style.padding = "0.4em 0 0 5px"; - span[i].style.opacity = "0"; - }); - setTimeout(() => { - side.style.zIndex = "0"; - }, 300); + searchbarRef.current?.focus(); } - }, [isSidebarOpen, profile]); + }, [isSidebarOpen]); const handle_sidebar_click = useCallback( (clicked_sidebar_idx: number) => { - const btn = document.querySelectorAll("button.sidebar-button"); + setSelectedButtonIndex(clicked_sidebar_idx); if (isSidebarOpen) { setSidebarOpen(false); - _handle_sidebar_hide(); } - // clusterfuck - btn.forEach((e, i) => { - btn[i].classList.remove("sidebar-button-selected"); - btn[i].classList.add("sidebar-button-deselected"); - }); - btn[clicked_sidebar_idx].classList.add("sidebar-button-selected"); - btn[clicked_sidebar_idx].classList.remove("sidebar-button-deselected"); }, - [isSidebarOpen, _handle_sidebar_hide] + [isSidebarOpen] ); - const _handle_sidebar_lock = () => { - if (!isSidebarLocked) { - _handle_sidebar_hide(); - setIsSidebarLocked(true); - setTimeout(() => setIsSidebarLocked(false), 300); - } - }; - const _handle_search_change = async (q: string) => { const searchResponse = await API.get_search(q); setSearchData(searchResponse); @@ -135,149 +83,199 @@ const Sidebar: React.FC = ({ React.useEffect(() => { if (path === "/") { - handle_sidebar_click(1); + setSelectedButtonIndex(1); } else if (path.includes("games")) { - handle_sidebar_click(2); + setSelectedButtonIndex(2); } else if (path.includes("rankings")) { - handle_sidebar_click(3); - } - // else if (path.includes("news")) { handle_sidebar_click(4) } - // else if (path.includes("scorelog")) { handle_sidebar_click(5) } - else if (path.includes("profile")) { - handle_sidebar_click(4); + setSelectedButtonIndex(3); + } else if (path.includes("profile")) { + setSelectedButtonIndex(4); } else if (path.includes("rules")) { - handle_sidebar_click(5); + setSelectedButtonIndex(5); } else if (path.includes("about")) { - handle_sidebar_click(6); + setSelectedButtonIndex(6); } - }, [path, handle_sidebar_click]); + }, [path]); + + const getButtonClasses = (buttonIndex: number) => { + const baseClasses = "flex items-center gap-3 w-full text-left bg-inherit cursor-pointer border-none rounded-lg py-3 px-3 transition-all duration-300 hover:bg-surface1"; + const selectedClasses = selectedButtonIndex === buttonIndex ? "bg-primary text-background" : "bg-transparent text-foreground"; + + return `${baseClasses} ${selectedClasses}`; + }; + + const iconClasses = "w-6 h-6 flex-shrink-0"; return ( -