import Link from "next/link"; import { notFound } from "next/navigation"; import type { Metadata } from "next"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { SessionTimelineChart } from "@/components/sessions/SessionTimelineChart"; import { SessionTitleEditor } from "@/components/sessions/SessionTitleEditor"; import { STATUS_VARIANT } from "@/components/sessions/SessionsTable"; import { getSessionDetail, getSessionName } from "@/lib/db/queries/sessions"; import { getSessionTimeline } from "@/lib/db/queries/stats"; import { Play } from "lucide-react"; export const dynamic = "force-dynamic"; export async function generateMetadata({ params }: { params: Promise<{ id: string }> }): Promise { const { id } = await params; const name = await getSessionName(Number(id)); return { title: name ?? `Session #${id}` }; } function formatDuration(ms: number | null): string { if (ms === null) return "-"; const totalSeconds = Math.round(ms / 1000); return `${Math.floor(totalSeconds / 60)}:${(totalSeconds % 60).toString().padStart(2, "0")}`; } export default async function SessionDetailPage({ params }: { params: Promise<{ id: string }> }) { const { id } = await params; const sessionId = Number(id); const [detail, timeline] = await Promise.all([getSessionDetail(sessionId), getSessionTimeline(sessionId)]); if (!detail) notFound(); const canReplay = detail.session.status === "completed" && detail.session.durationMs !== null; return (

{detail.session.status} · {formatDuration(detail.session.durationMs)} {detail.session.kind === "replay" && detail.replayedFromName !== undefined && ( <> · replayed from {detail.replayedFromName ?? `session #${detail.session.replayedSessionId}`} )} {detail.session.playCount > 0 && ( <> {" "} · replayed {detail.session.playCount}× {detail.session.lastPlayedAt && ` (last ${new Date(detail.session.lastPlayedAt).toLocaleString()})`} )}

{detail.session.description && (

{detail.session.description}

)}
{canReplay && ( )}
Intensity timeline Devices {detail.devices.map((d) => (
{d.slotLabel} ({d.deviceDisplayName ?? d.deviceBleName})
))}
); }