Files
MulliganMates/app/actions/scores.ts
T
2026-03-18 13:34:41 +01:00

62 lines
1.7 KiB
TypeScript

'use server'
import { z } from 'zod'
import { db } from '@/lib/db'
import { scores, roundPlayers, rounds } from '@/lib/db/schema'
import { eq, and } from 'drizzle-orm'
import { auth } from '@/lib/auth'
import { headers } from 'next/headers'
const UpsertScoreSchema = z.object({
roundId: z.string().uuid(),
holeId: z.string().uuid(),
playerId: z.string(),
strokes: z.number().int().min(1).max(20),
})
export async function upsertScore(
roundId: string,
holeId: string,
playerId: string,
strokes: number,
) {
const parsed = UpsertScoreSchema.safeParse({ roundId, holeId, playerId, strokes })
if (!parsed.success) return { error: parsed.error.issues[0]?.message ?? 'Invalid data' }
const session = await auth.api.getSession({ headers: await headers() })
if (!session) return { error: 'Not authenticated' }
// Caller must be a member of the round
const [membership] = await db
.select()
.from(roundPlayers)
.where(and(eq(roundPlayers.roundId, roundId), eq(roundPlayers.userId, session.user.id)))
.limit(1)
if (!membership) return { error: 'Not a member of this round' }
// Round must be active
const [round] = await db
.select({ status: rounds.status })
.from(rounds)
.where(eq(rounds.id, roundId))
.limit(1)
if (round?.status !== 'active') return { error: 'Round is not active' }
await db
.insert(scores)
.values({
roundId,
holeId,
playerId,
strokes,
updatedBy: session.user.id,
updatedAt: new Date(),
})
.onConflictDoUpdate({
target: [scores.roundId, scores.holeId, scores.playerId],
set: { strokes, updatedBy: session.user.id, updatedAt: new Date() },
})
return { success: true }
}