Skip to content

Commit 5951e3a

Browse files
Merge pull request #180 from DevLoversTeam/feature/leaderboard-style
fix:Update leaderboard: fixed background
2 parents e6480db + 7618c2c commit 5951e3a

3 files changed

Lines changed: 26 additions & 32 deletions

File tree

frontend/components/leaderboard/LeaderboardClient.tsx

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,15 @@
33
import { useRef } from 'react';
44
import { motion, useMotionTemplate, useMotionValue } from 'framer-motion';
55
import { useTranslations } from 'next-intl';
6+
import { cn } from '@/lib/utils';
67
import { LeaderboardPodium } from './LeaderboardPodium';
78
import { LeaderboardTable } from './LeaderboardTable';
8-
import { User } from './types';
9+
import { User, CurrentUser } from './types';
910

10-
// Імпортуємо тип з auth
11-
type AuthUser = { id: string; username: string; email: string };
1211

1312
interface LeaderboardClientProps {
1413
initialUsers: User[];
15-
currentUser?: AuthUser | null;
14+
currentUser?: CurrentUser | null;
1615
}
1716

1817
export default function LeaderboardClient({
@@ -21,13 +20,10 @@ export default function LeaderboardClient({
2120
}: LeaderboardClientProps) {
2221
const t = useTranslations('leaderboard');
2322

24-
// Використовуємо всіх користувачів для таблиці
2523
const allUsers = initialUsers;
26-
// Подіум тільки для тих, хто має бали
2724
const topThree = allUsers.filter(u => u.points > 0).slice(0, 3);
2825
const hasResults = topThree.length > 0;
2926

30-
// --- Логіка ефекту ліхтарика ---
3127
const containerRef = useRef<HTMLDivElement>(null);
3228
const mouseX = useMotionValue(0);
3329
const mouseY = useMotionValue(0);
@@ -37,9 +33,8 @@ export default function LeaderboardClient({
3733
clientX,
3834
clientY,
3935
}: React.MouseEvent) {
40-
const { left, top } = currentTarget.getBoundingClientRect();
41-
mouseX.set(clientX - left);
42-
mouseY.set(clientY - top);
36+
mouseX.set(clientX);
37+
mouseY.set(clientY);
4338
}
4439

4540
const maskImage = useMotionTemplate`radial-gradient(500px circle at ${mouseX}px ${mouseY}px, black, transparent)`;
@@ -48,41 +43,37 @@ export default function LeaderboardClient({
4843
<div
4944
ref={containerRef}
5045
onMouseMove={handleMouseMove}
51-
className="relative min-h-screen overflow-hidden bg-slate-50 dark:bg-slate-950 group transition-colors duration-300"
46+
className="relative min-h-screen bg-slate-50 dark:bg-slate-950 group transition-colors duration-300"
5247
>
53-
{/* Background Layers - КОНТУРНІ СЕРДЕЧКА 💖 */}
54-
55-
{/* 1. Статичний шар (сірі контури, ледь помітні) */}
5648
<div
57-
className="absolute inset-0 z-0 bg-repeat [mask-image:radial-gradient(ellipse_60%_50%_at_50%_0%,#000_70%,transparent_100%)]"
49+
className="fixed inset-0 z-0 bg-repeat opacity-60 pointer-events-none"
5850
style={{
59-
// stroke='%23808080' - це сірий колір обводки
60-
// fill='none' - прозорий центр
61-
backgroundImage: `url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z' stroke='%23808080' stroke-width='1.5' stroke-opacity='0.15' fill='none'/%3E%3C/svg%3E")`,
51+
backgroundImage: `url("data:image/svg+xml,%3Csvg width='40' height='40' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z' stroke='%23808080' stroke-width='0.2' stroke-opacity='0.2' fill='none'/%3E%3C/svg%3E")`,
6252
backgroundSize: '40px 40px',
6353
}}
6454
/>
6555

66-
{/* 2. Динамічний шар (МАЖЕНТО контури, світяться під мишкою) */}
6756
<motion.div
68-
className="absolute inset-0 z-0 bg-repeat"
57+
className="fixed inset-0 z-0 bg-repeat pointer-events-none"
6958
style={{
7059
maskImage,
71-
WebkitMaskImage: maskImage,
72-
// stroke='%23ff2d55' - це твій маженто колір обводки
73-
backgroundImage: `url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z' stroke='%23ff2d55' stroke-width='2' stroke-opacity='0.5' fill='none'/%3E%3C/svg%3E")`,
60+
backgroundImage: `url("data:image/svg+xml,%3Csvg width='40' height='40' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z' stroke='%23ff2d55' stroke-width='0.9' stroke-opacity='0.8' fill='none'/%3E%3C/svg%3E")`,
7461
backgroundSize: '40px 40px',
7562
}}
7663
/>
7764

78-
{/* Велика розмита пляма по центру */}
79-
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-[800px] h-[500px] bg-[#ff2d55]/15 blur-[120px] rounded-full pointer-events-none" />
65+
<div className="fixed top-0 left-1/2 -translate-x-1/2 w-[800px] h-[500px] bg-[#ff2d55]/10 blur-[120px] rounded-full pointer-events-none z-0" />
8066

8167
<div className="relative max-w-5xl mx-auto px-4 py-20 flex flex-col items-center z-10">
8268
<header className="text-center mb-16 animate-in fade-in slide-in-from-top-4 duration-700">
83-
<h1 className="text-5xl md:text-7xl font-bold tracking-tight text-[#ff2d55] mb-6 drop-shadow-sm">
69+
<h1 className={cn(
70+
"text-6xl md:text-8xl mb-6 uppercase select-none font-black tracking-tight",
71+
"text-[#ff2d55]",
72+
"drop-shadow-[0_0_25px_rgba(255,45,85,0.4)]"
73+
)}>
8474
{t('title')}
8575
</h1>
76+
8677
<p className="text-slate-600 dark:text-slate-400 text-lg md:text-xl max-w-2xl mx-auto leading-relaxed font-medium">
8778
{t('subtitle')}
8879
</p>
@@ -112,4 +103,4 @@ export default function LeaderboardClient({
112103
</div>
113104
</div>
114105
);
115-
}
106+
}

frontend/components/leaderboard/LeaderboardTable.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,11 @@ import { TrendingUp, Trophy, Medal } from 'lucide-react';
44
import { motion } from 'framer-motion';
55
import { useTranslations } from 'next-intl';
66
import { cn } from '@/lib/utils';
7-
import { User } from './types';
8-
9-
type AuthUser = { id: string; username: string; email: string };
7+
import { User, CurrentUser } from './types';
108

119
interface LeaderboardTableProps {
1210
users: User[];
13-
currentUser?: AuthUser | null;
11+
currentUser?: CurrentUser | null;
1412
}
1513

1614
export function LeaderboardTable({
@@ -227,4 +225,4 @@ function RankBadge({ rank }: { rank: number }) {
227225
{rank}
228226
</span>
229227
);
230-
}
228+
}

frontend/components/leaderboard/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,8 @@ export interface User {
66
avatar: string;
77
change: number;
88
}
9+
10+
export interface CurrentUser {
11+
id: string;
12+
username: string;
13+
}

0 commit comments

Comments
 (0)