From dc18d84ac88d9b274974342fde6ba3d9128d9fe5 Mon Sep 17 00:00:00 2001 From: Mohammed Al-yaseen Date: Mon, 10 Nov 2025 21:36:00 +0300 Subject: [PATCH] add extra group price --- src/features/order/orderSlice.ts | 6 +---- src/pages/product/components/ExtraGroups.tsx | 20 +++++++++------- .../product/components/ProductFooter.tsx | 13 ++++++---- src/pages/product/components/Variants.tsx | 2 +- src/pages/product/page.tsx | 24 ++++++++++--------- src/utils/types/appTypes.ts | 10 ++------ 6 files changed, 36 insertions(+), 39 deletions(-) diff --git a/src/features/order/orderSlice.ts b/src/features/order/orderSlice.ts index fa1916a..39d4cb3 100644 --- a/src/features/order/orderSlice.ts +++ b/src/features/order/orderSlice.ts @@ -628,11 +628,7 @@ export const selectCartTotal = (state: RootState) => state.order.items.reduce( // (total, item) => total + item.price * item.quantity, (total, item) => { - const extrasPrice = (item.extras || []).reduce( - (extraTotal, extraItem) => extraTotal + extraItem.price, - 0, - ); - const itemTotalPrice = (item.price + extrasPrice) * item.quantity; + const itemTotalPrice = item.price * item.quantity; return total + itemTotalPrice; }, 0, diff --git a/src/pages/product/components/ExtraGroups.tsx b/src/pages/product/components/ExtraGroups.tsx index 3fae008..b21e9a0 100644 --- a/src/pages/product/components/ExtraGroups.tsx +++ b/src/pages/product/components/ExtraGroups.tsx @@ -4,7 +4,7 @@ import ProText from "components/ProText"; import { Dispatch, SetStateAction } from "react"; import { useTranslation } from "react-i18next"; import { useAppSelector } from "redux/hooks"; -import { TheExtrasGroup } from "utils/types/appTypes"; +import { Extra, TheExtrasGroup } from "utils/types/appTypes"; import styles from "../product.module.css"; export default function ExtraGroups({ @@ -13,8 +13,8 @@ export default function ExtraGroups({ setSelectedExtrasByGroup, }: { groupsList: TheExtrasGroup[]; - selectedExtrasByGroup: Record; - setSelectedExtrasByGroup: Dispatch>>; + selectedExtrasByGroup: Extra[]; + setSelectedExtrasByGroup: Dispatch>; }) { const { isRTL } = useAppSelector((state) => state.locale); const { t } = useTranslation(); @@ -69,7 +69,10 @@ export default function ExtraGroups({ {group.force_limit_selection === 1 ? "Required" : "Optional"} - ({selectedExtrasByGroup[group.id]?.length || 0}/{group.limit}) + ( + {selectedExtrasByGroup.filter((extra) => extra.id === group.id) + .length || 0} + /{group.limit}) @@ -94,7 +97,7 @@ export default function ExtraGroups({ label: isRTL ? extra.name : extra.nameAR, price: `+${extra.price}`, }))} - value={selectedExtrasByGroup[group.id] || []} + value={selectedExtrasByGroup.map((extra) => extra.id.toString())} onChange={(values: string[]) => { // Check if the new selection would exceed the limit if (values.length > group.limit) { @@ -103,10 +106,9 @@ export default function ExtraGroups({ ); return; } - setSelectedExtrasByGroup((prev) => ({ - ...prev, - [group.id]: values, - })); + setSelectedExtrasByGroup( + group.extras.filter((o) => values?.includes(o.id.toString())), + ); }} /> diff --git a/src/pages/product/components/ProductFooter.tsx b/src/pages/product/components/ProductFooter.tsx index 95aacec..ab0aaca 100644 --- a/src/pages/product/components/ProductFooter.tsx +++ b/src/pages/product/components/ProductFooter.tsx @@ -7,23 +7,23 @@ import { useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { useAppDispatch, useAppSelector } from "redux/hooks"; import { colors, ProBlack2 } from "ThemeConstants"; -import { Product, Variant, Extra as ExtraType } from "utils/types/appTypes"; +import { Extra, Product, Variant } from "utils/types/appTypes"; import styles from "../product.module.css"; export default function ProductFooter({ product, isValid = true, - selectedVariant, selectedExtras, + selectedVariant, selectedGroups, quantity, onClose, }: { product: Product; isValid?: boolean; + selectedExtras: Extra[]; selectedVariant?: Variant; - selectedExtras: ExtraType[]; - selectedGroups: string[]; + selectedGroups: Extra[]; quantity: number; onClose?: () => void; }) { @@ -60,7 +60,10 @@ export default function ProductFooter({ item: { id: product?.id, name: product?.name, - price: selectedVariant?.price || product?.price, + price: + (selectedVariant?.price || product?.price) + + selectedExtras.reduce((acc, extra) => acc + extra.price, 0), + // selectedGroups.reduce((acc, extra) => acc + extra.price, 0), image: product?.image, description: product?.description, comment: specialRequest, diff --git a/src/pages/product/components/Variants.tsx b/src/pages/product/components/Variants.tsx index 8a80c04..bd42b38 100644 --- a/src/pages/product/components/Variants.tsx +++ b/src/pages/product/components/Variants.tsx @@ -168,7 +168,7 @@ export default function Variants({ return { value: value, label: value, - price: variant ? `+${variant.price}` : "", + price: variant ? `+${Number(variant.price).toFixed(2)}` : "", }; })} value={selectedVariants[index] || ""} diff --git a/src/pages/product/page.tsx b/src/pages/product/page.tsx index ec7047f..92ccee5 100644 --- a/src/pages/product/page.tsx +++ b/src/pages/product/page.tsx @@ -10,9 +10,9 @@ import ArabicPrice from "components/ArabicPrice"; import useBreakPoint from "hooks/useBreakPoint"; import { useCallback, useMemo, useState } from "react"; import { colors } from "ThemeConstants"; -import { Product, Extra as ExtraType } from "utils/types/appTypes"; +import { Extra, Product } from "utils/types/appTypes"; import BackButton from "../menu/components/BackButton"; -import Extra from "./components/Extra"; +import ExtraComponent from "./components/Extra"; import ExtraGroups from "./components/ExtraGroups"; import ProductFooter from "./components/ProductFooter"; import Variants from "./components/Variants"; @@ -37,12 +37,12 @@ export default function ProductDetailPage({ >({}); // State for selected extras - const [selectedExtras, setSelectedExtras] = useState([]); + const [selectedExtras, setSelectedExtras] = useState([]); // State for selected extras by group - const [selectedExtrasByGroup, setSelectedExtrasByGroup] = useState< - Record - >({}); + const [selectedExtrasByGroup, setSelectedExtrasByGroup] = useState( + [], + ); // Determine variant levels based on options array length const variantLevels = useMemo(() => { @@ -126,7 +126,9 @@ export default function ProductDetailPage({ const allRequiredExtraGroupsSatisfied = product.theExtrasGroups.every( (group) => { if (group.force_limit_selection === 1) { - const selectedCount = selectedExtrasByGroup[group.id]?.length || 0; + const selectedCount = + selectedExtrasByGroup.filter((extra) => extra.id === group.id) + .length || 0; return selectedCount === group.limit; } return true; // Optional groups are always satisfied @@ -277,7 +279,7 @@ export default function ProductDetailPage({ isValid={isValid} selectedVariant={getFinalSelectedVariant()} selectedExtras={selectedExtras} - selectedGroups={Object.values(selectedExtrasByGroup).flat()} + selectedGroups={selectedExtrasByGroup} quantity={quantity} onClose={onClose} /> @@ -300,8 +302,8 @@ export default function ProductDetailPage({ /> )} - {getExtras().length > 0 && ( - )} diff --git a/src/utils/types/appTypes.ts b/src/utils/types/appTypes.ts index 854a7e9..2dd0838 100644 --- a/src/utils/types/appTypes.ts +++ b/src/utils/types/appTypes.ts @@ -323,7 +323,7 @@ export interface CartItem { description: string; variant?: string; extras?: Extra[]; - extrasgroup?: string[]; + extrasgroup?: Extra[]; isHasLoyalty?: boolean; no_of_stamps_give?: number; comment?: string; @@ -547,7 +547,7 @@ export interface Product { available: boolean; currency: string; variants: Variant[]; - extras: Extra2[]; + extras: Extra[]; categoryId?: number; // to be sent isHasExtras: boolean; isHasVarint: boolean; @@ -584,12 +584,6 @@ export interface Extra { name: string; } -export interface Extra2 { - id: number; - price: number; - name: string; -} - export interface TheExtrasGroup { id: number; name: string;