elmeg-demo/frontend/app/profile/page.tsx

172 lines
6.6 KiB
TypeScript

"use client"
import { useEffect, useState } from "react"
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Trophy, Calendar } from "lucide-react"
import Link from "next/link"
import { BadgeList } from "@/components/profile/badge-list"
import { getApiUrl } from "@/lib/api-config"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { UserAttendanceList } from "@/components/profile/user-attendance-list"
import { UserReviewsList } from "@/components/profile/user-reviews-list"
import { UserGroupsList } from "@/components/profile/user-groups-list"
// Types
interface UserProfile {
id: number
email: string
username: string // Assuming we add this to UserRead or fetch separately
}
interface UserBadge {
id: number
badge: {
id: number
name: string
description: string
icon: string
slug: string
}
awarded_at: string
}
export default function ProfilePage() {
const [user, setUser] = useState<UserProfile | null>(null)
const [badges, setBadges] = useState<UserBadge[]>([])
const [loading, setLoading] = useState(true)
const [stats, setStats] = useState({ attendance_count: 0, review_count: 0, group_count: 0 })
useEffect(() => {
const token = localStorage.getItem("token")
if (!token) {
setLoading(false)
return
}
// Fetch User Data
fetch(`${getApiUrl()}/auth/users/me`, {
headers: { Authorization: `Bearer ${token}` }
})
.then(res => {
if (res.ok) return res.json()
throw new Error("Failed to fetch user")
})
.then(data => {
setUser(data)
// Fetch Badges
fetch(`${getApiUrl()}/badges/me`, {
headers: { Authorization: `Bearer ${token}` }
})
.then(res => res.ok ? res.json() : [])
.then(data => setBadges(data))
// Fetch Stats
fetch(`${getApiUrl()}/users/${data.id}/stats`, {
headers: { Authorization: `Bearer ${token}` }
})
.then(res => res.ok ? res.json() : { attendance_count: 0, review_count: 0, group_count: 0 })
.then((statsData: { attendance_count: number; review_count: number; group_count: number }) => setStats(statsData))
})
.catch(err => console.error(err))
.finally(() => setLoading(false))
}, [])
if (loading) {
return <div className="p-8 text-center">Loading profile...</div>
}
if (!user) {
return (
<div className="flex flex-col items-center justify-center gap-4 py-20">
<h1 className="text-2xl font-bold">Please Log In</h1>
<Link href="/login">
<Button>Log In</Button>
</Link>
</div>
)
}
// Transform badges for the list component
const displayBadges = badges.map(b => b.badge)
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div>
<h1 className="text-3xl font-bold tracking-tight">{user.email}</h1>
<p className="text-muted-foreground flex items-center gap-2">
<Calendar className="h-4 w-4" />
Member
</p>
</div>
<Link href="/settings">
<Button variant="outline">Settings</Button>
</Link>
</div>
<Tabs defaultValue="overview" className="w-full">
<TabsList>
<TabsTrigger value="overview">Overview</TabsTrigger>
<TabsTrigger value="attendance">Attendance</TabsTrigger>
<TabsTrigger value="reviews">Reviews</TabsTrigger>
<TabsTrigger value="groups">Groups</TabsTrigger>
</TabsList>
<TabsContent value="overview" className="space-y-6 mt-6">
<div className="grid gap-6 md:grid-cols-3">
<Card>
<CardHeader className="pb-2">
<CardTitle className="text-sm font-medium text-muted-foreground">Shows Attended</CardTitle>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{stats.attendance_count}</div>
</CardContent>
</Card>
<Card>
<CardHeader className="pb-2">
<CardTitle className="text-sm font-medium text-muted-foreground">Reviews Written</CardTitle>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{stats.review_count}</div>
</CardContent>
</Card>
<Card>
<CardHeader className="pb-2">
<CardTitle className="text-sm font-medium text-muted-foreground">Groups Joined</CardTitle>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{stats.group_count}</div>
</CardContent>
</Card>
</div>
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Trophy className="h-5 w-5 text-yellow-500" />
Badges
</CardTitle>
</CardHeader>
<CardContent>
<BadgeList badges={displayBadges} />
</CardContent>
</Card>
</TabsContent>
<TabsContent value="attendance" className="mt-6">
<UserAttendanceList userId={user.id} />
</TabsContent>
<TabsContent value="reviews" className="mt-6">
<UserReviewsList userId={user.id} />
</TabsContent>
<TabsContent value="groups" className="mt-6">
<UserGroupsList userId={user.id} />
</TabsContent>
</Tabs>
</div>
)
}