94 lines
2.8 KiB
TypeScript
94 lines
2.8 KiB
TypeScript
// /src/app/api/users/route.ts
|
|
import { NextResponse } from 'next/server'
|
|
import { prisma } from '@/lib/prisma'
|
|
import type { Prisma } from '@/generated/prisma' // ggf. '@prisma/client' verwenden, falls das dein Pfad ist
|
|
|
|
export const dynamic = 'force-dynamic'
|
|
|
|
type ApiUser = {
|
|
id: string
|
|
name: string
|
|
avatar?: string
|
|
steamId?: string
|
|
country?: string
|
|
rating?: number
|
|
team?: { id: string; name: string } | null
|
|
}
|
|
|
|
export async function GET(req: Request) {
|
|
try {
|
|
const { searchParams } = new URL(req.url)
|
|
const q = (searchParams.get('q') ?? '').trim()
|
|
const limit = Math.min(2000, Math.max(1, Number(searchParams.get('limit') ?? 1000)))
|
|
|
|
// Select separat halten → saubere Typinferenz inkl. Relation 'team'
|
|
const select = {
|
|
steamId: true,
|
|
name: true,
|
|
avatar: true,
|
|
location: true,
|
|
premierRank: true,
|
|
faceitNickname: true,
|
|
faceitAvatar: true,
|
|
faceitCountry: true,
|
|
team: { select: { id: true, name: true } },
|
|
} as const
|
|
|
|
// Basisfilter: lastActiveAt != null ODER (timeZone != null UND != '')
|
|
const activeOrTzFilter: Prisma.UserWhereInput = {
|
|
OR: [
|
|
{ lastActiveAt: { not: null } },
|
|
{ AND: [{ timeZone: { not: null } }, { timeZone: { not: '' } }] },
|
|
],
|
|
}
|
|
|
|
const insensitive = 'insensitive' as Prisma.QueryMode
|
|
|
|
// Optionaler Suchfilter
|
|
const searchFilter: Prisma.UserWhereInput | undefined = q
|
|
? {
|
|
OR: [
|
|
{ name: { contains: q, mode: insensitive } },
|
|
{ steamId: { contains: q, mode: insensitive } },
|
|
{ faceitNickname: { contains: q, mode: insensitive } },
|
|
{ team: { is: { name: { contains: q, mode: insensitive } } } },
|
|
],
|
|
}
|
|
: undefined
|
|
|
|
const where: Prisma.UserWhereInput = searchFilter
|
|
? { AND: [activeOrTzFilter, searchFilter] }
|
|
: activeOrTzFilter
|
|
|
|
const rows = await prisma.user.findMany({
|
|
take: limit,
|
|
where,
|
|
orderBy: [{ name: 'asc' }, { steamId: 'asc' }],
|
|
select,
|
|
})
|
|
|
|
// WICHTIG: keine Param-Typannotation hier!
|
|
const mapped: ApiUser[] = rows.map(u => ({
|
|
id: u.steamId,
|
|
name: u.name ?? u.faceitNickname ?? '—',
|
|
avatar: u.avatar ?? u.faceitAvatar ?? undefined,
|
|
steamId: u.steamId,
|
|
country: u.location ?? u.faceitCountry ?? undefined,
|
|
rating: u.premierRank ?? undefined,
|
|
team: u.team ? { id: u.team.id, name: u.team.name } : null,
|
|
}))
|
|
|
|
mapped.sort((a, b) =>
|
|
(a.name ?? '').localeCompare(b.name ?? '', 'de', { sensitivity: 'base' })
|
|
)
|
|
|
|
return NextResponse.json(
|
|
{ ok: true, users: mapped },
|
|
{ headers: { 'Cache-Control': 'no-store' } }
|
|
)
|
|
} catch (e) {
|
|
console.error('[GET /api/users] error:', e)
|
|
return NextResponse.json({ ok: false, error: 'Failed to load users' }, { status: 500 })
|
|
}
|
|
}
|