| @@ -1,7 +1,11 @@ | ||
| 1 | 1 | import React, { useMemo, useState, useEffect, Suspense, lazy } from "react"; |
| 2 | 2 | import Layout from "./components/Layout"; |
| 3 | 3 | import { Skeleton } from "./components/ui/skeleton"; |
| 4 | +import { | |
| 5 | + useMarkSectionSeen, | |
| 6 | + SUBPAGE_TO_SECTION, | |
| 7 | +} from "./hooks/useNotificationCounts"; | |
| 4 | 8 | |
| 5 | 9 | /* |
| 6 | 10 | * Page-loading strategy. |
| 7 | 11 | * |
| @@ -100,8 +104,9 @@ | ||
| 100 | 104 | const RecurringRuleForm = lazy(() => import("./pages/RecurringRuleForm")); |
| 101 | 105 | const Whatsapp = lazy(() => import("./pages/Whatsapp")); |
| 102 | 106 | const ChannelManager = lazy(() => import("./pages/ChannelManager")); |
| 103 | 107 | const Webhooks = lazy(() => import("./pages/Webhooks")); |
| 108 | +const ScheduledPayments = lazy(() => import("./pages/ScheduledPayments")); | |
| 104 | 109 | const TripConsentForm = lazy(() => import("./pages/TripConsentForm")); |
| 105 | 110 | const BookingForm = lazy(() => import("./pages/BookingForm")); |
| 106 | 111 | const ViewBooking = lazy(() => import("./pages/ViewBooking")); |
| 107 | 112 | const AvailabilityForm = lazy(() => import("./pages/AvailabilityForm")); |
| @@ -159,21 +164,33 @@ | ||
| 159 | 164 | // Get subpage, tab, and action from URL query parameters |
| 160 | 165 | const subpage = useMemo(() => { |
| 161 | 166 | const params = new URLSearchParams(window.location.search); |
| 162 | 167 | return params.get("subpage") || "dashboard"; |
| 163 | - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| 168 | + // eslint-disable-next-line react-hooks/exhaustive-deps | |
| 164 | 169 | }, [urlKey]); |
| 165 | 170 | |
| 171 | + // Mark a badged section seen when its page is opened, so the sidebar badge | |
| 172 | + // clears (bumps the wp_options marker server-side, then the shared counts | |
| 173 | + // query refreshes). Fires once per navigation into the page. | |
| 174 | + const markSectionSeen = useMarkSectionSeen(); | |
| 175 | + useEffect(() => { | |
| 176 | + const section = SUBPAGE_TO_SECTION[subpage.toLowerCase()]; | |
| 177 | + if (section) { | |
| 178 | + markSectionSeen.mutate(section); | |
| 179 | + } | |
| 180 | + // eslint-disable-next-line react-hooks/exhaustive-deps | |
| 181 | + }, [subpage]); | |
| 182 | + | |
| 166 | 183 | const tab = useMemo(() => { |
| 167 | 184 | const params = new URLSearchParams(window.location.search); |
| 168 | 185 | return params.get("tab") || "all"; |
| 169 | - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| 186 | + // eslint-disable-next-line react-hooks/exhaustive-deps | |
| 170 | 187 | }, [urlKey]); |
| 171 | 188 | |
| 172 | 189 | const action = useMemo(() => { |
| 173 | 190 | const params = new URLSearchParams(window.location.search); |
| 174 | 191 | return params.get("action"); |
| 175 | - // eslint-disable-next-line react-hooks/exhaustive-deps | |
| 192 | + // eslint-disable-next-line react-hooks/exhaustive-deps | |
| 176 | 193 | }, [urlKey, subpage]); |
| 177 | 194 | |
| 178 | 195 | // Render the appropriate page based on subpage, tab, and action parameters |
| 179 | 196 | const renderPage = () => { |
| @@ -337,8 +354,13 @@ | ||
| 337 | 354 | return <DiscountForm />; |
| 338 | 355 | } |
| 339 | 356 | return <Discounts />; |
| 340 | 357 | case "payments": |
| 358 | + // Scheduled balance payments (Pro module) live under Payments as a tab. | |
| 359 | + // Checked before the action branches because this tab has no forms. | |
| 360 | + if (tab.toLowerCase() === "scheduled") { | |
| 361 | + return <ScheduledPayments />; | |
| 362 | + } | |
| 341 | 363 | // Check if we're viewing, creating, or editing a payment |
| 342 | 364 | if (action === "view") { |
| 343 | 365 | return <ViewPayment />; |
| 344 | 366 | } |