Initial commit v1.1
This commit is contained in:
@@ -1,24 +1,28 @@
|
||||
import { createClient } from '@/lib/supabase/server'
|
||||
import { auth } from '@/lib/auth'
|
||||
import { db } from '@/lib/db'
|
||||
import { rounds, roundPlayers, holes, scores, courses, tees, user } from '@/lib/db/schema'
|
||||
import { eq, asc } from 'drizzle-orm'
|
||||
import { redirect, notFound } from 'next/navigation'
|
||||
import { headers } from 'next/headers'
|
||||
import { ScorecardView } from '@/components/scorecard/scorecard-view'
|
||||
|
||||
export type Hole = {
|
||||
id: string
|
||||
hole_number: number
|
||||
holeNumber: number
|
||||
par: number
|
||||
stroke_index: number
|
||||
strokeIndex: number
|
||||
}
|
||||
|
||||
export type Player = {
|
||||
user_id: string
|
||||
course_handicap: number | null
|
||||
handicap_index: number | null
|
||||
profile: { id: string; display_name: string; avatar_url: string | null } | null
|
||||
userId: string
|
||||
courseHandicap: number | null
|
||||
handicapIndex: string | null
|
||||
profile: { id: string; displayName: string; avatarUrl: string | null } | null
|
||||
}
|
||||
|
||||
export type ScoreRow = {
|
||||
hole_id: string
|
||||
player_id: string
|
||||
holeId: string
|
||||
playerId: string
|
||||
strokes: number
|
||||
}
|
||||
|
||||
@@ -27,8 +31,8 @@ export type RoundInfo = {
|
||||
name: string | null
|
||||
date: string
|
||||
status: string
|
||||
holes_count: number
|
||||
created_by: string
|
||||
holesCount: number
|
||||
createdBy: string
|
||||
course: { name: string } | null
|
||||
tee: { name: string; color: string } | null
|
||||
}
|
||||
@@ -39,66 +43,90 @@ export default async function ScorecardPage({
|
||||
params: Promise<{ id: string }>
|
||||
}) {
|
||||
const { id } = await params
|
||||
const supabase = await createClient()
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const db = supabase as any
|
||||
const session = await auth.api.getSession({ headers: await headers() })
|
||||
if (!session) redirect('/login')
|
||||
|
||||
const {
|
||||
data: { user },
|
||||
} = await supabase.auth.getUser()
|
||||
if (!user) redirect('/login')
|
||||
|
||||
const { data: round } = await db
|
||||
.from('rounds')
|
||||
.select(
|
||||
`id, name, date, status, holes_count, created_by,
|
||||
course:courses (name),
|
||||
tee:tees (name, color)`,
|
||||
)
|
||||
.eq('id', id)
|
||||
.single()
|
||||
const [round] = await db
|
||||
.select({
|
||||
id: rounds.id,
|
||||
name: rounds.name,
|
||||
date: rounds.date,
|
||||
status: rounds.status,
|
||||
holesCount: rounds.holesCount,
|
||||
createdBy: rounds.createdBy,
|
||||
courseId: rounds.courseId,
|
||||
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(eq(rounds.id, id))
|
||||
.limit(1)
|
||||
|
||||
if (!round) notFound()
|
||||
if (round.status === 'lobby') redirect(`/rounds/${id}`)
|
||||
|
||||
// Holes ordered by hole_number, limited to holes_count
|
||||
const { data: holes } = await db
|
||||
.from('holes')
|
||||
.select('id, hole_number, par, stroke_index')
|
||||
.eq('course_id', await getCourseId(db, id))
|
||||
.order('hole_number')
|
||||
.limit(round.holes_count)
|
||||
const holeRows = await db
|
||||
.select({
|
||||
id: holes.id,
|
||||
holeNumber: holes.holeNumber,
|
||||
par: holes.par,
|
||||
strokeIndex: holes.strokeIndex,
|
||||
})
|
||||
.from(holes)
|
||||
.where(eq(holes.courseId, round.courseId))
|
||||
.orderBy(asc(holes.holeNumber))
|
||||
.limit(round.holesCount)
|
||||
|
||||
const { data: players } = await db
|
||||
.from('round_players')
|
||||
.select(
|
||||
`user_id, course_handicap, handicap_index,
|
||||
profile:profiles (id, display_name, avatar_url)`,
|
||||
)
|
||||
.eq('round_id', id)
|
||||
.order('joined_at')
|
||||
const playerRows = await db
|
||||
.select({
|
||||
userId: roundPlayers.userId,
|
||||
courseHandicap: roundPlayers.courseHandicap,
|
||||
handicapIndex: roundPlayers.handicapIndex,
|
||||
displayName: user.name,
|
||||
avatarUrl: user.image,
|
||||
})
|
||||
.from(roundPlayers)
|
||||
.innerJoin(user, eq(roundPlayers.userId, user.id))
|
||||
.where(eq(roundPlayers.roundId, id))
|
||||
.orderBy(roundPlayers.joinedAt)
|
||||
|
||||
const { data: scores } = await db
|
||||
.from('scores')
|
||||
.select('hole_id, player_id, strokes')
|
||||
.eq('round_id', id)
|
||||
const scoreRows = await db
|
||||
.select({ holeId: scores.holeId, playerId: scores.playerId, strokes: scores.strokes })
|
||||
.from(scores)
|
||||
.where(eq(scores.roundId, id))
|
||||
|
||||
const roundInfo: RoundInfo = {
|
||||
id: round.id,
|
||||
name: round.name,
|
||||
date: round.date,
|
||||
status: round.status,
|
||||
holesCount: round.holesCount,
|
||||
createdBy: round.createdBy,
|
||||
course: { name: round.courseName },
|
||||
tee: { name: round.teeName, color: round.teeColor },
|
||||
}
|
||||
|
||||
const players: Player[] = playerRows.map((p) => ({
|
||||
userId: p.userId,
|
||||
courseHandicap: p.courseHandicap,
|
||||
handicapIndex: p.handicapIndex,
|
||||
profile: {
|
||||
id: p.userId,
|
||||
displayName: p.displayName,
|
||||
avatarUrl: p.avatarUrl,
|
||||
},
|
||||
}))
|
||||
|
||||
return (
|
||||
<ScorecardView
|
||||
round={round as RoundInfo}
|
||||
holes={(holes as Hole[]) ?? []}
|
||||
players={(players as Player[]) ?? []}
|
||||
initialScores={(scores as ScoreRow[]) ?? []}
|
||||
currentUserId={user.id}
|
||||
round={roundInfo}
|
||||
holes={holeRows}
|
||||
players={players}
|
||||
initialScores={scoreRows}
|
||||
currentUserId={session.user.id}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
async function getCourseId(db: any, roundId: string): Promise<string> {
|
||||
const { data } = await db
|
||||
.from('rounds')
|
||||
.select('course_id')
|
||||
.eq('id', roundId)
|
||||
.single()
|
||||
return data?.course_id ?? ''
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user