diff --git a/app/(dashboard)/shot-status/ShotStatusClient.tsx b/app/(dashboard)/shot-status/ShotStatusClient.tsx index 4a7cb47..251af70 100644 --- a/app/(dashboard)/shot-status/ShotStatusClient.tsx +++ b/app/(dashboard)/shot-status/ShotStatusClient.tsx @@ -1130,6 +1130,8 @@ export function ShotStatusClient({ const [expandedGroups, setExpandedGroups] = useState>(new Set()); const [groupMode, setGroupMode] = useState<"flat" | "scene" | "group">("flat"); const [selectedIds, setSelectedIds] = useState>(new Set()); + // Statuses picked from the summary badges; empty shows every shot. + const [statusFilter, setStatusFilter] = useState>(new Set()); // Which sections were open is restored before the scroll position: until // they are, the page is shorter and the saved offset would not fit. @@ -1141,6 +1143,7 @@ export function ShotStatusClient({ useEffect(() => { if (!selectedProjectId) return; setExpandRestored(false); + setStatusFilter(new Set()); const mode = (readStored(`shotStatus:${selectedProjectId}:groupMode`) ?? "flat") as "flat" | "scene" | "group"; setGroupMode(mode); setExpandedEpisodes(new Set(readStoredList(`shotStatus:${selectedProjectId}:episodeExpand`) ?? [])); @@ -1235,6 +1238,22 @@ export function ShotStatusClient({ const clearSelection = () => setSelectedIds(new Set()); + const toggleStatusFilter = (status: string) => { + const next = new Set(statusFilter); + next.has(status) ? next.delete(status) : next.add(status); + setStatusFilter(next); + // Bulk actions must never reach shots the filter has hidden. + if (next.size > 0) { + setSelectedIds((prev) => { + const kept = new Set(); + for (const s of shots) if (prev.has(s.id) && next.has(s.status)) kept.add(s.id); + return kept; + }); + } + }; + + const visibleShots = statusFilter.size > 0 ? shots.filter((s) => statusFilter.has(s.status)) : shots; + const handleBulkDueDate = async (date: string, includeTasks: boolean) => { try { const result = await bulkUpdateDueDates([...selectedIds], date, includeTasks); @@ -1320,7 +1339,7 @@ export function ShotStatusClient({ const episodeGroups: [string, ShotRow[]][] = isEpisodic ? (() => { const map = new Map(); - for (const shot of shots) { + for (const shot of visibleShots) { const key = shot.episode ?? "(No Episode)"; if (!map.has(key)) map.set(key, []); map.get(key)!.push(shot); @@ -1332,7 +1351,7 @@ export function ShotStatusClient({ const sceneGroups: [string, ShotRow[]][] = !isEpisodic && groupMode === "scene" ? (() => { const map = new Map(); - for (const shot of shots) { + for (const shot of visibleShots) { const key = shot.scene || "(No Scene)"; if (!map.has(key)) map.set(key, []); map.get(key)!.push(shot); @@ -1344,7 +1363,7 @@ export function ShotStatusClient({ const shotGroupGroups: [string, string, ShotRow[]][] = !isEpisodic && groupMode === "group" ? (() => { const map = new Map(); - for (const shot of shots) { + for (const shot of visibleShots) { const id = shot.shotGroup?.id ?? ""; const name = shot.shotGroup?.name ?? "(No Group)"; if (!map.has(id)) map.set(id, [name, []]); @@ -1437,16 +1456,45 @@ export function ShotStatusClient({
{selectionCount === 0 ? ( <> - {shots.length} shots total + + {statusFilter.size > 0 ? `${visibleShots.length} of ${shots.length} shots` : `${shots.length} shots total`} + {Object.entries(STATUS_CONFIG).map(([key, cfg]) => { const count = statusCounts[key] ?? 0; if (!count) return null; + const active = statusFilter.has(key); return ( - - {count} {cfg.label} - + ); })} + {statusFilter.size > 0 && ( + + )} ) : (
@@ -1669,7 +1717,7 @@ export function ShotStatusClient({ ) : (