[FEATURE]: Menu Item Customization Feature - #1159
Open
PrishaJain64 wants to merge 3 commits into
Open
Conversation
✅ Deploy Preview for theelighthouse ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Contributor
Author
|
hi @anushkasark08 , please review the pull request and let me know if any changes are to be made |
Owner
|
@PrishaJain64resolve merge conflicts! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
📌 Summary
Toppings/add-ons selection — Each menu item can define a list of toppings. Customers pick one or more via checkboxes. If an item sets allowMultipleToppings: false, it switches to radio buttons so only one can be picked (e.g. "Sweet" vs "Salted" lime soda).
Variant selection — A separate list (e.g. size, portion, flavor) shown as radio buttons — only one variant can be active at a time. Variants can raise or lower the price (e.g. "Half" biryani is cheaper than "Full").
Per-option price display — Every topping and variant shows its exact price impact right next to its name (e.g. "Extra Cheese (+₹40)"), so the customer always knows the cost before selecting.
Dynamic live price calculation — The displayed total recalculates instantly on every click — no submit button needed to see the new price. It's just base price + sum of selected toppings + variant modifier, all multiplied by quantity.
Quantity selector with live total — Simple +/− stepper (minimum 1) that multiplies into the final price shown on the Add to Cart button itself.
"Sold Out" handling — If a dish's isAvailable flag is false, the Add to Cart button disables and its label changes to "Currently Sold Out" — prevents adding something the kitchen can't make.
Add to Cart button (always visible) — Originally it only appeared when an item had customizations; fixed so every item gets the button, whether or not it has toppings/variants to choose.
"Added ✓" confirmation — After clicking Add to Cart, the button briefly shows "Added ✓" and disables, then the modal auto-closes — gives the customer clear feedback the action worked before it disappears.
Session-based cart (Context API) — Cart state lives in React memory via CartContext, not the database. It resets on page refresh — a deliberate choice since your app doesn't have an order/checkout flow yet, just reservations.
Cart drawer — A slide-out panel (like a typical e-commerce cart) listing every item added: thumbnail, name, chosen variant, chosen toppings, and price.
Per-item quantity edit / remove — Inside the drawer, each line item has its own +/− stepper and an × to remove it entirely, independent from the other items.
Clear cart button — Wipes all items at once, useful for restarting an order.
Cart total calculation — Sums unitPrice × quantity across all cart entries, shown at the bottom of the drawer.
Cart icon with badge in navbar — A 🛒 icon sits in the nav bar (visible whether logged in or not) with a small red-gold badge showing the total item count, so customers see at a glance whether they have things in their cart.
Portal-rendered drawer — The drawer is injected directly into document.body via createPortal rather than rendered inside the navbar's DOM tree. This was a bug fix: the navbar's glassmorphism effect uses backdrop-filter, which silently creates a new CSS containing block , so a normal position: fixed drawer nested inside it gets visually trapped to the navbar's box instead of covering the full screen.
Backend schema support — Added a customizations field to the MenuItem Mongoose model holding toppings[], variants[], and the allowMultipleToppings flag, so this data is stored per-dish in MongoDB rather than hardcoded in the frontend.
🎯 Related Issue
Closes #1131
🛠️ Type of Change
📋 What Changed?
Backend
MenuItem.js: addedcustomizationsschema fieldtoppings[]—{ name, price }variants[]—{ name, priceModifier }(supports negative values, e.g. Half vs Full portion)allowMultipleToppings: Boolean— toggles checkbox vs radio behavior for toppingsseed.js: added samplecustomizationsdata to 5 items (Masala Dosa, Butter Chicken, Hyderabadi Biryani, Gulab Jamun, Fresh Lime Soda) covering multi-select, single-select, and positive/negative price modifiersFrontend — New
context/CartContext.jsx: session-only cart state (cartItems,addToCart,removeFromCart,updateQuantity,clearCart, derivedcartCount/cartTotal)components/CartDrawer.jsx: slide-in cart panel with item list, per-item quantity controls, remove, clear cart, and totalcreatePortal(..., document.body)to escape the navbar'sbackdrop-filterstacking context (fixes drawer clipping to header bounds instead of covering the viewport)Frontend — Modified
components/MenuCard.jsxunitPrice = basePrice + toppingsTotal + variantModifier,finalPrice = unitPrice * quantityhandleAddToCartpushes selected options intoCartContextcustomizationsexisted)item.isAvailableis falsecomponents/Navbar.jsxCartDraweropen/close stateApp.jsxCartProvideralongside existingAuthProvider/MenuProvider🧪 Testing
Traced the price calculation logic (
unitPrice = basePrice + toppingsTotal + variantModifier) manually against sample data to confirm it produces correct sums for both positive and negative modifiersReviewed
MenuCard.jsxstate resets on modal reopen to confirm stale topping/variant selections wouldn't leak between different dishesReviewed the
hasCustomizationsconditional to confirm the Add to Cart button and panel now render for all items after the fixTested locally
Tested on Chrome
Tested responsive layouts
Verified no console errors
Existing functionality still works
📸 Screenshots
♿ Accessibility
If applicable:
✅ Checklist
CONTRIBUTING.md.