Recordings were just a thin named pointer over an already-captured session's events, so the whole separate feature (recordings table, API routes, pages, UI) is gone: any completed session can now be named and replayed directly. Replaying no longer creates a session or duplicates events of its own - it just bumps the source session's playCount/lastPlayedAt. Also renames play_sessions/playSession(s) to sessions/session(s) throughout the schema, queries, API routes, and UI for consistency, and updates the README to match the new flow. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
55 lines
1.7 KiB
TypeScript
55 lines
1.7 KiB
TypeScript
"use client";
|
|
|
|
import Link from "next/link";
|
|
import { usePathname } from "next/navigation";
|
|
import { ChevronRight, House } from "lucide-react";
|
|
|
|
const SECTION_LABELS: Record<string, string> = {
|
|
control: "Control",
|
|
sessions: "Sessions",
|
|
stats: "Stats",
|
|
devices: "Devices",
|
|
};
|
|
|
|
const LEAF_LABELS: Record<string, string> = {
|
|
replay: "Replay",
|
|
};
|
|
|
|
export function Breadcrumbs() {
|
|
const pathname = usePathname();
|
|
const segments = pathname.split("/").filter(Boolean);
|
|
|
|
if (segments.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
const crumbs = segments.reduce<{ label: string; href: string }[]>((acc, segment) => {
|
|
const href = `${acc.at(-1)?.href ?? ""}/${segment}`;
|
|
const label = /^\d+$/.test(segment) ? `#${segment}` : (LEAF_LABELS[segment] ?? SECTION_LABELS[segment] ?? segment);
|
|
return [...acc, { label, href }];
|
|
}, []);
|
|
|
|
return (
|
|
<nav aria-label="Breadcrumb" className="bp-glass mb-6 flex w-fit items-center gap-1.5 rounded-lg px-3 py-1.5 text-sm text-muted-foreground">
|
|
<Link href="/" className="flex items-center hover:text-foreground" aria-label="Dashboard">
|
|
<House className="size-3.5" />
|
|
</Link>
|
|
{crumbs.map((crumb, i) => {
|
|
const isLast = i === crumbs.length - 1;
|
|
return (
|
|
<span key={crumb.href} className="flex items-center gap-1.5">
|
|
<ChevronRight className="size-3.5 text-muted-foreground/50" />
|
|
{isLast ? (
|
|
<span className="font-medium text-foreground">{crumb.label}</span>
|
|
) : (
|
|
<Link href={crumb.href} className="hover:text-foreground">
|
|
{crumb.label}
|
|
</Link>
|
|
)}
|
|
</span>
|
|
);
|
|
})}
|
|
</nav>
|
|
);
|
|
}
|