add extra group price
This commit is contained in:
@@ -628,11 +628,7 @@ export const selectCartTotal = (state: RootState) =>
|
|||||||
state.order.items.reduce(
|
state.order.items.reduce(
|
||||||
// (total, item) => total + item.price * item.quantity,
|
// (total, item) => total + item.price * item.quantity,
|
||||||
(total, item) => {
|
(total, item) => {
|
||||||
const extrasPrice = (item.extras || []).reduce(
|
const itemTotalPrice = item.price * item.quantity;
|
||||||
(extraTotal, extraItem) => extraTotal + extraItem.price,
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
const itemTotalPrice = (item.price + extrasPrice) * item.quantity;
|
|
||||||
return total + itemTotalPrice;
|
return total + itemTotalPrice;
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import ProText from "components/ProText";
|
|||||||
import { Dispatch, SetStateAction } from "react";
|
import { Dispatch, SetStateAction } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useAppSelector } from "redux/hooks";
|
import { useAppSelector } from "redux/hooks";
|
||||||
import { TheExtrasGroup } from "utils/types/appTypes";
|
import { Extra, TheExtrasGroup } from "utils/types/appTypes";
|
||||||
import styles from "../product.module.css";
|
import styles from "../product.module.css";
|
||||||
|
|
||||||
export default function ExtraGroups({
|
export default function ExtraGroups({
|
||||||
@@ -13,8 +13,8 @@ export default function ExtraGroups({
|
|||||||
setSelectedExtrasByGroup,
|
setSelectedExtrasByGroup,
|
||||||
}: {
|
}: {
|
||||||
groupsList: TheExtrasGroup[];
|
groupsList: TheExtrasGroup[];
|
||||||
selectedExtrasByGroup: Record<number, string[]>;
|
selectedExtrasByGroup: Extra[];
|
||||||
setSelectedExtrasByGroup: Dispatch<SetStateAction<Record<number, string[]>>>;
|
setSelectedExtrasByGroup: Dispatch<SetStateAction<Extra[]>>;
|
||||||
}) {
|
}) {
|
||||||
const { isRTL } = useAppSelector((state) => state.locale);
|
const { isRTL } = useAppSelector((state) => state.locale);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -69,7 +69,10 @@ export default function ExtraGroups({
|
|||||||
{group.force_limit_selection === 1 ? "Required" : "Optional"}
|
{group.force_limit_selection === 1 ? "Required" : "Optional"}
|
||||||
</ProText>
|
</ProText>
|
||||||
<ProText style={{ fontSize: "0.75rem", color: "#666" }}>
|
<ProText style={{ fontSize: "0.75rem", color: "#666" }}>
|
||||||
({selectedExtrasByGroup[group.id]?.length || 0}/{group.limit})
|
(
|
||||||
|
{selectedExtrasByGroup.filter((extra) => extra.id === group.id)
|
||||||
|
.length || 0}
|
||||||
|
/{group.limit})
|
||||||
</ProText>
|
</ProText>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -94,7 +97,7 @@ export default function ExtraGroups({
|
|||||||
label: isRTL ? extra.name : extra.nameAR,
|
label: isRTL ? extra.name : extra.nameAR,
|
||||||
price: `+${extra.price}`,
|
price: `+${extra.price}`,
|
||||||
}))}
|
}))}
|
||||||
value={selectedExtrasByGroup[group.id] || []}
|
value={selectedExtrasByGroup.map((extra) => extra.id.toString())}
|
||||||
onChange={(values: string[]) => {
|
onChange={(values: string[]) => {
|
||||||
// Check if the new selection would exceed the limit
|
// Check if the new selection would exceed the limit
|
||||||
if (values.length > group.limit) {
|
if (values.length > group.limit) {
|
||||||
@@ -103,10 +106,9 @@ export default function ExtraGroups({
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setSelectedExtrasByGroup((prev) => ({
|
setSelectedExtrasByGroup(
|
||||||
...prev,
|
group.extras.filter((o) => values?.includes(o.id.toString())),
|
||||||
[group.id]: values,
|
);
|
||||||
}));
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -7,23 +7,23 @@ import { useMemo, useState } from "react";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useAppDispatch, useAppSelector } from "redux/hooks";
|
import { useAppDispatch, useAppSelector } from "redux/hooks";
|
||||||
import { colors, ProBlack2 } from "ThemeConstants";
|
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";
|
import styles from "../product.module.css";
|
||||||
|
|
||||||
export default function ProductFooter({
|
export default function ProductFooter({
|
||||||
product,
|
product,
|
||||||
isValid = true,
|
isValid = true,
|
||||||
selectedVariant,
|
|
||||||
selectedExtras,
|
selectedExtras,
|
||||||
|
selectedVariant,
|
||||||
selectedGroups,
|
selectedGroups,
|
||||||
quantity,
|
quantity,
|
||||||
onClose,
|
onClose,
|
||||||
}: {
|
}: {
|
||||||
product: Product;
|
product: Product;
|
||||||
isValid?: boolean;
|
isValid?: boolean;
|
||||||
|
selectedExtras: Extra[];
|
||||||
selectedVariant?: Variant;
|
selectedVariant?: Variant;
|
||||||
selectedExtras: ExtraType[];
|
selectedGroups: Extra[];
|
||||||
selectedGroups: string[];
|
|
||||||
quantity: number;
|
quantity: number;
|
||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
}) {
|
}) {
|
||||||
@@ -60,7 +60,10 @@ export default function ProductFooter({
|
|||||||
item: {
|
item: {
|
||||||
id: product?.id,
|
id: product?.id,
|
||||||
name: product?.name,
|
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,
|
image: product?.image,
|
||||||
description: product?.description,
|
description: product?.description,
|
||||||
comment: specialRequest,
|
comment: specialRequest,
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ export default function Variants({
|
|||||||
return {
|
return {
|
||||||
value: value,
|
value: value,
|
||||||
label: value,
|
label: value,
|
||||||
price: variant ? `+${variant.price}` : "",
|
price: variant ? `+${Number(variant.price).toFixed(2)}` : "",
|
||||||
};
|
};
|
||||||
})}
|
})}
|
||||||
value={selectedVariants[index] || ""}
|
value={selectedVariants[index] || ""}
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ import ArabicPrice from "components/ArabicPrice";
|
|||||||
import useBreakPoint from "hooks/useBreakPoint";
|
import useBreakPoint from "hooks/useBreakPoint";
|
||||||
import { useCallback, useMemo, useState } from "react";
|
import { useCallback, useMemo, useState } from "react";
|
||||||
import { colors } from "ThemeConstants";
|
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 BackButton from "../menu/components/BackButton";
|
||||||
import Extra from "./components/Extra";
|
import ExtraComponent from "./components/Extra";
|
||||||
import ExtraGroups from "./components/ExtraGroups";
|
import ExtraGroups from "./components/ExtraGroups";
|
||||||
import ProductFooter from "./components/ProductFooter";
|
import ProductFooter from "./components/ProductFooter";
|
||||||
import Variants from "./components/Variants";
|
import Variants from "./components/Variants";
|
||||||
@@ -37,12 +37,12 @@ export default function ProductDetailPage({
|
|||||||
>({});
|
>({});
|
||||||
|
|
||||||
// State for selected extras
|
// State for selected extras
|
||||||
const [selectedExtras, setSelectedExtras] = useState<ExtraType[]>([]);
|
const [selectedExtras, setSelectedExtras] = useState<Extra[]>([]);
|
||||||
|
|
||||||
// State for selected extras by group
|
// State for selected extras by group
|
||||||
const [selectedExtrasByGroup, setSelectedExtrasByGroup] = useState<
|
const [selectedExtrasByGroup, setSelectedExtrasByGroup] = useState<Extra[]>(
|
||||||
Record<number, string[]>
|
[],
|
||||||
>({});
|
);
|
||||||
|
|
||||||
// Determine variant levels based on options array length
|
// Determine variant levels based on options array length
|
||||||
const variantLevels = useMemo(() => {
|
const variantLevels = useMemo(() => {
|
||||||
@@ -126,7 +126,9 @@ export default function ProductDetailPage({
|
|||||||
const allRequiredExtraGroupsSatisfied = product.theExtrasGroups.every(
|
const allRequiredExtraGroupsSatisfied = product.theExtrasGroups.every(
|
||||||
(group) => {
|
(group) => {
|
||||||
if (group.force_limit_selection === 1) {
|
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 selectedCount === group.limit;
|
||||||
}
|
}
|
||||||
return true; // Optional groups are always satisfied
|
return true; // Optional groups are always satisfied
|
||||||
@@ -277,7 +279,7 @@ export default function ProductDetailPage({
|
|||||||
isValid={isValid}
|
isValid={isValid}
|
||||||
selectedVariant={getFinalSelectedVariant()}
|
selectedVariant={getFinalSelectedVariant()}
|
||||||
selectedExtras={selectedExtras}
|
selectedExtras={selectedExtras}
|
||||||
selectedGroups={Object.values(selectedExtrasByGroup).flat()}
|
selectedGroups={selectedExtrasByGroup}
|
||||||
quantity={quantity}
|
quantity={quantity}
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
/>
|
/>
|
||||||
@@ -300,8 +302,8 @@ export default function ProductDetailPage({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{getExtras().length > 0 && (
|
{getExtras().length && product.theExtrasGroups.length === 0 && (
|
||||||
<Extra
|
<ExtraComponent
|
||||||
extrasList={getExtras()}
|
extrasList={getExtras()}
|
||||||
selectedExtras={selectedExtras}
|
selectedExtras={selectedExtras}
|
||||||
setSelectedExtras={setSelectedExtras}
|
setSelectedExtras={setSelectedExtras}
|
||||||
@@ -326,7 +328,7 @@ export default function ProductDetailPage({
|
|||||||
isValid={isValid}
|
isValid={isValid}
|
||||||
selectedVariant={getFinalSelectedVariant()}
|
selectedVariant={getFinalSelectedVariant()}
|
||||||
selectedExtras={selectedExtras}
|
selectedExtras={selectedExtras}
|
||||||
selectedGroups={Object.values(selectedExtrasByGroup).flat()}
|
selectedGroups={selectedExtrasByGroup}
|
||||||
quantity={quantity}
|
quantity={quantity}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -323,7 +323,7 @@ export interface CartItem {
|
|||||||
description: string;
|
description: string;
|
||||||
variant?: string;
|
variant?: string;
|
||||||
extras?: Extra[];
|
extras?: Extra[];
|
||||||
extrasgroup?: string[];
|
extrasgroup?: Extra[];
|
||||||
isHasLoyalty?: boolean;
|
isHasLoyalty?: boolean;
|
||||||
no_of_stamps_give?: number;
|
no_of_stamps_give?: number;
|
||||||
comment?: string;
|
comment?: string;
|
||||||
@@ -547,7 +547,7 @@ export interface Product {
|
|||||||
available: boolean;
|
available: boolean;
|
||||||
currency: string;
|
currency: string;
|
||||||
variants: Variant[];
|
variants: Variant[];
|
||||||
extras: Extra2[];
|
extras: Extra[];
|
||||||
categoryId?: number; // to be sent
|
categoryId?: number; // to be sent
|
||||||
isHasExtras: boolean;
|
isHasExtras: boolean;
|
||||||
isHasVarint: boolean;
|
isHasVarint: boolean;
|
||||||
@@ -584,12 +584,6 @@ export interface Extra {
|
|||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Extra2 {
|
|
||||||
id: number;
|
|
||||||
price: number;
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TheExtrasGroup {
|
export interface TheExtrasGroup {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user