Skip to content

Use dynamic checkout steps on checkout#54

Merged
damianlegawiec merged 2 commits intomainfrom
fix/checkout-steps
Mar 11, 2026
Merged

Use dynamic checkout steps on checkout#54
damianlegawiec merged 2 commits intomainfrom
fix/checkout-steps

Conversation

@damianlegawiec
Copy link
Member

@damianlegawiec damianlegawiec commented Mar 11, 2026

Every order can have different checkout steps (eg. physical items require shipment), also fixed using next vs advance

Summary by CodeRabbit

  • New Features

    • Dynamic checkout progression and user-friendly step labels for more flexible multi-step flows.
    • Added a backend-backed "next step" progression used across address, delivery, and payment actions.
  • Refactor

    • Reworked checkout step handling and navigation to derive current step from order data.
  • Style

    • Adjusted header spacing, store logo alt text now shows store name, and removed Order # from header.
  • Tests

    • Added tests covering the new checkout progression flow.

Every order can have different checkout steps (eg. physical items require shipment), also fixed using next vs advance
@coderabbitai
Copy link

coderabbitai bot commented Mar 11, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 281f0ea5-a6fa-4552-9e43-6b75eb2e3b44

📥 Commits

Reviewing files that changed from the base of the PR and between da50e4e and 237b12e.

📒 Files selected for processing (4)
  • src/app/[country]/[locale]/(checkout)/checkout/[id]/page.tsx
  • src/components/checkout/DeliveryStep.tsx
  • src/components/checkout/PaymentStep.tsx
  • src/lib/data/__tests__/checkout.test.ts

Walkthrough

Replaces hardcoded checkout step handling with dynamic step derivation from order.checkout_steps and introduces nextCheckoutStep to advance checkout. Adjusts UI to use dynamic step labels, makes some back handlers optional, and tweaks header padding and logo alt text.

Changes

Cohort / File(s) Summary
Checkout Page Refactor
src/app/[country]/[locale]/(checkout)/checkout/[id]/page.tsx
Replaced static step mapping with getCheckoutStep(orderState, checkoutSteps) and getVisibleCheckoutSteps; currentStep changed from typed CheckoutStep to string; steps now derived from order.checkout_steps; navigation uses nextCheckoutStep instead of advanceCheckout; removed static "Order #…" header line.
Checkout Data Layer & Tests
src/lib/data/checkout.ts, src/lib/data/__tests__/checkout.test.ts
Added exported nextCheckoutStep(orderId: string) wrapping next(orderId) from @spree/next with actionResult handling; tests added/mocked for success, Error failure, and non-Error failure cases.
Checkout Layout
src/app/[country]/[locale]/(checkout)/layout.tsx
Removed vertical padding from header container and changed store logo alt text to use dynamic storeName.
Delivery & Payment Step Components
src/components/checkout/DeliveryStep.tsx, src/components/checkout/PaymentStep.tsx
Made onBack optional in both DeliveryStepProps and PaymentStepProps; guarded rendering of Edit/Back controls when onBack is absent.

Sequence Diagram(s)

sequenceDiagram
    participant Browser
    participant CheckoutPage
    participant CheckoutService
    participant SpreeNext

    Browser->>CheckoutPage: Load order (id)
    CheckoutPage->>CheckoutService: fetchOrder(id)
    CheckoutService->>SpreeNext: getOrder(...)
    SpreeNext-->>CheckoutService: order data (state, checkout_steps)
    CheckoutService-->>CheckoutPage: order
    CheckoutPage->>CheckoutPage: getCheckoutStep(order.state, order.checkout_steps)
    Browser->>CheckoutPage: Click "Next" / submit step
    CheckoutPage->>CheckoutService: nextCheckoutStep(order.id)
    CheckoutService->>SpreeNext: next(order.id)
    SpreeNext-->>CheckoutService: updated order
    CheckoutService-->>CheckoutPage: updated order/result
    CheckoutPage->>Browser: render updated step/state
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I hopped through steps that used to be hard,
Now labels bloom and flows move forward,
Next-step whispers from the backend tree,
Back buttons hide when they need to be,
A little hop, and checkout’s free ✨🛒

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main objective of the changeset: making checkout steps dynamic based on order configuration instead of hardcoded.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/checkout-steps

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/lib/data/__tests__/checkout.test.ts (1)

158-178: Add the non-Error rejection case for nextCheckoutStep.

Every other actionResult wrapper in this file asserts the fallback-message branch, but this suite only covers Error instances. Adding the "unexpected" case will pin "Failed to advance checkout" and keep the new action aligned with the existing coverage pattern.

🧪 Suggested test
   it("returns error on failure", async () => {
     mockNext.mockRejectedValue(new Error("Cannot advance"));

     const result = await nextCheckoutStep("order-1");

     expect(result).toEqual({
       success: false,
       error: "Cannot advance",
     });
   });
+
+  it("returns fallback message for non-Error throws", async () => {
+    mockNext.mockRejectedValue("unexpected");
+
+    const result = await nextCheckoutStep("order-1");
+
+    expect(result).toEqual({
+      success: false,
+      error: "Failed to advance checkout",
+    });
+  });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/data/__tests__/checkout.test.ts` around lines 158 - 178, Add a test
that covers non-Error rejections for nextCheckoutStep by making mockNext reject
with a non-Error value (e.g., a string or null) and asserting the actionResult
falls back to the generic message "Failed to advance checkout"; locate the suite
using describe("nextCheckoutStep") and the mock named mockNext to add an it(...)
case that calls nextCheckoutStep("order-1") and expects { success: false, error:
"Failed to advance checkout" } to mirror the other actionResult fallback tests.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/app/`[country]/[locale]/(checkout)/checkout/[id]/page.tsx:
- Around line 46-50: The navigation logic is using hardcoded step ids instead of
the dynamic visible steps, which causes currentStep to be outside the rendered
steps (e.g., getCheckoutStep and goToStep returning "delivery" when that step
was filtered out); update getCheckoutStep and any back/forward handlers (e.g.,
goToStep, the code paths around currentStep/currentStepIndex) to compute the
current and previous steps by using the same filtered checkoutSteps array you
render (use checkoutSteps.indexOf(orderState) and Math.max(0, index-1) to pick
previous, or fallback to checkoutSteps[0] when index is -1), and ensure any step
transitions always use checkoutSteps[n] from that filtered array rather than
hardcoded ids like "delivery" or "payment".

---

Nitpick comments:
In `@src/lib/data/__tests__/checkout.test.ts`:
- Around line 158-178: Add a test that covers non-Error rejections for
nextCheckoutStep by making mockNext reject with a non-Error value (e.g., a
string or null) and asserting the actionResult falls back to the generic message
"Failed to advance checkout"; locate the suite using
describe("nextCheckoutStep") and the mock named mockNext to add an it(...) case
that calls nextCheckoutStep("order-1") and expects { success: false, error:
"Failed to advance checkout" } to mirror the other actionResult fallback tests.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b532d83f-cb01-4189-b490-a160f964a9b5

📥 Commits

Reviewing files that changed from the base of the PR and between 231ed02 and da50e4e.

📒 Files selected for processing (4)
  • src/app/[country]/[locale]/(checkout)/checkout/[id]/page.tsx
  • src/app/[country]/[locale]/(checkout)/layout.tsx
  • src/lib/data/__tests__/checkout.test.ts
  • src/lib/data/checkout.ts

- Derive previous step from visible steps array instead of hardcoded IDs
- Make onBack optional on DeliveryStep/PaymentStep for edge cases
  where a step has no predecessor (e.g. digital-only orders)
- Add non-Error rejection test for nextCheckoutStep

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@damianlegawiec damianlegawiec merged commit 3d235a1 into main Mar 11, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant