Client Order Flow, Payment & Profile Integration - #48
Client Order Flow, Payment & Profile Integration#48Abdulrahman-AlSayed-1 wants to merge 15 commits into
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughThis PR adds Stripe Elements payment handling, revises order and profile contracts, removes delivery-fee calculations, adds authentication validation, updates mocks and profile UI, and introduces end-to-end payment-flow documentation and tests. ChangesOrder and payment flow
Profile and mock contracts
Auth validation
Testing and documentation
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 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 |
|
@coderabbitai full review |
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 18
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
src/pages/auth/Signup.jsx (1)
130-160: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winGuard the signup redirect on the
register()result
useAuthStore.register()returnsnullon failure instead of throwing, so thistry/catchnever reaches the error branch.navigate("/auth/login")still runs after a failed registration. Check the resolved value before redirecting, or rethrow from the store.🤖 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 `@src/pages/auth/Signup.jsx` around lines 130 - 160, The signup flow in handleSubmit is treating register() as if it throws on failure, but useAuthStore.register can resolve to null, so the redirect still happens after a failed signup. Update handleSubmit in Signup.jsx to inspect the returned value from register() before calling navigate("/auth/login"), and setSubmitError when the result is null; alternatively, adjust register() in the auth store to throw on failure so the existing error handling works consistently.src/components/OrderFlow/OrderConfirmationDetails.jsx (1)
44-52: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winDuplicate divider now renders as a double line.
The divider at Line 44 (end of items list) and the new divider at Line 48 (added right after removing Subtotal/Delivery rows) sit back-to-back with nothing between them, producing a redundant double-line visual artifact in the Totals block.
🎨 Proposed fix
{/* Totals */} <div className="space-y-3 md:w-1/2 md:ml-auto"> - <div className="border-t border-gray-100 my-3"></div> - <div className="flex justify-between items-center text-xl">🤖 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 `@src/components/OrderFlow/OrderConfirmationDetails.jsx` around lines 44 - 52, The Totals block in OrderConfirmationDetails is rendering two consecutive dividers, creating a double-line artifact. Update the totals markup so only one divider remains between the items list and the Total row, and remove the extra border element introduced near the Totals section while keeping the existing layout and styling intact.src/pages/Profile/components/OrderCard.jsx (1)
9-45: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winMissing icon/label cases for newly introduced statuses (
PAID,CANCELLATION_PENDING).This PR introduces
PAID(success) andCANCELLATION_PENDING(error) as valid order statuses, butgetStatusIcononly styles PENDING/PREPARING, CONFIRMED, READY, and CANCELED — the new statuses fall through to the plain-text default, which is visually inconsistent with sibling states.🤖 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 `@src/pages/Profile/components/OrderCard.jsx` around lines 9 - 45, Update the getStatusIcon helper in OrderCard.jsx to handle the newly supported PAID and CANCELLATION_PENDING statuses instead of falling through to the default plain-text render. Add a success-style icon/label for PAID and an error-style icon/label for CANCELLATION_PENDING, matching the existing pattern used for CONFIRMED, READY, and CANCELED so the status display stays visually consistent.
🧹 Nitpick comments (11)
src/main.jsx (1)
7-13: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winNo guard for a missing/misconfigured Stripe publishable key.
loadStripe(import.meta.env.VITE_STRIPE_PUBLISHABLE_KEY)runs unconditionally at module load. If the env var is missing in some deploy/preview environment, Stripe hooks resolve tonullapp-wide, and the only user-facing symptom is a static "Loading payment form..." message inStripeCardElement, with no indication of misconfiguration.Proposed guard
+if (!import.meta.env.VITE_STRIPE_PUBLISHABLE_KEY) { + console.error("VITE_STRIPE_PUBLISHABLE_KEY is not set; Stripe payments will not work."); +} const stripePromise = loadStripe(import.meta.env.VITE_STRIPE_PUBLISHABLE_KEY);🤖 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 `@src/main.jsx` around lines 7 - 13, The Stripe setup in main.jsx initializes loadStripe unconditionally with import.meta.env.VITE_STRIPE_PUBLISHABLE_KEY, so add a guard around the Stripe initialization path to handle a missing or empty publishable key. Update the module-level stripePromise setup and the StripeCardElement flow to detect misconfiguration early and render a clear error/fallback state instead of leaving users on “Loading payment form...”. Use the existing Elements/loadStripe/StripeCardElement symbols to locate the affected setup and UI path..env (1)
11-13: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low valuePublishable key committed directly instead of a placeholder.
Stripe publishable keys are safe to expose client-side, so the Betterleaks "generic API key" flag here is effectively a false positive. Still, consider keeping a
.env.examplewith a placeholder value and documenting that developers/CI must supply their ownVITE_STRIPE_PUBLISHABLE_KEY, rather than committing a real dashboard key to version control.🤖 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 @.env around lines 11 - 13, Replace the committed real Stripe value in the VITE_STRIPE_PUBLISHABLE_KEY entry with a placeholder in the environment template, and document that developers/CI should supply their own key at runtime. Update the .env example/guidance around the Stripe Publishable Key so it’s clear the key is expected from the Stripe Dashboard, while avoiding storing a real dashboard key in version control.Source: Linters/SAST tools
src/components/OrderFlow/Payment/StripeCardElement.jsx (1)
55-67: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winPrefer functional state updates to avoid stale-closure risk.
nextComplete/nextErrorsare derived by spreading closed-overcomplete/fieldErrorsstate. Under React's automatic batching, near-simultaneous field updates could read stale state. Using the functional updater form (setComplete(prev => ({...prev, [key]: event.complete}))) is more robust.Proposed fix
- const handleChange = (key) => (event) => { - const nextComplete = { ...complete, [key]: event.complete }; - const nextErrors = { ...fieldErrors, [key]: event.error ? event.error.message : null }; - - setComplete(nextComplete); - setFieldErrors(nextErrors); + const handleChange = (key) => (event) => { + setComplete((prev) => ({ ...prev, [key]: event.complete })); + setFieldErrors((prev) => ({ ...prev, [key]: event.error ? event.error.message : null })); if (key === "cardNumber" && event.brand) setBrand(event.brand);🤖 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 `@src/components/OrderFlow/Payment/StripeCardElement.jsx` around lines 55 - 67, The handleChange callback in StripeCardElement is deriving nextComplete and nextErrors from closed-over complete and fieldErrors state, which can become stale under batched updates. Update setComplete and setFieldErrors to use functional updaters based on the previous state, and then compute allComplete and firstError from the updated values within handleChange before calling onError. Keep the existing behavior for setBrand when key is cardNumber.Source: Linters/SAST tools
src/components/auth/StepTwo.jsx (1)
1-2: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider driving gender options from
GENDER_OPTIONSlikeGOAL_OPTIONS.The hardcoded
"MALE"/"FEMALE"/"OTHER"values already mirrorGENDER_OPTIONSinsrc/constants.js. Mapping over it (as done for goals) avoids future drift between the two sources of truth.♻️ Suggested refactor
-import { GOAL_OPTIONS } from "../../constants"; +import { GOAL_OPTIONS, GENDER_OPTIONS } from "../../constants"; ... - <label className="flex items-center gap-1"> - <input type="radio" name="gender" value="MALE" checked={formData.gender === "MALE"} onChange={onChange} />{" "} - Male - </label> - <label className="flex items-center gap-1"> - <input type="radio" name="gender" value="FEMALE" checked={formData.gender === "FEMALE"} onChange={onChange} />{" "} - Female - </label> - <label className="flex items-center gap-1"> - <input type="radio" name="gender" value="OTHER" checked={formData.gender === "OTHER"} onChange={onChange} />{" "} - Other - </label> + {GENDER_OPTIONS.map(({ value, label }) => ( + <label key={value} className="flex items-center gap-1"> + <input + type="radio" + name="gender" + value={value} + checked={formData.gender === value} + onChange={onChange} + />{" "} + {label} + </label> + ))}Also applies to: 53-54, 63-78
🤖 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 `@src/components/auth/StepTwo.jsx` around lines 1 - 2, The gender selection in StepTwo is hardcoded even though it already matches GENDER_OPTIONS, so it can drift from the shared constants. Update the StepTwo component to import and map over GENDER_OPTIONS the same way it uses GOAL_OPTIONS, and replace the explicit MALE/FEMALE/OTHER option rendering and any related state handling with the shared source of truth.src/pages/Profile/ProfileLayout.jsx (1)
26-35: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
authUsermissing from effect dependencies.The effect reads
authUser?.idbut doesn't listauthUserin its dependency array, so it won't re-run ifauthUserchanges after mount. GivenApp.jsxgates rendering until auth loading completes, this is unlikely to cause issues in practice, but it's worth adding for correctness/lint-cleanliness.🤖 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 `@src/pages/Profile/ProfileLayout.jsx` around lines 26 - 35, The ProfileLayout useEffect reads authUser?.id but omits authUser from its dependency list, so update the dependency array in ProfileLayout to include authUser alongside user, loading, error, and fetchProfile. Keep the fetchProfile guard logic the same, and remove any unused mounted variable cleanup if it is not serving a purpose.src/components/OrderFlow/OrderConfirmationDetails.jsx (1)
11-11: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDrop unused
deliveryFee/finalTotalprops.Neither prop is referenced in the component body anymore — only
totalAmountis used (Line 52). Keeping them in the signature is misleading now that delivery fee is removed from this display.🧹 Proposed fix
-export default function OrderConfirmationDetails({ items, totalAmount, deliveryFee, finalTotal }) { +export default function OrderConfirmationDetails({ items, totalAmount }) {🤖 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 `@src/components/OrderFlow/OrderConfirmationDetails.jsx` at line 11, The OrderConfirmationDetails component still accepts deliveryFee and finalTotal even though only totalAmount is used in the body, so remove those unused props from the function signature and keep the remaining props aligned with the actual display logic in OrderConfirmationDetails.src/components/OrderFlow/CartItem.jsx (1)
27-27: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winExtract the repeated fallback image path into a shared constant.
The literal
"/images/bowl.png"fallback is duplicated identically acrossCartItem.jsx,OrderConfirmationDetails.jsx,OrderSummary.jsx,PopularMenuCard.jsx, andRegularFoodCard.jsx. Centralizing it (e.g.,DEFAULT_MEAL_IMAGEinconstants.js) avoids drift if the asset path ever changes.♻️ Proposed direction
+// constants.js +export const DEFAULT_MEAL_IMAGE = "/images/bowl.png";-src={item.imageUrl || item.image || "/images/bowl.png"} +src={item.imageUrl || item.image || DEFAULT_MEAL_IMAGE}🤖 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 `@src/components/OrderFlow/CartItem.jsx` at line 27, The fallback image path is duplicated across multiple components, so centralize the shared default meal image into a constant such as DEFAULT_MEAL_IMAGE in a common constants module. Update CartItem and the related image-rendering components (including OrderConfirmationDetails, OrderSummary, PopularMenuCard, and RegularFoodCard) to import and use that constant instead of the hardcoded "/images/bowl.png" literal.src/components/OrderFlow/OrderSummary.jsx (1)
16-24: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
subtotalprop is now dead — never rendered.The Price Breakdown section only shows Total (Lines 85-89);
subtotalis destructured but unused. All three callers (Cart.jsx,Checkout.jsx,Payment.jsx) still pass it, which is now pointless.🧹 Proposed fix
export default function OrderSummary({ items, - subtotal, total, buttonText = "Checkout", buttonLink = "/checkout", showItems = false, onEdit }) {Also applies to: 85-89
🤖 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 `@src/components/OrderFlow/OrderSummary.jsx` around lines 16 - 24, The OrderSummary component currently destructures a subtotal prop but never renders it, so the prop is dead and should be removed. Update OrderSummary to stop accepting subtotal and clean up the callers in Cart, Checkout, and Payment so they no longer pass it; also adjust the Price Breakdown rendering in OrderSummary so it only reflects the remaining displayed values, using the OrderSummary component and its Price Breakdown section as the place to verify the change.src/pages/OrderFlow/Checkout.jsx (1)
18-51: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winCheckout page always redirects on mount — rendered JSX is effectively dead code.
The
useEffectunconditionally navigates away (to/or/payment) every time this component mounts, so the full grid/OrderSummaryrender below can only ever flash briefly before being replaced. Consider rendering a minimal placeholder (ornull) while the effect resolves, instead of building out the full page body that users will never meaningfully see.♻️ Proposed simplification
return ( - <div className="checkout-page bg-gray-50 min-h-screen pt-24 md:pt-32"> - <div className="max-w-7xl mx-auto px-4 py-8"> - <div className="grid grid-cols-1 lg:grid-cols-3 gap-8"> - {/* Checkout Form - Takes 2 columns */} - <div className="lg:col-span-2"> - {/* <CheckoutForm /> */} - </div> - - {/* Order Summary - Takes 1 column */} - <div> - <OrderSummary - items={items} - subtotal={totalAmount} - total={totalAmount} - buttonText="Continue" - buttonLink="/payment" - showItems={true} - onEdit={() => navigate("/cart")} - /> - </div> - </div> - </div> - </div> + <div className="checkout-page bg-gray-50 min-h-screen pt-24 md:pt-32 flex items-center justify-center"> + {/* Redirecting… */} + </div> );🤖 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 `@src/pages/OrderFlow/Checkout.jsx` around lines 18 - 51, The Checkout component’s `useEffect` always redirects on mount, so the JSX below in `Checkout` is effectively unreachable. Update `src/pages/OrderFlow/Checkout.jsx` so the component renders a minimal placeholder or `null` while navigation is happening, and avoid constructing the full checkout grid and `OrderSummary` UI when the page will immediately route away. Keep the redirect logic in `useEffect`, but make the returned markup reflect that `Checkout` is only a transition screen, not a full page.src/pages/OrderFlow/Thanks.jsx (1)
5-5: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winCommented-out
CustomerInfoSummary— restore or remove.The import and its usage block are commented out rather than removed, silently dropping the customer-info/payment-method confirmation card from the Thanks page. If this removal is intentional, delete the dead code instead of leaving it commented; if not, restore it.
♻️ Suggested cleanup (if intentionally removed)
-// import CustomerInfoSummary from "../../components/OrderFlow/CustomerInfoSummary";- {/* Customer Info Card */} - {/* <CustomerInfoSummary - customerDetails={customerDetails} - paymentMethod={lastOrder.paymentMethod} - /> */}Also applies to: 44-48
🤖 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 `@src/pages/OrderFlow/Thanks.jsx` at line 5, The Thanks page has commented-out CustomerInfoSummary import/usage instead of a clear decision, which hides whether the customer-info/payment-method confirmation card should render. In Thanks.jsx, either restore the CustomerInfoSummary import and its render block if the card is still needed, or remove the dead import and related JSX entirely if the removal is intentional; use the CustomerInfoSummary symbol and the Thanks component to locate and clean up the affected code.src/mocks/handlers.js (1)
174-181: 🗄️ Data Integrity & Integration | 🔵 Trivial | 💤 Low valueRemove the stale
/orders/mymock or switch it toclientId.
This route still filters onuserId, while the mock order shape and the rest of the app useclientId. Nothing in the repo calls/orders/my;order.service.jsuses/api/order/client/historyinstead.🤖 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 `@src/mocks/handlers.js` around lines 174 - 181, The `/orders/my` mock in the handlers setup is stale and still filters orders by userId, which no longer matches the app’s order shape or current API usage. Update the mock to use clientId if it is still needed, or remove this handler entirely since the app now calls the order history endpoint through order.service.js and no code references `/orders/my`. Use the existing mock route entry and the handler logic around mockOrders to keep the change aligned with the current API contract.
🤖 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 `@src/App.jsx`:
- Line 68: The /profile route is missing the auth guard, so unauthenticated
users can reach ProfileLayout and its nested pages. Update the Route definition
in App.jsx to wrap ProfileLayout with ProtectedRoute, matching the protected
customize and favorites routes and the surrounding routing pattern. Keep the
protection at the route level so /profile, /profile/orders, and /profile/rewards
all redirect to login when the user is not authenticated.
In `@src/components/auth/StepTwo.jsx`:
- Line 3: StepTwo is still using a singular error prop, but Signup now passes a
field-keyed errors object, so Step 2 validation feedback never renders. Update
StepTwo’s prop contract to accept errors and use it consistently in the
component, especially around the age, height, and weight inputs. Mirror
StepOne’s per-field error pattern by showing field-specific messages and styling
based on errors.age, errors.height, and errors.weight, and remove reliance on
the unused error prop in StepTwo.
In `@src/components/OrderFlow/Payment/StripeCardElement.jsx`:
- Around line 55-67: The handleChange logic in StripeCardElement computes
allComplete but never uses it, triggering the no-unused-vars lint error. Remove
the unused allComplete calculation and keep the rest of the state updates and
onError flow in handleChange unchanged; use the existing CARD_FIELD_KEYS,
nextComplete, and nextErrors references to locate the code.
- Around line 1-9: `StripeCardElement` is using the split Stripe fields, so the
existing `handleChange`/submit flow cannot rely on
`elements.getElement(CardElement)` and will never reach `submitOrder()` or
`confirmStripePayment()`. Update the payment lookup logic in `StripeCardElement`
to use the mounted `CardNumberElement` (or receive its ref from the modal) and
wire that into the credit-card path instead of `CardElement`. Also remove the
unused `allComplete` local from `handleChange` and keep the submit logic keyed
off the actual split element state.
In `@src/components/OrderFlow/PaymentForm.jsx`:
- Around line 39-44: Remove the unused handleMethodSelect helper from
PaymentForm since it is never referenced and causes lint failures; keep the
payment flow wired through PaymentMethodSelector via setPaymentMethod and
onAddCard directly, and delete any related dead code in the PaymentForm
component.
- Around line 70-74: The credit-card flow is using the wrong Stripe element and
never forwards the selected payment method into submitOrder. Update handleSubmit
in PaymentForm to use the mounted split fields rendered by StripeCardElement
instead of CardElement, and make sure submitOrder is called with the
stripePaymentMethod so the requiresPayment path can confirm the payment before
closing the card modal. Keep the card elements mounted through confirmation and
align the getElement lookup with the actual StripeCardElement field names.
In `@src/components/ui/AllergiesDropdown.jsx`:
- Line 21: The `AllergiesDropdown` map callback currently destructures an unused
`index` parameter, which triggers the `no-unused-vars` lint error. Update the
`HEALTH_CONDITIONS.map` callback to remove `index` (or otherwise use it if
needed) and keep only the parameters actually referenced in the JSX so the lint
warning is resolved.
- Around line 4-11: The handleToggle logic in AllergiesDropdown should restore
the special-case exclusivity for the "NONE" option to match HealthForm.jsx.
Update the selection handling so choosing "NONE" clears any other selected
conditions, and choosing any other condition removes "NONE" if it is already
selected; keep the behavior confined to handleToggle and the selected/onChange
flow used by AllergiesDropdown so Signup.jsx receives a valid healthConditions
array.
In `@src/mocks/orders.js`:
- Line 30: The mock order IDs in orders.js are using numeric literals beyond
Number.MAX_SAFE_INTEGER, causing precision loss and lint failures. Update the
affected clientId values in the mock data to use a safe representation such as
strings or another exact ID format, and make sure both occurrences in the orders
mock dataset are changed consistently so comparisons and filters remain exact.
In `@src/pages/Profile/components/HealthForm.jsx`:
- Around line 38-43: The phone validation message in HealthForm.jsx is too
specific and does not match the generic validatePhoneNumber helper used here.
Update the setPhoneError message in the phoneNumber check inside the HealthForm
component to a generic phone-format error that matches the E.164-style
validation used by validatePhoneNumber, consistent with the wording used in
Signup.jsx.
In `@src/pages/Profile/components/OrderDetailsModal.jsx`:
- Around line 90-103: The discount row in OrderDetailsModal is rendering
unconditionally because the JSX is wrapped in plain parentheses instead of a
condition. Update the price breakdown block in OrderDetailsModal.jsx so the
discount `<div>` only renders when `discount` is greater than zero, using the
existing discount/subtotal values to keep the display consistent. Use the
`subtotal`, `discount`, and `discountAmount` expressions in that component to
locate the conditional rendering logic.
In `@src/pages/Profile/Profile.jsx`:
- Around line 32-44: The fallback error in the Profile save handler is using a
stale `error` value captured from the store before `updateUserProfile` runs.
Update the `onSave` flow in `Profile.jsx` to read the latest store error after
the await completes (or use the error returned/raised by `updateUserProfile`)
before throwing, so the failure message reflects the actual update result rather
than the pre-call value.
In `@src/store/orderStore.js`:
- Line 565: The `paymentIntent` value destructured from
`stripe.confirmCardPayment` in `orderStore` is unused and will fail lint. Update
the `confirmCardPayment` call handling so only the needed `error` field is
destructured, or rename the unused field to match the repo’s allowed
unused-variable pattern if it must remain. Locate this in the payment flow
inside `orderStore` where `stripe.confirmCardPayment` is called.
- Around line 505-530: In submitOrder, success is currently hard-coded to
CONFIRMED, which causes cash orders that return PENDING to be treated as failed.
Update the success check in orderStore so it uses the same success-status set as
confirmStripePayment, and apply that same check consistently when setting the
transaction status, deciding whether to clearCart(), and determining the
returned boolean.
- Around line 466-481: The credit-card branch in submitOrder is gated on
stripePaymentMethod even though the method is called without an argument, so
remove that unused check and make sure the branch returns requiresPayment when
clientSecret is present. Also align the post-submit flow with the order-status
logic: in the pollOrderStatus path, treat the service/mock success state
(PENDING as well as CONFIRMED, if that’s the intended terminal success) as a
successful order so the cart is cleared and navigation proceeds, while keeping
confirmStripePayment and the PaymentForm/stripeClientSecret flow working through
pendingOrderId.
In `@src/store/profileStore.js`:
- Around line 24-41: Remove the PII leak in profileStore’s fetchProfile flow by
eliminating the console.log that prints the full user object after getProfile
resolves. Keep the existing loading/error handling in fetchProfile, and if
debugging is still needed, guard any logging behind a development-only check so
production never logs profile data.
- Around line 62-90: The deletePicture action in profileStore is keeping stale
avatar/photo data by falling back to get().user when deleteProfilePicture
returns no response body. Update deletePicture to clear the profile image fields
on success and set the updated user state explicitly instead of reusing the
pre-delete user; keep the existing uploadPicture behavior unchanged. Use the
deleteProfilePicture and deletePicture symbols to locate the fix.
In `@src/utils/authValidation.js`:
- Around line 6-23: In validatePassword and validatePhoneNumber, remove the
truly unnecessary regex escapes that ESLint flagged while keeping the required
ones intact. Update the passwordRegex in validatePassword to drop the
superfluous escaping for [, /, and any other characters that do not need
escaping inside the character class, and adjust the phone sanitizing regex in
validatePhoneNumber to remove the unnecessary escapes for ( and ) while
preserving the rest of the pattern behavior.
---
Outside diff comments:
In `@src/components/OrderFlow/OrderConfirmationDetails.jsx`:
- Around line 44-52: The Totals block in OrderConfirmationDetails is rendering
two consecutive dividers, creating a double-line artifact. Update the totals
markup so only one divider remains between the items list and the Total row, and
remove the extra border element introduced near the Totals section while keeping
the existing layout and styling intact.
In `@src/pages/auth/Signup.jsx`:
- Around line 130-160: The signup flow in handleSubmit is treating register() as
if it throws on failure, but useAuthStore.register can resolve to null, so the
redirect still happens after a failed signup. Update handleSubmit in Signup.jsx
to inspect the returned value from register() before calling
navigate("/auth/login"), and setSubmitError when the result is null;
alternatively, adjust register() in the auth store to throw on failure so the
existing error handling works consistently.
In `@src/pages/Profile/components/OrderCard.jsx`:
- Around line 9-45: Update the getStatusIcon helper in OrderCard.jsx to handle
the newly supported PAID and CANCELLATION_PENDING statuses instead of falling
through to the default plain-text render. Add a success-style icon/label for
PAID and an error-style icon/label for CANCELLATION_PENDING, matching the
existing pattern used for CONFIRMED, READY, and CANCELED so the status display
stays visually consistent.
---
Nitpick comments:
In @.env:
- Around line 11-13: Replace the committed real Stripe value in the
VITE_STRIPE_PUBLISHABLE_KEY entry with a placeholder in the environment
template, and document that developers/CI should supply their own key at
runtime. Update the .env example/guidance around the Stripe Publishable Key so
it’s clear the key is expected from the Stripe Dashboard, while avoiding storing
a real dashboard key in version control.
In `@src/components/auth/StepTwo.jsx`:
- Around line 1-2: The gender selection in StepTwo is hardcoded even though it
already matches GENDER_OPTIONS, so it can drift from the shared constants.
Update the StepTwo component to import and map over GENDER_OPTIONS the same way
it uses GOAL_OPTIONS, and replace the explicit MALE/FEMALE/OTHER option
rendering and any related state handling with the shared source of truth.
In `@src/components/OrderFlow/CartItem.jsx`:
- Line 27: The fallback image path is duplicated across multiple components, so
centralize the shared default meal image into a constant such as
DEFAULT_MEAL_IMAGE in a common constants module. Update CartItem and the related
image-rendering components (including OrderConfirmationDetails, OrderSummary,
PopularMenuCard, and RegularFoodCard) to import and use that constant instead of
the hardcoded "/images/bowl.png" literal.
In `@src/components/OrderFlow/OrderConfirmationDetails.jsx`:
- Line 11: The OrderConfirmationDetails component still accepts deliveryFee and
finalTotal even though only totalAmount is used in the body, so remove those
unused props from the function signature and keep the remaining props aligned
with the actual display logic in OrderConfirmationDetails.
In `@src/components/OrderFlow/OrderSummary.jsx`:
- Around line 16-24: The OrderSummary component currently destructures a
subtotal prop but never renders it, so the prop is dead and should be removed.
Update OrderSummary to stop accepting subtotal and clean up the callers in Cart,
Checkout, and Payment so they no longer pass it; also adjust the Price Breakdown
rendering in OrderSummary so it only reflects the remaining displayed values,
using the OrderSummary component and its Price Breakdown section as the place to
verify the change.
In `@src/components/OrderFlow/Payment/StripeCardElement.jsx`:
- Around line 55-67: The handleChange callback in StripeCardElement is deriving
nextComplete and nextErrors from closed-over complete and fieldErrors state,
which can become stale under batched updates. Update setComplete and
setFieldErrors to use functional updaters based on the previous state, and then
compute allComplete and firstError from the updated values within handleChange
before calling onError. Keep the existing behavior for setBrand when key is
cardNumber.
In `@src/main.jsx`:
- Around line 7-13: The Stripe setup in main.jsx initializes loadStripe
unconditionally with import.meta.env.VITE_STRIPE_PUBLISHABLE_KEY, so add a guard
around the Stripe initialization path to handle a missing or empty publishable
key. Update the module-level stripePromise setup and the StripeCardElement flow
to detect misconfiguration early and render a clear error/fallback state instead
of leaving users on “Loading payment form...”. Use the existing
Elements/loadStripe/StripeCardElement symbols to locate the affected setup and
UI path.
In `@src/mocks/handlers.js`:
- Around line 174-181: The `/orders/my` mock in the handlers setup is stale and
still filters orders by userId, which no longer matches the app’s order shape or
current API usage. Update the mock to use clientId if it is still needed, or
remove this handler entirely since the app now calls the order history endpoint
through order.service.js and no code references `/orders/my`. Use the existing
mock route entry and the handler logic around mockOrders to keep the change
aligned with the current API contract.
In `@src/pages/OrderFlow/Checkout.jsx`:
- Around line 18-51: The Checkout component’s `useEffect` always redirects on
mount, so the JSX below in `Checkout` is effectively unreachable. Update
`src/pages/OrderFlow/Checkout.jsx` so the component renders a minimal
placeholder or `null` while navigation is happening, and avoid constructing the
full checkout grid and `OrderSummary` UI when the page will immediately route
away. Keep the redirect logic in `useEffect`, but make the returned markup
reflect that `Checkout` is only a transition screen, not a full page.
In `@src/pages/OrderFlow/Thanks.jsx`:
- Line 5: The Thanks page has commented-out CustomerInfoSummary import/usage
instead of a clear decision, which hides whether the
customer-info/payment-method confirmation card should render. In Thanks.jsx,
either restore the CustomerInfoSummary import and its render block if the card
is still needed, or remove the dead import and related JSX entirely if the
removal is intentional; use the CustomerInfoSummary symbol and the Thanks
component to locate and clean up the affected code.
In `@src/pages/Profile/ProfileLayout.jsx`:
- Around line 26-35: The ProfileLayout useEffect reads authUser?.id but omits
authUser from its dependency list, so update the dependency array in
ProfileLayout to include authUser alongside user, loading, error, and
fetchProfile. Keep the fetchProfile guard logic the same, and remove any unused
mounted variable cleanup if it is not serving a purpose.
🪄 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: CHILL
Plan: Pro Plus
Run ID: 617468da-b159-437a-83bc-8bf692f81167
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json,!package-lock.json
📒 Files selected for processing (46)
.envpackage.jsonsrc/App.jsxsrc/components/OrderFlow/AddCard/CardInputs.jsxsrc/components/OrderFlow/AddCard/CardPreview.jsxsrc/components/OrderFlow/CartItem.jsxsrc/components/OrderFlow/OrderConfirmationDetails.jsxsrc/components/OrderFlow/OrderSummary.jsxsrc/components/OrderFlow/Payment/PaymentMethodSelector.jsxsrc/components/OrderFlow/Payment/StripeCardElement.jsxsrc/components/OrderFlow/PaymentForm.jsxsrc/components/auth/StepOne.jsxsrc/components/auth/StepThree.jsxsrc/components/auth/StepTwo.jsxsrc/components/ui/AllergiesDropdown.jsxsrc/components/ui/PopularMenuCard.jsxsrc/components/ui/RegularFoodCard.jsxsrc/constants.jssrc/main.jsxsrc/mocks/handlers.jssrc/mocks/orders.jssrc/pages/OrderFlow/Cart.jsxsrc/pages/OrderFlow/Checkout.jsxsrc/pages/OrderFlow/Payment.jsxsrc/pages/OrderFlow/Thanks.jsxsrc/pages/Profile/Profile.jsxsrc/pages/Profile/ProfileLayout.jsxsrc/pages/Profile/ProfileOrders.jsxsrc/pages/Profile/Rewards.jsxsrc/pages/Profile/components/HealthForm.jsxsrc/pages/Profile/components/InfoGrid.jsxsrc/pages/Profile/components/OrderCard.jsxsrc/pages/Profile/components/OrderDetailsModal.jsxsrc/pages/Profile/components/OrderTracking.jsxsrc/pages/auth/Login.jsxsrc/pages/auth/Signup.jsxsrc/services/auth.service.jssrc/services/order.service.jssrc/services/user.service.jssrc/store/authStore.jssrc/store/orderStore.jssrc/store/profileStore.jssrc/store/toastStore.jssrc/tests/stores/stores.test.jssrc/utils/authValidation.jssrc/utils/orderHelpers.js
| <Route path="thanks" element={<Thanks />} /> | ||
|
|
||
| <Route path="profile" element={<ProtectedRoute><ProfileLayout /></ProtectedRoute>}> | ||
| <Route path="profile" element={<ProfileLayout />}> |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Auth gate removed from /profile route.
The /profile route no longer wraps ProfileLayout in ProtectedRoute, unlike other protected routes (customize, favorites) and unlike the comment above stating "All other routes are PROTECTED via ProtectedRoute." Unauthenticated users can now reach /profile, /profile/orders, /profile/rewards without being redirected to login — ProfileLayout's authUser?.id guard only skips the profile fetch, it doesn't redirect.
🔒 Proposed fix
- <Route path="profile" element={<ProfileLayout />}>
+ <Route path="profile" element={<ProtectedRoute><ProfileLayout /></ProtectedRoute>}>
<Route index element={<Profile />} />
<Route path="orders" element={<ProfileOrders />} />
<Route path="rewards" element={<Rewards />} />
</Route>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <Route path="profile" element={<ProfileLayout />}> | |
| <Route path="profile" element={<ProtectedRoute><ProfileLayout /></ProtectedRoute>}> |
🤖 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 `@src/App.jsx` at line 68, The /profile route is missing the auth guard, so
unauthenticated users can reach ProfileLayout and its nested pages. Update the
Route definition in App.jsx to wrap ProfileLayout with ProtectedRoute, matching
the protected customize and favorites routes and the surrounding routing
pattern. Keep the protection at the route level so /profile, /profile/orders,
and /profile/rewards all redirect to login when the user is not authenticated.
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 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 `@src/mocks/handlers.js`:
- Around line 34-38: The destructuring in handlers.js that omits profile fields
into authUser is triggering no-unused-vars because the stripped sibling
variables are treated as unused. Fix this by updating the ESLint no-unused-vars
rule to enable ignoreRestSiblings, or refactor the handler to remove those
fields without binding them as unused locals. Make sure the change keeps the
auth response shape in the mocked handler while allowing the lint step to pass.
- Around line 264-269: The profile update handler in handler: (config) and the
user lookup with mockUsers.find(...) can return undefined, which makes
Object.assign(user, body) throw on unknown ids. Mirror the sibling GET handler’s
missing-user behavior by checking the result before applying the update and
returning the same not-found response shape when no user matches. Keep the fix
localized to the update path using extractId, mockUsers.find, and
toClientProfileDto.
- Around line 278-284: The profile picture handler is extracting the wrong
segment from the request URL, so it gets "picture" instead of the client ID and
never updates mockUsers. Update the logic in handlers.js to parse the
penultimate path segment from config.url for the PATCH/DELETE profile picture
routes, and use that ID consistently in the handler that currently calls
extractId(config.url) and updates mockUsers.
In `@src/pages/Profile/components/Sidebar.jsx`:
- Around line 55-83: The profile picture preview flow in Sidebar.jsx leaks blob
URLs because handlePictureUpload uses URL.createObjectURL(file) but only clears
localPreview afterward; update the upload/delete handling to revoke the created
object URL before resetting state, and ensure any preview URL is also cleaned up
on unmount. Use the handlePictureUpload and handleDeletePicture logic, along
with the localPreview state, to locate and fix the leak.
🪄 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: CHILL
Plan: Pro Plus
Run ID: cbf1affe-88d5-4a63-98ed-2d5620a8a262
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json,!package-lock.json
📒 Files selected for processing (23)
.envsrc/components/OrderFlow/OrderConfirmationDetails.jsxsrc/components/OrderFlow/Payment/StripeCardElement.jsxsrc/components/OrderFlow/PaymentForm.jsxsrc/components/auth/StepTwo.jsxsrc/components/ui/AllergiesDropdown.jsxsrc/components/ui/PopularMenuCard.jsxsrc/mocks/handlers.jssrc/mocks/orders.jssrc/mocks/users.jssrc/pages/Profile/Profile.jsxsrc/pages/Profile/ProfileLayout.jsxsrc/pages/Profile/components/HealthForm.jsxsrc/pages/Profile/components/OrderCard.jsxsrc/pages/Profile/components/OrderDetailsModal.jsxsrc/pages/Profile/components/Sidebar.jsxsrc/pages/auth/Signup.jsxsrc/services/auth.service.jssrc/store/authStore.jssrc/store/index.jssrc/store/orderStore.jssrc/store/profileStore.jssrc/utils/authValidation.js
💤 Files with no reviewable changes (1)
- src/components/OrderFlow/OrderConfirmationDetails.jsx
✅ Files skipped from review due to trivial changes (2)
- src/store/index.js
- .env
🚧 Files skipped from review as they are similar to previous changes (9)
- src/utils/authValidation.js
- src/components/OrderFlow/Payment/StripeCardElement.jsx
- src/pages/Profile/components/OrderDetailsModal.jsx
- src/pages/auth/Signup.jsx
- src/pages/Profile/components/OrderCard.jsx
- src/pages/Profile/components/HealthForm.jsx
- src/pages/Profile/Profile.jsx
- src/store/profileStore.js
- src/store/orderStore.js
c1214b8 to
357eb2a
Compare
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Payment Flow: - Add pollOrderStatus to order service for AWAITING_PAYMENT polling - Update orderStore submitOrder to handle Stripe payment flow - Add confirmStripePayment action for Stripe confirmation and status polling - Update PaymentForm to use Stripe clientSecret and card element - Add confirm button to StripeCardElement for explicit card validation - Handle multiple success statuses (PAID, CONFIRMED, PREPARING, READY) - Handle error statuses (CANCELED, CANCELLATION_PENDING) with user feedback - Add stripeClientSecret, stripePaymentIntentId, pendingOrderId to orderStore state - Update mock handlers to use AWAITING_PAYMENT and simulate webhook responses Pricing: - Set DELIVERY_FEE to 0.00 (no delivery feature currently) Health Conditions: - Fix Signup.jsx to send [NONE] when healthConditions array is empty - Ensure consistency with HealthForm.jsx health conditions logic Order History : - Fix date grouping in ProfileOrders with Today/Yesterday/full date labels - Add fallback for undefined order dates - Fix error/empty state overlap in order history display - Add /images/bowl.png fallback for missing item images across components
d6c6177 to
b387a12
Compare
|
@coderabbitai full review |
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 20
♻️ Duplicate comments (1)
src/utils/authValidation.js (1)
17-17: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winUnnecessary regex escapes
\(and\)still present on line 17.The past review flagged these and the fix was marked as addressed, but the current code still contains the unnecessary escapes. Inside a character class,
(and)don't need escaping.🤖 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 `@src/utils/authValidation.js` at line 17, Remove the unnecessary backslashes before the parentheses in the regular expression used by the phone-number sanitization logic in `sanitized`, leaving the character class to match whitespace, hyphens, and parentheses without escaping `(` or `)`.Source: Linters/SAST tools
🧹 Nitpick comments (6)
src/pages/auth/ResetPassword.jsx (1)
30-33: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winConsider using
validatePasswordfor consistency with the auth validation pattern.The Login page was updated to use
validateEmailfromauthValidation.js, butResetPasswordonly checkspassword.length < 8. If the password policy requires uppercase, lowercase, number, and special character (as defined invalidatePassword), the reset form should enforce the same rules to prevent users from setting passwords that would fail at login.♻️ Proposed refactor
+import { validatePassword } from "../../utils/authValidation"; + // ... inside handleSubmit: - if (password.length < 8) { - toast.error("Password must be at least 8 characters long"); + if (!validatePassword(password)) { + toast.error("Password must be at least 8 characters with uppercase, lowercase, number, and special character"); return; }🤖 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 `@src/pages/auth/ResetPassword.jsx` around lines 30 - 33, Replace the manual password-length check in the ResetPassword submit handler with the shared validatePassword helper from authValidation.js, handling its validation result and displaying the returned error through toast before returning; preserve the existing reset flow for valid passwords.tests/e2e/order-payment-flow.spec.js (1)
14-14: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse Playwright's
baseURLconfig instead of hardcodedlocalhost:5173.Hardcoding
http://localhost:5173/reduces portability across environments. Playwright supports abaseURLin its config thatpage.goto()andpage.waitForURL()can use with relative paths.♻️ Proposed refactor
- await page.waitForURL('http://localhost:5173/', { timeout: 15000 }); + await page.waitForURL('/', { timeout: 15000 });- await page.goto('http://localhost:5173/'); + await page.goto('/');🤖 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 `@tests/e2e/order-payment-flow.spec.js` at line 14, Replace the hardcoded URL in the order flow test’s page.waitForURL call with the relative root path, relying on Playwright’s configured baseURL. Update the relevant waitForURL usage in order-payment-flow.spec.js without changing the timeout.src/pages/Profile/components/Sidebar.jsx (1)
12-18: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winUse
useShallowselectors to prevent unnecessary re-renders.Both
useAuthStore()anduseProfileStore()are called without selectors, causingSidebarto re-render on every state change (includingloading,error,hasHydrated).ProfileLayoutalready follows theuseShallowpattern — apply it here for consistency and performance.♻️ Proposed refactor
- const { user: authUser } = useAuthStore(); + const authUser = useAuthStore((state) => state.user); const { user: profileUser, uploadPicture, deletePicture, } = useProfileStore( + useShallow((state) => ({ + user: state.user, + uploadPicture: state.uploadPicture, + deletePicture: state.deletePicture, + })) );Add the import at the top:
+ import { useShallow } from "zustand/shallow";🤖 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 `@src/pages/Profile/components/Sidebar.jsx` around lines 12 - 18, Update Sidebar’s useAuthStore and useProfileStore calls to use selectors wrapped with useShallow, selecting only authUser and the required profile actions/data (profileUser, uploadPicture, deletePicture, fetchProfile). Add the matching useShallow import and follow ProfileLayout’s existing selector pattern to avoid re-renders from unrelated store state changes.src/components/OrderFlow/Payment/StripeCardElement.jsx (2)
75-82: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueReuse the render-scope
allCompleteinhandleConfirmCard.
handleConfirmCardrecomputesallCompletefromcompletestate, duplicating the computation already done at line 98. Reference the outer variable instead.♻️ Proposed refactor
const handleConfirmCard = () => { - const allComplete = CARD_FIELD_KEYS.every((k) => complete[k]); const firstError = CARD_FIELD_KEYS.map((k) => fieldErrors[k]).find(Boolean) || null; if (allComplete && !firstError) { onCardComplete(); } };🤖 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 `@src/components/OrderFlow/Payment/StripeCardElement.jsx` around lines 75 - 82, Reuse the existing render-scope allComplete value in handleConfirmCard instead of recomputing it from complete via CARD_FIELD_KEYS.every; remove the duplicate local calculation while preserving the firstError check and onCardComplete behavior.
57-73: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winUse functional state updates to avoid stale closure.
handleChangecomputesnextComplete/nextErrorsfrom closure-capturedcomplete/fieldErrors. If the same Stripe element fires multipleonChangeevents before a re-render, intermediate state is lost. Use the functional update form.♻️ Proposed refactor
const handleChange = (key) => (event) => { - const nextComplete = { ...complete, [key]: event.complete }; - const nextErrors = { ...fieldErrors, [key]: event.error ? event.error.message : null }; - - setComplete(nextComplete); - setFieldErrors(nextErrors); + setComplete((prev) => ({ ...prev, [key]: event.complete })); + setFieldErrors((prev) => ({ ...prev, [key]: event.error ? event.error.message : null })); if (key === "cardNumber" && event.brand) setBrand(event.brand); - const firstError = CARD_FIELD_KEYS.map((k) => nextErrors[k]).find(Boolean) || null; + const latestErrors = CARD_FIELD_KEYS.map((k) => + k === key ? (event.error ? event.error.message : null) : fieldErrors[k] + ); + const firstError = latestErrors.find(Boolean) || null; onError(firstError); // Notify parent when card number element is ready if (key === "cardNumber" && cardNumberRef.current && onElementReady) { onElementReady(cardNumberRef.current); } };🤖 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 `@src/components/OrderFlow/Payment/StripeCardElement.jsx` around lines 57 - 73, Update handleChange to use functional setComplete and setFieldErrors callbacks, deriving each next state from the previous state rather than closure-captured complete and fieldErrors. Compute firstError from the updated errors within the functional fieldErrors update and invoke onError accordingly, while preserving the brand and element-ready behavior.Source: Linters/SAST tools
src/components/OrderFlow/Payment/PaymentMethodSelector.jsx (1)
8-59: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAdd
aria-pressedto communicate selection state.Both option buttons indicate selection visually (background + check icon) but lack
aria-pressed, so screen readers can't determine which method is active.♿ Proposed accessibility fix
<button type="button" + aria-pressed={paymentMethod === "CASH"} onClick={() => setPaymentMethod("CASH")} className={`w-full text-left flex items-center gap-4 p-5 transition-all border-b border-gray-100 cursor-pointer ${<button type="button" + aria-pressed={paymentMethod === "CREDIT_CARD"} onClick={() => setPaymentMethod("CREDIT_CARD")} className={`w-full text-left flex items-center gap-4 p-5 transition-all cursor-pointer ${🤖 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 `@src/components/OrderFlow/Payment/PaymentMethodSelector.jsx` around lines 8 - 59, Add aria-pressed to both payment option buttons in PaymentMethodSelector: set it to paymentMethod === "CASH" for the cash button and paymentMethod === "CREDIT_CARD" for the credit-card button, preserving their existing selection behavior.
🤖 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 `@ORDER_PAYMENT_VALIDATION_REPORT.md`:
- Around line 179-180: Correct ORDER_PAYMENT_VALIDATION_REPORT.md by changing
the reported test suite total from 6 to 7, and update the invalid TC-ERROR-004
reference near the Error Handling results to an existing test case identifier
from TC-ERROR-001 through TC-ERROR-003.
In `@src/components/OrderFlow/PaymentForm.jsx`:
- Around line 60-76: Wrap the await of submitOrder() in handleSubmit with a
try-catch so thrown network or parsing errors are handled instead of becoming
unhandled rejections. Preserve the existing null-response handling, and in the
catch block setStripeError using the caught error message with an appropriate
fallback, matching the pattern used by handleCardComplete.
- Around line 36-53: Update handleCardComplete to set a clear Stripe error when
confirmStripePayment resolves false, while preserving the success navigation
path. Ensure errors from both the false result and catch block are passed to the
StripeCardElement’s modal-visible error state or onError handling, rather than
only the form-level display behind the modal; update the related modal rendering
and error state wiring accordingly.
In `@src/components/ui/RegularFoodCard.jsx`:
- Around line 147-155: Replace the hardcoded dollar suffix in RegularFoodCard’s
price rendering with the shared currency formatter, applying it to both the
discounted price and displayPrice values so the configured EGP POST format is
respected.
In `@src/main.jsx`:
- Around line 7-21: Guard the module-scope Stripe initialization by reading
VITE_STRIPE_PUBLISHABLE_KEY and passing null to loadStripe when it is missing,
so the Elements wrapper can still mount without a configured key. Update the
stripePromise initialization near the render setup; do not pass an undefined
value directly.
In `@src/mocks/handlers.js`:
- Around line 1-4: Remove the unused `dash` namespace import from
`src/mocks/handlers.js`, leaving the other mock imports unchanged.
- Around line 191-221: The order mock handler’s credit-card contract is
inconsistent with the frontend: update the payment method check in the POST
/api/order handler to recognize “CREDIT_CARD” and return status “PENDING” while
preserving the Stripe client secret and payment intent fields, so PaymentForm
can open the card modal.
In `@src/mocks/orders.js`:
- Line 91: Replace the unsafe numeric clientId literals in the mock order data
with exact representations, such as BigInt literals or strings consistent with
the clientId type, for both affected entries. Update any related comparisons or
schemas if needed, and ensure the values remain distinct and ESLint’s
no-loss-of-precision rule passes.
In `@src/pages/OrderFlow/Checkout.jsx`:
- Around line 40-46: Remove the unused handleCheckout function from the checkout
component, including its explanatory comments, since OrderSummary already
navigates through buttonLink="/payment". Also remove any now-unused imports or
references associated with handleCheckout.
In `@src/pages/OrderFlow/Thanks.jsx`:
- Line 28: Remove the unused status property from the destructuring assignment
in the Thanks component, leaving only the lastOrder fields that are referenced.
In `@src/pages/Profile/components/OrderCard.jsx`:
- Around line 147-157: Update the image alt text in the OrderCard component to
use the same fallback as the displayed item name: prefer item.name, then
item.snapshotName, and finally "meal".
In `@src/pages/Profile/components/Sidebar.jsx`:
- Around line 22-26: Remove the redundant profile-fetching useEffect that
depends on profileUser, and remove fetchProfile from the destructured values in
Sidebar. ProfileLayout already performs the guarded fetch, so Sidebar should no
longer call fetchProfile or retain related dependencies.
In `@src/pages/Profile/Rewards.jsx`:
- Line 59: The rewards description currently displays USD while the application
currency configuration and formatCurrency use EGP. Update the copy near the “5
USD” text in the Rewards component to say “5 EGP”; only change the global
currency configuration if USD is intentionally the application-wide currency.
In `@src/services/user.service.js`:
- Around line 26-32: Remove the explicit multipart Content-Type override from
uploadProfilePicture; omit the headers option or set Content-Type to undefined
so Axios/the browser can generate the FormData boundary instead of inheriting
the shared JSON header.
In `@src/store/orderStore.js`:
- Line 383: Update the order notification message in the relevant order-handling
function to use customerDetails?.firstName instead of customerDetails?.name,
preserving the existing "Customer" fallback.
- Around line 294-305: Fix submitOrder by removing the inner try-catch around
placeOrder and declaring response in the surrounding scope, or otherwise keeping
it accessible after the call; let the existing outer catch handle placement
errors, then use response.data for orderData only after a successful placeOrder
call.
In `@src/store/profileStore.js`:
- Around line 45-48: Remove the temporary loyalty-points override and its
associated test comments from the profile-fetch logic in profileStore, ensuring
user.loyaltyPoints remains the value returned by the backend.
In `@src/utils/authValidation.js`:
- Around line 8-10: Restore the `[` character to the special-character class in
`passwordRegex` within the password validation function, ensuring it is escaped
or positioned safely so the regex remains valid and accepts passwords containing
`[`.
In `@src/utils/orderHelpers.js`:
- Around line 44-58: Update mergeOrdersWithLastOrder’s sort comparator to handle
orders with missing or invalid createdAt values without producing NaN; validate
each parsed timestamp and apply a deterministic fallback ordering for invalid
dates while preserving newest-first sorting for valid timestamps.
In `@tests/e2e/order-payment-flow.spec.js`:
- Around line 160-170: Replace every conditional success pattern in the affected
test cases—TC-CASH-002, TC-STRIPE-001, TC-HISTORY-001, TC-TRACKING-002, and
TC-CANCEL-001—with explicit handling when expected requests, responses, or
orders are absent. Use test.skip() only when backend unavailability is an
intentional environment condition; otherwise call expect.fail() in each fallback
branch, including the related blocks around lines 540-551 and 664-686, so these
tests cannot pass silently.
---
Duplicate comments:
In `@src/utils/authValidation.js`:
- Line 17: Remove the unnecessary backslashes before the parentheses in the
regular expression used by the phone-number sanitization logic in `sanitized`,
leaving the character class to match whitespace, hyphens, and parentheses
without escaping `(` or `)`.
---
Nitpick comments:
In `@src/components/OrderFlow/Payment/PaymentMethodSelector.jsx`:
- Around line 8-59: Add aria-pressed to both payment option buttons in
PaymentMethodSelector: set it to paymentMethod === "CASH" for the cash button
and paymentMethod === "CREDIT_CARD" for the credit-card button, preserving their
existing selection behavior.
In `@src/components/OrderFlow/Payment/StripeCardElement.jsx`:
- Around line 75-82: Reuse the existing render-scope allComplete value in
handleConfirmCard instead of recomputing it from complete via
CARD_FIELD_KEYS.every; remove the duplicate local calculation while preserving
the firstError check and onCardComplete behavior.
- Around line 57-73: Update handleChange to use functional setComplete and
setFieldErrors callbacks, deriving each next state from the previous state
rather than closure-captured complete and fieldErrors. Compute firstError from
the updated errors within the functional fieldErrors update and invoke onError
accordingly, while preserving the brand and element-ready behavior.
In `@src/pages/auth/ResetPassword.jsx`:
- Around line 30-33: Replace the manual password-length check in the
ResetPassword submit handler with the shared validatePassword helper from
authValidation.js, handling its validation result and displaying the returned
error through toast before returning; preserve the existing reset flow for valid
passwords.
In `@src/pages/Profile/components/Sidebar.jsx`:
- Around line 12-18: Update Sidebar’s useAuthStore and useProfileStore calls to
use selectors wrapped with useShallow, selecting only authUser and the required
profile actions/data (profileUser, uploadPicture, deletePicture, fetchProfile).
Add the matching useShallow import and follow ProfileLayout’s existing selector
pattern to avoid re-renders from unrelated store state changes.
In `@tests/e2e/order-payment-flow.spec.js`:
- Line 14: Replace the hardcoded URL in the order flow test’s page.waitForURL
call with the relative root path, relying on Playwright’s configured baseURL.
Update the relevant waitForURL usage in order-payment-flow.spec.js without
changing the timeout.
🪄 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: CHILL
Plan: Pro Plus
Run ID: d5fe860d-4f33-4579-9541-3a3288a53a4b
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json,!package-lock.json
📒 Files selected for processing (60)
.envORDER_PAYMENT_TESTING_GUIDE.mdORDER_PAYMENT_VALIDATION_REPORT.mdeslint.config.jspackage.jsonsrc/App.jsxsrc/components/OrderFlow/AddCard/CardInputs.jsxsrc/components/OrderFlow/AddCard/CardPreview.jsxsrc/components/OrderFlow/CartItem.jsxsrc/components/OrderFlow/OrderConfirmationDetails.jsxsrc/components/OrderFlow/OrderSummary.jsxsrc/components/OrderFlow/Payment/PaymentMethodSelector.jsxsrc/components/OrderFlow/Payment/StripeCardElement.jsxsrc/components/OrderFlow/PaymentForm.jsxsrc/components/OrderFlow/VoucherSelection.jsxsrc/components/auth/StepOne.jsxsrc/components/auth/StepThree.jsxsrc/components/auth/StepTwo.jsxsrc/components/ui/AllergiesDropdown.jsxsrc/components/ui/PopularMenuCard.jsxsrc/components/ui/RegularFoodCard.jsxsrc/constants.jssrc/main.jsxsrc/mocks/handlers.jssrc/mocks/orders.jssrc/mocks/users.jssrc/pages/OrderFlow/Cart.jsxsrc/pages/OrderFlow/Checkout.jsxsrc/pages/OrderFlow/Payment.jsxsrc/pages/OrderFlow/Thanks.jsxsrc/pages/Profile/Profile.jsxsrc/pages/Profile/ProfileLayout.jsxsrc/pages/Profile/ProfileOrders.jsxsrc/pages/Profile/Rewards.jsxsrc/pages/Profile/components/HealthForm.jsxsrc/pages/Profile/components/InfoGrid.jsxsrc/pages/Profile/components/OrderCard.jsxsrc/pages/Profile/components/OrderDetailsModal.jsxsrc/pages/Profile/components/OrderTracking.jsxsrc/pages/Profile/components/Sidebar.jsxsrc/pages/StoreDebug.jsxsrc/pages/auth/ForgotPassword.jsxsrc/pages/auth/Login.jsxsrc/pages/auth/ResetPassword.jsxsrc/pages/auth/Signup.jsxsrc/pages/index.jssrc/services/auth.service.jssrc/services/order.service.jssrc/services/user.service.jssrc/store/authStore.jssrc/store/index.jssrc/store/orderStore.jssrc/store/paymentStore.jssrc/store/profileStore.jssrc/store/toastStore.jssrc/tests/App.test.jsxsrc/tests/stores/stores.test.jssrc/utils/authValidation.jssrc/utils/orderHelpers.jstests/e2e/order-payment-flow.spec.js
💤 Files with no reviewable changes (2)
- src/pages/StoreDebug.jsx
- src/tests/App.test.jsx
| // Triggered when user enters valid card data and hits "Pay" inside the StripeCardElement | ||
| const handleCardComplete = async () => { | ||
| if (!stripe || !cardElement || !currentClientSecret) { | ||
| setStripeError("Payment credentials or card elements are missing."); | ||
| return; | ||
| } | ||
|
|
||
| try { | ||
| // Pass the extracted stripeClientSecret directly to Stripe's SDK action | ||
| const success = await confirmStripePayment(stripe, cardElement, currentClientSecret); | ||
| if (success) { | ||
| setIsAddCardOpen(false); | ||
| navigate("/thanks"); | ||
| } | ||
| } catch (err) { | ||
| setStripeError(err.message || "Card validation failed. Please try again."); | ||
| } | ||
| }; |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Add feedback when confirmStripePayment returns false.
If confirmStripePayment resolves to false without throwing, the modal stays open with no error message — the user gets no indication that confirmation failed. Add an else branch to show an error.
Additionally, setStripeError is called in the catch block, but the error display (line 111-115) is in the form behind the modal, so the user won't see it while the modal is open. Consider propagating errors into the StripeCardElement (e.g., via a shared error state or the onError callback) so they render inside the modal.
🛡️ Proposed fix for missing feedback
try {
const success = await confirmStripePayment(stripe, cardElement, currentClientSecret);
if (success) {
setIsAddCardOpen(false);
navigate("/thanks");
+ } else {
+ setStripeError("Payment confirmation failed. Please try again.");
}
} catch (err) {
setStripeError(err.message || "Card validation failed. Please try again.");
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Triggered when user enters valid card data and hits "Pay" inside the StripeCardElement | |
| const handleCardComplete = async () => { | |
| if (!stripe || !cardElement || !currentClientSecret) { | |
| setStripeError("Payment credentials or card elements are missing."); | |
| return; | |
| } | |
| try { | |
| // Pass the extracted stripeClientSecret directly to Stripe's SDK action | |
| const success = await confirmStripePayment(stripe, cardElement, currentClientSecret); | |
| if (success) { | |
| setIsAddCardOpen(false); | |
| navigate("/thanks"); | |
| } | |
| } catch (err) { | |
| setStripeError(err.message || "Card validation failed. Please try again."); | |
| } | |
| }; | |
| // Triggered when user enters valid card data and hits "Pay" inside the StripeCardElement | |
| const handleCardComplete = async () => { | |
| if (!stripe || !cardElement || !currentClientSecret) { | |
| setStripeError("Payment credentials or card elements are missing."); | |
| return; | |
| } | |
| try { | |
| // Pass the extracted stripeClientSecret directly to Stripe's SDK action | |
| const success = await confirmStripePayment(stripe, cardElement, currentClientSecret); | |
| if (success) { | |
| setIsAddCardOpen(false); | |
| navigate("/thanks"); | |
| } else { | |
| setStripeError("Payment confirmation failed. Please try again."); | |
| } | |
| } catch (err) { | |
| setStripeError(err.message || "Card validation failed. Please try again."); | |
| } | |
| }; |
🤖 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 `@src/components/OrderFlow/PaymentForm.jsx` around lines 36 - 53, Update
handleCardComplete to set a clear Stripe error when confirmStripePayment
resolves false, while preserving the success navigation path. Ensure errors from
both the false result and catch block are passed to the StripeCardElement’s
modal-visible error state or onError handling, rather than only the form-level
display behind the modal; update the related modal rendering and error state
wiring accordingly.
|
@coderabbitai full review |
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 `@src/pages/OrderFlow/Cart.jsx`:
- Around line 19-23: Use useProfileStore’s hasHydrated state in the Cart
component before deciding checkoutButtonLink; while the profile is not hydrated,
avoid treating loyalty points as 0 by deferring navigation or using a
loading-safe link, and only route eligible users to /checkout after hydration
confirms their points.
In `@tests/e2e/order-payment-flow.spec.js`:
- Line 169: Replace every unsupported expect.fail() call in the test, including
the branches near the API request checks and the other referenced locations,
with throw new Error(...) using the existing failure messages, or an equivalent
supported Playwright assertion.
🪄 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: CHILL
Plan: Pro Plus
Run ID: 7713036a-cda5-46fc-85dc-82d553268e31
📒 Files selected for processing (13)
ORDER_PAYMENT_VALIDATION_REPORT.mdplaywright-report/index.htmlsrc/components/OrderFlow/Payment/PaymentMethodSelector.jsxsrc/components/OrderFlow/PaymentForm.jsxsrc/components/ui/RegularFoodCard.jsxsrc/main.jsxsrc/pages/OrderFlow/Cart.jsxsrc/pages/OrderFlow/Checkout.jsxsrc/store/orderStore.jssrc/store/profileStore.jssrc/utils/authValidation.jssrc/utils/orderHelpers.jstests/e2e/order-payment-flow.spec.js
💤 Files with no reviewable changes (1)
- src/store/profileStore.js
✅ Files skipped from review due to trivial changes (2)
- playwright-report/index.html
- ORDER_PAYMENT_VALIDATION_REPORT.md
🚧 Files skipped from review as they are similar to previous changes (6)
- src/components/ui/RegularFoodCard.jsx
- src/main.jsx
- src/utils/orderHelpers.js
- src/components/OrderFlow/Payment/PaymentMethodSelector.jsx
- src/components/OrderFlow/PaymentForm.jsx
- src/pages/OrderFlow/Checkout.jsx
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/pages/OrderFlow/Cart.jsx (1)
40-69: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low valueMinor edge case:
VoucherSelectioncan render null inside the selector view.
VoucherSelectionindependently guards onpoints < 100and returnsnull. If profile data changes while the selector is open (e.g., points drop below 100 due to a concurrent action), the user sees an empty container with only the "Back to Cart" button. This is unlikely but worth noting. A fallback message or keeping the selector closed when eligibility changes would improve robustness.🤖 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 `@src/pages/OrderFlow/Cart.jsx` around lines 40 - 69, Handle the eligibility edge case in the showVoucherSelector branch of OrderFlow: prevent an empty selector container when VoucherSelection returns null because points fall below 100. Add a fallback message or automatically close the selector when eligibility changes, using the existing showVoucherSelector state and eligibility data while preserving the Back to Cart action.
🤖 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.
Nitpick comments:
In `@src/pages/OrderFlow/Cart.jsx`:
- Around line 40-69: Handle the eligibility edge case in the showVoucherSelector
branch of OrderFlow: prevent an empty selector container when VoucherSelection
returns null because points fall below 100. Add a fallback message or
automatically close the selector when eligibility changes, using the existing
showVoucherSelector state and eligibility data while preserving the Back to Cart
action.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: c2c9ee48-056b-4aa5-ba50-97beb3858ee3
📒 Files selected for processing (6)
playwright-report/index.htmlsrc/App.jsxsrc/components/OrderFlow/CartSection.jsxsrc/pages/OrderFlow/Cart.jsxsrc/pages/index.jstests/e2e/order-payment-flow.spec.js
💤 Files with no reviewable changes (1)
- src/pages/index.js
🚧 Files skipped from review as they are similar to previous changes (2)
- playwright-report/index.html
- tests/e2e/order-payment-flow.spec.js
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
src/store/orderStore.js (1)
305-316: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win
responseis block-scoped inside the innertry—response.dataon line 316 throwsReferenceErrorevery time.
const responseis declared inside the innertryblock (line 306). Due toconstblock scoping, it is inaccessible on line 316. WhetherplaceOrdersucceeds or fails, line 316 always throwsReferenceError: response is not defined, caught by the outercatchon line 400. This meanssubmitOrderalways returnsnulland no order can ever be placed. This was previously flagged but remains unfixed.🐛 Proposed fix: remove the inner try-catch and let the outer catch handle errors
- try { - const response = await placeOrder(orderPayload); - console.log("[orderStore] placeOrder response received:", response); - } catch (error) { - console.log( - "[orderStore] placeOrder error received:", - error?.response?.data?.message, - ); - } - - // Extract properties from the structured response schema - const orderData = response.data; // Includes: { id, status, stripeClientSecret, ... } + const response = await placeOrder(orderPayload); + const orderData = response.data; // Includes: { id, status, stripeClientSecret, ... }🤖 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 `@src/store/orderStore.js` around lines 305 - 316, Fix submitOrder by removing the inner try-catch around placeOrder and declaring response in the surrounding scope so it remains available for response.data extraction. Let the existing outer catch handle placement errors, preserving the successful order-processing flow.
🧹 Nitpick comments (1)
src/store/orderStore.js (1)
1-1: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDuplicated
newOrderconstruction acrosssubmitOrderandconfirmStripePayment. Both functions build the same ~23-linenewOrderobject from a polledfinalOrderand capturedstate. Diverging fixes applied to one copy but not the other would cause subtle bugs in the order flow.
src/store/orderStore.js#L342-364: Extract thenewOrderconstruction into a shared helper (e.g.,buildOrderFromPoll(finalOrder, state, totalWithDelivery)) and call it here.src/store/orderStore.js#L446-468: Replace this duplicated block with a call to the same helper.♻️ Proposed refactor
+// Add near the other helpers (e.g., after calculateTotals) +function buildOrderFromPoll(finalOrder, state, totalWithDelivery) { + return { + id: finalOrder.id, + clientId: finalOrder.clientId, + createdAt: finalOrder.createdAt || new Date().toISOString(), + status: finalOrder.status, + totalPrice: finalOrder.totalPrice || totalWithDelivery, + discount: finalOrder.discount || 0, + items: + finalOrder.items || + state.items.map((item) => ({ + id: item.id, + mealId: item.id, + quantity: item.quantity, + snapshotName: item.name, + snapshotPrice: item.price, + imageUrl: item.image, + })), + customerDetails: state.customerDetails, + paymentMethod: state.paymentMethod, + note: state.note, + stripeClientSecret: finalOrder.stripeClientSecret || "", + stripePaymentIntentId: finalOrder.stripePaymentIntentId || "", + }; +}Then in both
submitOrderandconfirmStripePayment:- const newOrder = { - id: finalOrder.id, - clientId: finalOrder.clientId, - ... - stripePaymentIntentId: finalOrder.stripePaymentIntentId || "", - }; + const newOrder = buildOrderFromPoll(finalOrder, state, totalWithDelivery);🤖 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 `@src/store/orderStore.js` at line 1, Extract the duplicated newOrder construction from submitOrder and confirmStripePayment into a shared helper such as buildOrderFromPoll(finalOrder, state, totalWithDelivery). Preserve all existing field mappings and calculations, then replace both inline object blocks with calls to this helper using their respective finalOrder, state, and totalWithDelivery values.
🤖 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 @.env.example:
- Line 5: Update the environment template defaults to use VITE_ENV=local and
VITE_USE_MOCK=true, ensuring copied configuration cannot target the production
API or make real requests by default.
In `@src/store/orderStore.js`:
- Line 1: Update submitOrder and confirmStripePayment so both checkout paths
invalidate the same query keys: add ["kitchen"] invalidation to submitOrder
alongside orders and ingredients, and add ["ingredients"] invalidation to
confirmStripePayment alongside kitchen and orders.
---
Duplicate comments:
In `@src/store/orderStore.js`:
- Around line 305-316: Fix submitOrder by removing the inner try-catch around
placeOrder and declaring response in the surrounding scope so it remains
available for response.data extraction. Let the existing outer catch handle
placement errors, preserving the successful order-processing flow.
---
Nitpick comments:
In `@src/store/orderStore.js`:
- Line 1: Extract the duplicated newOrder construction from submitOrder and
confirmStripePayment into a shared helper such as buildOrderFromPoll(finalOrder,
state, totalWithDelivery). Preserve all existing field mappings and
calculations, then replace both inline object blocks with calls to this helper
using their respective finalOrder, state, and totalWithDelivery values.
🪄 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: CHILL
Plan: Pro Plus
Run ID: abb66b43-892b-4d95-bb56-245e4acbdf00
📒 Files selected for processing (36)
.env.exampleplaywright-report/index.htmlsrc/App.jsxsrc/Layout/DashboardLayout.jsxsrc/components/Dashboard/DashboardHeader.jsxsrc/components/Dashboard/DashboardSidebar.jsxsrc/components/Dashboard/NotificationsView.jsxsrc/components/Dashboard/shared/useToast.jsxsrc/components/OrderFlow/CartSection.jsxsrc/components/OrderFlow/PaymentForm.jsxsrc/hooks/dashboard/useDashboardRealtime.jssrc/hooks/dashboard/useIngredients.jssrc/hooks/dashboard/useKitchenOrders.jssrc/hooks/dashboard/useMenuItems.jssrc/hooks/dashboard/useMenuUploads.jssrc/hooks/dashboard/useOrders.jssrc/hooks/useAuthInit.jssrc/pages/Menu/Sections/MenuFilter.jsxsrc/pages/OrderFlow/Cart.jsxsrc/pages/customization/Customization.jsxsrc/pages/customization/Sections/BaseSelector.jsxsrc/pages/customization/Sections/CommentBox.jsxsrc/pages/customization/Sections/ExtrasSection.jsxsrc/pages/customization/Sections/IngredientsSection.jsxsrc/pages/customization/Sections/ItemsRow.jsxsrc/pages/customization/Sections/SaucesSection.jsxsrc/pages/customization/Sections/SummaryBox.jsxsrc/pages/index.jssrc/services/loyalty.service.jssrc/store/__tests__/useCustomizeStore.test.jssrc/store/authStore.jssrc/store/index.jssrc/store/orderStore.jssrc/store/recommendationStore.jssrc/tests/services/session.test.jstests/e2e/order-payment-flow.spec.js
💤 Files with no reviewable changes (1)
- src/pages/index.js
✅ Files skipped from review due to trivial changes (13)
- src/pages/customization/Customization.jsx
- src/pages/customization/Sections/IngredientsSection.jsx
- src/pages/customization/Sections/BaseSelector.jsx
- src/store/tests/useCustomizeStore.test.js
- src/pages/customization/Sections/ItemsRow.jsx
- src/pages/customization/Sections/ExtrasSection.jsx
- src/pages/customization/Sections/CommentBox.jsx
- src/pages/customization/Sections/SaucesSection.jsx
- src/services/loyalty.service.js
- src/pages/customization/Sections/SummaryBox.jsx
- src/hooks/dashboard/useMenuItems.js
- src/components/Dashboard/DashboardHeader.jsx
- playwright-report/index.html
🚧 Files skipped from review as they are similar to previous changes (6)
- src/App.jsx
- src/components/OrderFlow/CartSection.jsx
- src/store/authStore.js
- src/pages/OrderFlow/Cart.jsx
- src/components/OrderFlow/PaymentForm.jsx
- tests/e2e/order-payment-flow.spec.js
| # Copy this file to .env and fill in the actual values | ||
|
|
||
| # Set environment to local, dev, or prod | ||
| VITE_ENV=prod |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
Unsafe defaults in .env.example risk accidental production targeting.
VITE_ENV=prod combined with VITE_USE_MOCK=false means a developer who copies this file to .env without reading carefully will immediately make real requests against the production API. Default to VITE_ENV=local and VITE_USE_MOCK=true for safety.
🛡️ Proposed fix for safe defaults
# Set environment to local, dev, or prod
-VITE_ENV=prod
+VITE_ENV=local # Set to true to use mock data (no backend required)
# Set to false when the real backend is ready
-VITE_USE_MOCK=false
+VITE_USE_MOCK=trueAlso applies to: 14-14
🤖 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 @.env.example at line 5, Update the environment template defaults to use
VITE_ENV=local and VITE_USE_MOCK=true, ensuring copied configuration cannot
target the production API or make real requests by default.
- Add error code mapping for test cards (declined, insufficient funds, expired, CVC, 3D Secure) - Centralize error handling in orderStore
Client Order Flow, Payment & Profile Integration
What this PR does
Implements the complete client-side checkout flow — from cart review through
Stripe payment confirmation — and wires it up to the order-service and
payment-service backends.
Order Flow
"Checkout" click. The intermediate /checkout route was removed.
shown when the user has ≥100 loyalty points. Skipping it sends
points: 0.with the same cart contents. Now only blocks resubmission of a genuinely
successful prior order.
Payment Integration
stripeClientSecret→ confirm viaStripe Elements client-side → poll order status until CONFIRMED → show receipt
error.messagefrom Stripe rather than a generic fallbackCONFIRMEDstatus — all intermediate statuses(PENDING, PAID, PREPARING) are handled by the order tracking page
Profile Integration
Store fixes
useProfileStore: addedhasHydratedflag so components can distinguish"store not yet read from localStorage" from "confirmed no user" — prevents
race conditions on loyalty-points-gated UI
usePaymentStore:addTransactionnow upserts on duplicate order ID insteadof silently dropping — fixes stale "failed" status persisting after a
successful retry on the same order
useOrderStore:submitOrderpayload trimmed to match backend contract(
items,points,paymentMethodonly)Backend contract
Request:
{ items: [{mealId, quantity}], points: 0|100|200|300, paymentMethod: "CASH"|"CREDIT_CARD" }
Response includes
stripeClientSecretwhen paymentMethod is CREDIT_CARD.Currency: EGP throughout.