Files
MulliganMates/app/(app)/dashboard/page.tsx
T
2026-03-18 13:34:41 +01:00

98 lines
3.3 KiB
TypeScript

import { redirect } from 'next/navigation'
import Link from 'next/link'
import { auth } from '@/lib/auth'
import { db } from '@/lib/db'
import { rounds, roundPlayers, courses, tees } from '@/lib/db/schema'
import { eq, inArray } from 'drizzle-orm'
import { buttonVariants } from '@/components/ui/button'
import { cn } from '@/lib/utils'
import { headers } from 'next/headers'
export default async function DashboardPage() {
const session = await auth.api.getSession({ headers: await headers() })
if (!session) redirect('/login')
const memberships = await db
.select({ roundId: roundPlayers.roundId })
.from(roundPlayers)
.where(eq(roundPlayers.userId, session.user.id))
const roundIds = memberships.map((m) => m.roundId)
const activeRounds =
roundIds.length > 0
? await db
.select({
id: rounds.id,
name: rounds.name,
date: rounds.date,
status: rounds.status,
holesCount: rounds.holesCount,
courseName: courses.name,
teeName: tees.name,
teeColor: tees.color,
})
.from(rounds)
.innerJoin(courses, eq(rounds.courseId, courses.id))
.innerJoin(tees, eq(rounds.teeId, tees.id))
.where(inArray(rounds.id, roundIds))
.orderBy(rounds.date)
: []
const visibleRounds = activeRounds.filter((r) => r.status !== 'completed')
return (
<div className="p-4 space-y-4">
<div className="flex items-center justify-between">
<h1 className="text-2xl font-bold">Rounds</h1>
<Link href="/rounds/new" className={cn(buttonVariants({ size: 'sm' }))}>
New round
</Link>
</div>
{visibleRounds.length === 0 && (
<p className="py-8 text-center text-sm text-muted-foreground">
No active rounds. Start one!
</p>
)}
<div className="space-y-3">
{visibleRounds.map((round) => (
<Link
key={round.id}
href={round.status === 'active' ? `/rounds/${round.id}/scorecard` : `/rounds/${round.id}`}
className="block rounded-xl border p-4 space-y-1 transition-colors hover:bg-muted"
>
<div className="flex items-center justify-between">
<span className="font-semibold">{round.courseName}</span>
<StatusBadge status={round.status} />
</div>
<div className="text-sm text-muted-foreground">
{round.name && <span>{round.name} · </span>}
<span
className="inline-block h-2.5 w-2.5 rounded-full border align-middle mr-1"
style={{ backgroundColor: round.teeColor }}
/>
{round.teeName} · {round.holesCount} holes ·{' '}
{new Date(round.date).toLocaleDateString()}
</div>
</Link>
))}
</div>
</div>
)
}
function StatusBadge({ status }: { status: string }) {
const styles: Record<string, string> = {
lobby: 'bg-yellow-100 text-yellow-800',
active: 'bg-green-100 text-green-800',
completed: 'bg-gray-100 text-gray-600',
}
return (
<span className={`rounded-full px-2 py-0.5 text-xs font-medium ${styles[status] ?? styles.completed}`}>
{status}
</span>
)
}