Extract order items summary into reusable component - #537
Merged
mnindrazaka merged 1 commit intoSep 18, 2026
Merged
Conversation
Baristas and customers previously saw only "order is ready" with no item list, so there was no way to verify order contents at pickup or review them from order history. Extract the item-list rendering (already used by OrderPreparingView) into a shared OrderItemsSummary component and reuse it in OrderReadyView; the payment entity already carries items end-to-end, so no usecase/API changes are needed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015LLRrnUHRWWJgtAZA4j6ic
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
mnindrazaka
added a commit
that referenced
this pull request
Sep 18, 2026
* fix(order): show ordered items on the ready-for-pickup screen (#537) Baristas and customers previously saw only "order is ready" with no item list, so there was no way to verify order contents at pickup or review them from order history. Extract the item-list rendering (already used by OrderPreparingView) into a shared OrderItemsSummary component and reuse it in OrderReadyView; the payment entity already carries items end-to-end, so no usecase/API changes are needed. Claude-Session: https://claude.ai/code/session_015LLRrnUHRWWJgtAZA4j6ic Co-authored-by: Claude <noreply@anthropic.com> * fix(pos): reset item amount and re-validate stock before adding to cart (#535) Selecting a product while the grid was mid-revalidate or mid-param-change silently dropped the click, leaving the picker on the previous product's amount. SELECT_PRODUCT now also resets amount to 1 from those states, not just 'loaded'. Also add a soft stock check: the amount picked before pressing Submit can be stale by the time the fresh variant comes back (another cashier may have sold the last ones in the meantime). FETCH_VARIANT_SUCCESS now caps the amount to the freshly fetched sellableQuantity, or bounces back to the picker if the variant just went sold out, instead of blindly adding the stale amount to the cart. Claude-Session: https://claude.ai/code/session_016oePpwRYKhb8cuhcu6V8pc Co-authored-by: Claude <noreply@anthropic.com> * fix(api): send KDS pushes at high priority so a locked phone is woken (#536) The Expo push payload omitted `priority`, so Expo defaulted to `priority: 'default'` — FCM `normal` on Android, `apns-priority: 5` on iOS. Both platforms treat that as deliverable whenever convenient: Android holds normal-priority messages for the duration of Doze and iOS batches priority-5 pushes to conserve power. A barista locking the phone therefore got nothing, and every held order arrived at once the moment the screen came back on. Expo delivers to FCM as a data message that `expo-notifications`' own service turns into the visible notification, so waking the app is a precondition for the notification existing at all — and a normal-priority data message in Doze wakes nothing. `KdsPushPriorityHigh` is set in the domain next to `Sound` and `ChannelId`, and used by both construction sites: the dispatched order and the setup screen's test notification, which would otherwise behave differently from the real thing. Claude-Session: https://claude.ai/code/session_01AhcJGVXhTqVvjHnJhqgHQ8 Co-authored-by: Claude <noreply@anthropic.com> * docs: PRD for guest web push notifications in order-web (#538) * docs: add PRD for guest web push notifications in order-web The order app tells a guest their order is ready only by short polling from an open tab (OrderStatusUsecase's 10s interval), so a guest who locks their phone or switches apps learns nothing. The staff side of the same gap was closed by docs/prd-kds-order-notifications.md; this is the guest-facing half. Specifies Web Push with VAPID signed by apps/api, a hand-written service worker in apps/order-web, subscriptions keyed to the existing gl_session_id guest identity, and a guest_notifications outbox enqueued inside CompleteTransaction. Covers the new tables, API contract, backend and libs/ui file layout, and the iOS Home-Screen constraint that decides most of the UX. Broken into nine phases, one PR each. No code changes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014ErZwY6wGvnRSiAUYbDKWY * docs: add phase dependency graph to web push PRD The numbered phase list read as a strict sequence when three of the nine phases depend on nothing. Adds a Phase dependencies section: a per-phase table separating hard dependencies (does not compile or test without the other) from soft ones (merge order and acceptance only), plus the six parallel waves the graph collapses into and the six-phase critical path. Splits the transport types into domain/web_push_gateway_repository.go so phases 1 and 2 share no symbol and can be built at the same time (D17), recorded as a deliberate departure from the convention both existing gateway interfaces follow, with the cost of reverting it stated. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014ErZwY6wGvnRSiAUYbDKWY --------- Co-authored-by: Claude <noreply@anthropic.com> * feat(api): add web push subscription table, contract and endpoints (#540) Phase 1 of docs/prd-order-web-push-notifications.md: the guest-facing subscription slice for order-ready web push. Adds the web_push_subscriptions table, WebPushSubscriptionRepository with its MySQL implementation and mock, WebPushSubscriptionUsecase (subscribe upserting on endpoint, unsubscribe soft-deleting, list by session, config), the three contract schemas/operations, the web-push-subscription handler/route wrapped in RequireSessionId, the public VAPID config route, and the WEB_PUSH_VAPID_PUBLIC_KEY / WEB_PUSH_VAPID_PRIVATE_KEY / WEB_PUSH_SUBJECT env vars. Nothing sends a push yet — that lands in later phases. Claude-Session: https://claude.ai/code/session_017QR4LhgGxxLcyq7GYUUumC Co-authored-by: Claude <noreply@anthropic.com> * feat(order-web): add service worker, manifest and icons for web push (#539) Phase 6 of docs/prd-order-web-push-notifications.md. Ships the inert static prerequisites for guest web push: sw.js handles push and notificationclick, manifest.webmanifest enables standalone install (required for iOS Web Push per D12), icons derived from the venue logo, and next.config.js serves sw.js/the manifest with Cache-Control: no-cache so an updated worker isn't stuck behind Vercel's default caching. No registration code yet — phase 7 wires the browser repository that calls navigator.serviceWorker.register. Claude-Session: https://claude.ai/code/session_01J7xY2DeP62zXsQB7XJjLAu Co-authored-by: Claude <noreply@anthropic.com> * feat(api): add the Web Push gateway repository (#541) Implements phase 2 of docs/prd-order-web-push-notifications.md: WebPushGatewayRepository, sending VAPID-signed, RFC 8291-encrypted notifications via github.com/SherClockHolmes/webpush-go, mirroring data/expopush's shape. A 404/410 from the push service maps to WebPushErrorCodeGone so the dispatcher (phase 5) can prune the dead subscription; every other failure is transient and left for a retry. Adds the three WEB_PUSH_* VAPID env vars, since phase 1 (which would otherwise declare the public key) hasn't landed yet. Claude-Session: https://claude.ai/code/session_01RuApWSajokdXCzxhje9RtX Co-authored-by: Claude <noreply@anthropic.com> * feat(api): add guest notification outbox table and message rule (#542) Phase 3 of docs/prd-order-web-push-notifications.md: the guest_notifications table, GuestNotification/GuestNotificationStatus, the pure BuildGuestPushMessage message rule (FR-5), the GuestNotificationRepository with its MySQL implementation and generated mock, and PaymentRepository.GetPaymentByTransactionId, which FR-2's session resolution needs and did not exist yet. Nothing calls any of it yet — wiring lands in phase 4. Claude-Session: https://claude.ai/code/session_018uc2bsM4Qf2h2pidvQCpCE Co-authored-by: Claude <noreply@anthropic.com> * feat(ui): add order notification subscribe frontend domain slice (#543) Phase 7 of docs/prd-order-web-push-notifications.md: the WebPushSubscription/ WebPushConfig entities, the browser-side (WebPushRepository) and API-side (WebPushSubscriptionRepository) interfaces, their API and browser implementations, mock repositories, and the OrderNotificationSubscribeUsecase FSM per FR-6. No UI wiring yet — that's phase 8. Claude-Session: https://claude.ai/code/session_01RnkFJUWC9TZdgwzLCWn65g Co-authored-by: Claude <noreply@anthropic.com> * feat(api): enqueue guest notification on completion, delete on uncompletion (#544) Phase 4 of docs/prd-order-web-push-notifications.md. CompleteTransaction resolves the guest's session from the payment row and enqueues a guest_notifications row after the completion write succeeds, tolerating a missing payment as a skipped row rather than failing the completion (FR-2). UncompleteTransaction deletes the outbox row so a correction doesn't suppress the next real completion (D7). Nothing dispatches these rows yet. Claude-Session: https://claude.ai/code/session_015WHemhoFz8dJ5KPodVa6G2 Co-authored-by: Claude <noreply@anthropic.com> * feat(api): dispatch guest web push notifications on completion (phase 5) (#545) GuestNotificationUsecase.DispatchPending claims pending outbox rows and delivers each to every live subscription for its session, pruning subscriptions the push service reports gone (410/404) and retrying everything else up to the existing attempt ceiling. CompleteTransaction kicks a dispatch after its commit, and the sweeper (renamed runNotificationSweeper) now drives both the KDS and guest outboxes from one ticker per docs/prd-order-web-push-notifications.md D5. Claude-Session: https://claude.ai/code/session_01DFUNkiPqmE1cdMm9YfbDBs Co-authored-by: Claude <noreply@anthropic.com> * feat(ui): add the guest notification opt-in card (phase 8) (#546) Adds OrderNotificationOptIn, rendered by OrderPreparingView and driven by OrderStatusHandler's second use case (OrderNotificationSubscribeUsecase). The composition root in app/order/OrderStatus.tsx now wires up ServiceWorkerWebPushRepository and ApiWebPushSubscriptionRepository, so a guest can tap "Beri tahu saya" and actually receive a push once phase 5's dispatcher fires — the first phase where the feature is guest-visible. Claude-Session: https://claude.ai/code/session_01JV1mYWtZpUB58Y28SLU3dy Co-authored-by: Claude <noreply@anthropic.com> * feat: improve ux of order app * feat(kds-mobile): bundle a custom order-alert.wav notification sound (#548) Adds the placeholder chime as the KDS push sound per D23: wires it through the expo-notifications config plugin's sounds array, bumps the Android channel id to orders-v2 (a channel's sound is immutable after creation), and points KDS_PUSH_SOUND at the same filename so the API-built payload and the bundled asset agree. Claude-Session: https://claude.ai/code/session_016CkPhzZeN5QCniQDuCUfmt Co-authored-by: Claude <noreply@anthropic.com> * docs: documentation and e2e coverage for guest web push notifications (phase 9) (#547) Closes out docs/prd-order-web-push-notifications.md: a docs-site page explaining the feature to an operator (including the iOS Home Screen requirement and what to check when a guest reports nothing arrived), the three VAPID env vars documented in .env.example and README.md with a runnable key-generation command (apps/api/cmd/generatevapidkeys, mirroring the existing cmd/dokucheck and cmd/dokustub tools), and an order-web-e2e spec that drives a real browser subscription from the preparing screen and confirms a web_push_subscriptions row exists for the guest's session. Note: .github/workflows/e2e-main.yml also needs a throwaway VAPID keypair generated for the API step (the same way it already does for the DOKU signing key) so this spec has a real key to subscribe against post-merge — not included here because this token lacks the `workflow` OAuth scope to push workflow file changes. See the PR description for the exact diff to apply by hand. Claude-Session: https://claude.ai/code/session_011j7au7oUXbhNzcxh5ijis2 Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> * feat: update kds notification sound * Add web push configuration to deploy workflow * Generate a throwaway VAPID keypair on e2e setup * fix(ui): mock CheckCircle2 icon used by OrderReadyView The jest mock for @tamagui/lucide-icons was missing CheckCircle2, so OrderReadyView rendered undefined and failed OrderStatusHandler's "already ready" test. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YLHEzYqXJTqXbpRQZDMQUL --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Extracts the order items and total amount display logic from
OrderPreparingViewinto a new reusableOrderItemsSummarycomponent, then applies it toOrderReadyViewto display order details when an order is ready for pickup.Changes
OrderItemsSummarydisplays a list of order items with quantities, options, notes, and subtotals, plus a total amount rowOrderPreparingViewnow usesOrderItemsSummaryinstead of inline JSX, reducing duplicationOrderReadyViewnow displays the full order summary (items and total) alongside the pickup instructionsOrderStatusScreenpassesitemsandamountprops toOrderReadyViewOrderStatusHandler.test.tsxto verify items display in ready stateOrderReadyView.stories.tsxwith sample payment itemsImplementation details
OrderItemsSummaryacceptsitems: PaymentItem[]andamount: numberpropsYStack/XStackfor layout andformatRupiahutility for currency formattingorderStatus/index.tsfor barrel disciplinehttps://claude.ai/code/session_015LLRrnUHRWWJgtAZA4j6ic