fix(leaderboard): fix leaderboard mapping

This commit is contained in:
shafin-r
2026-01-19 10:35:51 +06:00
parent 9fd3a7b0e2
commit d208a9336f
12 changed files with 300 additions and 3184 deletions

View File

@ -10,6 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
"@radix-ui/react-avatar": "^1.1.11",
"@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-tabs": "^1.1.13",

96
pnpm-lock.yaml generated
View File

@ -8,6 +8,9 @@ importers:
.:
dependencies:
'@radix-ui/react-avatar':
specifier: ^1.1.11
version: 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
'@radix-ui/react-dropdown-menu':
specifier: ^2.1.16
version: 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
@ -49,7 +52,7 @@ importers:
version: 4.1.18
zustand:
specifier: ^5.0.9
version: 5.0.9(@types/react@19.2.7)(react@19.2.3)
version: 5.0.9(@types/react@19.2.7)(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3))
devDependencies:
'@eslint/js':
specifier: ^9.39.1
@ -433,6 +436,19 @@ packages:
'@types/react-dom':
optional: true
'@radix-ui/react-avatar@1.1.11':
resolution: {integrity: sha512-0Qk603AHGV28BOBO34p7IgD5m+V5Sg/YovfayABkoDDBM5d3NCx0Mp4gGrjzLGes1jV5eNOE1r3itqOR33VC6Q==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-collection@1.1.7':
resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==}
peerDependencies:
@ -464,6 +480,15 @@ packages:
'@types/react':
optional: true
'@radix-ui/react-context@1.1.3':
resolution: {integrity: sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@radix-ui/react-direction@1.1.1':
resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==}
peerDependencies:
@ -595,6 +620,19 @@ packages:
'@types/react-dom':
optional: true
'@radix-ui/react-primitive@2.1.4':
resolution: {integrity: sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
'@radix-ui/react-roving-focus@1.1.11':
resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==}
peerDependencies:
@ -675,6 +713,15 @@ packages:
'@types/react':
optional: true
'@radix-ui/react-use-is-hydrated@0.1.0':
resolution: {integrity: sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==}
peerDependencies:
'@types/react': '*'
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
peerDependenciesMeta:
'@types/react':
optional: true
'@radix-ui/react-use-layout-effect@1.1.1':
resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==}
peerDependencies:
@ -1669,6 +1716,11 @@ packages:
'@types/react':
optional: true
use-sync-external-store@1.6.0:
resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==}
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
vite@7.3.0:
resolution: {integrity: sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==}
engines: {node: ^20.19.0 || >=22.12.0}
@ -2048,6 +2100,19 @@ snapshots:
'@types/react': 19.2.7
'@types/react-dom': 19.2.3(@types/react@19.2.7)
'@radix-ui/react-avatar@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
dependencies:
'@radix-ui/react-context': 1.1.3(@types/react@19.2.7)(react@19.2.3)
'@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.7)(react@19.2.3)
'@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.2.7)(react@19.2.3)
'@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.7)(react@19.2.3)
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
optionalDependencies:
'@types/react': 19.2.7
'@types/react-dom': 19.2.3(@types/react@19.2.7)
'@radix-ui/react-collection@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
dependencies:
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3)
@ -2072,6 +2137,12 @@ snapshots:
optionalDependencies:
'@types/react': 19.2.7
'@radix-ui/react-context@1.1.3(@types/react@19.2.7)(react@19.2.3)':
dependencies:
react: 19.2.3
optionalDependencies:
'@types/react': 19.2.7
'@radix-ui/react-direction@1.1.1(@types/react@19.2.7)(react@19.2.3)':
dependencies:
react: 19.2.3
@ -2203,6 +2274,15 @@ snapshots:
'@types/react': 19.2.7
'@types/react-dom': 19.2.3(@types/react@19.2.7)
'@radix-ui/react-primitive@2.1.4(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
dependencies:
'@radix-ui/react-slot': 1.2.4(@types/react@19.2.7)(react@19.2.3)
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
optionalDependencies:
'@types/react': 19.2.7
'@types/react-dom': 19.2.3(@types/react@19.2.7)
'@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
dependencies:
'@radix-ui/primitive': 1.1.3
@ -2278,6 +2358,13 @@ snapshots:
optionalDependencies:
'@types/react': 19.2.7
'@radix-ui/react-use-is-hydrated@0.1.0(@types/react@19.2.7)(react@19.2.3)':
dependencies:
react: 19.2.3
use-sync-external-store: 1.6.0(react@19.2.3)
optionalDependencies:
'@types/react': 19.2.7
'@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.2.7)(react@19.2.3)':
dependencies:
react: 19.2.3
@ -3192,6 +3279,10 @@ snapshots:
optionalDependencies:
'@types/react': 19.2.7
use-sync-external-store@1.6.0(react@19.2.3):
dependencies:
react: 19.2.3
vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2):
dependencies:
esbuild: 0.27.2
@ -3222,7 +3313,8 @@ snapshots:
zod@4.3.5: {}
zustand@5.0.9(@types/react@19.2.7)(react@19.2.3):
zustand@5.0.9(@types/react@19.2.7)(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)):
optionalDependencies:
'@types/react': 19.2.7
react: 19.2.3
use-sync-external-store: 1.6.0(react@19.2.3)

View File

@ -1,172 +0,0 @@
/*
* Prefixed by https://autoprefixer.github.io
* PostCSS: v8.4.14,
* Autoprefixer: v10.4.7
* Browsers: last 4 version
*/
/*
* Prefixed by https://autoprefixer.github.io
* PostCSS: v8.4.14,
* Autoprefixer: v10.4.7
* Browsers: last 4 version
*/
/* Auth Pages Styling */
.login-container {
min-height: 100vh;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
background-color: var(--secondary-bg);
background-image: -o-linear-gradient(315deg, #f5f5f5 0%, #ffffff 100%);
background-image: linear-gradient(135deg, #f5f5f5 0%, #ffffff 100%);
padding: 1rem;
}
.auth-container {
max-width: 420px;
width: 100%;
padding: 2.5rem;
border-radius: 12px;
-webkit-box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
background-color: var(--tertiary-bg);
border: 1px solid var(--secondary-border);
-webkit-transition: all 0.3s ease;
-o-transition: all 0.3s ease;
transition: all 0.3s ease;
}
.auth-container:hover {
-webkit-box-shadow: 0 12px 32px rgba(0, 0, 0, 0.12);
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.12);
-webkit-transform: translateY(-5px);
-ms-transform: translateY(-5px);
transform: translateY(-5px);
}
.auth-title {
text-align: center;
margin-bottom: 1.5rem;
color: var(--intensive-text);
font-weight: 700;
font-size: 1.75rem;
}
.auth-footer {
text-align: center;
margin-top: 1.5rem;
font-size: 0.9rem;
color: var(--neutral);
}
.auth-footer a {
color: var(--primary-text);
font-weight: 500;
-webkit-transition: all 0.2s ease;
-o-transition: all 0.2s ease;
transition: all 0.2s ease;
}
.auth-footer a:hover {
text-decoration: underline;
}
/* Form Styling */
.auth-container .field {
margin-bottom: 1.25rem;
}
.auth-container .label {
color: var(--intensive-text) !important;
font-weight: 600;
font-size: 0.9rem;
margin-bottom: 0.5rem;
}
.auth-container .input {
color: var(--intensive-text) !important;
border-radius: 8px;
border: 1px solid var(--secondary-border);
padding: 0.75rem 1rem;
height: auto;
font-size: 1rem;
-webkit-box-shadow: none;
box-shadow: none;
-webkit-transition: all 0.2s ease;
-o-transition: all 0.2s ease;
transition: all 0.2s ease;
}
.auth-container .input:focus {
border-color: var(--primary-bg);
-webkit-box-shadow: 0 0 0 2px rgba(110, 68, 255, 0.1);
box-shadow: 0 0 0 2px rgba(110, 68, 255, 0.1);
}
.auth-container .input.is-danger {
border-color: var(--error-bg);
}
.auth-container .button {
height: auto;
padding: 0.75rem 1.5rem;
font-weight: 600;
font-size: 1rem;
border-radius: 8px;
-webkit-transition: all 0.3s ease;
-o-transition: all 0.3s ease;
transition: all 0.3s ease;
}
.auth-container .button.is-primary {
background-color: var(--primary-bg);
border: none;
}
.auth-container .button.is-primary:hover {
background-color: var(--primary-dark);
-webkit-box-shadow: 0 4px 12px rgba(110, 68, 255, 0.3);
box-shadow: 0 4px 12px rgba(110, 68, 255, 0.3);
-webkit-transform: translateY(-2px);
-ms-transform: translateY(-2px);
transform: translateY(-2px);
}
.auth-container .checkbox {
font-size: 0.9rem;
color: var(--neutral-dark);
}
.auth-container .help.is-danger {
font-size: 0.8rem;
margin-top: 0.25rem;
}
.auth-container .notification {
border-radius: 8px;
padding: 1rem;
margin-bottom: 1.5rem;
}
.auth-container .notification .delete {
position: absolute;
right: 0.75rem;
top: 0.75rem;
}
/* Responsive Adjustments */
@media screen and (max-width: 768px) {
.auth-container {
padding: 2rem;
max-width: 100%;
margin: 0 1rem;
}
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -1,132 +0,0 @@
/*
* Prefixed by https://autoprefixer.github.io
* PostCSS: v8.4.14,
* Autoprefixer: v10.4.7
* Browsers: last 4 version
*/
/* Math Rendering Styles */
/* General math container */
.math-content {
font-size: 1rem;
line-height: 1.6;
}
/* Inline math */
.math-inline {
display: inline-block;
vertical-align: middle;
}
/* Block math */
.math-block {
display: block;
margin: 1rem 0;
overflow-x: auto;
text-align: center;
}
/* Math editor toolbar */
.math-symbols-toolbar {
background-color: #f7f7f7;
border-radius: 6px;
padding: 0.75rem;
margin-top: 0.5rem;
-webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}
.math-symbols-toolbar button {
margin-right: 0.25rem;
margin-bottom: 0.25rem;
-webkit-transition: all 0.2s ease;
-o-transition: all 0.2s ease;
transition: all 0.2s ease;
}
.math-symbols-toolbar button:hover {
background-color: #6e44ff;
color: white;
}
/* Math examples section */
.math-examples {
background-color: #f8f9fa;
border-radius: 6px;
padding: 0.75rem;
margin-top: 0.5rem;
border: 1px solid #e9ecef;
}
.math-examples table {
margin-bottom: 0;
}
.math-examples th,
.math-examples td {
padding: 0.4rem 0.5rem;
vertical-align: middle;
}
.math-examples code {
background-color: rgba(110, 68, 255, 0.1);
color: #6e44ff;
padding: 0.2rem 0.4rem;
border-radius: 4px;
}
/* Question option styling */
.option-content {
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1;
max-width: calc(100% - 60px);
}
/* Short answer styling */
.short-answer-content {
background-color: rgba(0, 199, 164, 0.05);
border: 1px solid #00c7a4;
border-radius: 6px;
padding: 1rem;
}
/* Katex specific overrides */
.katex {
font-size: 1.1em;
}
.katex-display {
overflow-x: auto;
overflow-y: hidden;
padding: 0.5rem 0;
}
/* Preview mode styling */
.preview-container {
min-height: 100px;
background-color: #fff;
border: 1px solid #dbdbdb;
border-radius: 6px;
padding: 1rem;
-webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.05);
}
/* Tabs styling */
.tabs ul {
border-bottom-color: #dbdbdb;
}
.tabs li.is-active a {
border-bottom-color: #6e44ff;
color: #6e44ff;
}
/* Textarea focus styling */
#math-editor-textarea:focus {
border-color: #6e44ff;
-webkit-box-shadow: 0 0 0 0.125em rgba(110, 68, 255, 0.25);
box-shadow: 0 0 0 0.125em rgba(110, 68, 255, 0.25);
}

View File

@ -1,781 +0,0 @@
/*
* Prefixed by https://autoprefixer.github.io
* PostCSS: v8.4.14,
* Autoprefixer: v10.4.7
* Browsers: last 4 version
*/
/* Student Profile Custom Styles - Unconventional Design */
/* Container */
.student-profile-container {
max-width: 1400px;
margin: 0 auto;
padding: 2rem 1rem;
overflow-x: hidden;
}
/* Back Button */
.back-button-container {
margin-bottom: 2rem;
position: relative;
z-index: 10;
}
/* Hero Section */
.student-profile-hero {
background: -o-linear-gradient(315deg, #6e44ff 0%, #9f84ff 100%);
background: linear-gradient(135deg, #6e44ff 0%, #9f84ff 100%);
border-radius: 0;
padding: 0;
margin-bottom: 3rem;
position: relative;
overflow: hidden;
color: white;
min-height: 400px;
-webkit-box-shadow: 0 15px 30px rgba(110, 68, 255, 0.2);
box-shadow: 0 15px 30px rgba(110, 68, 255, 0.2);
}
.student-profile-hero::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url("data:image/svg+xml,%3Csvg width='100' height='100' viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M11 18c3.866 0 7-3.134 7-7s-3.134-7-7-7-7 3.134-7 7 3.134 7 7 7zm48 25c3.866 0 7-3.134 7-7s-3.134-7-7-7-7 3.134-7 7 3.134 7 7 7zm-43-7c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zm63 31c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zM34 90c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zm56-76c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zM12 86c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm28-65c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm23-11c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm-6 60c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm29 22c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zM32 63c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm57-13c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm-9-21c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM60 91c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM35 41c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM12 60c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2z' fill='%23ffffff' fill-opacity='0.1' fill-rule='evenodd'/%3E%3C/svg%3E");
opacity: 0.5;
}
.hero-content {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
padding: 3rem 2rem;
position: relative;
z-index: 2;
}
.student-info {
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1;
padding-right: 2rem;
}
.hero-illustration {
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: end;
-ms-flex-pack: end;
justify-content: flex-end;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
position: relative;
}
.hero-illustration img {
max-width: 100%;
max-height: 350px;
-webkit-transform: scale(1.2) translateY(-20px);
-ms-transform: scale(1.2) translateY(-20px);
transform: scale(1.2) translateY(-20px);
-webkit-filter: drop-shadow(0 10px 15px rgba(0, 0, 0, 0.2));
filter: drop-shadow(0 10px 15px rgba(0, 0, 0, 0.2));
}
/* Student Profile Elements */
.student-profile-avatar {
width: 120px;
height: 120px;
border-radius: 0;
border: 4px solid white;
-webkit-box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
margin-bottom: 1.5rem;
}
.student-profile-name {
font-size: 2.5rem;
font-weight: 700;
margin-bottom: 0.5rem;
}
.student-profile-email {
font-size: 1.1rem;
opacity: 0.9;
margin-bottom: 1rem;
}
.student-profile-tags {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
margin-bottom: 1.5rem;
}
.student-profile-tag {
background-color: rgba(255, 255, 255, 0.2);
color: white;
border-radius: 0;
padding: 0.3rem 1rem;
margin-right: 0.5rem;
font-weight: 500;
}
.student-profile-tag.is-active {
background-color: #00c7a4;
}
.student-profile-tag.is-inactive {
background-color: #ff2c73;
}
.student-profile-tag.is-suspended {
background-color: #ffa500;
}
.student-meta {
margin-top: 1.5rem;
}
.student-meta-item {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
margin-bottom: 0.5rem;
}
.student-meta-item .icon {
margin-right: 0.5rem;
}
/* Main Content Layout */
.student-profile-main {
display: -ms-grid;
display: grid;
-ms-grid-columns: 1fr 2rem 2fr;
grid-template-columns: 1fr 2fr;
gap: 2rem;
margin-top: 2rem;
}
/* Sections */
.student-profile-section {
background-color: white;
border-radius: 0;
-webkit-box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
padding: 1.5rem;
margin-bottom: 2rem;
position: relative;
overflow: hidden;
-webkit-transition: -webkit-transform 0.3s ease, -webkit-box-shadow 0.3s ease;
transition: -webkit-transform 0.3s ease, -webkit-box-shadow 0.3s ease;
-o-transition: transform 0.3s ease, box-shadow 0.3s ease;
transition: transform 0.3s ease, box-shadow 0.3s ease;
transition: transform 0.3s ease, box-shadow 0.3s ease,
-webkit-transform 0.3s ease, -webkit-box-shadow 0.3s ease;
}
.student-profile-section:hover {
-webkit-transform: translateY(-5px);
-ms-transform: translateY(-5px);
transform: translateY(-5px);
-webkit-box-shadow: 0 8px 30px rgba(0, 0, 0, 0.1);
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.1);
}
.student-profile-section-title {
font-size: 1.5rem;
font-weight: 700;
margin-bottom: 1.5rem;
color: #333;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.student-profile-section-title::after {
content: "";
-webkit-box-flex: 1;
-ms-flex-positive: 1;
flex-grow: 1;
height: 2px;
background-color: #f0f0f0;
margin-left: 1rem;
}
/* Statistics Section */
.stats-section {
position: relative;
overflow: hidden;
}
.stats-illustration-container {
position: absolute;
top: -20px;
right: -20px;
opacity: 0.1;
z-index: 0;
-webkit-transform: rotate(10deg);
-ms-transform: rotate(10deg);
transform: rotate(10deg);
}
.stats-illustration {
width: 150px;
height: auto;
}
/* Performance Overview */
.performance-overview {
margin-bottom: 1.5rem;
position: relative;
z-index: 1;
}
.performance-header {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
margin-bottom: 1rem;
}
.performance-title {
font-size: 1.2rem;
font-weight: 600;
color: #333;
}
.performance-badge {
background-color: #6e44ff;
color: white;
padding: 0.3rem 1rem;
font-weight: 600;
font-size: 0.9rem;
border-radius: 0;
}
/* Stats Grid */
.stats-grid {
display: -ms-grid;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
gap: 1rem;
position: relative;
z-index: 1;
margin-bottom: 2rem;
}
.student-profile-stat {
text-align: center;
padding: 1.5rem;
background-color: #f9f9f9;
border-radius: 0;
-webkit-transition: all 0.3s ease;
-o-transition: all 0.3s ease;
transition: all 0.3s ease;
}
.student-profile-stat:hover {
background-color: #6e44ff;
color: white;
-webkit-transform: translateY(-5px);
-ms-transform: translateY(-5px);
transform: translateY(-5px);
}
.student-profile-stat:hover .student-profile-stat-value,
.student-profile-stat:hover .student-profile-stat-label,
.student-profile-stat:hover .stat-trend {
color: white;
}
.student-profile-stat-value {
font-size: 2.5rem;
font-weight: 700;
color: #6e44ff;
line-height: 1;
margin-bottom: 0.5rem;
}
.student-profile-stat-label {
font-size: 0.9rem;
color: #666;
text-transform: uppercase;
letter-spacing: 1px;
font-weight: 600;
margin-bottom: 0.5rem;
}
.stat-trend {
font-size: 0.8rem;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
gap: 0.25rem;
}
.stat-trend.positive {
color: #00c7a4;
}
.stat-trend.negative {
color: #ff2c73;
}
.stat-trend.neutral {
color: #999;
}
/* Subject Performance */
.subject-performance {
position: relative;
z-index: 1;
}
.subject-performance-title {
font-size: 1.2rem;
font-weight: 600;
color: #333;
margin-bottom: 1rem;
}
.subject-cards {
display: -ms-grid;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 1rem;
}
.subject-card {
background-color: white;
border: 1px solid #f0f0f0;
-webkit-box-shadow: 0 4px 10px rgba(0, 0, 0, 0.05);
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.05);
-webkit-transition: all 0.3s ease;
-o-transition: all 0.3s ease;
transition: all 0.3s ease;
overflow: hidden;
}
.subject-card:hover {
-webkit-transform: translateY(-5px);
-ms-transform: translateY(-5px);
transform: translateY(-5px);
-webkit-box-shadow: 0 8px 15px rgba(0, 0, 0, 0.1);
box-shadow: 0 8px 15px rgba(0, 0, 0, 0.1);
}
.subject-card-header {
background-color: #6e44ff;
color: white;
padding: 0.75rem 1rem;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.subject-card-label {
font-weight: 600;
font-size: 1rem;
}
.subject-card-score {
font-weight: 700;
font-size: 1.2rem;
}
.subject-card-body {
padding: 1rem;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.subject-card-icon {
width: 40px;
height: 40px;
background-color: rgba(110, 68, 255, 0.1);
border-radius: 0;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
margin-right: 1rem;
color: #6e44ff;
font-size: 1.2rem;
}
.subject-card-info {
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1;
}
.subject-card-trend {
font-size: 0.9rem;
font-weight: 600;
margin-bottom: 0.25rem;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
gap: 0.25rem;
}
.subject-card-trend.positive {
color: #00c7a4;
}
.subject-card-trend.negative {
color: #ff2c73;
}
.subject-card-trend.neutral {
color: #999;
}
.subject-card-status {
font-size: 0.8rem;
color: #666;
text-transform: uppercase;
letter-spacing: 1px;
}
/* Settings Section */
.settings-section {
margin-top: 2rem;
}
.settings-content {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
}
.settings-illustration-container {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
margin-bottom: 1.5rem;
}
.settings-illustration {
max-width: 100%;
height: 150px;
}
/* Practice Sheets Section */
.practice-sheets-section {
position: relative;
}
.practice-sheets-content {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
}
.practice-illustration-container {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
margin-bottom: 1.5rem;
}
.practice-illustration {
height: 120px;
width: auto;
}
.practice-sheets-table-container {
position: relative;
z-index: 1;
}
/* Activity Section */
.activity-section {
position: relative;
}
.activity-content {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
}
.activity-illustration-container {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
margin-bottom: 1.5rem;
}
.activity-illustration {
height: 120px;
width: auto;
}
.activity-timeline-container {
position: relative;
z-index: 1;
}
.activity-timeline {
position: relative;
padding-left: 2rem;
}
.activity-timeline::before {
content: "";
position: absolute;
top: 0;
left: 8px;
height: 100%;
width: 2px;
background-color: #f0f0f0;
}
.activity-item {
position: relative;
padding-bottom: 1.5rem;
}
.activity-item:last-child {
padding-bottom: 0;
}
.activity-marker {
position: absolute;
left: -2rem;
top: 0;
width: 18px;
height: 18px;
border-radius: 0;
background-color: #6e44ff;
border: 3px solid white;
-webkit-box-shadow: 0 0 0 2px #f0f0f0;
box-shadow: 0 0 0 2px #f0f0f0;
z-index: 1;
}
.activity-marker.is-success {
background-color: #00c7a4;
}
.activity-marker.is-warning {
background-color: #ffd166;
}
.activity-date {
font-size: 0.8rem;
color: #999;
margin-bottom: 0.25rem;
font-weight: 500;
}
.activity-content {
font-weight: 500;
color: #333;
}
.activity-score {
font-weight: 700;
color: #6e44ff;
}
/* Illustration Sections */
.math-illustration-section,
.study-illustration-section {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
padding: 2rem;
background-color: #f9f9f9;
min-height: 300px;
}
.math-illustration,
.study-illustration {
max-width: 100%;
max-height: 250px;
-webkit-filter: drop-shadow(0 10px 15px rgba(0, 0, 0, 0.1));
filter: drop-shadow(0 10px 15px rgba(0, 0, 0, 0.1));
}
/* Button Styles */
.hip-button {
background-color: #6e44ff;
color: white;
border: none;
border-radius: 0;
padding: 0.5rem 1.5rem;
font-weight: 600;
-webkit-transition: all 0.3s ease;
-o-transition: all 0.3s ease;
transition: all 0.3s ease;
-webkit-box-shadow: 0 4px 10px rgba(110, 68, 255, 0.3);
box-shadow: 0 4px 10px rgba(110, 68, 255, 0.3);
}
.hip-button:hover {
background-color: #5a36d5;
-webkit-transform: translateY(-2px);
-ms-transform: translateY(-2px);
transform: translateY(-2px);
-webkit-box-shadow: 0 6px 15px rgba(110, 68, 255, 0.4);
box-shadow: 0 6px 15px rgba(110, 68, 255, 0.4);
color: white;
}
.hip-button.is-small {
padding: 0.25rem 0.75rem;
font-size: 0.85rem;
}
/* Responsive Styles */
@media screen and (max-width: 1200px) {
.student-profile-main {
-ms-grid-columns: 1fr;
grid-template-columns: 1fr;
}
.hero-content {
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
text-align: center;
}
.student-info {
padding-right: 0;
margin-bottom: 2rem;
}
.student-profile-tags {
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
}
.student-meta {
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
}
.student-meta-item {
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
}
}
@media screen and (max-width: 768px) {
.student-profile-hero {
min-height: auto;
}
.hero-content {
padding: 2rem 1rem;
}
.student-profile-name {
font-size: 2rem;
}
.student-profile-avatar {
width: 100px;
height: 100px;
}
.hero-illustration img {
max-height: 200px;
}
.math-illustration-section,
.study-illustration-section {
min-height: 200px;
}
.math-illustration,
.study-illustration {
max-height: 180px;
}
}

View File

@ -0,0 +1,51 @@
import * as React from "react";
import * as AvatarPrimitive from "@radix-ui/react-avatar";
import { cn } from "../../lib/utils";
function Avatar({
className,
...props
}: React.ComponentProps<typeof AvatarPrimitive.Root>) {
return (
<AvatarPrimitive.Root
data-slot="avatar"
className={cn(
"relative flex size-8 shrink-0 overflow-hidden rounded-full",
className,
)}
{...props}
/>
);
}
function AvatarImage({
className,
...props
}: React.ComponentProps<typeof AvatarPrimitive.Image>) {
return (
<AvatarPrimitive.Image
data-slot="avatar-image"
className={cn("aspect-square size-full", className)}
{...props}
/>
);
}
function AvatarFallback({
className,
...props
}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
return (
<AvatarPrimitive.Fallback
data-slot="avatar-fallback"
className={cn(
"bg-muted flex size-full items-center justify-center rounded-full",
className,
)}
{...props}
/>
);
}
export { Avatar, AvatarImage, AvatarFallback };

View File

@ -29,3 +29,17 @@ export function formatTimeFilter(time: string) {
return "Today";
}
}
export function getRandomColor() {
const colors = [
"bg-red-700",
"bg-blue-700",
"bg-green-700",
"bg-yellow-700",
"bg-purple-700",
"bg-pink-700",
"bg-indigo-700",
"bg-gray-700",
];
return colors[Math.floor(Math.random() * colors.length)];
}

View File

@ -1,4 +1,7 @@
// import { useAuthStore } from "../../stores/authStore";
import { useAuthStore } from "../../stores/authStore";
import firstTrophy from "../../assets/icons/first_trophy.png";
import secondTrophy from "../../assets/icons/second_trophy.png";
import thirdTrophy from "../../assets/icons/third_trophy.png";
import { useState } from "react";
// import {
@ -23,12 +26,23 @@ import {
DropdownMenuRadioItem,
DropdownMenuTrigger,
} from "../../components/ui/dropdown-menu";
import { formatTimeFilter } from "../../lib/utils";
import { formatTimeFilter, getRandomColor } from "../../lib/utils";
import { Avatar, AvatarFallback } from "../../components/ui/avatar";
import { Zap } from "lucide-react";
export const Rewards = () => {
// const user = useAuthStore((state) => state.user);
const user = useAuthStore((state) => state.user);
const [time, setTime] = useState("bottom");
const leaderboard = [
{ id: 1, name: "Alice", xp: 587 },
{ id: 2, name: "Bob", xp: 560 },
{ id: 3, name: "Charlie", xp: 540 },
{ id: 4, name: "David", xp: 510 },
{ id: 5, name: "Emma", xp: 495 },
];
const trophies = [firstTrophy, secondTrophy, thirdTrophy];
return (
<main className="flex flex-col gap-8 items-start min-h-screen mx-auto px-4 sm:px-6 lg:px-8 py-8">
<header className="flex flex-col items-center h-fit w-full gap-3">
@ -38,8 +52,8 @@ export const Rewards = () => {
<span className="underline">Start a lesson.</span>
</p>
</header>
<section className="">
<Tabs defaultValue="xp" className="w-full ">
<section className="w-full">
<Tabs defaultValue="xp" className="space-y-6">
<TabsList className="bg-transparent p-0 w-full justify-between ">
<TabsTrigger
value="xp"
@ -86,13 +100,129 @@ export const Rewards = () => {
</DropdownMenuContent>
</DropdownMenu>
</TabsList>
<TabsContent value="xp">
<div className="space-y-6"></div>
<TabsContent value="xp" className="space-y-6">
{leaderboard.map((user, index) => {
const isTopThree = index < 3;
return (
<div
key={user.id}
className="flex justify-between items-center"
>
<div className="flex items-center gap-3">
{isTopThree ? (
<img
src={trophies[index]}
alt={`trophy_${index + 1}`}
className="w-12 h-12"
/>
) : (
<span className="w-12 text-center font-satoshi-bold text-gray-400">
{index + 1}
</span>
)}
<Avatar className={`p-6 ${getRandomColor()}`}>
<AvatarFallback className="text-white font-satoshi-bold">
{user.name.slice(0, 1).toUpperCase()}
</AvatarFallback>
</Avatar>
<p className="font-satoshi-medium text-gray-600">
{user.name}
</p>
</div>
<div className="flex items-center gap-1">
<p className="font-satoshi-medium">{user.xp}</p>
<Zap size={20} color="darkgreen" />
</div>
</div>
);
})}
</TabsContent>
<TabsContent value="questions">
<div className="space-y-6"></div>
<TabsContent value="questions" className="space-y-6">
{leaderboard.map((user, index) => {
const isTopThree = index < 3;
return (
<div
key={user.id}
className="flex justify-between items-center"
>
<div className="flex items-center gap-3">
{isTopThree ? (
<img
src={trophies[index]}
alt={`trophy_${index + 1}`}
className="w-12 h-12"
/>
) : (
<span className="w-12 text-center font-satoshi-bold text-gray-400">
{index + 1}
</span>
)}
<Avatar className={`p-6 ${getRandomColor()}`}>
<AvatarFallback className="text-white font-satoshi-bold">
{user.name.slice(0, 1).toUpperCase()}
</AvatarFallback>
</Avatar>
<p className="font-satoshi-medium text-gray-600">
{user.name}
</p>
</div>
<div className="flex items-center gap-1">
<p className="font-satoshi-medium">{user.xp}</p>
<Zap size={20} color="darkgreen" />
</div>
</div>
);
})}
</TabsContent>
<TabsContent value="streak" className="space-y-6">
{leaderboard.map((user, index) => {
const isTopThree = index < 3;
return (
<div
key={user.id}
className="flex justify-between items-center"
>
<div className="flex items-center gap-3">
{isTopThree ? (
<img
src={trophies[index]}
alt={`trophy_${index + 1}`}
className="w-12 h-12"
/>
) : (
<span className="w-12 text-center font-satoshi-bold text-gray-400">
{index + 1}
</span>
)}
<Avatar className={`p-6 ${getRandomColor()}`}>
<AvatarFallback className="text-white font-satoshi-bold">
{user.name.slice(0, 1).toUpperCase()}
</AvatarFallback>
</Avatar>
<p className="font-satoshi-medium text-gray-600">
{user.name}
</p>
</div>
<div className="flex items-center gap-1">
<p className="font-satoshi-medium">{user.xp}</p>
<Zap size={20} color="darkgreen" />
</div>
</div>
);
})}
</TabsContent>
<TabsContent value="streak"></TabsContent>
</Tabs>
</section>
</main>