Show session status as a badge on the detail page

Reuses SessionsTable's STATUS_VARIANT mapping (now exported) so the
detail page's status matches the table's badge instead of plain text.
Also drops the now-stale px-1.5 alignment padding on the meta lines
now that the title input carries no horizontal padding of its own.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WzyfRyA7h5rs5SCAahLAWd
This commit is contained in:
2026-08-30 21:03:00 +02:00
co-authored by Claude Sonnet 5
parent 354c30d641
commit e9d5bb37d2
3 changed files with 9 additions and 6 deletions
+6 -3
View File
@@ -1,10 +1,12 @@
import Link from "next/link"; import Link from "next/link";
import { notFound } from "next/navigation"; import { notFound } from "next/navigation";
import type { Metadata } from "next"; import type { Metadata } from "next";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { SessionTimelineChart } from "@/components/sessions/SessionTimelineChart"; import { SessionTimelineChart } from "@/components/sessions/SessionTimelineChart";
import { SessionTitleEditor } from "@/components/sessions/SessionTitleEditor"; import { SessionTitleEditor } from "@/components/sessions/SessionTitleEditor";
import { STATUS_VARIANT } from "@/components/sessions/SessionsTable";
import { getSessionDetail, getSessionName } from "@/lib/db/queries/sessions"; import { getSessionDetail, getSessionName } from "@/lib/db/queries/sessions";
import { getSessionTimeline } from "@/lib/db/queries/stats"; import { getSessionTimeline } from "@/lib/db/queries/stats";
import { Play } from "lucide-react"; import { Play } from "lucide-react";
@@ -36,8 +38,9 @@ export default async function SessionDetailPage({ params }: { params: Promise<{
<div className="flex items-center justify-between gap-4"> <div className="flex items-center justify-between gap-4">
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<SessionTitleEditor sessionId={detail.session.id} initialName={detail.session.name} /> <SessionTitleEditor sessionId={detail.session.id} initialName={detail.session.name} />
<p className="mt-1 px-1.5 text-sm text-muted-foreground"> <p className="mt-1 flex flex-wrap items-center gap-x-1 text-sm text-muted-foreground">
{detail.session.status} · {formatDuration(detail.session.durationMs)} <Badge variant={STATUS_VARIANT[detail.session.status]}>{detail.session.status}</Badge>
· {formatDuration(detail.session.durationMs)}
{detail.session.kind === "replay" && detail.replayedFromName !== undefined && ( {detail.session.kind === "replay" && detail.replayedFromName !== undefined && (
<> · replayed from {detail.replayedFromName ?? `session #${detail.session.replayedSessionId}`}</> <> · replayed from {detail.replayedFromName ?? `session #${detail.session.replayedSessionId}`}</>
)} )}
@@ -50,7 +53,7 @@ export default async function SessionDetailPage({ params }: { params: Promise<{
)} )}
</p> </p>
{detail.session.description && ( {detail.session.description && (
<p className="mt-1 px-1.5 text-sm text-muted-foreground">{detail.session.description}</p> <p className="mt-1 text-sm text-muted-foreground">{detail.session.description}</p>
)} )}
</div> </div>
{canReplay && ( {canReplay && (
+2 -2
View File
@@ -46,13 +46,13 @@ export function SessionTitleEditor({ sessionId, initialName }: { sessionId: numb
}, [status]); }, [status]);
return ( return (
<div className="-ml-1.5 flex items-center gap-2"> <div className="flex items-center gap-2">
<input <input
value={value} value={value}
onChange={(e) => setValue(e.target.value)} onChange={(e) => setValue(e.target.value)}
placeholder={`Session #${sessionId}`} placeholder={`Session #${sessionId}`}
aria-label="Session name" aria-label="Session name"
className="min-w-0 max-w-full border-b-2 border-transparent bg-transparent px-1.5 py-0.5 font-heading text-2xl font-semibold text-foreground outline-none transition-colors placeholder:text-muted-foreground/70 hover:border-b-border focus:border-b-primary [field-sizing:content]" className="min-w-0 max-w-full border-b-2 border-transparent bg-transparent font-heading text-2xl font-semibold text-foreground outline-none transition-colors placeholder:text-muted-foreground/70 hover:border-b-border focus:border-b-primary [field-sizing:content]"
/> />
<div className="relative flex size-4 shrink-0 items-center justify-center"> <div className="relative flex size-4 shrink-0 items-center justify-center">
<Loader2 <Loader2
+1 -1
View File
@@ -25,7 +25,7 @@ export interface SessionRow {
durationMs: number | null; durationMs: number | null;
} }
const STATUS_VARIANT = { export const STATUS_VARIANT = {
active: "default", active: "default",
completed: "secondary", completed: "secondary",
aborted: "destructive", aborted: "destructive",