Files
marketplaces/docs/superpowers/specs/2026-08-15-admin-purchase-notifications-design.md
2026-08-15 02:08:36 +04:00

2.9 KiB

Admin purchase notifications — design

Status: Approved Date: 2026-08-15 Related backlog item: #7 (marked ВАЖНО — important)

Problem

Admin has no signal when a purchase happens on the marketplace. Orders only surface if someone manually opens the Orders list and refreshes. Backend exposes no WebSocket/SSE (confirmed in BACKEND-API-REFERENCE.md:20 — every "live" feature today, e.g. payment status, is plain polling), so this has to be poll-based like the rest of the app.

Architecture

AdminOrderWatcherService (new, providedIn: root, admin-scoped)

  • Polls AdminOrdersLocalGateway.loadOrders() (sorted createdAt desc, already the default sort) on an interval.
  • Diffs the newest order's id/createdAt against the last-seen value, kept in memory and persisted via LocalStorageService (survives page reload, same pattern as AdminPreferencesService).
  • On finding order(s) newer than last-seen: fires one toast per new order and increments an unreadCount signal.
  • Started once at the admin shell root, so it keeps polling regardless of which admin page is open.

Poll interval

  • Editable by admin, default 15s.
  • Setting lives in the same admin-settings page as currency rates (admin-settings-page.component.ts), persisted via LocalStorageService.

Toast delivery

  • Reuses the existing UserNotificationService / FloatingNotificationsComponent (already global — providedIn: root, mounted once in app.html). No new toast UI.
  • UserNotification gains an optional route: string[] field.
  • FloatingNotificationsComponent gets a click handler: navigate to route (if set) then dismiss.

Badge

  • unreadCount signal (from AdminOrderWatcherService) rendered on the admin sidebar's "Orders" nav item.
  • Visiting the orders list marks all currently-known orders as seen → badge resets to 0.

Click behavior

  • Toast click → /admin/orders/:id (the new order's detail page).
  • Badge click → orders list.

Data flow

AdminOrderWatcherService (interval timer)
  -> AdminOrdersLocalGateway.loadOrders()
  -> diff against last-seen order id/createdAt (LocalStorageService)
  -> new order(s) found?
       -> UserNotificationService.show(message, 'info', { route: ['/admin/orders', id] })
       -> unreadCount.update(n => n + 1)
  -> admin clicks toast/badge -> router navigate -> orders-list visit resets unreadCount

Error handling

Poll failures are silent/logged only (console.error), consistent with existing polling code (payment status polling in cart.component.ts). No toast spam on transient network errors — watcher just retries on the next interval.

Out of scope

  • Native OS push notifications (tab not focused) — user explicitly chose in-app toast/badge only, not browser Notification API.
  • Sound alerts — not selected.
  • Telegram/email alerts to staff — not selected, would need backend bot/mail integration.