arch-atlas

CheckoutState

models/checkout_state.dart

domain

Overview

Immutable snapshot of the entire checkout flow: backend cart id + Cart, Stripe clientSecret, selected shipping option / payment provider, promo code, available providers, booking questions + answers, plus the global isLoading / error flags.

User Flow

  1. Constructed empty in CheckoutController.build().
  2. copyWith re-issues every field except error which is intentionally pass-through (so passing error: null clears it).
  3. Almost every controller method does state.copyWith(isLoading: true) on entry and ...(isLoading: false) on exit.

Cases & Edge Cases

  • removePromoCode rebuilds the state via the full constructor (not copyWith) specifically so it can null out promoCode — copyWith's ?? would keep the old code.
  • questionAnswers and bookingQuestions default to const [] / const {} so the screen can render before initCheckout returns.
  • availableShippingOptions and availablePaymentProviders are List<dynamic> — typed payment_provider.dart and shipping_option.dart exist but the controller still passes the raw maps through.

Code References

  • lib/src/features/shared/checkout/models/checkout_state.dart:3 // CheckoutState
  • lib/src/features/shared/checkout/models/checkout_state.dart:34 // copyWith

API Calls

Empty — fill this in later. Open the manifest and add content here.

Notes

Booking-questions live here rather than in a dedicated notifier because validating them must happen at the same instant as confirming payment — splitting state across notifiers would create a race.