2025-08-17 23:22:06 +02:00

134 lines
4.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// /app/api/matches/[id]/mapvote/reset/route.ts
import { NextRequest, NextResponse } from 'next/server'
import { getServerSession } from 'next-auth'
import { authOptions } from '@/app/lib/auth'
import { prisma } from '@/app/lib/prisma'
import { sendServerSSEMessage } from '@/app/lib/sse-server-client'
import { MAP_OPTIONS } from '@/app/lib/mapOptions'
import { createHash } from 'crypto'
export const runtime = 'nodejs'
export const dynamic = 'force-dynamic'
function shapeState(vote: any) {
const ACTION_MAP = { BAN: 'ban', PICK: 'pick', DECIDER: 'decider' } as const
const steps = [...vote.steps]
.sort((a, b) => a.order - b.order)
.map((s: any) => ({
order : s.order,
action : ACTION_MAP[s.action as keyof typeof ACTION_MAP],
teamId : s.teamId,
map : s.map,
chosenAt: s.chosenAt ? s.chosenAt.toISOString() : null,
chosenBy: s.chosenBy ?? null,
}))
return {
bestOf : vote.bestOf,
mapPool : vote.mapPool as string[],
currentIndex: vote.currentIdx,
locked : vote.locked as boolean,
opensAt : vote.opensAt ? new Date(vote.opensAt).toISOString() : null,
steps,
adminEdit: vote.adminEditingBy
? {
enabled: true,
by: vote.adminEditingBy as string,
since: vote.adminEditingSince ? new Date(vote.adminEditingSince).toISOString() : null,
}
: { enabled: false, by: null, since: null },
}
}
function buildMapVisuals(matchId: string, mapPool: string[]) {
const visuals: Record<string, { label: string; bg: string; images?: string[] }> = {}
for (const key of mapPool) {
const opt = MAP_OPTIONS.find(o => o.key === key)
const label = opt?.label ?? key
const imgs = opt?.images ?? []
let bg = `/assets/img/maps/${key}/1.jpg`
if (imgs.length > 0) {
const h = createHash('sha256').update(`${matchId}:${key}`).digest('hex')
const n = parseInt(h.slice(0, 8), 16)
const idx = n % imgs.length
bg = imgs[idx]
}
visuals[key] = { label, bg }
}
return visuals
}
export async function POST(req: NextRequest, { params }: { params: { matchId: string } }) {
const session = await getServerSession(authOptions(req))
const me = session?.user as { steamId: string; isAdmin?: boolean } | undefined
if (!me?.steamId) return NextResponse.json({ message: 'Nicht eingeloggt' }, { status: 401 })
const matchId = params.matchId
if (!matchId) return NextResponse.json({ message: 'Missing id' }, { status: 400 })
try {
const match = await prisma.match.findUnique({
where: { id: matchId },
include: { mapVote: { include: { steps: true } } },
})
if (!match?.mapVote) {
return NextResponse.json({ message: 'Map-Vote nicht gefunden' }, { status: 404 })
}
// optional: nur Admins erlauben falls gewünscht:
// if (!me.isAdmin) return NextResponse.json({ message: 'Nur Admins dürfen resetten' }, { status: 403 })
const vote = match.mapVote
// Reset in einer Transaktion
await prisma.$transaction(async (tx) => {
// alle Steps zurücksetzen
await Promise.all(
vote.steps.map(s =>
tx.mapVoteStep.update({
where: { id: s.id },
data : { map: null, chosenAt: null, chosenBy: null },
})
)
)
// Vote Zustand zurücksetzen
await tx.mapVote.update({
where: { id: vote.id },
data : {
currentIdx: 0,
locked: false,
adminEditingBy: null,
adminEditingSince: null,
},
})
})
const updated = await prisma.mapVote.findUnique({
where: { id: vote.id },
include: { steps: true },
})
if (!updated) {
return NextResponse.json({ message: 'Reset fehlgeschlagen' }, { status: 500 })
}
// Events: zuerst map-vote-updated (UI neu laden)
await sendServerSSEMessage({ type: 'map-vote-updated', matchId })
// dann map-vote-reset (globale Overlays schließen, lokale Flags löschen)
await sendServerSSEMessage({ type: 'map-vote-reset', matchId })
const mapVisuals = buildMapVisuals(match.id, updated.mapPool)
return NextResponse.json(
{ ...shapeState(updated), mapVisuals },
{ headers: { 'Cache-Control': 'no-store' } },
)
} catch (e) {
console.error('[map-vote-reset][POST] error', e)
return NextResponse.json({ message: 'Reset fehlgeschlagen' }, { status: 500 })
}
}