From a488065d104453e9c4911e76bbc1ae6fd7049faa Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 20:58:33 +0000 Subject: [PATCH 01/12] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/routes/calendar.index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/routes/calendar.index.tsx b/src/routes/calendar.index.tsx index 8c37a17..b1cc10b 100644 --- a/src/routes/calendar.index.tsx +++ b/src/routes/calendar.index.tsx @@ -35,6 +35,7 @@ import { ChevronRight, CalendarDays, MapPin, + Trash2, } from "lucide-react"; import { format, From e5b328b72a055efb06265a74819ace01242fe414 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 20:58:45 +0000 Subject: [PATCH 02/12] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/routes/calendar.index.tsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/routes/calendar.index.tsx b/src/routes/calendar.index.tsx index b1cc10b..4467e05 100644 --- a/src/routes/calendar.index.tsx +++ b/src/routes/calendar.index.tsx @@ -94,6 +94,8 @@ interface Evt { event_type: string; case_id: string | null; case_label: string | null; + client_id: string | null; + client_label: string | null; owner_id: string | null; owner_name: string | null; location: string | null; @@ -106,6 +108,11 @@ interface CaseRow { case_number: string; } +interface ClientRow { + id: string; + name: string; +} + interface StaffRow { id: string; full_name: string; From 7a71f73fdac24e4f5d9d43d6beddb00e32378d2f Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 20:59:28 +0000 Subject: [PATCH 03/12] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/routes/calendar.index.tsx | 52 +++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/src/routes/calendar.index.tsx b/src/routes/calendar.index.tsx index 4467e05..b229a67 100644 --- a/src/routes/calendar.index.tsx +++ b/src/routes/calendar.index.tsx @@ -127,6 +127,7 @@ function CalendarPage() { const [events, setEvents] = useState([]); const [cases, setCases] = useState([]); + const [clients, setClients] = useState([]); const [staff, setStaff] = useState([]); const [loading, setLoading] = useState(true); @@ -138,6 +139,7 @@ function CalendarPage() { // dialog state const [dialogOpen, setDialogOpen] = useState(false); + const [editingId, setEditingId] = useState(null); const [saving, setSaving] = useState(false); const [fTitle, setFTitle] = useState(""); const [fType, setFType] = useState("client_meeting"); @@ -146,25 +148,40 @@ function CalendarPage() { const [fEndTime, setFEndTime] = useState("10:00"); const [fAllDay, setFAllDay] = useState(false); const [fCase, setFCase] = useState("none"); + const [fClient, setFClient] = useState("none"); const [fLocation, setFLocation] = useState(""); const [fNotes, setFNotes] = useState(""); const [fAssignee, setFAssignee] = useState("self"); const reload = async () => { setLoading(true); - const [eventsRes, tasksRes, casesRes, staffRes] = await Promise.all([ + // Pull a wide window around the cursor so month/week/list views are populated. + // (Avoids hitting Supabase's default 1000-row cap on large event tables.) + const winStart = format(addMonths(startOfMonth(cursor), -6), "yyyy-MM-dd"); + const winEnd = format(addMonths(endOfMonth(cursor), 12), "yyyy-MM-dd"); + + const [eventsRes, tasksRes, casesRes, clientsRes, staffRes] = await Promise.all([ supabase .from("events") - .select("id,title,start_at,end_at,all_day,event_type,case_id,location,description,created_by"), + .select( + "id,title,start_at,end_at,all_day,event_type,case_id,client_id,location,description,created_by", + ) + .gte("start_at", `${winStart}T00:00:00`) + .lte("start_at", `${winEnd}T23:59:59`) + .order("start_at", { ascending: true }) + .limit(5000), supabase .from("tasks") .select("id,title,due_date,case_id,status,created_by") .not("due_date", "is", null) - .eq("status", "incomplete"), + .eq("status", "incomplete") + .gte("due_date", winStart) + .lte("due_date", winEnd), supabase .from("cases") - .select("id,title,case_number,next_hearing_date,next_hearing_notes") + .select("id,title,case_number,next_hearing_date,next_hearing_notes,client_id") .order("title"), + supabase.from("clients").select("id,name").order("name"), supabase.from("profiles").select("id,full_name,email").order("full_name"), ]); @@ -172,16 +189,25 @@ function CalendarPage() { (staffRes.data ?? []).forEach((p) => profileMap.set(p.id, { id: p.id, full_name: p.full_name || p.email, email: p.email }), ); - const caseMap = new Map(); + const caseMap = new Map(); (casesRes.data ?? []).forEach((c) => - caseMap.set(c.id, { id: c.id, title: c.title, case_number: c.case_number }), + caseMap.set(c.id, { + id: c.id, + title: c.title, + case_number: c.case_number, + client_id: c.client_id ?? null, + }), ); + const clientMap = new Map(); + (clientsRes.data ?? []).forEach((c) => clientMap.set(c.id, { id: c.id, name: c.name })); const evts: Evt[] = []; for (const e of eventsRes.data ?? []) { const owner = e.created_by ? profileMap.get(e.created_by) : null; const c = e.case_id ? caseMap.get(e.case_id) : null; + const clientId = e.client_id ?? c?.client_id ?? null; + const cl = clientId ? clientMap.get(clientId) : null; evts.push({ id: e.id, source: "event", @@ -192,6 +218,8 @@ function CalendarPage() { event_type: e.event_type ?? "other", case_id: e.case_id, case_label: c ? `${c.case_number} — ${c.title}` : null, + client_id: clientId, + client_label: cl?.name ?? null, owner_id: e.created_by, owner_name: owner?.full_name ?? null, location: e.location ?? null, @@ -202,6 +230,7 @@ function CalendarPage() { for (const t of tasksRes.data ?? []) { const owner = t.created_by ? profileMap.get(t.created_by) : null; const c = t.case_id ? caseMap.get(t.case_id) : null; + const cl = c?.client_id ? clientMap.get(c.client_id) : null; evts.push({ id: t.id, source: "task", @@ -212,6 +241,8 @@ function CalendarPage() { event_type: "task", case_id: t.case_id, case_label: c ? `${c.case_number} — ${c.title}` : null, + client_id: c?.client_id ?? null, + client_label: cl?.name ?? null, owner_id: t.created_by, owner_name: owner?.full_name ?? null, location: null, @@ -221,6 +252,7 @@ function CalendarPage() { for (const c of casesRes.data ?? []) { if (!c.next_hearing_date) continue; + const cl = c.client_id ? clientMap.get(c.client_id) : null; evts.push({ id: c.id, source: "case_hearing", @@ -231,6 +263,8 @@ function CalendarPage() { event_type: "hearing", case_id: c.id, case_label: `${c.case_number} — ${c.title}`, + client_id: c.client_id ?? null, + client_label: cl?.name ?? null, owner_id: null, owner_name: null, location: null, @@ -239,14 +273,16 @@ function CalendarPage() { } setEvents(evts); - setCases(Array.from(caseMap.values())); + setCases(Array.from(caseMap.values()).map(({ id, title, case_number }) => ({ id, title, case_number }))); + setClients(Array.from(clientMap.values())); setStaff(Array.from(profileMap.values())); setLoading(false); }; useEffect(() => { reload(); - }, []); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [cursor.getFullYear(), cursor.getMonth()]); const visibleEvents = useMemo(() => { return events.filter((e) => { From 5371698cd437fc643ca2367ace607cb626b675e1 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 20:59:51 +0000 Subject: [PATCH 04/12] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/routes/calendar.index.tsx | 49 ++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/src/routes/calendar.index.tsx b/src/routes/calendar.index.tsx index b229a67..862fc16 100644 --- a/src/routes/calendar.index.tsx +++ b/src/routes/calendar.index.tsx @@ -341,6 +341,7 @@ function CalendarPage() { }; const openCreate = (presetDate?: Date) => { + setEditingId(null); setFTitle(""); setFType("client_meeting"); setFStart(presetDate ?? selected); @@ -348,12 +349,33 @@ function CalendarPage() { setFEndTime("10:00"); setFAllDay(false); setFCase("none"); + setFClient("none"); setFLocation(""); setFNotes(""); setFAssignee("self"); setDialogOpen(true); }; + const openEdit = (evt: Evt) => { + if (evt.source !== "event") return; // tasks/hearings edit elsewhere + setEditingId(evt.id); + setFTitle(evt.title); + setFType((EVENT_TYPE_MAP[evt.event_type] ? evt.event_type : "other") as EventTypeKey); + const dt = parseISO(evt.start); + setFStart(dt); + setFAllDay(evt.all_day); + if (!evt.all_day) { + setFStartTime(format(dt, "HH:mm")); + setFEndTime(evt.end ? format(parseISO(evt.end), "HH:mm") : format(dt, "HH:mm")); + } + setFCase(evt.case_id ?? "none"); + setFClient(evt.client_id ?? "none"); + setFLocation(evt.location ?? ""); + setFNotes(evt.description ?? ""); + setFAssignee(evt.owner_id ?? "self"); + setDialogOpen(true); + }; + const handleCreate = async () => { if (!user || !fTitle.trim() || !fStart) { toast.error("Title and date are required"); @@ -365,23 +387,42 @@ function CalendarPage() { const endISO = fAllDay ? null : `${dateStr}T${fEndTime}:00`; const ownerId = fAssignee === "self" ? user.id : fAssignee; - const { error } = await supabase.from("events").insert({ + const payload = { title: fTitle.trim(), event_type: fType, start_at: startISO, end_at: endISO, all_day: fAllDay, case_id: fCase === "none" ? null : fCase, + client_id: fClient === "none" ? null : fClient, location: fLocation.trim() || null, description: fNotes.trim() || null, - created_by: ownerId, - }); + }; + + const { error } = editingId + ? await supabase.from("events").update(payload).eq("id", editingId) + : await supabase.from("events").insert({ ...payload, created_by: ownerId }); setSaving(false); if (error) { toast.error(error.message); return; } - toast.success("Event scheduled"); + toast.success(editingId ? "Event updated" : "Event scheduled"); + setDialogOpen(false); + reload(); + }; + + const handleDelete = async () => { + if (!editingId) return; + if (!confirm("Delete this event?")) return; + setSaving(true); + const { error } = await supabase.from("events").delete().eq("id", editingId); + setSaving(false); + if (error) { + toast.error(error.message); + return; + } + toast.success("Event deleted"); setDialogOpen(false); reload(); }; From 5958b46d731df39e06b69289584d4ede0e34c2c0 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 21:00:04 +0000 Subject: [PATCH 05/12] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/routes/calendar.index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/calendar.index.tsx b/src/routes/calendar.index.tsx index 862fc16..899a6ab 100644 --- a/src/routes/calendar.index.tsx +++ b/src/routes/calendar.index.tsx @@ -634,7 +634,7 @@ function CalendarPage() { - Add event + {editingId ? "Edit event" : "Add event"}
From 86c1e9aae4885317fa22aaad5eb503850c35f8d9 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 21:00:17 +0000 Subject: [PATCH 06/12] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/routes/calendar.index.tsx | 48 ++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/src/routes/calendar.index.tsx b/src/routes/calendar.index.tsx index 899a6ab..2ce43bd 100644 --- a/src/routes/calendar.index.tsx +++ b/src/routes/calendar.index.tsx @@ -722,21 +722,39 @@ function CalendarPage() {
)} -
- - +
+
+ + +
+
+ + +
From 69ecf856741ca05a73c7bbd48e34362326d69196 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 21:00:30 +0000 Subject: [PATCH 07/12] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/routes/calendar.index.tsx | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/routes/calendar.index.tsx b/src/routes/calendar.index.tsx index 2ce43bd..7bc6e80 100644 --- a/src/routes/calendar.index.tsx +++ b/src/routes/calendar.index.tsx @@ -769,13 +769,20 @@ function CalendarPage() {