When a booking status is changed, confirmed, or deleted in any tab, the dashboard summary cards re-fetch to show updated counts. Previously the dashboard was stale until page reload.
83 lines
3.0 KiB
TypeScript
83 lines
3.0 KiB
TypeScript
"use client";
|
|
|
|
import { useState, useEffect, useMemo } from "react";
|
|
import { adminFetch } from "@/lib/csrf";
|
|
import { type BookingFilter, type BaseBooking, type BookingGroup } from "./types";
|
|
import { LoadingSpinner } from "./BookingComponents";
|
|
import { GenericBookingsList } from "./GenericBookingsList";
|
|
|
|
interface McRegistration extends BaseBooking {
|
|
masterClassTitle: string;
|
|
}
|
|
|
|
interface McSlot { date: string; startTime: string }
|
|
interface McItem { title: string; slots: McSlot[] }
|
|
|
|
export function McRegistrationsTab({ filter, onDataChange }: { filter: BookingFilter; onDataChange?: () => void }) {
|
|
const [regs, setRegs] = useState<McRegistration[]>([]);
|
|
const [mcDates, setMcDates] = useState<Record<string, string>>({});
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
Promise.all([
|
|
adminFetch("/api/admin/mc-registrations").then((r) => r.json()),
|
|
adminFetch("/api/admin/sections/masterClasses").then((r) => r.json()),
|
|
]).then(([regData, mcData]: [McRegistration[], { items?: McItem[] }]) => {
|
|
setRegs(regData);
|
|
const dates: Record<string, string> = {};
|
|
const mcItems = mcData.items || [];
|
|
for (const mc of mcItems) {
|
|
const earliestSlot = mc.slots?.reduce((min, s) => s.date < min ? s.date : min, mc.slots[0]?.date ?? "");
|
|
if (earliestSlot) dates[mc.title] = earliestSlot;
|
|
}
|
|
const regTitles = new Set(regData.map((r) => r.masterClassTitle));
|
|
for (const regTitle of regTitles) {
|
|
if (dates[regTitle]) continue;
|
|
for (const mc of mcItems) {
|
|
const earliestSlot = mc.slots?.reduce((min, s) => s.date < min ? s.date : min, mc.slots[0]?.date ?? "");
|
|
if (!earliestSlot) continue;
|
|
if (regTitle.toLowerCase().includes(mc.title.toLowerCase()) || mc.title.toLowerCase().includes(regTitle.toLowerCase())) {
|
|
dates[regTitle] = earliestSlot;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
setMcDates(dates);
|
|
}).catch(() => {}).finally(() => setLoading(false));
|
|
}, []);
|
|
|
|
const today = new Date().toISOString().split("T")[0];
|
|
|
|
const groups = useMemo((): BookingGroup<McRegistration>[] => {
|
|
const map: Record<string, McRegistration[]> = {};
|
|
for (const r of regs) {
|
|
if (!map[r.masterClassTitle]) map[r.masterClassTitle] = [];
|
|
map[r.masterClassTitle].push(r);
|
|
}
|
|
return Object.entries(map).map(([title, items]) => {
|
|
const date = mcDates[title];
|
|
const isArchived = !date || date < today;
|
|
return {
|
|
key: title,
|
|
label: title,
|
|
dateBadge: date ? new Date(date + "T12:00").toLocaleDateString("ru-RU", { day: "numeric", month: "short" }) : undefined,
|
|
items,
|
|
isArchived,
|
|
};
|
|
});
|
|
}, [regs, mcDates, today]);
|
|
|
|
if (loading) return <LoadingSpinner />;
|
|
|
|
return (
|
|
<GenericBookingsList<McRegistration>
|
|
items={regs}
|
|
endpoint="/api/admin/mc-registrations"
|
|
filter={filter}
|
|
onItemsChange={setRegs}
|
|
onDataChange={onDataChange}
|
|
groups={groups}
|
|
/>
|
|
);
|
|
}
|