Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
3.4 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()(sortedcreatedAtdesc, already the default sort) on an interval. - Diffs the newest order's
id/createdAtagainst the last-seen value, kept in memory and persisted viaLocalStorageService(survives page reload, same pattern asAdminPreferencesService). - On finding order(s) newer than last-seen: fires one toast per new order and
increments an
unreadCountsignal. - 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 viaLocalStorageService.
Toast delivery
- Reuses the existing
UserNotificationService/FloatingNotificationsComponent(already global —providedIn: root, mounted once inapp.html). No new toast UI. UserNotificationgains an optionalroute: string[]field.FloatingNotificationsComponentgets a click handler: navigate toroute(if set) then dismiss.
Badge — reuses existing topbar bell
admin-layout.component.html:141-157 already has an unused bell icon +
dropdown panel (currently hardcoded to always show "no notifications").
Wire the watcher's data into it instead of adding a new indicator:
unreadCountsignal (fromAdminOrderWatcherService) rendered as a badge on the bell icon (admin-layout__icon-button).- Opening the panel (
notificationsOpen(), already wired to the bell click) lists the unread new orders instead of the static "notificationsEmpty" text. - Opening the panel marks all currently-known orders as seen → badge resets
to 0 (same trigger
AdminLayoutComponent.toggleNotifications()already has).
Click behavior
- Toast click →
/admin/orders/:id(the new order's detail page). - Clicking an order row inside the bell panel → same, then closes the panel.
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.