Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com>
This commit is contained in:
gpt-engineer-app[bot]
2026-04-18 20:59:28 +00:00
co-authored by renee-png
parent e5b328b72a
commit 7a71f73fda
+44 -8
View File
@@ -127,6 +127,7 @@ function CalendarPage() {
const [events, setEvents] = useState<Evt[]>([]);
const [cases, setCases] = useState<CaseRow[]>([]);
const [clients, setClients] = useState<ClientRow[]>([]);
const [staff, setStaff] = useState<StaffRow[]>([]);
const [loading, setLoading] = useState(true);
@@ -138,6 +139,7 @@ function CalendarPage() {
// dialog state
const [dialogOpen, setDialogOpen] = useState(false);
const [editingId, setEditingId] = useState<string | null>(null);
const [saving, setSaving] = useState(false);
const [fTitle, setFTitle] = useState("");
const [fType, setFType] = useState<EventTypeKey>("client_meeting");
@@ -146,25 +148,40 @@ function CalendarPage() {
const [fEndTime, setFEndTime] = useState("10:00");
const [fAllDay, setFAllDay] = useState(false);
const [fCase, setFCase] = useState<string>("none");
const [fClient, setFClient] = useState<string>("none");
const [fLocation, setFLocation] = useState("");
const [fNotes, setFNotes] = useState("");
const [fAssignee, setFAssignee] = useState<string>("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<string, CaseRow>();
const caseMap = new Map<string, CaseRow & { client_id: string | null }>();
(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<string, ClientRow>();
(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) => {