Policies section (business-details-form.tsx) Late Arrival Policy, Booking Terms and Privacy Policy URL are gone. The section now has Cancellation Policy plus the Terms & Privacy name and email dropdowns. Their database columns stay, so nothing is lost. Saving no longer touches them. Email and push only One switch, IN_APP_NOTIFICATIONS_VISIBLE in in-app.ts, is set to false and controls everything below. Bell icon: gone for customers, staff and owners, including the unread badge. Notification pages: /notifications, /staff/notifications and /owner/notifications now return 404. Settings: Settings → Notifications shows only Email and Push toggles. Testing: I checked all of this in a local test app as the owner.
This commit is contained in:
19 files changed
+263
-40
No files matched your search
+46
-9
@@ -5,8 +5,8 @@
|
||||
// balances) — caching that would risk serving stale or, worse, another
|
||||
// user's data. So this file does NOT try to make the booking flow work
|
||||
// offline. What it does do:
|
||||
// - Push notifications (`push`/`notificationclick` — unchanged from the
|
||||
// original Phase 7 push-notifications work).
|
||||
// - Push notifications (`push`/`notificationclick`), plus an app-icon
|
||||
// badge number counting the ones still unread (see updateAppBadge).
|
||||
// - Precache + serve a small static app shell (offline fallback page,
|
||||
// manifest, icons) so a lost connection shows a real "you're offline"
|
||||
// screen instead of the browser's own dinosaur/error page.
|
||||
@@ -92,6 +92,34 @@ self.addEventListener("message", (event) => {
|
||||
if (event.data?.type === "SKIP_WAITING") self.skipWaiting();
|
||||
});
|
||||
|
||||
/**
|
||||
* App-icon badge = how many of this app's push notifications are still
|
||||
* sitting in the notification shelf. Counting what the OS is actually
|
||||
* showing (instead of a stored counter) means nothing needs persisting —
|
||||
* a service worker can be stopped at any moment, losing in-memory state.
|
||||
* The page clears the badge and the shelf when the app is opened (see
|
||||
* service-worker-manager.tsx).
|
||||
*
|
||||
* Needs the Badging API: installed PWAs on Android/desktop Chrome and
|
||||
* Home Screen web apps on iOS 16.4+. Everywhere else this is a no-op.
|
||||
*/
|
||||
async function updateAppBadge() {
|
||||
if (!("setAppBadge" in self.navigator)) return;
|
||||
try {
|
||||
const count = (await self.registration.getNotifications()).length;
|
||||
if (count > 0) await self.navigator.setAppBadge(count);
|
||||
else await self.navigator.clearAppBadge();
|
||||
} catch {
|
||||
// Badging is cosmetic — never let it break showing the notification.
|
||||
}
|
||||
}
|
||||
|
||||
/** True when the app is open and in front of the person — a badge on the icon is pointless (and stale the moment they leave) then. */
|
||||
async function appIsInForeground() {
|
||||
const windows = await self.clients.matchAll({ type: "window", includeUncontrolled: true });
|
||||
return windows.some((client) => client.visibilityState === "visible");
|
||||
}
|
||||
|
||||
self.addEventListener("push", (event) => {
|
||||
if (!event.data) return;
|
||||
|
||||
@@ -114,7 +142,13 @@ self.addEventListener("push", (event) => {
|
||||
badge: "/icons/icon-192.png",
|
||||
};
|
||||
|
||||
event.waitUntil(self.registration.showNotification(title, options));
|
||||
event.waitUntil(
|
||||
self.registration
|
||||
.showNotification(title, options)
|
||||
.then(async () => {
|
||||
if (!(await appIsInForeground())) await updateAppBadge();
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
self.addEventListener("notificationclick", (event) => {
|
||||
@@ -122,11 +156,14 @@ self.addEventListener("notificationclick", (event) => {
|
||||
const url = event.notification.data?.url || "/";
|
||||
|
||||
event.waitUntil(
|
||||
self.clients.matchAll({ type: "window", includeUncontrolled: true }).then((clientList) => {
|
||||
for (const client of clientList) {
|
||||
if (client.url.includes(url) && "focus" in client) return client.focus();
|
||||
}
|
||||
if (self.clients.openWindow) return self.clients.openWindow(url);
|
||||
}),
|
||||
Promise.all([
|
||||
updateAppBadge(),
|
||||
self.clients.matchAll({ type: "window", includeUncontrolled: true }).then((clientList) => {
|
||||
for (const client of clientList) {
|
||||
if (client.url.includes(url) && "focus" in client) return client.focus();
|
||||
}
|
||||
if (self.clients.openWindow) return self.clients.openWindow(url);
|
||||
}),
|
||||
]),
|
||||
);
|
||||
});
|
||||
Reference in new issue
Block a user