Skip to content

Commit 277c945

Browse files
Merge pull request #277 from DevLoversTeam/fix/ui-text-and-dashboard
style: update dashboard UI and fix canonical Tailwind v4 classes
2 parents 3df6b02 + ffb9d68 commit 277c945

11 files changed

Lines changed: 238 additions & 251 deletions

File tree

frontend/app/[locale]/dashboard/page.tsx

Lines changed: 26 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { PostAuthQuizSync } from '@/components/auth/PostAuthQuizSync';
44
import { ProfileCard } from '@/components/dashboard/ProfileCard';
55
import { QuizSavedBanner } from '@/components/dashboard/QuizSavedBanner';
66
import { StatsCard } from '@/components/dashboard/StatsCard';
7+
import { DynamicGridBackground } from '@/components/shared/DynamicGridBackground';
78
import { getUserQuizStats } from '@/db/queries/quiz';
89
import { getUserProfile } from '@/db/queries/users';
910
import { redirect } from '@/i18n/routing';
@@ -75,42 +76,35 @@ export default async function DashboardPage({
7576
};
7677

7778
const outlineBtnStyles =
78-
'inline-flex items-center justify-center rounded-full border border-slate-200 dark:border-slate-700 bg-white/50 dark:bg-slate-900/50 backdrop-blur-sm px-6 py-2 text-sm font-medium text-slate-600 dark:text-slate-300 transition-colors hover:bg-white hover:text-sky-600 dark:hover:bg-slate-800 dark:hover:text-sky-400';
79+
'inline-flex items-center justify-center rounded-full border border-gray-200 dark:border-white/10 bg-white/50 dark:bg-neutral-900/50 backdrop-blur-sm px-6 py-2 text-sm font-medium text-gray-600 dark:text-gray-300 transition-colors hover:bg-white hover:text-(--accent-primary) dark:hover:bg-neutral-800 dark:hover:text-(--accent-primary)';
7980

8081
return (
81-
<main className="relative min-h-[calc(100vh-80px)] overflow-hidden">
82+
<div className="min-h-screen">
8283
<PostAuthQuizSync />
83-
<div
84-
className="pointer-events-none absolute inset-0 -z-10"
85-
aria-hidden="true"
84+
<DynamicGridBackground
85+
showStaticGrid
86+
className="min-h-screen bg-gray-50 py-12 transition-colors duration-300 dark:bg-transparent"
8687
>
87-
<div className="absolute inset-0 bg-linear-to-b from-sky-50 via-white to-rose-50 dark:from-slate-950 dark:via-slate-950 dark:to-black" />
88-
<div className="absolute top-0 left-1/4 h-96 w-xl -translate-x-1/2 rounded-full bg-sky-300/20 blur-3xl dark:bg-sky-500/10" />
89-
<div className="absolute right-0 bottom-0 h-104 w-104 rounded-full bg-violet-300/30 blur-3xl dark:bg-violet-500/10" />
90-
<div className="absolute bottom-10 left-10 h-80 w-[20rem] rounded-full bg-pink-300/20 blur-3xl dark:bg-fuchsia-500/10" />
91-
</div>
92-
93-
<div className="relative z-10 mx-auto max-w-5xl px-6 py-12">
94-
<header className="mb-12 flex flex-col justify-between gap-6 md:flex-row md:items-center">
95-
<div>
96-
<h1 className="text-4xl font-black tracking-tight drop-shadow-sm md:text-5xl">
97-
<span className="bg-linear-to-r from-sky-400 via-violet-400 to-pink-400 bg-clip-text text-transparent dark:from-sky-400 dark:via-indigo-400 dark:to-fuchsia-500">
98-
{t('title')}
99-
</span>
100-
</h1>
101-
<p className="mt-2 text-lg text-slate-600 dark:text-slate-400">
102-
{t('subtitle')}
103-
</p>
88+
<main className="relative z-10 mx-auto max-w-5xl px-6">
89+
<header className="mb-12 flex flex-col justify-between gap-6 md:flex-row md:items-center">
90+
<div>
91+
<h1 className="text-4xl font-black tracking-tight md:text-5xl">
92+
<span className="text-(--accent-primary)">{t('title')}</span>
93+
</h1>
94+
<p className="mt-2 text-lg text-gray-600 dark:text-gray-400">
95+
{t('subtitle')}
96+
</p>
97+
</div>
98+
99+
<span className={outlineBtnStyles}>{t('supportLink')}</span>
100+
</header>
101+
<QuizSavedBanner />
102+
<div className="grid gap-8 md:grid-cols-2">
103+
<ProfileCard user={userForDisplay} locale={locale} />
104+
<StatsCard stats={stats} />
104105
</div>
105-
106-
<span className={outlineBtnStyles}>{t('supportLink')}</span>
107-
</header>
108-
<QuizSavedBanner />
109-
<div className="grid gap-8 md:grid-cols-2">
110-
<ProfileCard user={userForDisplay} locale={locale} />
111-
<StatsCard stats={stats} />
112-
</div>
113-
</div>
114-
</main>
106+
</main>
107+
</DynamicGridBackground>
108+
</div>
115109
);
116110
}

frontend/app/not-found.tsx

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,23 @@ export default async function NotFound() {
2626
return (
2727
<main className="bg-background relative flex min-h-screen items-center justify-center overflow-hidden transition-colors duration-300">
2828
<div className="pointer-events-none absolute inset-0 opacity-60">
29-
<div className="absolute -top-32 left-1/2 h-96 w-[36rem] -translate-x-1/2 rounded-full bg-[var(--accent-primary)]/20 blur-3xl" />
30-
<div className="absolute bottom-[-12rem] left-1/4 h-[22rem] w-[22rem] rounded-full bg-[var(--accent-hover)]/15 blur-3xl" />
31-
<div className="absolute right-0 bottom-[-10rem] h-[26rem] w-[26rem] rounded-full bg-[var(--accent-primary)]/25 blur-3xl" />
29+
<div className="absolute -top-32 left-1/2 h-96 w-xl -translate-x-1/2 rounded-full bg-(--accent-primary)/20 blur-3xl" />
30+
<div className="absolute -bottom-48 left-1/4 h-88 w-88 rounded-full bg-(--accent-hover)/15 blur-3xl" />
31+
<div className="absolute -bottom-40 right-0 h-104 w-104 rounded-full bg-(--accent-primary)/25 blur-3xl" />
3232
</div>
3333

3434
<div className="pointer-events-none absolute inset-0 opacity-40 dark:opacity-60">
35-
<span className="absolute top-[18%] left-[10%] h-1 w-1 rounded-full bg-[var(--accent-primary)]" />
36-
<span className="absolute top-[8%] left-[35%] h-1 w-1 rounded-full bg-[var(--accent-hover)]" />
37-
<span className="absolute top-[16%] left-[70%] h-1 w-1 rounded-full bg-[var(--accent-primary)]" />
38-
<span className="absolute top-[40%] left-[80%] h-1 w-1 rounded-full bg-[var(--accent-hover)]" />
39-
<span className="absolute top-[60%] left-[18%] h-1 w-1 rounded-full bg-[var(--accent-primary)]" />
35+
<span className="absolute top-[18%] left-[10%] h-1 w-1 rounded-full bg-(--accent-primary)" />
36+
<span className="absolute top-[8%] left-[35%] h-1 w-1 rounded-full bg-(--accent-hover)" />
37+
<span className="absolute top-[16%] left-[70%] h-1 w-1 rounded-full bg-(--accent-primary)" />
38+
<span className="absolute top-[40%] left-[80%] h-1 w-1 rounded-full bg-(--accent-hover)" />
39+
<span className="absolute top-[60%] left-[18%] h-1 w-1 rounded-full bg-(--accent-primary)" />
4040
</div>
4141

4242
<div className="relative z-10 px-6 py-12 text-center">
4343
<div className="relative mt-4 inline-block">
4444
<h1 className="text-4xl font-black tracking-tight sm:text-5xl md:text-6xl lg:text-7xl xl:text-8xl">
45-
<span className="relative inline-block bg-gradient-to-r from-[var(--accent-primary)]/70 via-[color-mix(in_srgb,var(--accent-primary)_70%,white)]/70 to-[var(--accent-hover)]/70 bg-clip-text text-transparent">
45+
<span className="relative inline-block bg-linear-to-r from-(--accent-primary)/70 via-[color-mix(in_srgb,var(--accent-primary)_70%,white)]/70 to-(--accent-hover)/70 bg-clip-text text-transparent">
4646
DevL
4747
</span>
4848
<span
@@ -51,7 +51,7 @@ export default async function NotFound() {
5151
>
5252
Ø
5353
</span>
54-
<span className="relative inline-block bg-gradient-to-r from-[var(--accent-primary)]/70 via-[color-mix(in_srgb,var(--accent-primary)_70%,white)]/70 to-[var(--accent-hover)]/70 bg-clip-text text-transparent">
54+
<span className="relative inline-block bg-linear-to-r from-(--accent-primary)/70 via-[color-mix(in_srgb,var(--accent-primary)_70%,white)]/70 to-(--accent-hover)/70 bg-clip-text text-transparent">
5555
vers
5656
</span>
5757
</h1>
@@ -67,7 +67,7 @@ export default async function NotFound() {
6767

6868
<a
6969
href={`/${locale}`}
70-
className="mt-8 inline-flex items-center justify-center rounded-full bg-[var(--accent-primary)] px-6 py-3 text-sm font-medium text-white transition-colors hover:bg-[var(--accent-hover)]"
70+
className="mt-8 inline-flex items-center justify-center rounded-full bg-(--accent-primary) px-6 py-3 text-sm font-medium text-white transition-colors hover:bg-(--accent-hover)"
7171
>
7272
{t.backHome}
7373
</a>

frontend/components/dashboard/ProfileCard.tsx

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,58 +17,56 @@ export function ProfileCard({ user, locale }: ProfileCardProps) {
1717
const t = useTranslations('dashboard.profile');
1818

1919
const cardStyles = `
20-
relative overflow-hidden rounded-[2rem]
21-
border border-slate-200/70 dark:border-slate-700/80
22-
bg-white/60 dark:bg-slate-900/60 backdrop-blur-md
23-
shadow-[0_18px_45px_rgba(15,23,42,0.05)]
24-
dark:shadow-[0_22px_60px_rgba(0,0,0,0.2)]
25-
p-8 transition-all hover:border-sky-200 dark:hover:border-sky-800
20+
relative overflow-hidden rounded-2xl
21+
border border-gray-100 dark:border-white/5
22+
bg-white/60 dark:bg-neutral-900/60 backdrop-blur-xl
23+
p-8 transition-all hover:border-(--accent-primary)/30 dark:hover:border-(--accent-primary)/30
2624
`;
2725

2826
return (
2927
<section className={cardStyles} aria-labelledby="profile-heading">
3028
<div className="flex items-start gap-6">
3129
<div
32-
className="relative rounded-full bg-gradient-to-br from-sky-400 to-pink-400 p-[3px]"
30+
className="relative rounded-full bg-linear-to-br from-(--accent-primary) to-(--accent-hover) p-0.75"
3331
aria-hidden="true"
3432
>
35-
<div className="flex h-20 w-20 items-center justify-center rounded-full bg-white text-3xl font-bold text-slate-700 dark:bg-slate-900 dark:text-slate-200">
33+
<div className="flex h-20 w-20 items-center justify-center rounded-full bg-white text-3xl font-bold text-gray-700 dark:bg-neutral-900 dark:text-gray-200">
3634
{user.name?.[0]?.toUpperCase() || user.email[0].toUpperCase()}
3735
</div>
3836
</div>
3937

4038
<div className="flex-1">
4139
<h2
4240
id="profile-heading"
43-
className="text-2xl font-bold text-slate-800 dark:text-slate-100"
41+
className="text-2xl font-bold text-gray-900 dark:text-white"
4442
>
4543
{user.name || t('defaultName')}
4644
</h2>
47-
<p className="font-mono text-sm text-slate-500 dark:text-slate-400">
45+
<p className="font-mono text-sm text-gray-500 dark:text-gray-400">
4846
{user.email}
4947
</p>
5048

51-
<div className="mt-3 inline-flex items-center rounded-full bg-sky-100 px-3 py-1 text-xs font-bold tracking-wider text-sky-700 uppercase dark:bg-sky-900/30 dark:text-sky-300">
49+
<div className="mt-3 inline-flex items-center rounded-full bg-(--accent-primary)/10 px-3 py-1 text-xs font-bold tracking-wider text-(--accent-primary) uppercase">
5250
{user.role || t('defaultRole')}
5351
</div>
5452
</div>
5553
</div>
5654

57-
<dl className="mt-8 grid grid-cols-2 gap-6 border-t border-slate-100 pt-6 dark:border-slate-800/50">
55+
<dl className="mt-8 grid grid-cols-2 gap-6 border-t border-gray-100 pt-6 dark:border-white/5">
5856
<div>
59-
<dt className="text-xs font-semibold tracking-wider text-slate-400 uppercase">
57+
<dt className="text-xs font-semibold tracking-wider text-gray-400 uppercase">
6058
{t('totalPoints')}
6159
</dt>
6260

63-
<dd className="mt-1 text-3xl font-black text-slate-800 dark:text-white">
61+
<dd className="mt-1 text-3xl font-black text-gray-900 dark:text-white">
6462
{user.points}
6563
</dd>
6664
</div>
6765
<div>
68-
<dt className="text-xs font-semibold tracking-wider text-slate-400 uppercase">
66+
<dt className="text-xs font-semibold tracking-wider text-gray-400 uppercase">
6967
{t('joined')}
7068
</dt>
71-
<dd className="mt-2 text-lg font-medium text-slate-700 dark:text-slate-300">
69+
<dd className="mt-2 text-lg font-medium text-gray-700 dark:text-gray-300">
7270
{user.createdAt
7371
? new Date(user.createdAt).toLocaleDateString(locale)
7472
: '-'}

frontend/components/dashboard/QuizSavedBanner.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@ export function QuizSavedBanner() {
3737
if (!info) return null;
3838

3939
return (
40-
<div className="mb-6 rounded-xl border border-green-200 bg-green-50 p-4 dark:border-green-800 dark:bg-green-900/20">
40+
<div className="mb-6 rounded-xl border border-green-500/20 bg-green-500/10 p-4 backdrop-blur-sm">
4141
<div className="space-y-2 text-center">
42-
<p className="text-lg font-medium text-green-800 dark:text-green-200">
42+
<p className="text-lg font-medium text-green-700 dark:text-green-300">
4343
🎉 {t('title')}
4444
</p>
45-
<p className="text-green-700 dark:text-green-300">
45+
<p className="text-green-600 dark:text-green-400">
4646
{t('scored')}{' '}
4747
<strong>
4848
{info.score}/{info.total}
@@ -62,13 +62,13 @@ export function QuizSavedBanner() {
6262
<div className="flex justify-center gap-3 pt-2">
6363
<Link
6464
href="/leaderboard"
65-
className="text-green-600 underline hover:no-underline dark:text-green-400"
65+
className="font-medium text-green-600 underline hover:no-underline dark:text-green-400"
6666
>
6767
{t('viewLeaderboard')}
6868
</Link>
6969
<Link
7070
href={`/quiz/${info.quizSlug}`}
71-
className="text-green-600 underline hover:no-underline dark:text-green-400"
71+
className="font-medium text-green-600 underline hover:no-underline dark:text-green-400"
7272
>
7373
{t('tryAgain')}
7474
</Link>

frontend/components/dashboard/StatsCard.tsx

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,69 +18,61 @@ export function StatsCard({ stats }: StatsCardProps) {
1818
const hasActivity = stats && stats.totalAttempts > 0;
1919

2020
const cardStyles = `
21-
relative overflow-hidden rounded-[2rem]
22-
border border-slate-200/70 dark:border-slate-700/80
23-
bg-white/60 dark:bg-slate-900/60 backdrop-blur-md
24-
shadow-[0_18px_45px_rgba(15,23,42,0.05)]
25-
dark:shadow-[0_22px_60px_rgba(0,0,0,0.2)]
26-
p-8 transition-all hover:border-sky-200 dark:hover:border-sky-800
21+
relative overflow-hidden rounded-2xl
22+
border border-gray-100 dark:border-white/5
23+
bg-white/60 dark:bg-neutral-900/60 backdrop-blur-xl
24+
p-8 transition-all hover:border-[var(--accent-primary)]/30 dark:hover:border-[var(--accent-primary)]/30
2725
flex flex-col items-center justify-center text-center
2826
`;
2927

3028
const primaryBtnStyles = `
3129
group relative inline-flex items-center justify-center rounded-full
3230
px-8 py-3 text-sm font-semibold tracking-widest uppercase text-white
33-
bg-gradient-to-r from-sky-500 via-indigo-500 to-pink-500
34-
shadow-[0_4px_14px_rgba(56,189,248,0.4)]
35-
dark:shadow-[0_4px_20px_rgba(129,140,248,0.4)]
36-
transition-all hover:scale-105 hover:shadow-lg
31+
bg-[var(--accent-primary)] hover:bg-[var(--accent-hover)]
32+
transition-all hover:scale-105
3733
`;
3834

3935
return (
4036
<section className={cardStyles} aria-labelledby="stats-heading">
4137
<div
42-
className="mb-6 rounded-full bg-slate-50 p-4 shadow-inner dark:bg-slate-800/50"
38+
className="mb-6 rounded-full bg-gray-100 p-4 dark:bg-neutral-800/50"
4339
aria-hidden="true"
4440
>
4541
<span className="text-4xl">📊</span>
4642
</div>
4743

4844
<h3
4945
id="stats-heading"
50-
className="mb-2 text-xl font-bold text-slate-800 dark:text-slate-100"
46+
className="mb-2 text-xl font-bold text-gray-900 dark:text-white"
5147
>
5248
{t('title')}
5349
</h3>
5450

5551
{!hasActivity ? (
5652
<>
57-
<p className="mx-auto mb-8 max-w-xs text-slate-500 dark:text-slate-400">
53+
<p className="mx-auto mb-8 max-w-xs text-gray-500 dark:text-gray-400">
5854
{t('noActivity')}
5955
</p>
6056
<Link href="/quizzes" className={primaryBtnStyles}>
6157
<span className="relative z-10">{t('startQuiz')}</span>
62-
<span
63-
className="absolute inset-0 rounded-full bg-gradient-to-r from-white/20 to-transparent opacity-0 transition-opacity group-hover:opacity-100"
64-
aria-hidden="true"
65-
/>
6658
</Link>
6759
</>
6860
) : (
6961
<dl className="mt-2 grid w-full grid-cols-2 gap-4">
70-
<div className="rounded-2xl border border-slate-100 bg-slate-50/50 p-4 dark:border-slate-700 dark:bg-slate-800/50">
71-
<dt className="mb-1 flex items-center justify-center gap-2 text-xs font-semibold tracking-wider text-slate-400 uppercase">
62+
<div className="rounded-xl border border-gray-100 bg-gray-50/50 p-4 dark:border-white/5 dark:bg-neutral-800/50">
63+
<dt className="mb-1 flex items-center justify-center gap-2 text-xs font-semibold tracking-wider text-gray-400 uppercase">
7264
<History className="h-3 w-3" /> {t('attempts')}
7365
</dt>
74-
<dd className="text-2xl font-black text-slate-800 dark:text-white">
66+
<dd className="text-2xl font-black text-gray-900 dark:text-white">
7567
{stats?.totalAttempts}
7668
</dd>
7769
</div>
7870

79-
<div className="rounded-2xl border border-slate-100 bg-slate-50/50 p-4 dark:border-slate-700 dark:bg-slate-800/50">
80-
<dt className="mb-1 flex items-center justify-center gap-2 text-xs font-semibold tracking-wider text-slate-400 uppercase">
71+
<div className="rounded-xl border border-gray-100 bg-gray-50/50 p-4 dark:border-white/5 dark:bg-neutral-800/50">
72+
<dt className="mb-1 flex items-center justify-center gap-2 text-xs font-semibold tracking-wider text-gray-400 uppercase">
8173
<TrendingUp className="h-3 w-3" /> {t('avgScore')}
8274
</dt>
83-
<dd className="text-2xl font-black text-slate-800 dark:text-white">
75+
<dd className="text-2xl font-black text-gray-900 dark:text-white">
8476
{stats?.averageScore}%
8577
</dd>
8678
</div>

0 commit comments

Comments
 (0)