Desktop POS — Phase 4
Что сделано
Domain layer
packages/domain/src/types/aggregator.ts(new):AggregatorProvider = "yandex_eats" | "market_delivery" | "delivery_club" | stringAggregatorOrderListItem— соответствует JavaOrderListItemсexternal_providerAGGREGATOR_PROVIDER_LABELmap → русские названияaggregatorProviderLabel(p)helper
API client
packages/api-client/src/endpoints/aggregatorOrders.ts(new):list()→AggregatorOrderListItem[]getById(orderId)→Orderaccept / ready / handOver / reject(orderId, reason?)→ POST в BFF
Stores
stores/aggregatorStore.ts(new):items(полный список),loading/error/loadedknownIds: Set<string>— все заказы которые мы уже виделиnewSinceLastReload: string[]— diff между предыдущим и текущим reload (только status=new)load()/reload()/accept/ready/handOver/reject(с auto-reload)newCount() / acceptedCount()— для badge / column countersclearNew()— после того как звук проиграли
Lib
apps/desktop/src/lib/notificationSound.ts(new):playNewOrderSound()через Web Audio API- Двойной beep: 880 Гц → 1320 Гц, 0.16с each
- Ленивый
AudioContext, переиспользуется
Screens
screens/AggregatorOrdersScreen.tsx(new,/aggregator):- 3 columns layout (Новые / Готовятся / Готовы — статусы distributed)
- Cards: order_number + StatusBadge + provider label + external_order_id + elapsed time + total
- Actions per status: new → Принять/Отказать; accepted → Готов; ready → Передан курьеру
- reject —
prompt()для reason usePolling(reload, 15s)useEffectслушаетnewSinceLastReload→ играет звук + toast →clearNew()
Components / Wiring
components/AppShell.tsx(extended):- NavItem «Агрегаторы» с
badge={aggNewCount}— pulsing red badge - Новый
NavItemпринимаетbadge?: number— рендерит отдельный pill справа от текста - Фоновый
useEffect: pollaggReload()каждые 30 сек (всегда, не только на /aggregator) - Fallback
useEffect: если NEW появились на не-/aggregatorэкране — играем звук и push toast прямо отсюда (пользователь не пропустит) <style>с@keyframes pulseдля badge animation
- NavItem «Агрегаторы» с
App.tsx—/aggregatorroute под Protected+RequireShift+AppShellapi/client.ts—getAggregatorOrdersEndpoints()factoryapi/mockEndpoints.ts:- 3 seed заказа:
Y-1024 new(Я.Еда),M-2057 accepted(Маркет),Y-1019 ready(Я.Еда) createMockAggregatorOrdersEndpoints— accept меняет status, hand-over/reject убирает из массива
- 3 seed заказа:
Файлы
Created (5):
packages/domain/src/types/aggregator.tspackages/api-client/src/endpoints/aggregatorOrders.tsapps/desktop/src/stores/aggregatorStore.tsapps/desktop/src/lib/notificationSound.tsapps/desktop/src/screens/AggregatorOrdersScreen.tsx
Modified (5):
packages/domain/src/types/index.tspackages/api-client/src/index.tsapps/desktop/src/App.tsxapps/desktop/src/components/AppShell.tsxapps/desktop/src/api/client.tsapps/desktop/src/api/mockEndpoints.ts
Тесты
pnpm typecheck— zero errorspnpm exec vite build— passing (201 modules, +5)- Mock-mode E2E:
- Открыть /aggregator → видим 3 карточки
- Принять Y-1024 → перешла из «Новые» в «Готовятся»
- В фоне (через 30 сек) — symptom: badge число обновляется
- Открытие /main с предыдущим mock seed: badge показывает «1» (Y-1024 в new)
Ссылки
- Store Service / Order Service — соседние задачи