updated AppContext for size and topping, created popup for selecting item sizes and toppings

This commit is contained in:
Juthatip McDevitt 2024-05-23 01:43:15 -05:00
parent 3d11d8e696
commit d9ee93365f
7 changed files with 55 additions and 20 deletions

View file

@ -23,7 +23,11 @@ const MenuItemSchema = new Schema({
},
sizes:{
type: [ExtraPriceSchema]
}
},
extraItems:{
type: [ExtraPriceSchema]
},
}, {timestamps: true})
export const MenuItem = models?.MenuItem || model('MenuItem', MenuItemSchema)

View file

@ -19,11 +19,11 @@ const MenuPage = () => {
return (
<div className='w-full h-full pb-20 md:pb-40'>
<div className='pb-20 md:pb-40'>
{categories?.length > 0 && categories.map(c => (
<div className='px-5 lg:px-10 py-5 sm:py-10'>
<p className='text-center text-3xl md:text-4xl text-pink-500 uppercase font-bold drop-shadow-[0_2px_2px_rgba(105,105,105,1)]'>{c.name}</p>
<div className='grid grid-cols-1 min-[480px]:grid-cols-2 md:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-5 mt-10'>
<div className='px-10 min-[380px]:px-5 lg:px-10 py-5 sm:py-10'>
<p className='text-center text-2xl sm:text-3xl md:text-4xl text-pink-500 uppercase font-bold drop-shadow-[0_2px_2px_rgba(105,105,105,1)]'>{c.name}</p>
<div className='grid grid-cols-1 min-[380px]:grid-cols-2 md:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-4 min-[380px]:gap-5 mt-5 sm:mt-10'>
{menuItems.filter(item => item.category === c._id).map(item => (
<Menu {...item}/>
))}

View file

@ -37,9 +37,9 @@ const AppProvider = ({children}) => {
}
}
function addToCart(product, size=null){
function addToCart(product, size=null, extra=[]){
setCartProducts(prevProducts => {
const cartProduct = {...product, size}
const cartProduct = {...product, size, extra}
const newProducts = [...prevProducts, cartProduct];
saveCartProductsToLocalStorage(newProducts);
return newProducts

View file

@ -9,6 +9,7 @@ const MenuItemForm = ({handleMenuFormSubmit, menuItem}) => {
const [description, setDescription] = useState(menuItem?.description || '');
const [basePrice, setBasePrice] = useState(menuItem?.basePrice || '');
const [sizes, setSizes] = useState(menuItem?.sizes || []);
const [extraItems, setExtraItems] = useState(menuItem?.extraItems || []);
const [category, setCategory] = useState(menuItem?.category || '');
const [categories, setCategories] = useState([]);
@ -23,7 +24,7 @@ const MenuItemForm = ({handleMenuFormSubmit, menuItem}) => {
return (
<form className='mt-10' onSubmit={ev => handleMenuFormSubmit(ev, {menuImg, itemName, description, basePrice, sizes, category,})}>
<form className='mt-10' onSubmit={ev => handleMenuFormSubmit(ev, {menuImg, itemName, description, basePrice, sizes, extraItems, category,})}>
<div className='flex flex-col gap-2 justify-center items-center max-w-[100px] mx-auto mb-5'>
<EditImage link={menuImg} setLink={setMenuImg}/>
</div>
@ -47,7 +48,8 @@ const MenuItemForm = ({handleMenuFormSubmit, menuItem}) => {
<label className='-mb-1 text-gray-700 font-semibold text-sm flex'>Price</label>
<input type='text' placeholder='Enter base price' value={basePrice} onChange={ev => setBasePrice(ev.target.value)}/>
</div>
<MenuItemProps props={sizes} setProps={setSizes}/>
<MenuItemProps name={'Sizes'} props={sizes} setProps={setSizes} addLabel={'Add sizes'}/>
<MenuItemProps name={'Toppings'} props={extraItems} setProps={setExtraItems} addLabel={'Add toppings'}/>
<button type='submit' className='w-full bg-pink-500 text-white p-2 rounded-md hover:opacity-80 duration-300'>Save</button>
</form>
)

View file

@ -2,7 +2,7 @@ import React, { useState } from 'react'
import { IoTrashOutline } from "react-icons/io5";
import { MdKeyboardArrowDown, MdKeyboardArrowUp } from "react-icons/md";
const MenuItemProps = ({props, setProps}) => {
const MenuItemProps = ({name, addLabel, props, setProps}) => {
const [isOpen, setIsOpen] = useState(false);
function addProp(){
@ -29,7 +29,7 @@ const MenuItemProps = ({props, setProps}) => {
<div>
<div className='border p-2 block my-2 w-full rounded-md outline-none border-[#DCA0AE]'>
<button onClick={() => setIsOpen(prev => !prev)} type='button' className='w-full flex justify-between items-center text-[#DCA0AE] '>
<label className='mb-2 text-gray-700 font-semibold text-sm flex'>Box of donuts ({props.length})</label>
<label className='mb-2 text-gray-700 font-semibold text-sm flex'>{name}({props.length})</label>
{isOpen && (
<MdKeyboardArrowUp/>
)}
@ -41,8 +41,8 @@ const MenuItemProps = ({props, setProps}) => {
{props?.length > 0 && props.map((size, index) => (
<div className='flex gap-2 items-center'>
<div>
<label className='-mb-1 text-gray-700 text-sm flex'>Donuts</label>
<input type='text' placeholder='Donuts' value={size.itemName} onChange={ev => editProp(ev, index, 'itemName')}/>
<label className='-mb-1 text-gray-700 text-sm flex'>Name</label>
<input type='text' placeholder='Size name' value={size.itemName} onChange={ev => editProp(ev, index, 'itemName')}/>
</div>
<div>
<label className='-mb-1 text-gray-700 text-sm flex'>Price</label>
@ -53,7 +53,7 @@ const MenuItemProps = ({props, setProps}) => {
</div>
</div>
))}
<button type='button' onClick={addProp} className='bg-gray-200 w-full p-2 rounded-md hover:opacity-80'>Add donuts</button>
<button type='button' onClick={addProp} className='bg-gray-200 w-full p-2 rounded-md hover:opacity-80'>{addLabel}</button>
</div>
</div>
</div>

View file

@ -4,12 +4,12 @@ import { CartContext } from '../AppContext';
import toast from 'react-hot-toast';
const Menu = (menuItem) => {
const {menuImg, itemName, description, basePrice, sizes} = menuItem
const {menuImg, itemName, description, basePrice, sizes, extraItems} = menuItem
const {addToCart} = useContext(CartContext);
const [showPopup, setShowPopup] = useState(false);
function handleAddToCartButtonClick(){
if(sizes.length === 0 ){
if(sizes.length === 0 && extraItems.length === 0){
toast.success('Add to cart');
addToCart(menuItem);
} else{
@ -17,16 +17,45 @@ const Menu = (menuItem) => {
}
}
return (
<>
{showPopup && (
<div className='fixed inset-0 bg-black/80 block sm:flex justify-center items-center'>
<div className='bg-white p-5 rounded-md'>test</div>
<div className='fixed inset-0 bg-black/80 flex justify-center items-center'>
<div className='bg-white p-5 rounded-md'>
<div className='py-0 sm:py-5 flex flex-col gap-2 sm:gap-4 justify-center items-center text-center px-0 sm:px-10'>
<Image src={menuImg} width={300} height={300} alt='menu-donut' className='w-[100px] min-[550px]:w-[120px]'/>
<p className='text-sm sm:text-base font-semibold capitalize text-[#95743D] px-2'>{itemName}</p>
<p className='text-xs sm:text-sm px-2 line-clamp-2 text-[#95743D]'>{description}</p>
{sizes?.length > 0 && (
<div className='w-full border-t-[1px] border-pink-500 border-dashed'>
<p className='text-xs sm:text-sm font-semibold capitalize text-[#95743D] px-2 m-2'>Choose your size</p>
{sizes.map(size => (
<div className='flex justify-start text-start text-xs sm:text-sm gap-2 py-1'>
<input type='radio' name='size'/>{size.itemName} ${basePrice + size.price}
</div>
))}
</div>
)}
{extraItems?.length > 0 && (
<div className='w-full border-t-[1px] border-pink-500 border-dashed'>
<p className='text-xs sm:text-sm font-semibold capitalize text-[#95743D] px-2 m-2'>Extra toppings</p>
{extraItems.map(extraTopping => (
<div className='flex justify-start text-start text-xs sm:text-sm gap-2 py-1'>
<input type='checkbox' name={extraTopping.itemName}/>{extraTopping.itemName} (${extraTopping.price})
</div>
))}
</div>
)}
<button type='button' className='bg-pink-500 text-white p-1 sm:p-2 text-sm sm:text-base rounded-md hover:opacity-80 duration-300 mt-5'>Add to cart</button>
</div>
</div>
</div>
)}
<div className='py-1 sm:py-5 flex flex-col gap-2 sm:gap-4 justify-center items-center text-center rounded-xl border border-pink-500 h-[300px] sm:h-[400px] lg:h-[450px] shadow-md hover:shadow-[#E78895] duration-300'>
<Image src={menuImg} width={300} height={300} alt='menu-donut' className='w-[150px] sm:w-[180px] lg:w-[230px]'/>
<Image src={menuImg} width={300} height={300} alt='menu-donut' className='w-[100px] min-[450px]:w-[150px] min-[550px]:w-[180px] lg:w-[230px]'/>
<p className='text-sm sm:text-base font-semibold capitalize text-[#95743D] px-2'>{itemName}</p>
<p className='text-xs sm:text-sm px-2 line-clamp-2 text-[#95743D]'>{description}</p>
<p className='text-[#95743D] text-sm font-semibold'>${basePrice}</p>

View file

@ -27,7 +27,7 @@ const MenuItem = (menuItem) => {
<div className='py-1 sm:py-5 flex flex-col gap-2 sm:gap-4 justify-center items-center text-center rounded-xl bg-white h-[350px] sm:h-[450px]'>
<Image src={menuImg} width={300} height={300} alt='menu-donut' className='w-[200px] sm:w-[250px]'/>
<p className='text-sm sm:text-base font-semibold capitalize text-[#95743D] px-2'>{itemName}</p>
<p className='text-xs sm:text-sm px-2 line-clamp-2'>{description}</p>
<p className='text-xs sm:text-sm px-2 line-clamp-2 text-[#95743D]'>{description}</p>
<p className='text-[#95743D] text-sm'>${basePrice}</p>
<button type='button' onClick={handleAddToCartButtonClick} className='px-2 py-1 sm:px-4 sm:py-2 rounded-full text-xs sm:text-sm border border-[#E78895] text-[#95743D] font-semibold hover:bg-[#E78895] hover:text-[#FDE2DE] duration-300'>Add to cart</button>
</div>