diff --git a/src/routes/calendar.index.tsx b/src/routes/calendar.index.tsx index 9b94f3b..a5de950 100644 --- a/src/routes/calendar.index.tsx +++ b/src/routes/calendar.index.tsx @@ -964,7 +964,17 @@ function WeekStrip({ ); } -function ListView({ events, onEdit }: { events: Evt[]; onEdit?: (e: Evt) => void }) { +function ListView({ + events, + onEdit, + staff, + onBulkUpdated, +}: { + events: Evt[]; + onEdit?: (e: Evt) => void; + staff: StaffRow[]; + onBulkUpdated: () => void | Promise; +}) { const today = startOfDay(new Date()); const upcoming = [...events] .filter((e) => parseISO(e.start) >= today) @@ -976,10 +986,119 @@ function ListView({ events, onEdit }: { events: Evt[]; onEdit?: (e: Evt) => void arr.push(e); grouped.set(k, arr); }); + + // Bulk-edit state. Only rows with source === "event" can be bulk updated + // because they're the only ones backed by the editable `events` table. + const [selected, setSelected] = useState>(new Set()); + const [bulkType, setBulkType] = useState(""); + const [bulkAssignee, setBulkAssignee] = useState(""); + const [applying, setApplying] = useState(false); + + const editableUpcoming = upcoming.filter((e) => e.source === "event"); + const allEditableSelected = + editableUpcoming.length > 0 && editableUpcoming.every((e) => selected.has(e.id)); + + const toggleOne = (id: string) => { + setSelected((s) => { + const n = new Set(s); + if (n.has(id)) n.delete(id); + else n.add(id); + return n; + }); + }; + const toggleAll = () => { + if (allEditableSelected) setSelected(new Set()); + else setSelected(new Set(editableUpcoming.map((e) => e.id))); + }; + + const applyBulk = async () => { + if (selected.size === 0) { + toast.error("Select at least one event"); + return; + } + if (!bulkType && !bulkAssignee) { + toast.error("Choose a category or assignee to update"); + return; + } + setApplying(true); + const patch: Record = {}; + if (bulkType) patch.event_type = bulkType; + if (bulkAssignee) patch.assigned_to = bulkAssignee; + const { error } = await supabase + .from("events") + .update(patch) + .in("id", Array.from(selected)); + setApplying(false); + if (error) { + toast.error(error.message); + return; + } + toast.success(`Updated ${selected.size} event${selected.size === 1 ? "" : "s"}`); + setSelected(new Set()); + setBulkType(""); + setBulkAssignee(""); + await onBulkUpdated(); + }; + if (upcoming.length === 0) return

No upcoming events.

; + return (
+ {/* Bulk action toolbar */} +
+ +
+ + + + {selected.size > 0 && ( + + )} +
+ {Array.from(grouped.entries()).map(([day, evts]) => (

@@ -987,7 +1106,20 @@ function ListView({ events, onEdit }: { events: Evt[]; onEdit?: (e: Evt) => void

    {evts.map((e) => ( - +
  • + {e.source === "event" ? ( + toggleOne(e.id)} + /> + ) : ( + + )} +
    + +
    +
  • ))}