import Link from "next/link"; import { prisma } from "@/lib/prisma"; import { siteSettings } from "@/lib/services/site-settings"; // Radio config + today's schedule are read live from the DB / settings table. export const dynamic = "force-dynamic"; // Sub-pages linked from the radio home hub. const RADIO_LINKS: { label: string; href: string }[] = [ { label: "Schedule", href: "/radio/schedule" }, { label: "Shouts", href: "/radio/shouts" }, { label: "Requests", href: "/radio/requests" }, { label: "Apply as DJ", href: "/radio/apply" }, { label: "Leaderboard", href: "/radio/leaderboard" }, ]; // Canonical weekday order so today's slots come out chronologically and we can // match the current day against whatever casing the `day` column stores. const WEEKDAYS = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", ]; // radio_schedules.start_time / end_time are stored as TIME and surface through // Prisma as a Date with the time component on a 1970 epoch date — render just // the HH:MM portion in UTC to avoid timezone drift. function formatTime(d: Date | null | undefined): string { if (!d) return ""; return d.toISOString().slice(11, 16); } export default async function RadioPage() { // ── Radio config from website_settings (graceful fallbacks) ── const [streamUrl, currentDj, currentSong] = await Promise.all([ siteSettings.get("radio_stream_url", ""), siteSettings.get("radio_current_dj", ""), siteSettings.get("radio_current_song", ""), ]); // ── Today's schedule (isolated; a DB hiccup degrades to empty) ── const today = WEEKDAYS[new Date().getUTCDay()] ?? ""; const schedules = await prisma.radioSchedules .findMany({ where: { isActive: true }, orderBy: { startTime: "asc" }, }) .catch(() => []); const todaysSlots = schedules.filter( (s) => s.day.toLowerCase() === today.toLowerCase(), ); // Resolve DJ usernames for today's slots in one query. radio_schedules.user_id // is an UnsignedBigInt while users.id is an Int, so narrow to Number for the // lookup (DJ ids comfortably fit in a JS-safe integer). const djIds = Array.from(new Set(todaysSlots.map((s) => Number(s.userId)))); const djs = djIds.length ? await prisma.user .findMany({ where: { id: { in: djIds } }, select: { id: true, username: true }, }) .catch(() => []) : []; const djById = new Map(djs.map((d) => [d.id, d.username])); return (
{/* ── Hero: live stream + now playing ─────────────────────── */}

Radio

Tune in to the hotel radio — live DJ sets, requests and shoutouts.

Now playing

{currentSong ? currentSong : Nothing playing right now.}

{currentDj ? `On air: ${currentDj}` : "No DJ on air."}

{streamUrl ? ( ) : (

The stream is currently offline.

)}
{/* ── Sub-page links ──────────────────────────────────────── */}
{RADIO_LINKS.map((l) => ( {l.label} ))}
{/* ── Today's schedule ────────────────────────────────────── */}

Today’s schedule{today ? ` · ${today}` : ""}

{todaysSlots.length === 0 ? (

No shows scheduled for today.

) : (
{todaysSlots.map((s) => { const djName = djById.get(Number(s.userId)); return ( ); })}
Time Show DJ
{formatTime(s.startTime)} – {formatTime(s.endTime)} {s.showName || Untitled show} {djName ? ( {djName} ) : ( {`User #${s.userId}`} )}
)}
); }