diff --git a/src/pages/product/components/ExtraGroups.tsx b/src/pages/product/components/ExtraGroups.tsx deleted file mode 100644 index b21e9a0..0000000 --- a/src/pages/product/components/ExtraGroups.tsx +++ /dev/null @@ -1,119 +0,0 @@ -import { Divider, message } from "antd"; -import ProCheckboxGroups from "components/ProCheckboxGroups/ProCheckboxGroups"; -import ProText from "components/ProText"; -import { Dispatch, SetStateAction } from "react"; -import { useTranslation } from "react-i18next"; -import { useAppSelector } from "redux/hooks"; -import { Extra, TheExtrasGroup } from "utils/types/appTypes"; -import styles from "../product.module.css"; - -export default function ExtraGroups({ - groupsList, - selectedExtrasByGroup, - setSelectedExtrasByGroup, -}: { - groupsList: TheExtrasGroup[]; - selectedExtrasByGroup: Extra[]; - setSelectedExtrasByGroup: Dispatch>; -}) { - const { isRTL } = useAppSelector((state) => state.locale); - const { t } = useTranslation(); - - return ( - <> - {groupsList.length > 0 && ( -
- - -
- - {t("menu.youMightAlsoLike")} - - - - {t("menu.optional")} - -
- - {/* - {t("menu.choose1")} - */} -
- )} - - {groupsList?.map((group: TheExtrasGroup) => ( -
-
- - {isRTL ? group.nameAR : group.name} - -
- - {group.force_limit_selection === 1 ? "Required" : "Optional"} - - - ( - {selectedExtrasByGroup.filter((extra) => extra.id === group.id) - .length || 0} - /{group.limit}) - -
-
- - {group.force_limit_selection === 1 && ( - - * You must select exactly {group.limit} option - {group.limit > 1 ? "s" : ""} - - )} - -
- ({ - value: extra.id.toString(), - label: isRTL ? extra.name : extra.nameAR, - price: `+${extra.price}`, - }))} - value={selectedExtrasByGroup.map((extra) => extra.id.toString())} - onChange={(values: string[]) => { - // Check if the new selection would exceed the limit - if (values.length > group.limit) { - message.error( - `You can only select up to ${group.limit} option${group.limit > 1 ? "s" : ""} from this group.`, - ); - return; - } - setSelectedExtrasByGroup( - group.extras.filter((o) => values?.includes(o.id.toString())), - ); - }} - /> -
-
- ))} - - ); -} diff --git a/src/pages/product/components/ExtraGroupsContainer.tsx b/src/pages/product/components/ExtraGroupsContainer.tsx new file mode 100644 index 0000000..2ca926c --- /dev/null +++ b/src/pages/product/components/ExtraGroupsContainer.tsx @@ -0,0 +1,65 @@ +import { Divider } from "antd"; +import ProText from "components/ProText"; +import { Dispatch, SetStateAction } from "react"; +import { useTranslation } from "react-i18next"; + +import { TheExtrasGroup } from "utils/types/appTypes"; + +import ExtrasGroup from "pages/product/components/ExtrasGroup.tsx"; + +export default function ExtraGroupsContainer({ + groupsList, + selectedExtrasByGroup, + setSelectedExtrasByGroup, +}: { + groupsList: TheExtrasGroup[]; + selectedExtrasByGroup: Record; + setSelectedExtrasByGroup: Dispatch>>; +}) { + const { t } = useTranslation(); + + return ( + <> + {groupsList.length > 0 && ( +
+ + +
+ + {t("menu.youMightAlsoLike")} + + + + {t("menu.optional")} + +
+ + {/* + {t("menu.choose1")} + */} +
+ )} + + {groupsList?.map((group: TheExtrasGroup) => ( + { + setSelectedExtrasByGroup({ + ...selectedExtrasByGroup, + [group.id]: + group.extras + .filter((o) => values?.includes(o.id.toString())) + .map((e) => e.id.toString()) || [], + }); + }} + /> + ))} + + ); +} diff --git a/src/pages/product/components/ExtrasGroup.tsx b/src/pages/product/components/ExtrasGroup.tsx new file mode 100644 index 0000000..7da8a99 --- /dev/null +++ b/src/pages/product/components/ExtrasGroup.tsx @@ -0,0 +1,87 @@ +import ProText from "components/ProText.tsx"; +import styles from "pages/product/product.module.css"; +import ProCheckboxGroups from "components/ProCheckboxGroups/ProCheckboxGroups.tsx"; +import { message } from "antd"; +import { TheExtrasGroup } from "utils/types/appTypes.ts"; +import { useAppSelector } from "redux/hooks.ts"; + +type Props = { + group: TheExtrasGroup; + selectedExtras: Array; + onChange: (values: Array) => void; +}; +export default function ExtrasGroup({ + group, + selectedExtras, + onChange, +}: Props) { + const { isRTL } = useAppSelector((state) => state.locale); + + return ( +
+
+ + {isRTL ? group.nameAR : group.name} + +
+ + {group.force_limit_selection === 1 ? "Required" : "Optional"} + + + ({selectedExtras?.length || 0}/{group.limit}) + +
+
+ + {group.force_limit_selection === 1 && ( + + * You must select exactly {group.limit} option + {group.limit > 1 ? "s" : ""} + + )} + +
+ ({ + value: extra.id.toString(), + label: isRTL ? extra.name : extra.nameAR, + price: `+${extra.price}`, + }))} + value={selectedExtras} + onChange={(values: string[]) => { + // Check if the new selection would exceed the limit + if (values.length > group.limit) { + message.error( + `You can only select up to ${group.limit} option${group.limit > 1 ? "s" : ""} from this group.`, + ); + return; + } + onChange( + group.extras + .filter((o) => values?.includes(o.id.toString())) + .map((e) => e.id.toString()) || [], + ); + }} + /> +
+
+ ); +} diff --git a/src/pages/product/components/ProductFooter.tsx b/src/pages/product/components/ProductFooter.tsx index f200824..284b4d8 100644 --- a/src/pages/product/components/ProductFooter.tsx +++ b/src/pages/product/components/ProductFooter.tsx @@ -23,7 +23,7 @@ export default function ProductFooter({ isValid?: boolean; selectedExtras: Extra[]; selectedVariant?: Variant; - selectedGroups: Extra[]; + selectedGroups: Record; quantity: number; onClose?: () => void; }) { @@ -69,7 +69,11 @@ export default function ProductFooter({ comment: specialRequest, variant: selectedVariant, extras: selectedExtras, - extrasgroup: selectedGroups, + extrasgroupnew: Object.keys(selectedGroups).map((key) => ({ + groupid: key, + extrasid: selectedGroups[Number(key)], + })), + extrasgroup: [""], isHasLoyalty: product?.isHasLoyalty, no_of_stamps_give: product?.no_of_stamps_give, }, diff --git a/src/pages/product/page.tsx b/src/pages/product/page.tsx index 92ccee5..3b3f064 100644 --- a/src/pages/product/page.tsx +++ b/src/pages/product/page.tsx @@ -13,7 +13,7 @@ import { colors } from "ThemeConstants"; import { Extra, Product } from "utils/types/appTypes"; import BackButton from "../menu/components/BackButton"; import ExtraComponent from "./components/Extra"; -import ExtraGroups from "./components/ExtraGroups"; +import ExtraGroupsContainer from "pages/product/components/ExtraGroupsContainer.tsx"; import ProductFooter from "./components/ProductFooter"; import Variants from "./components/Variants"; import styles from "./product.module.css"; @@ -40,9 +40,9 @@ export default function ProductDetailPage({ const [selectedExtras, setSelectedExtras] = useState([]); // State for selected extras by group - const [selectedExtrasByGroup, setSelectedExtrasByGroup] = useState( - [], - ); + const [selectedExtrasByGroup, setSelectedExtrasByGroup] = useState< + Record> + >([]); // Determine variant levels based on options array length const variantLevels = useMemo(() => { @@ -126,9 +126,7 @@ export default function ProductDetailPage({ const allRequiredExtraGroupsSatisfied = product.theExtrasGroups.every( (group) => { if (group.force_limit_selection === 1) { - const selectedCount = - selectedExtrasByGroup.filter((extra) => extra.id === group.id) - .length || 0; + const selectedCount = selectedExtrasByGroup[group.id]?.length || 0; return selectedCount === group.limit; } return true; // Optional groups are always satisfied @@ -311,7 +309,7 @@ export default function ProductDetailPage({ )} {product.theExtrasGroups.length > 0 && ( - }>; + extrasgroup?: Array; isHasLoyalty?: boolean; no_of_stamps_give?: number; comment?: string;