fix: auto-refresh bookings silently instead of showing update banner
Polling detects new bookings and silently re-fetches tab data + dashboard counts. No more "press to update" banner — data appears automatically.
This commit is contained in:
@@ -699,29 +699,24 @@ function BookingsPageInner() {
|
||||
const [addOpen, setAddOpen] = useState(false);
|
||||
const [searchResults, setSearchResults] = useState<SearchResult[] | null>(null);
|
||||
const [statusFilter, setStatusFilter] = useState<BookingFilter>("all");
|
||||
const [newBookingsBanner, setNewBookingsBanner] = useState(false);
|
||||
const [refreshKey, setRefreshKey] = useState(0);
|
||||
const lastTotalRef = useRef<number | null>(null);
|
||||
const { showError } = useToast();
|
||||
|
||||
// #10: Pause polling when browser tab not visible
|
||||
// Poll for new bookings, auto-refresh silently
|
||||
useEffect(() => {
|
||||
let id: ReturnType<typeof setInterval>;
|
||||
function startPolling() {
|
||||
id = setInterval(() => {
|
||||
if (document.hidden) return;
|
||||
adminFetch("/api/admin/unread-counts")
|
||||
.then((r) => r.json())
|
||||
.then((data: { total: number }) => {
|
||||
if (lastTotalRef.current !== null && data.total !== lastTotalRef.current) {
|
||||
// #6: Show banner instead of remounting with key
|
||||
setNewBookingsBanner(true);
|
||||
}
|
||||
lastTotalRef.current = data.total;
|
||||
})
|
||||
.catch(() => {});
|
||||
}, 10000);
|
||||
}
|
||||
startPolling();
|
||||
const id = setInterval(() => {
|
||||
if (document.hidden) return;
|
||||
adminFetch("/api/admin/unread-counts")
|
||||
.then((r) => r.json())
|
||||
.then((data: { total: number }) => {
|
||||
if (lastTotalRef.current !== null && data.total !== lastTotalRef.current) {
|
||||
setRefreshKey((k) => k + 1);
|
||||
}
|
||||
lastTotalRef.current = data.total;
|
||||
})
|
||||
.catch(() => {});
|
||||
}, 10000);
|
||||
return () => clearInterval(id);
|
||||
}, []);
|
||||
|
||||
@@ -772,16 +767,6 @@ function BookingsPageInner() {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* #6: New bookings banner instead of full remount */}
|
||||
{newBookingsBanner && (
|
||||
<button
|
||||
onClick={() => { setNewBookingsBanner(false); window.location.reload(); }}
|
||||
className="mt-3 w-full rounded-lg border border-gold/30 bg-gold/10 px-4 py-2 text-sm text-gold hover:bg-gold/20 transition-all text-center"
|
||||
>
|
||||
Появились новые записи — нажмите для обновления
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* Search */}
|
||||
<div className="mt-3">
|
||||
<SearchBar
|
||||
@@ -829,7 +814,7 @@ function BookingsPageInner() {
|
||||
) : (
|
||||
<>
|
||||
{/* Dashboard — what needs attention */}
|
||||
<DashboardSummary onNavigate={setTab} />
|
||||
<DashboardSummary key={refreshKey} onNavigate={setTab} />
|
||||
|
||||
{/* Tabs */}
|
||||
<div className="mt-5 flex border-b border-white/10">
|
||||
@@ -851,8 +836,8 @@ function BookingsPageInner() {
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Tab content — no key={refreshKey}, banner handles new data */}
|
||||
<div className="mt-4">
|
||||
{/* Tab content — auto-refreshes when new bookings detected */}
|
||||
<div className="mt-4" key={refreshKey}>
|
||||
{tab === "reminders" && <RemindersTab />}
|
||||
{tab === "classes" && <GroupBookingsTab filter={statusFilter} />}
|
||||
{tab === "master-classes" && <McRegistrationsTab filter={statusFilter} />}
|
||||
@@ -864,7 +849,7 @@ function BookingsPageInner() {
|
||||
<AddBookingModal
|
||||
open={addOpen}
|
||||
onClose={() => setAddOpen(false)}
|
||||
onAdded={() => setNewBookingsBanner(true)}
|
||||
onAdded={() => setRefreshKey((k) => k + 1)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user