111 lines
3.7 KiB
TypeScript
111 lines
3.7 KiB
TypeScript
import { NextResponse } from 'next/server'
|
||
import { prisma } from '@/app/lib/prisma'
|
||
|
||
export async function GET(req: Request) {
|
||
try {
|
||
const { searchParams } = new URL(req.url)
|
||
const matchType = searchParams.get('type') // z. B. "community"
|
||
|
||
const matches = await prisma.match.findMany({
|
||
where : matchType ? { matchType } : undefined,
|
||
orderBy: { demoDate: 'desc' },
|
||
include: {
|
||
teamA : true,
|
||
teamB : true,
|
||
players: { include: { user: true, stats: true, team: true } },
|
||
mapVote: { include: { steps: true } },
|
||
},
|
||
})
|
||
|
||
const formatted = matches.map(m => {
|
||
let status: 'not_started' | 'in_progress' | 'completed' | null = null
|
||
let opensAtISO: string | null = null
|
||
let isOpen = false // <-- immer boolean
|
||
let currentIndex: number | null = null
|
||
let currentAction: 'BAN'|'PICK'|'DECIDER' | null = null
|
||
let decidedCount: number | null = null
|
||
let totalSteps: number | null = null
|
||
let opensInMinutes: number | null = null // <-- optional
|
||
|
||
if (m.mapVote) {
|
||
const stepsSorted = [...m.mapVote.steps].sort((a, b) => a.order - b.order)
|
||
const anyChosen = stepsSorted.some(s => !!s.chosenAt)
|
||
status = m.mapVote.locked ? 'completed' : (anyChosen ? 'in_progress' : 'not_started')
|
||
|
||
const computedOpensAt =
|
||
m.mapVote.opensAt ??
|
||
(() => {
|
||
const base = m.matchDate ?? m.demoDate ?? new Date()
|
||
return new Date(base.getTime() - 60 * 60 * 1000) // 1h vorher
|
||
})()
|
||
|
||
opensAtISO = computedOpensAt?.toISOString() ?? null
|
||
if (opensAtISO) {
|
||
const now = Date.now()
|
||
const oa = new Date(opensAtISO).getTime()
|
||
isOpen = now >= oa
|
||
opensInMinutes = Math.max(0, Math.ceil((oa - now) / 60000))
|
||
}
|
||
|
||
currentIndex = m.mapVote.currentIdx
|
||
const cur = stepsSorted.find(s => s.order === m.mapVote?.currentIdx)
|
||
currentAction = (cur?.action as 'BAN'|'PICK'|'DECIDER') ?? null
|
||
decidedCount = stepsSorted.filter(s => !!s.chosenAt).length
|
||
totalSteps = stepsSorted.length
|
||
}
|
||
|
||
// Fallback für Anzeige-Datum im Frontend
|
||
const displayDate = m.demoDate ?? m.matchDate
|
||
|
||
return {
|
||
id : m.id,
|
||
map : m.map,
|
||
demoDate : m.demoDate, // unverändert
|
||
matchDate : m.matchDate, // falls du’s im UI brauchst
|
||
displayDate, // <-- neu (für sicheres Rendern)
|
||
matchType : m.matchType,
|
||
scoreA : m.scoreA,
|
||
scoreB : m.scoreB,
|
||
winnerTeam: m.winnerTeam ?? null,
|
||
|
||
mapVote: m.mapVote ? {
|
||
status,
|
||
opensAt: opensAtISO,
|
||
isOpen,
|
||
opensInMinutes, // <-- optional
|
||
currentIndex,
|
||
currentAction,
|
||
decidedCount,
|
||
totalSteps,
|
||
} : null,
|
||
|
||
teamA: {
|
||
id : m.teamA?.id ?? null,
|
||
name : m.teamA?.name ?? 'CT',
|
||
logo : m.teamA?.logo ?? null,
|
||
score: m.scoreA,
|
||
},
|
||
teamB: {
|
||
id : m.teamB?.id ?? null,
|
||
name : m.teamB?.name ?? 'T',
|
||
logo : m.teamB?.logo ?? null,
|
||
score: m.scoreB,
|
||
},
|
||
players: m.players.map(p => ({
|
||
steamId : p.steamId,
|
||
name : p.user?.name,
|
||
avatar : p.user?.avatar,
|
||
stats : p.stats,
|
||
teamId : p.teamId,
|
||
teamName: p.team?.name ?? null,
|
||
})),
|
||
}
|
||
})
|
||
|
||
return NextResponse.json(formatted)
|
||
} catch (err) {
|
||
console.error('GET /matches failed:', err)
|
||
return NextResponse.json({ error: 'Failed to load matches' }, { status: 500 })
|
||
}
|
||
}
|