This commit is contained in:
2026-02-02 23:13:09 +01:00
parent d0b4a53f80
commit 0951ad4799
3 changed files with 237 additions and 236 deletions
+2 -4
View File
@@ -9,7 +9,7 @@ import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"; import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
const Problems = () => { export default function Problems() {
const [viewMode, setViewMode] = useState<"grid" | "list">("grid"); const [viewMode, setViewMode] = useState<"grid" | "list">("grid");
const categories = ["All", "Arrays", "Trees", "Graphs", "DP", "Strings"]; const categories = ["All", "Arrays", "Trees", "Graphs", "DP", "Strings"];
@@ -90,9 +90,7 @@ const Problems = () => {
</div> </div>
</div> </div>
); );
}; }
export default Problems;
/* ---------------- data ---------------- */ /* ---------------- data ---------------- */
+207 -232
View File
@@ -1,15 +1,15 @@
import { "use client";
Trophy,
Timer, import { Trophy, Timer, Zap, Target, Calendar, Award } from "lucide-react";
Zap,
Target, import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
Calendar, import { Badge } from "@/components/ui/badge";
TrendingUp, import { Button } from "@/components/ui/button";
Award, import { Separator } from "@/components/ui/separator";
} from "lucide-react";
import StatCard from "@/components/app/StatCard"; import StatCard from "@/components/app/StatCard";
const Profile = () => { export default function Profile() {
const user = { const user = {
username: "speedmaster_x", username: "speedmaster_x",
joinDate: "Jan 2024", joinDate: "Jan 2024",
@@ -21,139 +21,49 @@ const Profile = () => {
favoriteCategory: "Any%", favoriteCategory: "Any%",
}; };
const recentRuns = [
{
id: 1,
category: "Any%",
time: "2:38.54",
date: "2 hours ago",
status: "clean",
},
{
id: 2,
category: "Any%",
time: "2:45.12",
date: "3 hours ago",
status: "clean",
},
{
id: 3,
category: "Easy Only",
time: "1:23.45",
date: "5 hours ago",
status: "clean",
},
{
id: 4,
category: "Any%",
time: "--:--",
date: "5 hours ago",
status: "reset",
},
{
id: 5,
category: "Any%",
time: "2:51.33",
date: "Yesterday",
status: "clean",
},
{
id: 6,
category: "No DP",
time: "3:45.67",
date: "Yesterday",
status: "clean",
},
];
const achievements = [
{
name: "First Blood",
description: "Complete your first run",
icon: Zap,
unlocked: true,
},
{
name: "Sub-3 Club",
description: "Finish a run under 3 minutes",
icon: Timer,
unlocked: true,
},
{
name: "World Record",
description: "Hold a world record",
icon: Trophy,
unlocked: true,
},
{
name: "Century",
description: "Complete 100 runs",
icon: Target,
unlocked: true,
},
{
name: "Perfectionist",
description: "100 clean runs",
icon: Award,
unlocked: false,
},
{
name: "Marathon",
description: "10 hours of running",
icon: Calendar,
unlocked: true,
},
];
return ( return (
<div className="min-h-screen pt-24 pb-16"> <div className="min-h-screen pt-24 pb-16">
<div className="container mx-auto px-6"> <div className="container mx-auto px-6 space-y-8">
{/* Profile Header */} {/* Profile Header */}
<div className="bg-card border border-border rounded-2xl p-8 mb-8 relative overflow-hidden"> <Card className="relative overflow-hidden">
{/* Background gradient */} <div className="absolute inset-0 bg-linear-to-r from-primary/10 via-transparent to-transparent" />
<div className="absolute inset-0 bg-linear-to-r from-primary/10 via-transparent to-transparent pointer-events-none" />
<div className="relative flex flex-col md:flex-row items-start md:items-center gap-6"> <CardContent className="relative p-8 flex flex-col md:flex-row gap-6">
{/* Avatar */} {/* Avatar */}
<div className="relative"> <div className="relative">
<div className="w-24 h-24 rounded-2xl bg-linear-to-br from-primary to-primary/50 flex items-center justify-center text-3xl font-bold text-primary-foreground glow-purple"> <div className="w-24 h-24 rounded-2xl bg-linear-to-br from-primary to-primary/60 flex items-center justify-center text-3xl font-bold text-primary-foreground glow-purple">
{user.username.charAt(0).toUpperCase()} {user.username[0].toUpperCase()}
</div> </div>
<div className="absolute -bottom-2 -right-2 w-8 h-8 rounded-lg rank-gold flex items-center justify-center text-sm font-bold glow-gold"> <div className="absolute -bottom-2 -right-2 w-8 h-8 rounded-lg rank-gold flex items-center justify-center text-sm font-bold glow-gold">
#1 #{user.rank}
</div> </div>
</div> </div>
{/* User Info */} {/* User Info */}
<div className="flex-1"> <div className="flex-1">
<h1 className="text-3xl font-bold text-foreground mb-1"> <h1 className="text-3xl font-bold">{user.username}</h1>
{user.username}
</h1>
<p className="text-muted-foreground mb-3"> <p className="text-muted-foreground mb-3">
Runner since {user.joinDate} Runner since {user.joinDate}
</p> </p>
<div className="flex flex-wrap gap-3">
<span className="px-3 py-1 rounded-lg bg-primary/10 text-primary text-sm font-medium border border-primary/30"> <div className="flex flex-wrap gap-2">
World Record Holder <Badge>World Record Holder</Badge>
</span> <Badge variant="secondary">{user.favoriteCategory} Main</Badge>
<span className="px-3 py-1 rounded-lg bg-secondary text-secondary-foreground text-sm">
{user.favoriteCategory} Main
</span>
</div> </div>
</div> </div>
{/* Quick Stats */} {/* PB */}
<div className="text-right"> <div className="text-right">
<p className="text-4xl font-bold font-mono text-primary text-glow"> <p className="text-4xl font-bold font-mono text-primary text-glow">
{user.pb} {user.pb}
</p> </p>
<p className="text-sm text-muted-foreground">Personal Best</p> <p className="text-sm text-muted-foreground">Personal Best</p>
</div> </div>
</div> </CardContent>
</div> </Card>
{/* Stats Grid */} {/* Stats */}
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-8"> <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
<StatCard <StatCard
label="Total Runs" label="Total Runs"
value={user.totalRuns.toLocaleString()} value={user.totalRuns.toLocaleString()}
@@ -183,80 +93,71 @@ const Profile = () => {
<div className="grid lg:grid-cols-3 gap-8"> <div className="grid lg:grid-cols-3 gap-8">
{/* Recent Runs */} {/* Recent Runs */}
<div className="lg:col-span-2"> <Card className="lg:col-span-2">
<div className="bg-card border border-border rounded-xl p-6"> <CardHeader className="flex flex-row items-center justify-between">
<div className="flex items-center justify-between mb-6"> <CardTitle>Recent Runs</CardTitle>
<h2 className="text-xl font-bold text-foreground"> <Button variant="link" size="sm">
Recent Runs View all
</h2> </Button>
<button className="text-sm text-primary hover:underline"> </CardHeader>
View All
</button>
</div>
<div className="space-y-3"> <CardContent className="space-y-3">
{recentRuns.map((run, i) => ( {recentRuns.map((run, i) => (
<div <div
key={run.id} key={run.id}
className="flex items-center justify-between py-3 px-4 rounded-lg bg-secondary/30 hover:bg-secondary/50 transition-colors animate-fade-in opacity-0" className="flex items-center justify-between rounded-lg px-4 py-3 bg-secondary/30 hover:bg-secondary/50 transition animate-fade-in opacity-0"
style={{ style={{
animationDelay: `${i * 0.1}s`, animationDelay: `${i * 0.1}s`,
animationFillMode: "forwards", animationFillMode: "forwards",
}} }}
> >
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<div <div
className={`w-2 h-2 rounded-full ${ className={`w-2 h-2 rounded-full ${
run.status === "clean" run.status === "clean" ? "bg-emerald-400" : "bg-red-400"
? "bg-emerald-400" }`}
: "bg-red-400" />
}`} <div>
/> <p className="font-medium">{run.category}</p>
<div> <p className="text-xs text-muted-foreground">
<p className="font-medium text-foreground"> {run.date}
{run.category}
</p>
<p className="text-xs text-muted-foreground">
{run.date}
</p>
</div>
</div>
<div className="text-right">
<p
className={`font-mono font-semibold ${
run.status === "reset"
? "text-red-400"
: "text-foreground"
}`}
>
{run.time}
</p>
<p className="text-xs text-muted-foreground capitalize">
{run.status}
</p> </p>
</div> </div>
</div> </div>
))}
</div>
</div>
</div>
{/* Achievements */} <div className="text-right">
<div className="lg:col-span-1"> <p
<div className="bg-card border border-border rounded-xl p-6"> className={`font-mono font-semibold ${
<div className="flex items-center justify-between mb-6"> run.status === "reset"
<h2 className="text-xl font-bold text-foreground"> ? "text-red-400"
Achievements : "text-foreground"
</h2> }`}
<span className="text-sm text-muted-foreground">5/6</span> >
</div> {run.time}
</p>
<p className="text-xs text-muted-foreground capitalize">
{run.status}
</p>
</div>
</div>
))}
</CardContent>
</Card>
<div className="space-y-3"> {/* Achievements + PB */}
{achievements.map((achievement, i) => ( <div className="space-y-4">
<Card>
<CardHeader className="flex flex-row items-center justify-between">
<CardTitle>Achievements</CardTitle>
<span className="text-sm text-muted-foreground">5 / 6</span>
</CardHeader>
<CardContent className="space-y-3">
{achievements.map((a, i) => (
<div <div
key={achievement.name} key={a.name}
className={`flex items-center gap-3 p-3 rounded-lg transition-all animate-fade-in opacity-0 ${ className={`flex items-center gap-3 rounded-lg p-3 animate-fade-in opacity-0 ${
achievement.unlocked a.unlocked
? "bg-primary/10 border border-primary/20" ? "bg-primary/10 border border-primary/20"
: "bg-secondary/30 opacity-50" : "bg-secondary/30 opacity-50"
}`} }`}
@@ -267,39 +168,33 @@ const Profile = () => {
> >
<div <div
className={`p-2 rounded-lg ${ className={`p-2 rounded-lg ${
achievement.unlocked a.unlocked
? "bg-primary/20 text-primary" ? "bg-primary/20 text-primary"
: "bg-secondary text-muted-foreground" : "bg-secondary text-muted-foreground"
}`} }`}
> >
<achievement.icon className="h-4 w-4" /> <a.icon className="h-4 w-4" />
</div> </div>
<div className="flex-1"> <div className="flex-1">
<p <p className="text-sm font-medium">{a.name}</p>
className={`text-sm font-medium ${
achievement.unlocked
? "text-foreground"
: "text-muted-foreground"
}`}
>
{achievement.name}
</p>
<p className="text-xs text-muted-foreground"> <p className="text-xs text-muted-foreground">
{achievement.description} {a.description}
</p> </p>
</div> </div>
{achievement.unlocked && (
{a.unlocked && (
<div className="w-5 h-5 rounded-full bg-primary flex items-center justify-center"> <div className="w-5 h-5 rounded-full bg-primary flex items-center justify-center">
<svg <svg
className="w-3 h-3 text-primary-foreground" className="w-3 h-3 text-primary-foreground"
fill="none"
viewBox="0 0 24 24" viewBox="0 0 24 24"
fill="none"
stroke="currentColor" stroke="currentColor"
strokeWidth={3}
> >
<path <path
strokeLinecap="round" strokeLinecap="round"
strokeLinejoin="round" strokeLinejoin="round"
strokeWidth={3}
d="M5 13l4 4L19 7" d="M5 13l4 4L19 7"
/> />
</svg> </svg>
@@ -307,44 +202,124 @@ const Profile = () => {
)} )}
</div> </div>
))} ))}
</div> </CardContent>
</div> </Card>
{/* PB History */} {/* PB History */}
<div className="bg-card border border-border rounded-xl p-6 mt-4"> <Card>
<h2 className="text-xl font-bold text-foreground mb-4"> <CardHeader>
PB History <CardTitle>PB History</CardTitle>
</h2> </CardHeader>
<div className="space-y-2"> <CardContent className="space-y-2">
<div className="flex justify-between items-center py-2 border-b border-border"> {pbHistory.map((pb, i) => (
<span className="text-muted-foreground text-sm">2:34.21</span> <div key={i}>
<span className="text-xs text-muted-foreground">Today</span> <div className="flex justify-between text-sm">
</div> <span className="text-muted-foreground">{pb.time}</span>
<div className="flex justify-between items-center py-2 border-b border-border"> <span className="text-muted-foreground">{pb.date}</span>
<span className="text-muted-foreground text-sm">2:38.54</span> </div>
<span className="text-xs text-muted-foreground"> {i !== pbHistory.length - 1 && (
3 days ago <Separator className="my-2" />
</span> )}
</div> </div>
<div className="flex justify-between items-center py-2 border-b border-border"> ))}
<span className="text-muted-foreground text-sm">2:45.12</span> </CardContent>
<span className="text-xs text-muted-foreground"> </Card>
1 week ago
</span>
</div>
<div className="flex justify-between items-center py-2">
<span className="text-muted-foreground text-sm">2:52.33</span>
<span className="text-xs text-muted-foreground">
2 weeks ago
</span>
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
); );
}; }
export default Profile; /* ---------------- data ---------------- */
const recentRuns = [
{
id: 1,
category: "Any%",
time: "2:38.54",
date: "2 hours ago",
status: "clean",
},
{
id: 2,
category: "Any%",
time: "2:45.12",
date: "3 hours ago",
status: "clean",
},
{
id: 3,
category: "Easy Only",
time: "1:23.45",
date: "5 hours ago",
status: "clean",
},
{
id: 4,
category: "Any%",
time: "--:--",
date: "5 hours ago",
status: "reset",
},
{
id: 5,
category: "Any%",
time: "2:51.33",
date: "Yesterday",
status: "clean",
},
{
id: 6,
category: "No DP",
time: "3:45.67",
date: "Yesterday",
status: "clean",
},
];
const achievements = [
{
name: "First Blood",
description: "Complete your first run",
icon: Zap,
unlocked: true,
},
{
name: "Sub-3 Club",
description: "Finish a run under 3 minutes",
icon: Timer,
unlocked: true,
},
{
name: "World Record",
description: "Hold a world record",
icon: Trophy,
unlocked: true,
},
{
name: "Century",
description: "Complete 100 runs",
icon: Target,
unlocked: true,
},
{
name: "Perfectionist",
description: "100 clean runs",
icon: Award,
unlocked: false,
},
{
name: "Marathon",
description: "10 hours of running",
icon: Calendar,
unlocked: true,
},
];
const pbHistory = [
{ time: "2:34.21", date: "Today" },
{ time: "2:38.54", date: "3 days ago" },
{ time: "2:45.12", date: "1 week ago" },
{ time: "2:52.33", date: "2 weeks ago" },
];
+28
View File
@@ -0,0 +1,28 @@
"use client"
import * as React from "react"
import { Separator as SeparatorPrimitive } from "radix-ui"
import { cn } from "@/lib/utils"
function Separator({
className,
orientation = "horizontal",
decorative = true,
...props
}: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
return (
<SeparatorPrimitive.Root
data-slot="separator"
decorative={decorative}
orientation={orientation}
className={cn(
"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
className
)}
{...props}
/>
)
}
export { Separator }