import { useState, useMemo } from "react"; import { useParams, Link } from "react-router-dom"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { api } from "../api/client"; interface SongSummary { id: string; title: string; status: string; tags: string[]; global_key: string | null; global_bpm: number | null; version_count: number; } interface SessionDetail { id: string; band_id: string; date: string; label: string | null; notes: string | null; recording_count: number; songs: SongSummary[]; } function formatDate(iso: string): string { const d = new Date(iso.slice(0, 10) + "T12:00:00"); return d.toLocaleDateString(undefined, { weekday: "long", year: "numeric", month: "long", day: "numeric" }); } function computeWaveBars(seed: string): number[] { let s = seed.split("").reduce((acc, c) => acc + c.charCodeAt(0), 31337); return Array.from({ length: 14 }, () => { s = ((s * 1664525 + 1013904223) & 0xffffffff) >>> 0; return Math.max(15, Math.floor((s / 0xffffffff) * 100)); }); } function MiniWaveBars({ seed }: { seed: string }) { const bars = useMemo(() => computeWaveBars(seed), [seed]); return (
{bars.map((h, i) => (
))}
); } export function SessionPage() { const { bandId, sessionId } = useParams<{ bandId: string; sessionId: string }>(); const qc = useQueryClient(); const [editingMeta, setEditingMeta] = useState(false); const [labelInput, setLabelInput] = useState(""); const [notesInput, setNotesInput] = useState(""); const { data: session, isLoading } = useQuery({ queryKey: ["session", sessionId], queryFn: () => api.get(`/bands/${bandId}/sessions/${sessionId}`), enabled: !!sessionId && !!bandId, }); const updateMutation = useMutation({ mutationFn: (data: { label?: string; notes?: string }) => api.patch(`/bands/${bandId}/sessions/${sessionId}`, data), onSuccess: () => { qc.invalidateQueries({ queryKey: ["session", sessionId] }); setEditingMeta(false); }, }); function startEdit() { setLabelInput(session?.label ?? ""); setNotesInput(session?.notes ?? ""); setEditingMeta(true); } if (isLoading) return
Loading...
; if (!session) return
Session not found
; return (
← Library {/* Header */}

{formatDate(session.date)}

{session.label && (

{session.label}

)}

{session.recording_count} recording{session.recording_count !== 1 ? "s" : ""}

{!editingMeta && ( )}
{session.notes && !editingMeta && (

{session.notes}

)} {editingMeta && (
setLabelInput(e.target.value)} placeholder="e.g. pre-gig warmup" style={{ width: "100%", padding: "8px 12px", background: "var(--bg-inset)", border: "1px solid var(--border)", borderRadius: 7, color: "var(--text)", fontSize: 13, boxSizing: "border-box", marginBottom: 10 }} />