feat(frontend): saga timeline + narrator on order detail (epic #130 Phase 3)#167
Conversation
…hase 3) The centerpiece feature: the order-detail page now renders a live Placed → Paid → Shipped timeline off the polled order status, with a narrator panel explaining what the backend just did at each hop (202 + transactional outbox → RabbitMQ fanout → idempotent consumers → choreography, no orchestrator). Unblocked by the saga actually flowing locally on RabbitMQ (PR #159). - features/orders/saga.ts: OrderStatus union mirroring the backend enum, step model with teaching-grade narration copy, deriveStepStates + isSagaSettled. - api/orders.ts: status typed as OrderStatus; orderByIdQuery polls every 2s via dynamic refetchInterval while the saga is in flight and stops once it settles (Shipped/Delivered/Cancelled/PaymentFailed). Polling lives in the query definition, not component timers. - components/SagaTimeline.tsx: pure-render timeline + narrator panel; aria-current marks the live step; failure branch (PaymentFailed/Cancelled) renders loud, not stuck. - Tests (11 new, AAA-narrated per canon): saga helper table tests pin the full visual contract per status + the polling lifecycle; RTL component tests cover in-flight, settled, and failure states by role/label. typecheck + eslint clean; vitest 24/24. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Important Review skippedNo new commits to review since the last review. ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
WalkthroughChangesOrder saga timeline
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant OrderDetail
participant orderByIdQuery
participant SagaTimeline
OrderDetail->>orderByIdQuery: load order status
orderByIdQuery-->>OrderDetail: return current status
OrderDetail->>SagaTimeline: pass data.status
SagaTimeline->>SagaTimeline: derive states and narration
SagaTimeline-->>OrderDetail: render live timeline
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
CI failure triage: not this PR's code. The failing build/integration checks are |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@frontend/src/features/orders/components/SagaTimeline.test.tsx`:
- Around line 1-62: Add a test in the SagaTimeline describe block for
status="Cancelled" that verifies the terminal heading "Saga stopped: Cancelled"
and confirms the "What the backend just did" panel renders the
Cancelled-specific narration. Keep the assertions focused on the distinct
terminal narration and visual state, matching the existing PaymentFailed
coverage.
In `@frontend/src/features/orders/saga.ts`:
- Around line 56-65: Update the order progress rendering around the PROGRESS
mapping so Cancelled does not always use the Paid-step failure position.
Preserve the distinct cancellation paths from Order.Cancel by rendering
cancellation separately or carrying the prior order state, ensuring cancellation
from Placed does not mark payment as failed while cancellation from Paid remains
accurate.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 624fc564-fff3-468a-8123-5f8ef867c84e
📒 Files selected for processing (6)
frontend/src/features/orders/api/orders.tsfrontend/src/features/orders/components/OrderDetail.tsxfrontend/src/features/orders/components/SagaTimeline.test.tsxfrontend/src/features/orders/components/SagaTimeline.tsxfrontend/src/features/orders/saga.test.tsfrontend/src/features/orders/saga.ts
…p the status can't blame CodeRabbit findings on #167: Cancel() is legal from both Placed and Paid, and the DTO carries only the current status — so PROGRESS[Cancelled]=1 rendering Paid as 'failed' misstated a cancel-before-payment. Cancelled now renders Placed complete + remaining steps pending; the terminal panel (Saga stopped: Cancelled) carries the story. Adds the missing Cancelled error-path tests (derivation table + timeline render), per the frontend canon's error-path coverage rule. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Both findings addressed in 4eb6c62: |
|
@coderabbitai resolve |
|
@coderabbitai review |
✅ Action performedReview finished.
|
✅ Action performedComments resolved and changes approved. |
What
Phase 3 of epic #130 — the saga narrator, the demo's centerpiece: the order-detail page now shows a live Placed → Paid → Shipped timeline that advances as the backend saga runs, with a per-step panel explaining what the backend just did:
How
saga.ts—OrderStatusunion mirroringOrderService.Domain.OrderStatus, the step model + narration copy,deriveStepStates/isSagaSettled. Narration is a projection of the real architecture (per frontend canon: "the saga-narrator feature IS the documentation").orderByIdQuerypolls every 2 s via dynamicrefetchIntervalwhile the saga is in flight and stops the moment it settles — polling lives in the query definition, so there are no component-level timers.SagaTimeline.tsxis pure render off the status prop;aria-current="step"marks the live step (not color-only).Architecture-review gate
Assessed per the CLAUDE.md gate: pattern-conforming — an epic-planned frontend phase following the established feature-folder + TanStack Query patterns, no new dependencies, no cross-cutting changes, single feature folder. Proceeding under the gate's pattern-conforming carve-out (no agent pass).
Test plan
tscclean,eslintclean, vitest 24/24.Part of #130 (Phase 3).
🤖 Generated with Claude Code
Summary by CodeRabbit