Skip to content

28 checkout flow#74

Merged
rk234 merged 25 commits into
mainfrom
28-checkout-flow
May 17, 2026
Merged

28 checkout flow#74
rk234 merged 25 commits into
mainfrom
28-checkout-flow

Conversation

@akhilapnuri
Copy link
Copy Markdown
Collaborator

@akhilapnuri akhilapnuri commented Apr 27, 2026

Pull Request

Description

Built the checkout flow for donors to claim gifts. Built CheckoutAuthModal for register/login popup and useCheckoutFlow hook to manage states.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)
  • Performance improvement
  • Other (please describe):

Related Issues (put task name here from notion)

Screenshots (If it is a front end feature screenshot is required)

Log in and create account pop up when user pressed claim gift without being logged into an account:

image image Screenshot 2026-04-27 at 12 13 34 AM Screenshot 2026-04-27 at 12 13 49 AM

Error Toast when gift becomes unavilable:

Screenshot 2026-04-27 at 12 17 11 AM

Additional Notes

Summary by CodeRabbit

  • New Features

    • Integrated login and create-account modals into the checkout flow
    • Centralized checkout flow state with unified loading and action controls
  • User Experience

    • Real-time password requirements checklist during registration
    • Enhanced form inputs with per-field error messages, phone input support, and password show/hide
  • Bug Fixes / Behavior

    • Confirmation panel can show a disabling message and will disable claim action when present

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 27, 2026

Warning

Rate limit exceeded

@rk234 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 39 minutes and 27 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1a2573d8-6b1d-4810-83b2-1699e3768899

📥 Commits

Reviewing files that changed from the base of the PR and between 0e60afc and 3b9a12c.

📒 Files selected for processing (1)
  • app/src/hooks/useCheckoutFlow.ts
📝 Walkthrough

Walkthrough

Centralizes checkout state in a new useCheckoutFlow hook, adds auth UI (auth selector, login, create-account) and a reusable form input, and refactors the checkout route and ConfirmationPanel to use the flow for modal and claim orchestration.

Changes

Authentication Modals & Inputs

Layer / File(s) Summary
Form input component
app/src/components/storefront/CheckoutFieldInput.tsx
New reusable input supporting PhoneInput vs Input, error rendering, aria attributes, left startIcon, and password visibility toggle.
Create-account form & validators
app/src/components/storefront/CheckoutCreateAccountModal.tsx
Registration form with TanStack form fields for fullName, phoneNumber, email, password, confirmPassword; real-time password-criteria checklist; phone -> E.164 conversion; and submit calling flow.submitRegister.
Auth modal & selector
app/src/components/storefront/CheckoutAuthModal.tsx, app/src/components/storefront/CheckoutLoginModal.tsx
Top-level Dialog controlled by flow.authModalOpen, mode switch buttons (login/register), conditional rendering of CheckoutLoginModal or CheckoutCreateAccountModal, and header/logo UI.
Checkout state management hook
app/src/hooks/useCheckoutFlow.ts
New useCheckoutFlow(auth) exposing state (authModalOpen, confirmModalOpen, authMode, isPending, disabledMessage) and actions (start, confirmClaim, submitLogin, submitRegister, closeAll, setAuthMode) that coordinate cart validation, mutations, cart clearing, navigation, and error handling.
Route & panel integration
app/src/routes/_storefront/checkout.tsx, app/src/components/storefront/ConfirmationPanel.tsx
Checkout route now consumes useCheckoutFlow; ConfirmationPanel accepts disabledMessage; confirm modal and auth modal visibility and handlers are driven by the flow object.

Sequence Diagram

sequenceDiagram
  participant User
  participant CheckoutPage
  participant CheckoutFlow
  participant AuthModal
  participant ConfirmModal
  participant API as Mutations
  participant Nav as Navigation

  User->>CheckoutPage: Click "Claim Gifts"
  CheckoutPage->>CheckoutFlow: flow.start()
  alt unauthenticated
    CheckoutFlow->>CheckoutPage: authModalOpen = true
    CheckoutPage->>AuthModal: render CheckoutAuthModal
    User->>AuthModal: Select login or register
    AuthModal->>CheckoutFlow: flow.submitLogin / flow.submitRegister
    CheckoutFlow->>API: Login/Register mutation
    API-->>CheckoutFlow: Success/Error
    CheckoutFlow->>CheckoutFlow: confirmClaim()
  else authenticated donor
    CheckoutFlow->>CheckoutPage: confirmModalOpen = true
    CheckoutPage->>ConfirmModal: render with isPending
  end
  User->>ConfirmModal: Confirm
  ConfirmModal->>CheckoutFlow: flow.confirmClaim()
  CheckoutFlow->>API: ClaimGifts mutation
  API-->>CheckoutFlow: Claimed
  CheckoutFlow->>Nav: navigate to /donor/home
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • ArnavGupta23
  • rk234

Poem

🐰 I hopped through forms and dialogs bright,
Switched modes in a modal, toggled sight,
Password checks ticking, phone numbers made neat,
The flow took the cart from click to seat,
Hooray — gifts claimed and the checkout's complete!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title '28 checkout flow' uses a ticket/issue number prefix followed by a vague, generic term that does not clearly convey the nature or scope of the changes. Revise the title to be more descriptive and self-contained, e.g., 'Add checkout flow with authentication modals' to clearly communicate the main feature being introduced.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 28-checkout-flow

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.

@akhilapnuri
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 27, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@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: 9

🧹 Nitpick comments (3)
app/src/components/storefront/CheckoutFieldInput.tsx (1)

14-28: Default type so the rendered input never has type={undefined}.

When the consumer omits type, inputType evaluates to undefined and is forwarded to <Input>. It works (browser defaults to "text"), but it makes the prop signature ambiguous and breaks features like password autofill / numeric keyboards if the consumer simply forgot to pass it. A small default makes the contract explicit and keeps isPassword derivation clean.

♻️ Proposed refactor
 export function CheckoutFieldInput({
-  type,
+  type = "text",
   field,
   placeholder,
   disabled,
   startIcon,
 }: CheckoutFieldInputProps) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/components/storefront/CheckoutFieldInput.tsx` around lines 14 - 28,
The CheckoutFieldInput component lets the input `type` be undefined which causes
`inputType` to become undefined and be forwarded to <Input>, so set a sensible
default for the `type` prop (e.g., default to "text") in the CheckoutFieldInput
signature or destructuring to ensure `type` is never undefined; update the
derivation of `isPassword` / `inputType` (symbols: CheckoutFieldInput, type,
isPassword, inputType) to rely on that default and keep password toggle logic
intact.
app/src/components/storefront/CheckoutAuthModal.tsx (1)

46-50: Use strict equality.

Prefer === over == for the authMode comparisons.

-            {flow.authMode == "login" ? "User Login" : "Create Account"}
+            {flow.authMode === "login" ? "User Login" : "Create Account"}
...
-          {flow.authMode == "login" ? (
+          {flow.authMode === "login" ? (
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/components/storefront/CheckoutAuthModal.tsx` around lines 46 - 50, In
CheckoutAuthModal replace the loose equality checks on flow.authMode with strict
equality (use === instead of ==) for every comparison (e.g., the ternary that
renders the header and the conditional that chooses the login vs create-account
block) so the component uses strict type-safe comparisons against "login".
app/src/components/storefront/CheckoutCreateAccountModal.tsx (1)

143-189: Avoid side-effects inside the validator.

setPasswordCriterias is called from within validators.onChange, mixing validation with imperative React state updates. Prefer deriving the checklist from the live password value via form.Subscribe / useStore, which keeps the validator pure and avoids redundant renders. The criteria block itself can also be condensed:

-              if (value.length < 8) newCriterias[0] = false;
-              else newCriterias[0] = true;
-
-              if (!/[A-Z]/.test(value)) newCriterias[1] = false;
-              else newCriterias[1] = true;
-
-              if (!/[a-z]/.test(value)) newCriterias[2] = false;
-              else newCriterias[2] = true;
-
-              if (!/\d/.test(value)) newCriterias[3] = false;
-              else newCriterias[3] = true;
-
-              if (!/[@$!%*?&#^()]/.test(value)) newCriterias[4] = false;
-              else newCriterias[4] = true;
+              newCriterias[0] = value.length >= 8;
+              newCriterias[1] = /[A-Z]/.test(value);
+              newCriterias[2] = /[a-z]/.test(value);
+              newCriterias[3] = /\d/.test(value);
+              newCriterias[4] = /[@$!%*?&#^()]/.test(value);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/components/storefront/CheckoutCreateAccountModal.tsx` around lines
143 - 189, The validator for the password field in CheckoutCreateAccountModal
(validators.onChange on the form.Field "password") is performing a side-effect
by calling setPasswordCriterias; remove that state mutation from the validator
so the validator is a pure function that only returns validation errors. Move
the checklist derivation into a subscription or effect (e.g., form.Subscribe or
useStore / useEffect that watches the "password" field value) and there compute
the five boolean criteria (length, uppercase, lowercase, digit, special char) in
a compact map of regex tests and call setPasswordCriterias from that
subscription; keep validators.onChange to only run the same tests and return
undefined or the error string, but do not call setPasswordCriterias there.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/src/components/storefront/CheckoutAuthModal.tsx`:
- Line 49: In the CheckoutAuthModal component update the logo <img> that uses
the KFKLogo (the JSX element currently rendered as <img src={KFKLogo}
className="w-75 mx-auto mb-5" />) to include an appropriate alt attribute—either
a meaningful description like alt="KFK logo" if relevant to users or alt="" if
it is purely decorative—so screen readers won't announce the filename.
- Around line 16-20: The JSX in CheckoutAuthModal contains a nested <p> (outer
paragraph with an inner <p>), which is invalid; update the markup in the
CheckoutAuthModal component so the inner element is not a <p> (e.g., replace the
inner <p> with a <span> or plain text with a <br/>), ensuring the outer
paragraph remains a single valid <p> element and the visual text/line break is
preserved.

In `@app/src/components/storefront/CheckoutCreateAccountModal.tsx`:
- Around line 197-215: The confirmPassword field's validator (in the form.Field
for name "confirmPassword") only runs on the confirm field change; add
onChangeListenTo: ["password"] to its validators configuration so the
confirmPassword validator re-runs when the "password" field changes, ensuring
cross-field validation updates in real time; update the validators object on the
form.Field named "confirmPassword" (the same place that currently defines
onChange) to include onChangeListenTo: ["password"] alongside the existing
onChange handler.
- Around line 217-296: The selector in form.Subscribe returns four values but
the render destructures three, causing misalignment; update the selector to
return only [state.canSubmit, state.fieldMeta.password?.isTouched,
state.fieldMeta.password?.isDirty] (remove state.isSubmitting) so the children
destructure ([canSubmit, isTouched, isDirty]) correctly and isPasswordPristine =
!isTouched && !isDirty works as intended; locate form.Subscribe, the selector
function, and the destructuring block around isPasswordPristine to make this
change.

In `@app/src/components/storefront/CheckoutFieldInput.tsx`:
- Around line 38-70: The input needs accessible wiring so screen readers
announce validations: when errorMessage is present, set aria-invalid="true" on
the <Input> (component using props in CheckoutFieldInput) and add
aria-describedby pointing to a unique id for the error span (e.g.,
`${field.id}-error`); then give the error <span> that id and add role="alert"
(or aria-live="polite") so the message is announced when it appears. Update the
Input props to include aria-invalid and aria-describedby conditionally based on
errorMessage, and update the error span to include the matching id and
role/aria-live.
- Around line 38-65: The password-eye overlaps input text because the Input's
className only adds left padding (pl-8) for the start icon and not right padding
for the absolutely-positioned toggle; update the Input's className in
CheckoutFieldInput (the Input element rendered near isPassword / showPassword
and the Button toggle that calls setShowPassword) to conditionally add right
padding (e.g., pr-8 or pr-10) when isPassword is true so the typed text doesn't
flow under the Eye toggle and touch targets remain on the input.
- Around line 51-64: The password visibility toggle (Button in
CheckoutFieldInput, wrapped by isPassword and using setShowPassword/showPassword
with Eye/EyeOff) is currently icon-only and lacks accessibility attributes;
update the Button to keep type="button" and add an accessible name and state by
setting aria-label dynamically to "Show password" when showPassword is false and
"Hide password" when true, and include aria-pressed={showPassword} (or
role="switch" + aria-checked if preferred) so screen readers get both the label
and current state; ensure the visual icon rendering (Eye/EyeOff) stays the same
while these ARIA attributes provide the accessible semantics.
- Around line 6-12: Change the CheckoutFieldInputProps type to use the exported
AnyFieldApi from `@tanstack/react-form` instead of any: replace the field: any
property with field: AnyFieldApi and add an import for AnyFieldApi from
'@tanstack/react-form'. Update any usages of CheckoutFieldInputProps/field (in
the CheckoutFieldInput component) to accept the new type without other code
changes.

In `@app/src/hooks/useCheckoutFlow.ts`:
- Around line 74-99: submitLogin and submitRegister call confirmClaim() with a
stale captured auth and thus bypass the donor-role UI gate; update both to read
fresh session/auth after successful auth (e.g., use the resolved loginMutation
result or call queryClient.getQueryData(queries.session.verify.queryKey)) and
only call confirmClaim() if the current auth.role === UserRole.DONOR, otherwise
surface the disabledMessage; also adjust submitRegister's error handling to
distinguish failures from register vs login (report the actual error from the
step that threw rather than always "Failed to register").

---

Nitpick comments:
In `@app/src/components/storefront/CheckoutAuthModal.tsx`:
- Around line 46-50: In CheckoutAuthModal replace the loose equality checks on
flow.authMode with strict equality (use === instead of ==) for every comparison
(e.g., the ternary that renders the header and the conditional that chooses the
login vs create-account block) so the component uses strict type-safe
comparisons against "login".

In `@app/src/components/storefront/CheckoutCreateAccountModal.tsx`:
- Around line 143-189: The validator for the password field in
CheckoutCreateAccountModal (validators.onChange on the form.Field "password") is
performing a side-effect by calling setPasswordCriterias; remove that state
mutation from the validator so the validator is a pure function that only
returns validation errors. Move the checklist derivation into a subscription or
effect (e.g., form.Subscribe or useStore / useEffect that watches the "password"
field value) and there compute the five boolean criteria (length, uppercase,
lowercase, digit, special char) in a compact map of regex tests and call
setPasswordCriterias from that subscription; keep validators.onChange to only
run the same tests and return undefined or the error string, but do not call
setPasswordCriterias there.

In `@app/src/components/storefront/CheckoutFieldInput.tsx`:
- Around line 14-28: The CheckoutFieldInput component lets the input `type` be
undefined which causes `inputType` to become undefined and be forwarded to
<Input>, so set a sensible default for the `type` prop (e.g., default to "text")
in the CheckoutFieldInput signature or destructuring to ensure `type` is never
undefined; update the derivation of `isPassword` / `inputType` (symbols:
CheckoutFieldInput, type, isPassword, inputType) to rely on that default and
keep password toggle logic intact.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: a2343511-d6f0-4e97-96c2-14bf75a1f1a1

📥 Commits

Reviewing files that changed from the base of the PR and between 794a086 and 2f579f8.

📒 Files selected for processing (7)
  • app/src/components/storefront/CheckoutAuthModal.tsx
  • app/src/components/storefront/CheckoutCreateAccountModal.tsx
  • app/src/components/storefront/CheckoutFieldInput.tsx
  • app/src/components/storefront/CheckoutLoginModal.tsx
  • app/src/components/storefront/ConfirmationPanel.tsx
  • app/src/hooks/useCheckoutFlow.ts
  • app/src/routes/_storefront/checkout.tsx

Comment thread app/src/components/storefront/CheckoutAuthModal.tsx Outdated
Comment thread app/src/components/storefront/CheckoutAuthModal.tsx Outdated
Comment thread app/src/components/storefront/CheckoutCreateAccountModal.tsx
Comment thread app/src/components/storefront/CheckoutCreateAccountModal.tsx
Comment thread app/src/components/storefront/CheckoutFieldInput.tsx
Comment thread app/src/components/storefront/CheckoutFieldInput.tsx Outdated
Comment thread app/src/components/storefront/CheckoutFieldInput.tsx Outdated
Comment thread app/src/components/storefront/CheckoutFieldInput.tsx
Comment thread app/src/hooks/useCheckoutFlow.ts
Copy link
Copy Markdown
Contributor

@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

♻️ Duplicate comments (1)
app/src/hooks/useCheckoutFlow.ts (1)

73-97: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Await the auth mutations to honor the async contract.

submitLogin() and the login portion of submitRegister() declare async but return immediately because loginMutation.mutate() is callback-based and not awaited. Callers expecting a Promise<void> will resume before authentication and confirmClaim() complete.

Convert both to mutateAsync() with try/catch:

Proposed fix
 const submitLogin = async (email: string, password: string) => {
-  loginMutation.mutate(
-    { email, password },
-    {
-      onSuccess: async (session) => {
-        if (!session || session.role !== UserRole.DONOR) {
-          setAuthModalOpen(false);
-          setDisabledMessage(
-            "Only donors can claim gifts. Please log in with a donor account.",
-          );
-          return;
-        }
-
-        setAuthModalOpen(false);
-        await confirmClaim();
-      },
-      onError: (error) => {
-        const message =
-          error instanceof Error ? error.message : "Failed to login";
-        console.log(message);
-        toast.error("Failed to login. Check your username and password.");
-      },
-    },
-  );
+  try {
+    const session = await loginMutation.mutateAsync({ email, password });
+
+    if (!session || session.role !== UserRole.DONOR) {
+      setAuthModalOpen(false);
+      setDisabledMessage(
+        "Only donors can claim gifts. Please log in with a donor account.",
+      );
+      return;
+    }
+
+    setAuthModalOpen(false);
+    await confirmClaim();
+  } catch (error) {
+    const message =
+      error instanceof Error ? error.message : "Failed to login";
+    console.error(message);
+    toast.error("Failed to login. Check your username and password.");
+  }
 };
 
 const submitRegister = async (data: RegisterDonorInput) => {
   try {
     await registerMutation.mutateAsync({ data });
-    loginMutation.mutate(
-      {
-        email: data.email,
-        password: data.password,
-      },
-      {
-        onSuccess: async (session) => {
-          if (!session || session.role !== UserRole.DONOR) {
-            setAuthModalOpen(false);
-            setDisabledMessage(
-              "Only donors can claim gifts. Please log in with a donor account.",
-            );
-            return;
-          }
-
-          await confirmClaim();
-        },
-        onError: (error) => {
-          const message =
-            error instanceof Error
-              ? error.message
-              : "Failed to register or login";
-          console.error(message);
-          toast.error("Failed to login");
-        },
-      },
-    );
+    const session = await loginMutation.mutateAsync({
+      email: data.email,
+      password: data.password,
+    });
+
+    if (!session || session.role !== UserRole.DONOR) {
+      setAuthModalOpen(false);
+      setDisabledMessage(
+        "Only donors can claim gifts. Please log in with a donor account.",
+      );
+      return;
+    }
+
+    setAuthModalOpen(false);
+    await confirmClaim();
   } catch (error) {
     const message =
       error instanceof Error ? error.message : "Failed to register or login";
     console.error(message);
     toast.error("Failed to register or login");
   }
 };

Applies to lines 73–97 and 99–135.

🤖 Prompt for 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.

In `@app/src/hooks/useCheckoutFlow.ts` around lines 73 - 97, submitLogin and the
register flow use the callback-based
loginMutation.mutate/registerMutation.mutate so they return immediately despite
being declared async; change both flows (submitLogin and the login portion of
submitRegister) to call await loginMutation.mutateAsync(...) and await
registerMutation.mutateAsync(...) inside a try/catch so callers actually wait
for authentication and confirmClaim to complete, preserve the existing onSuccess
logic (check session && session.role === UserRole.DONOR,
setAuthModalOpen(false), call await confirmClaim(), setDisabledMessage on
non-donor) and in the catch block log the error and show the toast (use error
instanceof Error ? error.message : "Failed to login"/"Failed to register" as
before).
🤖 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 `@app/src/hooks/useCheckoutFlow.ts`:
- Around line 108-117: In the onSuccess handler (the branch that currently
checks session and UserRole.DONOR), close the auth modal before calling
confirmClaim() so the UI matches submitLogin() behavior: call
setAuthModalOpen(false) prior to awaiting confirmClaim() to ensure the modal is
dismissed even if confirmClaim() fails; keep the existing role check and
setDisabledMessage flow intact and only reorder the calls in onSuccess to
setAuthModalOpen(false) then await confirmClaim().

---

Duplicate comments:
In `@app/src/hooks/useCheckoutFlow.ts`:
- Around line 73-97: submitLogin and the register flow use the callback-based
loginMutation.mutate/registerMutation.mutate so they return immediately despite
being declared async; change both flows (submitLogin and the login portion of
submitRegister) to call await loginMutation.mutateAsync(...) and await
registerMutation.mutateAsync(...) inside a try/catch so callers actually wait
for authentication and confirmClaim to complete, preserve the existing onSuccess
logic (check session && session.role === UserRole.DONOR,
setAuthModalOpen(false), call await confirmClaim(), setDisabledMessage on
non-donor) and in the catch block log the error and show the toast (use error
instanceof Error ? error.message : "Failed to login"/"Failed to register" as
before).
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2676ba36-e589-4655-ac41-66b2f65c119f

📥 Commits

Reviewing files that changed from the base of the PR and between 2f579f8 and 0e60afc.

📒 Files selected for processing (5)
  • app/src/components/storefront/CheckoutAuthModal.tsx
  • app/src/components/storefront/CheckoutCreateAccountModal.tsx
  • app/src/components/storefront/CheckoutFieldInput.tsx
  • app/src/hooks/useCheckoutFlow.ts
  • app/src/routes/_storefront/checkout.tsx
🚧 Files skipped from review as they are similar to previous changes (4)
  • app/src/components/storefront/CheckoutCreateAccountModal.tsx
  • app/src/routes/_storefront/checkout.tsx
  • app/src/components/storefront/CheckoutFieldInput.tsx
  • app/src/components/storefront/CheckoutAuthModal.tsx

Comment thread app/src/hooks/useCheckoutFlow.ts Outdated
Copy link
Copy Markdown
Member

@rk234 rk234 left a comment

Choose a reason for hiding this comment

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

Great work!

@rk234 rk234 merged commit 58c4a3b into main May 17, 2026
4 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request May 17, 2026
7 tasks
@rk234 rk234 deleted the 28-checkout-flow branch May 18, 2026 01:51
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.

4 participants