diff --git a/frontend/src/application/mappers/MenuItem.mapper.ts b/frontend/src/application/mappers/MenuItem.mapper.ts index ecd4b50e..76ed72bf 100644 --- a/frontend/src/application/mappers/MenuItem.mapper.ts +++ b/frontend/src/application/mappers/MenuItem.mapper.ts @@ -1,3 +1,4 @@ +import { ItemsSummary } from "../../components/CartItemsList"; import { CartItem, selectedItem } from "../../reducers"; export const selectedItemToMenuMapper = (selectedItem: selectedItem): Partial => { @@ -7,3 +8,11 @@ export const selectedItemToMenuMapper = (selectedItem: selectedItem): Partial { + return { + id: item.id, + name: item.name, + qty: item.quantity || 0, + }; +}; \ No newline at end of file diff --git a/frontend/src/components/AddToCart.tsx b/frontend/src/components/AddToCart.tsx index 3a57e611..79f04056 100644 --- a/frontend/src/components/AddToCart.tsx +++ b/frontend/src/components/AddToCart.tsx @@ -4,6 +4,7 @@ import { QtyButton } from "./addItemButton"; const addToCartStyle: CSSProperties = { textAlign: "center", + marginRight: "10px", }; type addItemToCart = { diff --git a/frontend/src/components/CartItemsList.tsx b/frontend/src/components/CartItemsList.tsx new file mode 100644 index 00000000..28b2ef83 --- /dev/null +++ b/frontend/src/components/CartItemsList.tsx @@ -0,0 +1,42 @@ +import { Stack } from "react-bootstrap"; +import { ItemToSummaryMapper } from "../application/mappers/MenuItem.mapper"; +import { useShoppingCart } from "../hooks/UseShoppingCart"; + +export type ItemsSummary = { + id: string; + name: string; + qty: number; +}; + +export const CartItemsList = () => { + const { menus } = useShoppingCart(); + let itemSummaries: ItemsSummary[] = []; + if (menus && menus.length) { + const itemsMap = new Map(); + const selectedItems = menus.map((menu) => menu.selectedItems || []); + const flattenedSelectedItems = selectedItems.flat(); + flattenedSelectedItems.forEach((item) => { + const selectedItem = ItemToSummaryMapper(item); + if (itemsMap.has(item.id)) { + itemsMap.get(item.id)!.qty += 1; + } else { + itemsMap.set(item.id, selectedItem); + } + }); + for (const item of itemsMap.values()) { + itemSummaries.push(item); + } + } + + return ( +
+ + {itemSummaries.map((item) => ( + + +{item.name.toLowerCase()} x {item.qty} + + ))} + +
+ ); +}; diff --git a/frontend/src/components/FoodItemList.tsx b/frontend/src/components/FoodItemList.tsx index 5e53d043..6bdb1957 100644 --- a/frontend/src/components/FoodItemList.tsx +++ b/frontend/src/components/FoodItemList.tsx @@ -4,7 +4,8 @@ import { storeItemProps } from "./StoreItem"; import { QtyButton } from "./addItemButton"; type foodItem = storeItemProps & { itemId: string; itemPrice: number }; -export const FoodItemList = ({ name, itemId, itemPrice, id, basePrice }: foodItem) => { + +export const FoodItemList = ({ name, itemId, itemPrice, id, basePrice }: Omit) => { const { addItemToCart } = useShoppingCart(); const handleClick = () => { return addItemToCart({ diff --git a/frontend/src/components/MenuItem.tsx b/frontend/src/components/MenuItem.tsx index efb6b709..1f602186 100644 --- a/frontend/src/components/MenuItem.tsx +++ b/frontend/src/components/MenuItem.tsx @@ -10,7 +10,7 @@ type menuItemProps = { export const MenuItem = ({ name, url, description, basePrice }: menuItemProps) => { return ( - +
diff --git a/frontend/src/components/StoreItem.tsx b/frontend/src/components/StoreItem.tsx index bb5bd065..cdea4b74 100644 --- a/frontend/src/components/StoreItem.tsx +++ b/frontend/src/components/StoreItem.tsx @@ -1,6 +1,7 @@ import { Card, Col, Row } from "react-bootstrap"; import { FoodItemList } from "./FoodItemList"; import { Item } from "../reducers"; +import { CartItemsList } from "./CartItemsList"; export type storeItemProps = { id: string; @@ -38,12 +39,11 @@ export const StoreItem = ({ id, name, description, imageUrl, basePrice, items, q More Portion

- <> +
{items.map((item) => ( -
+
))} - +
diff --git a/frontend/src/contexts/shoppingCartContext.tsx b/frontend/src/contexts/shoppingCartContext.tsx index 8c7b7e24..5398803c 100644 --- a/frontend/src/contexts/shoppingCartContext.tsx +++ b/frontend/src/contexts/shoppingCartContext.tsx @@ -84,29 +84,34 @@ export const ShoppingCartProvider = ({ children }: shoppingCartProviderProps) => state.menus.forEach((menu) => { if (menuItem.menuId === menu.id) selectedItems = menu.selectedItems; }); - selectedItems?.forEach((item) => selectedItemMap.set(item.menuId, item)); - state.menus.forEach((menu) => { - if (selectedItemMap.has(menu.id!)) { - const selectedItem = selectedItemMap.get(menu.id!); - if (selectedItem!.id === menuItem.id) { - selectedItem!.quantity! += 1; - selectedItem!.total = selectedItem!.total! + selectedItem!.price; - } else { - menuItem.total = price; - menuItem.quantity = 1; - selectedItems?.push(menuItem); - } + + if (selectedItems?.length) { + const index = selectedItems.findIndex((item) => item.id === menuItem.id); + if (index === -1) { + menuItem.total = price; + menuItem.quantity = 0; + selectedItems.push(menuItem); } - }); + } + + selectedItems?.forEach((item) => selectedItemMap.set(item.id, item)); + for (const item of selectedItemMap.values()) { + if (item.id === menuItem.id) { + item.quantity! += 1; + item.total = item.total! + item.price; + } + } } + if (selectedItems && selectedItems.length) { let totalItemPrice: number = 0; selectedItems.forEach((item) => { totalItemPrice += item.quantity! * item.price; }); - + console.log(state); state.totalPrice = totalItemPrice + menuItem.menuPrice; } + dispatch({ type: CartActionsType.ADD_ITEM_TO_CART, }); diff --git a/frontend/src/index.css b/frontend/src/index.css index 7bd64f80..63c1ff63 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -44,4 +44,22 @@ hr { .card { border: 1px solid #f3f3f3; +} + +.menuCard { + margin: 0; + box-shadow: 0 1px 6px rgba(0, 0, 0, .16); + border-radius: 20px; + height: 100%; + display: flex; + flex-direction: column; +} + +.elBg { + background-color: #fff; +} + +.addToCart { + padding-bottom: 15px; + border-top: 0.1rem solid #f1f1f1; } \ No newline at end of file diff --git a/frontend/src/pages/FoodMenu.tsx b/frontend/src/pages/FoodMenu.tsx index c4e4c698..78e38d71 100644 --- a/frontend/src/pages/FoodMenu.tsx +++ b/frontend/src/pages/FoodMenu.tsx @@ -4,6 +4,7 @@ import { AddToCartButton, StoreItem } from "../components"; import { useShoppingCart } from "../hooks/UseShoppingCart"; import { IItem } from "../models/item.model"; import { Item } from "../reducers"; +import { CartItemsList } from "../components/CartItemsList"; const mapItems = (items: IItem[]): Item[] => { const stateItem = @@ -26,7 +27,6 @@ export const FoodMenu = () => { if (id) { const { isLoading, data: menu } = getMenuById(id); const { addToCart, quantity, totalPrice } = useShoppingCart(); - const items = mapItems(menu?.data?.items!); if (isLoading) { @@ -45,12 +45,17 @@ export const FoodMenu = () => { basePrice={basePrice} id={id} /> - addToCart({ id, name, basePrice, quantity, items })} - amount={totalPrice > 0 ? totalPrice : basePrice} - onAddItemToCartClick={() => addToCart({ id, name, basePrice, quantity, items })} - onRemoveItemFromCartClick={() => addToCart({ id, name, basePrice, quantity, items })} - /> +
+
+ +
+ addToCart({ id, name, basePrice, quantity, items })} + amount={totalPrice > 0 ? totalPrice : basePrice} + onAddItemToCartClick={() => addToCart({ id, name, basePrice, quantity, items })} + onRemoveItemFromCartClick={() => addToCart({ id, name, basePrice, quantity, items })} + /> +
); } diff --git a/frontend/src/reducers/cartReducer.tsx b/frontend/src/reducers/cartReducer.tsx index 1ad81460..ba7dc115 100644 --- a/frontend/src/reducers/cartReducer.tsx +++ b/frontend/src/reducers/cartReducer.tsx @@ -18,7 +18,7 @@ export type selectedItem = { id: string; menuId: string; name: string; - quantity?: number; + quantity?: number | 0; total?: number; price: number; menuPrice: number;