Compare commits

..

5 Commits

10 changed files with 379 additions and 422 deletions

View File

@@ -0,0 +1,162 @@
import { Space, Divider } from "antd";
import ProText from "components/ProText.tsx";
import styles from "pages/cart/cart.module.css";
import ArabicPrice from "components/ArabicPrice";
import ImageWithFallback from "components/ImageWithFallback";
import CartActionsButtons from "components/CartActionsButtons/CartActionsButtons.tsx";
import { CartItem } from "utils/types/appTypes.ts";
import { useAppSelector } from "redux/hooks.ts";
import useBreakPoint from "hooks/useBreakPoint.ts";
import { OrderItem } from "pages/checkout/hooks/types.ts";
type ProductChoicesCardProps = {
product: CartItem | OrderItem;
addDividerAfter: boolean;
};
export default function ProductChoicesCard({
product,
addDividerAfter,
}: ProductChoicesCardProps) {
const { isRTL } = useAppSelector((state) => state.locale);
const { isMobile, isTablet } = useBreakPoint();
const getMenuItemImageStyle = () => {
if (isMobile) {
return {
width: 115,
height: 96,
};
}
return {
width: 120,
height: 120,
};
};
return (
<div style={{ position: "relative" }}>
<Space
size="middle"
style={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
height: "100%",
}}
>
<Space orientation="vertical" size="small">
<div
style={{
position: "absolute",
top: 0,
[isRTL ? "right" : "left"]: 0,
}}
>
<ProText
style={{
margin: 0,
lineClamp: 1,
fontSize: isMobile ? 14 : isTablet ? 16 : 18,
fontWeight: 600,
}}
>
{product.name}
</ProText>
<br />
<ProText
type="secondary"
className={`${styles.itemDescription} responsive-text`}
style={{
margin: 0,
lineClamp: 1,
padding: isMobile ? "3px 0" : isTablet ? 8 : 10,
fontSize: isMobile ? 14 : isTablet ? 18 : 20,
display: "-webkit-box",
WebkitBoxOrient: "vertical",
WebkitLineClamp: 1,
overflow: "hidden",
textOverflow: "ellipsis",
wordWrap: "break-word",
overflowWrap: "break-word",
lineHeight: "1.4",
maxHeight: isMobile ? "3em" : isTablet ? "5em" : "7em",
fontWeight: 500,
letterSpacing: "0.01em",
width: "100%",
}}
>
{product.type === "CartItem" &&
(isRTL
? product.variant?.optionsAR.map((o) => o.value).join(", ")
: product.variant?.options.map((o) => o.value).join(", "))}
{product.type === "OrderItem" && product.variantName}
</ProText>
{product.type === "CartItem"
? product.extrasgroupnew?.map((o) => (
<ProText
type="secondary"
className={`${styles.itemDescription} responsive-text`}
style={{
margin: 0,
lineClamp: 1,
padding: isMobile ? "3px 0" : isTablet ? 8 : 10,
fontSize: isMobile ? 14 : isTablet ? 18 : 20,
display: "-webkit-box",
WebkitBoxOrient: "vertical",
WebkitLineClamp: 1,
overflow: "hidden",
textOverflow: "ellipsis",
wordWrap: "break-word",
overflowWrap: "break-word",
lineHeight: "1.4",
maxHeight: isMobile ? "3em" : isTablet ? "5em" : "7em",
fontWeight: 500,
letterSpacing: "0.01em",
width: "100%",
}}
>
{isRTL ? o.extrasStringAR : o.extrasString}
</ProText>
))
: // ToDo
product.itemline}
</div>
<div
style={{
position: "absolute",
bottom: addDividerAfter ? 16 : 3,
[isRTL ? "right" : "left"]: 0,
}}
>
<ArabicPrice price={product.price} style={{ fontStyle: "bold" }} />
</div>
</Space>
<div style={{ position: "relative" }}>
<ImageWithFallback
src={product.image}
alt={product.name}
className={`${styles.menuItemImage} responsive-image`}
{...getMenuItemImageStyle()}
fallbackSrc={
"https://fascano-space.s3.me-central-1.amazonaws.com/uploads/restorants/685a8fc884a8c_large.jpg"
}
/>
{product.type === "CartItem" && (
<div
style={{
position: "absolute",
right: 3,
bottom: 3,
}}
>
<CartActionsButtons item={product} />
</div>
)}
</div>
</Space>
{addDividerAfter && <Divider style={{ margin: "10px 0" }} />}
</div>
);
}

View File

@@ -1,9 +1,6 @@
import { Card, Divider, Space, Layout, Button, Popconfirm } from "antd"; import { Card, Divider, Space, Layout, Button, Popconfirm } from "antd";
import ArabicPrice from "components/ArabicPrice";
import CartActionsButtons from "components/CartActionsButtons/CartActionsButtons.tsx";
import ImageWithFallback from "components/ImageWithFallback";
import ProHeader from "components/ProHeader/ProHeader.tsx"; import ProHeader from "components/ProHeader/ProHeader.tsx";
import ProText from "components/ProText.tsx";
import ProTitle from "components/ProTitle.tsx"; import ProTitle from "components/ProTitle.tsx";
import { clearCart, selectCart } from "features/order/orderSlice.ts"; import { clearCart, selectCart } from "features/order/orderSlice.ts";
import styles from "pages/cart/cart.module.css"; import styles from "pages/cart/cart.module.css";
@@ -20,10 +17,10 @@ import SpecialRequestCard from "pages/cart/components/specialRequest/SpecialRequ
import TableNumberCard from "pages/cart/components/TableNumberCard.tsx"; import TableNumberCard from "pages/cart/components/TableNumberCard.tsx";
import { OrderType } from "pages/checkout/hooks/types"; import { OrderType } from "pages/checkout/hooks/types";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Variant } from "utils/types/appTypes";
import DeleteIcon from "components/Icons/DeleteIcon"; import DeleteIcon from "components/Icons/DeleteIcon";
import PlusIcon from "components/Icons/PlusIcon"; import PlusIcon from "components/Icons/PlusIcon";
import { GiftItemsCard } from "pages/redeem/components/GiftItemsCard"; import { GiftItemsCard } from "pages/redeem/components/GiftItemsCard";
import ProductChoicesCard from "components/productChoicesCard/ProductChoicesCard.tsx";
interface CartMobileTabletLayoutProps { interface CartMobileTabletLayoutProps {
form: FormInstance; form: FormInstance;
@@ -41,18 +38,6 @@ export default function CartMobileTabletLayout({
const getResponsiveClass = () => (isTablet ? "tablet" : "mobile"); const getResponsiveClass = () => (isTablet ? "tablet" : "mobile");
const navigate = useNavigate(); const navigate = useNavigate();
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const getMenuItemImageStyle = () => {
if (isMobile) {
return {
width: 115,
height: 96,
};
}
return {
width: 120,
height: 120,
};
};
return ( return (
<Layout> <Layout>
@@ -137,112 +122,11 @@ export default function CartMobileTabletLayout({
<Divider style={{ margin: "8px 0px 12px 0px" }} /> <Divider style={{ margin: "8px 0px 12px 0px" }} />
)} )}
{items.map((item, index) => ( {items.map((item, index) => (
<div key={index} style={{ position: "relative" }}> <ProductChoicesCard
<Space key={index}
size="middle" product={item}
style={{ addDividerAfter={index !== items.length - 1}
display: "flex", />
alignItems: "center",
justifyContent: "space-between",
height: "100%",
}}
>
<Space orientation="vertical" size="small">
<div
style={{
position: "absolute",
top: 0,
[isRTL ? "right" : "left"]: 0,
}}
>
<ProText
style={{
margin: 0,
lineClamp: 1,
fontSize: isMobile ? 14 : isTablet ? 16 : 18,
fontWeight: 600,
}}
>
{item.name}{" "}
<span
style={{
fontWeight: 400,
}}
>
{isRTL
? (item.variant as Variant)?.optionsAR?.[0]?.value
: (item.variant as Variant)?.options?.[0]?.value}
</span>
</ProText>
<br />
<ProText
type="secondary"
className={`${styles.itemDescription} responsive-text`}
style={{
margin: 0,
lineClamp: 1,
padding: isMobile ? "3px 0" : isTablet ? 8 : 10,
fontSize: isMobile ? 14 : isTablet ? 18 : 20,
display: "-webkit-box",
WebkitBoxOrient: "vertical",
WebkitLineClamp: 1,
overflow: "hidden",
textOverflow: "ellipsis",
wordWrap: "break-word",
overflowWrap: "break-word",
lineHeight: "1.4",
maxHeight: isMobile
? "3em"
: isTablet
? "5em"
: "7em",
fontWeight: 500,
letterSpacing: "0.01em",
width: "55%",
}}
>
{item.description}
</ProText>
</div>
<div
style={{
position: "absolute",
bottom: index !== items.length - 1 ? 16 : 3,
[isRTL ? "right" : "left"]: 0,
}}
>
<ArabicPrice
price={item.price}
style={{ fontStyle: "bold" }}
/>
</div>
</Space>
<div style={{ position: "relative" }}>
<ImageWithFallback
src={item.image}
alt={item.name}
className={`${styles.menuItemImage} responsive-image`}
{...getMenuItemImageStyle()}
fallbackSrc={
"https://fascano-space.s3.me-central-1.amazonaws.com/uploads/restorants/685a8fc884a8c_large.jpg"
}
/>
<div
style={{
position: "absolute",
right: 3,
bottom: 3,
}}
>
<CartActionsButtons item={item} />
</div>
</div>
</Space>
{index !== items.length - 1 && (
<Divider style={{ margin: "10px 0" }} />
)}
</div>
))} ))}
<Button <Button
style={{ width: "100%", marginTop: 24, color: "#4C4A58" }} style={{ width: "100%", marginTop: 24, color: "#4C4A58" }}

View File

@@ -106,7 +106,7 @@ export default function YouMightAlsoLike() {
price: item.price, price: item.price,
image: item.image, image: item.image,
description: item.description, description: item.description,
variant: "None", variant: undefined,
isHasLoyalty: item.isHasLoyalty, isHasLoyalty: item.isHasLoyalty,
no_of_stamps_give: item.no_of_stamps_give, no_of_stamps_give: item.no_of_stamps_give,
}, },

View File

@@ -1,6 +1,3 @@
import { Variant } from "pages/orders/types";
import { Extra3 } from "utils/types/appTypes";
export interface OrderDetails { export interface OrderDetails {
orderItems: OrderItem[]; orderItems: OrderItem[];
order: Order; order: Order;
@@ -18,7 +15,18 @@ export interface OrderDetails {
itemsImagePrefix: string; itemsImagePrefix: string;
} }
export interface OrderItem { type OrderVariant = {
id: number;
price: number;
options: string;
local_name: string;
optionsArray: { id: number; name: string }[];
OptionsList: string;
extras: any[];
};
export type OrderItem = {
type: "OrderItem";
id: number; id: number;
is_loyalty_used: number; is_loyalty_used: number;
no_of_stamps_give: number; no_of_stamps_give: number;
@@ -31,16 +39,19 @@ export interface OrderItem {
image: string; image: string;
imageName: string; imageName: string;
variantName: string; variantName: string;
variantLocalName?: string; variantLocalName: string;
extras: any[]; extras: any[];
descriptionEN: string;
descriptionAR: string;
itemline: string; itemline: string;
itemlineAR: string; itemlineAR: string;
itemlineAREN: string; itemlineAREN: string;
extrasgroups: any[]; extrasgroups: string[];
extragroupnew: any[];
itemComment: string; itemComment: string;
variant?: Variant; variant: OrderVariant;
itemExtras: any[]; itemExtras: any[];
AvaiilableVariantExtras: Extra3[]; AvaiilableVariantExtras: any[];
isPrinted: number; isPrinted: number;
category_id: number; category_id: number;
pos_order_id: string; pos_order_id: string;
@@ -56,7 +67,7 @@ export interface OrderItem {
pricing_method: string; pricing_method: string;
is_already_paid: number; is_already_paid: number;
hash_item: string; hash_item: string;
} };
export interface Order { export interface Order {
id: number; id: number;
@@ -247,5 +258,5 @@ export enum OrderType {
ToOffice = "office", ToOffice = "office",
Booking = "booking", Booking = "booking",
Pay = "pay", Pay = "pay",
Redeem = "redeem" Redeem = "redeem",
} }

View File

@@ -38,7 +38,7 @@ export function AddToCartButton({ item }: { item: Product }) {
// Find basic cart item (no variants/extras) - the one added by quick add // Find basic cart item (no variants/extras) - the one added by quick add
const basicCartItem = cartItemsForProduct.find( const basicCartItem = cartItemsForProduct.find(
(cartItem) => (cartItem) =>
(!cartItem.variant || cartItem.variant === "None") && !cartItem.variant &&
(!cartItem.extras || cartItem.extras.length === 0) && (!cartItem.extras || cartItem.extras.length === 0) &&
(!cartItem.extrasgroupnew || cartItem.extrasgroupnew.length === 0), (!cartItem.extrasgroupnew || cartItem.extrasgroupnew.length === 0),
); );
@@ -67,7 +67,7 @@ export function AddToCartButton({ item }: { item: Product }) {
price: item.price, price: item.price,
image: item.image, image: item.image,
description: item.description, description: item.description,
variant: "None", variant: undefined,
isHasLoyalty: item.isHasLoyalty, isHasLoyalty: item.isHasLoyalty,
no_of_stamps_give: item.no_of_stamps_give, no_of_stamps_give: item.no_of_stamps_give,
}, },
@@ -145,7 +145,7 @@ export function AddToCartButton({ item }: { item: Product }) {
price: item.price, price: item.price,
image: item.image, image: item.image,
description: item.description, description: item.description,
variant: "None", variant: undefined,
isHasLoyalty: item.isHasLoyalty, isHasLoyalty: item.isHasLoyalty,
no_of_stamps_give: item.no_of_stamps_give, no_of_stamps_give: item.no_of_stamps_give,
}, },

View File

@@ -1,19 +1,15 @@
import { Button, Card, Divider, Form, Layout, Space } from "antd"; import { Button, Card, Form, Layout } from "antd";
import { useGetOrderDetailsQuery } from "redux/api/others"; import { useGetOrderDetailsQuery } from "redux/api/others";
import { useAppSelector } from "redux/hooks";
import styles from "./OrderDetails.module.css"; import styles from "./OrderDetails.module.css";
import ProHeader from "components/ProHeader/ProHeader"; import ProHeader from "components/ProHeader/ProHeader";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import ProText from "components/ProText";
import useBreakPoint from "hooks/useBreakPoint";
import ImageWithFallback from "components/ImageWithFallback";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import ProductChoicesCard from "components/productChoicesCard/ProductChoicesCard.tsx";
export default function OrderDetails() { export default function OrderDetails() {
const { orderId } = useParams(); const { orderId } = useParams();
const { t } = useTranslation(); const { t } = useTranslation();
const { isRTL } = useAppSelector((state) => state.locale);
const { isMobile, isTablet } = useBreakPoint();
const { data: orderDetails } = useGetOrderDetailsQuery( const { data: orderDetails } = useGetOrderDetailsQuery(
{ {
@@ -25,138 +21,18 @@ export default function OrderDetails() {
}, },
); );
const getMenuItemImageStyle = () => {
if (isMobile) {
return {
width: 115,
height: 96,
};
}
return {
width: 120,
height: 120,
};
};
return ( return (
<Form layout="vertical"> <Form layout="vertical">
<Layout> <Layout>
<ProHeader>{t("order.yourOrder")}</ProHeader> <ProHeader>{t("order.yourOrder")}</ProHeader>
<Layout.Content className={styles.orderDetailsContainer}> <Layout.Content className={styles.orderDetailsContainer}>
<Card className={styles.cartItem}> <Card className={styles.cartItem}>
{orderDetails?.orderItems.map((item: any, index: number) => ( {orderDetails?.orderItems.map((item, index) => (
<div key={index} style={{ position: "relative" }}> <ProductChoicesCard
<Space key={index}
size="middle" product={item}
style={{ addDividerAfter={index !== orderDetails?.orderItems.length - 1}
display: "flex", />
alignItems: "center",
justifyContent: "space-between",
height: "100%",
padding: 8,
}}
>
<Space orientation="vertical" size="small">
<div
style={{
position: "absolute",
top: 8,
[isRTL ? "right" : "left"]: 8,
}}
>
<ProText
style={{
margin: 0,
lineClamp: 1,
fontSize: isMobile ? 14 : isTablet ? 16 : 18,
fontWeight: 600,
}}
>
{item.name}
<span
style={{
fontWeight: 400,
}}
>
{/* {isRTL
? (item.variant as Variant)?.optionsAR?.[0]?.value
: (item.variant as Variant)?.options?.[0]?.value} */}
</span>
</ProText>
<br />
<ProText
type="secondary"
style={{
margin: 0,
lineClamp: 1,
padding: isMobile ? "3px 0" : isTablet ? 8 : 10,
fontSize: isMobile ? 14 : isTablet ? 18 : 20,
display: "-webkit-box",
WebkitBoxOrient: "vertical",
WebkitLineClamp: 1,
overflow: "hidden",
textOverflow: "ellipsis",
wordWrap: "break-word",
overflowWrap: "break-word",
lineHeight: "1.4",
maxHeight: isMobile
? "3em"
: isTablet
? "5em"
: "7em",
fontWeight: 500,
letterSpacing: "0.01em",
width: "55%",
}}
>
{item.description}
</ProText>
</div>
<div
style={{
position: "absolute",
bottom:
index !== orderDetails?.orderItems?.length - 1
? 20
: 7,
[isRTL ? "right" : "left"]: 8,
}}
>
<Button
shape="circle"
iconPlacement="start"
size="small"
className={styles.addButton}
style={{
background: "#F5F5F6",
width: 28,
height: 28,
border: "none",
}}
>
<ProText style={{ color: "#1F1C2E" }}>
{item.qty}{" "}
</ProText>
</Button>
</div>
</Space>
<div style={{ position: "relative" }}>
<ImageWithFallback
src={item.image}
alt={item.name}
className={`${styles.menuItemImage} responsive-image`}
{...getMenuItemImageStyle()}
fallbackSrc={
"https://fascano-space.s3.me-central-1.amazonaws.com/uploads/restorants/685a8fc884a8c_large.jpg"
}
/>
</div>
</Space>
{index !== orderDetails?.orderItems?.length - 1 && (
<Divider style={{ margin: "16px 0" }} />
)}
</div>
))} ))}
</Card> </Card>
</Layout.Content> </Layout.Content>

View File

@@ -2,12 +2,9 @@ import { Button } from "antd";
import { ProBottomSheet } from "components/ProBottomSheet/ProBottomSheet.tsx"; import { ProBottomSheet } from "components/ProBottomSheet/ProBottomSheet.tsx";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAppSelector } from "redux/hooks";
import ProText from "components/ProText"; import ProText from "components/ProText";
import ArabicPrice from "components/ArabicPrice"; import ArabicPrice from "components/ArabicPrice";
import styles from "../order.module.css"; import styles from "../order.module.css";
import NextIcon from "components/Icons/NextIcon";
import BackIcon from "components/Icons/BackIcon";
interface SplitBillParticipantsBottomSheetProps { interface SplitBillParticipantsBottomSheetProps {
isOpen: boolean; isOpen: boolean;
@@ -19,7 +16,6 @@ export function SplitBillParticipantsBottomSheet({
onClose, onClose,
}: SplitBillParticipantsBottomSheetProps) { }: SplitBillParticipantsBottomSheetProps) {
const { t } = useTranslation(); const { t } = useTranslation();
const { isRTL } = useAppSelector((state) => state.locale);
const taxesChargesStyle = { const taxesChargesStyle = {
fontWeight: 400, fontWeight: 400,
@@ -59,13 +55,15 @@ export function SplitBillParticipantsBottomSheet({
placeItems: "center", placeItems: "center",
}} }}
> >
<div style={{ <div
display: "flex", style={{
flexDirection: "row", display: "flex",
justifyContent: "flex-start", flexDirection: "row",
placeItems: "center", justifyContent: "flex-start",
gap: 10, placeItems: "center",
}}> gap: 10,
}}
>
<Button <Button
shape="circle" shape="circle"
iconPlacement="start" iconPlacement="start"

View File

@@ -1,92 +1,93 @@
export interface ProductDetails { export interface ProductDetails {
data: Daum[] data: Daum[];
name: string name: string;
nameAR: string nameAR: string;
image: string image: string;
price: number price: number;
variants: Variant[] variants: Variant[];
theExtrasGroups: TheExtrasGroup[] theExtrasGroups: TheExtrasGroup[];
discount: number discount: number;
options: Option[] options: Option[];
hasVariants: number hasVariants: number;
currency: string currency: string;
short_description: string short_description: string;
short_descriptionAR: string short_descriptionAR: string;
} }
export interface Daum { export interface Daum {
id: number id: number;
name: string name: string;
data: string[] data: string[];
prices: string[] prices: string[];
pricesNew: string[] pricesNew: string[];
nameAR: string nameAR: string;
dataAR: string[] dataAR: string[];
} }
type VariantOptionType = { option: string; value: string };
export interface Variant { export interface Variant {
id: number id: number;
price: number price: number;
options: string options: VariantOptionType[];
image: string optionsAR: VariantOptionType[];
qty: number image: string;
enable_qty: number qty: number;
order: number enable_qty: number;
item_id: number order: number;
created_at: string item_id: number;
updated_at: string created_at: string;
deleted_at: any updated_at: string;
available: string deleted_at: any;
OptionsList: string available: string;
extras: any[] OptionsList: string;
} extras: any[];
}
export interface TheExtrasGroup { export interface TheExtrasGroup {
id: number id: number;
name: string name: string;
nameAR: string nameAR: string;
label: string label: string;
labelAR: string labelAR: string;
limit: number limit: number;
item_id: number item_id: number;
created_at: string created_at: string;
updated_at: string updated_at: string;
deleted_at: any deleted_at: any;
force_limit_selection: number force_limit_selection: number;
extras: Extra[] extras: Extra[];
} }
export interface Extra { export interface Extra {
id: number id: number;
item_id: number item_id: number;
price: number price: number;
name: string name: string;
nameAR: string nameAR: string;
created_at: string created_at: string;
updated_at: string updated_at: string;
deleted_at: any deleted_at: any;
extra_for_all_variants: number extra_for_all_variants: number;
is_custome: number is_custome: number;
is_available: number is_available: number;
modifier_id: any modifier_id: any;
pivot: Pivot pivot: Pivot;
} }
export interface Pivot { export interface Pivot {
group_id: number group_id: number;
extra_id: number extra_id: number;
} }
export interface Option {
id: number
item_id: number
name: string
nameAR: string
options: string
optionsAR: string
optionprices: string
created_at: string
updated_at: string
deleted_at: any
}
export interface Option {
id: number;
item_id: number;
name: string;
nameAR: string;
options: string;
optionsAR: string;
optionprices: string;
created_at: string;
updated_at: string;
deleted_at: any;
}

View File

@@ -85,10 +85,23 @@ export default function ProductFooter({
comment: specialRequest, comment: specialRequest,
variant: selectedVariant, variant: selectedVariant,
extras: selectedExtras, extras: selectedExtras,
extrasgroupnew: Object.keys(selectedGroups).map((key) => ({ extrasgroupnew: Object.keys(selectedGroups).map((key) => {
groupid: key, const groupInfo = product.theExtrasGroups?.find(
extrasid: selectedGroups[Number(key)], (g) => g.id.toString() === key,
})), );
const selectedGroupExtrasIds = selectedGroups[Number(key)];
const extrasInfo = groupInfo?.extras.filter((e) =>
selectedGroupExtrasIds.includes(e.id.toString()),
);
console.log(extrasInfo);
return {
groupid: key,
extrasid: selectedGroupExtrasIds,
extrasString: `${groupInfo?.name}: ${extrasInfo?.map((e) => e.name).join(", ")}`,
extrasStringAR: `${groupInfo?.nameAR}: ${extrasInfo?.map((e) => e.nameAR).join(" + ")}`,
};
}),
extrasgroup: Object.entries(selectedGroups).flatMap( extrasgroup: Object.entries(selectedGroups).flatMap(
([groupId, extrasIds]) => { ([groupId, extrasIds]) => {
if (!extrasIds || extrasIds.length === 0) { if (!extrasIds || extrasIds.length === 0) {
@@ -117,7 +130,7 @@ export default function ProductFooter({
}), }),
); );
// Navigate back to menu - scroll position will be restored automatically // Navigate back to menu - scroll position will be restored automatically
if (!isDesktop && !isBottomSheetView ) window.history.back(); if (!isDesktop && !isBottomSheetView) window.history.back();
else { else {
onClose?.(); onClose?.();
} }
@@ -175,46 +188,44 @@ export default function ProductFooter({
width: "100%", width: "100%",
}} }}
> >
<ActionsButtons <ActionsButtons
quantity={quantity} quantity={quantity}
setQuantity={setQuantity} setQuantity={setQuantity}
max={100} max={100}
min={1} min={1}
/> />
<Button <Button
type="primary" type="primary"
icon={<ShoppingCartOutlined />} icon={<ShoppingCartOutlined />}
onClick={handleAddToCart} onClick={handleAddToCart}
disabled={!isValid} disabled={!isValid}
style={{ style={{
flex: 1, flex: 1,
height: 48, height: 48,
fontSize: isMobile ? "1rem" : "16px", fontSize: isMobile ? "1rem" : "16px",
transition: "all 0.3s ease", transition: "all 0.3s ease",
width: "100%", width: "100%",
borderRadius: 888, borderRadius: 888,
boxShadow: "none", boxShadow: "none",
backgroundColor: isValid backgroundColor: isValid
? colors.primary ? colors.primary
: "rgba(233, 233, 233, 1)", : "rgba(233, 233, 233, 1)",
color: isValid ? "#FFF" : "#999", color: isValid ? "#FFF" : "#999",
cursor: isValid ? "pointer" : "not-allowed", cursor: isValid ? "pointer" : "not-allowed",
}} }}
onMouseEnter={(e) => { onMouseEnter={(e) => {
if (!isMobile && isValid) { if (!isMobile && isValid) {
e.currentTarget.style.transform = "translateY(-2px)"; e.currentTarget.style.transform = "translateY(-2px)";
} }
}} }}
onMouseLeave={(e) => { onMouseLeave={(e) => {
if (!isMobile) { if (!isMobile) {
e.currentTarget.style.transform = "translateY(0)"; e.currentTarget.style.transform = "translateY(0)";
} }
}} }}
> >
{isValid {isValid ? t("menu.addToCart") : t("menu.selectRequiredOptions")}
? t("menu.addToCart") </Button>
: t("menu.selectRequiredOptions")}
</Button>
</div> </div>
</div> </div>
</Row> </Row>

View File

@@ -314,24 +314,29 @@ export interface Translation {
// ################################################# // #################################################
export interface CartItem { export type CartItem = {
type: "CartItem";
id: number | string; id: number | string;
name: string; name: string;
price: number; price: number;
image: string; image: string;
quantity: number; quantity: number;
description: string; description: string;
variant?: Variant | string; variant?: Variant;
extras?: Extra[]; extras?: Extra[];
extrasgroupnew?: Array<{ groupid: string; extrasid: Array<string> }>; extrasgroupnew?: Array<{
groupid: string;
extrasid: Array<string>;
extrasString: string;
extrasStringAR: string;
}>;
extrasgroup?: Array<string>; extrasgroup?: Array<string>;
isHasLoyalty?: boolean; isHasLoyalty?: boolean;
no_of_stamps_give?: number; no_of_stamps_give?: number;
comment?: string; comment?: string;
// Unique identifier for cart items with the same product but different variants/extras/comments // Unique identifier for cart items with the same product but different variants/extras/comments
uniqueId?: string; uniqueId?: string;
};
}
export interface UserType { export interface UserType {
id: number; id: number;
@@ -616,8 +621,17 @@ export interface Option {
export interface Extra { export interface Extra {
id: number; id: number;
item_id: number;
price: number; price: number;
name: string; name: string;
nameAR: string;
created_at: string;
updated_at: string;
deleted_at: any;
extra_for_all_variants: number;
is_custome: number;
is_available: number;
modifier_id: any;
} }
export interface TheExtrasGroup { export interface TheExtrasGroup {