import Link from 'next/link'; import { prisma } from '@/lib/prisma'; import { deleteShout } from '@/actions/admin-radio'; import { StatusCard } from '@/components/admin/dashboard'; export const dynamic = 'force-dynamic'; type Shout = { id: bigint; userId: bigint; message: string; createdAt: Date | null; }; type Application = { id: bigint; userId: bigint; realName: string; age: number; status: string; musicStyle: string | null; discordUsername: string | null; createdAt: Date | null; }; type Schedule = { id: bigint; userId: bigint; day: string; startTime: Date; endTime: Date; showName: string | null; isActive: boolean; }; function formatDate(d: Date | null): string { return d ? d.toISOString().slice(0, 16).replace('T', ' ') : '—'; } function formatTime(d: Date | null): string { return d ? d.toISOString().slice(11, 16) : '—'; } // Map an application status to an ok/danger/neutral pill tone. function statusBadgeClass(status: string): string { const s = status.toLowerCase(); if (s === 'approved' || s === 'accepted') return 'ok'; if (s === 'rejected' || s === 'denied') return 'danger'; return ''; } export default async function AdminRadioPage() { let shouts: Shout[] = []; let applications: Application[] = []; let schedules: Schedule[] = []; try { shouts = await prisma.radioShouts.findMany({ select: { id: true, userId: true, message: true, createdAt: true }, orderBy: { id: 'desc' }, take: 25, }); } catch { shouts = []; } try { applications = await prisma.radioApplications.findMany({ select: { id: true, userId: true, realName: true, age: true, status: true, musicStyle: true, discordUsername: true, createdAt: true, }, orderBy: { id: 'desc' }, take: 25, }); } catch { applications = []; } try { schedules = await prisma.radioSchedules.findMany({ select: { id: true, userId: true, day: true, startTime: true, endTime: true, showName: true, isActive: true, }, orderBy: { id: 'desc' }, take: 25, }); } catch { schedules = []; } const pendingApps = applications.filter( (a) => a.status.toLowerCase() === 'pending', ).length; const activeSchedules = schedules.filter((sc) => sc.isActive).length; return (

Radio Moderation

Latest shouts, DJ applications and on-air schedules (25 most recent of each).

0 ? 'warn' : 'ok'} icon="📝" /> 0 ? 'ok' : 'neutral'} icon="🎙️" />

Recent Shouts ({shouts.length})

{shouts.length === 0 ? (

No shouts to moderate.

) : ( {shouts.map((s) => ( ))}
ID User Message Posted
{String(s.id)} {String(s.userId)} {s.message} {formatDate(s.createdAt)}
)}

DJ Applications ({applications.length})

{applications.length === 0 ? (

No applications submitted.

) : ( {applications.map((a) => ( ))}
ID User Real Name Age Style Discord Status Applied
{String(a.id)} {String(a.userId)} {a.realName} {a.age} {a.musicStyle ?? '—'} {a.discordUsername ?? '—'} {a.status} {formatDate(a.createdAt)}
)}

Schedules ({schedules.length})

{schedules.length === 0 ? (

No schedules configured.

) : ( {schedules.map((sc) => ( ))}
ID User Day Start End Show Active
{String(sc.id)} {String(sc.userId)} {sc.day} {formatTime(sc.startTime)} {formatTime(sc.endTime)} {sc.showName ?? '—'} {sc.isActive ? 'active' : 'inactive'}
)}
); }