Compare commits

..

10 Commits

31 changed files with 1166 additions and 582 deletions

View File

@@ -377,7 +377,10 @@
"howWasYourExperienceWithFascanoRestaurant": "كيف كانت تجربتك مع مطعم فاسكانو؟", "howWasYourExperienceWithFascanoRestaurant": "كيف كانت تجربتك مع مطعم فاسكانو؟",
"rateOrder": "تقييم الطلب", "rateOrder": "تقييم الطلب",
"submitRating": "إرسال التقييم", "submitRating": "إرسال التقييم",
"pleaseLoginToAllowRating": "يرجى تسجيل الدخول لتمكين التقييم" "pleaseLoginToAllowRating": "يرجى تسجيل الدخول لتمكين التقييم",
"remainingTime": "الوقت المتبقي",
"sec": "ثانية",
"min": "دقيقة"
}, },
"orderTypes": { "orderTypes": {
"dine-in": "في المطعم", "dine-in": "في المطعم",
@@ -425,7 +428,11 @@
"yourAmount": "مبلغك", "yourAmount": "مبلغك",
"selectedTotal": "المجموع المحدد", "selectedTotal": "المجموع المحدد",
"splitBillAmount": "مبلغ تقسيم الفاتورة", "splitBillAmount": "مبلغ تقسيم الفاتورة",
"removeSplitWay": "إزالة طريقة التقسيم", "removeSplit": "إزالة التقسيم",
"amount": "المبلغ" "amount": "المبلغ",
"howMuchWouldYouLikeToPay": "كم مبلغ تريد دفعه؟",
"confirm": "تأكيد",
"totalBill": "الفاتورة الكلية",
"remainingToPay": "المبلغ المتبقي"
} }
} }

View File

@@ -388,7 +388,10 @@
"howWasYourExperienceWithFascanoRestaurant": "How was your experience with Fascano Restaurant?", "howWasYourExperienceWithFascanoRestaurant": "How was your experience with Fascano Restaurant?",
"rateOrder": "Rate Order", "rateOrder": "Rate Order",
"submitRating": "Submit Rating", "submitRating": "Submit Rating",
"pleaseLoginToAllowRating": "Please login to allow rating" "pleaseLoginToAllowRating": "Please login to allow rating",
"remainingTime": "Remaining Time",
"sec": "Sec",
"min": "Min"
}, },
"orderTypes": { "orderTypes": {
"dine-in": "Dine In", "dine-in": "Dine In",
@@ -437,7 +440,11 @@
"yourAmount": "Your Amount", "yourAmount": "Your Amount",
"selectedTotal": "Selected Total", "selectedTotal": "Selected Total",
"splitBillAmount": "Split Bill Amount", "splitBillAmount": "Split Bill Amount",
"removeSplitWay": "Remove Split Way", "removeSplit": "Remove Split",
"amount": "Amount" "amount": "Amount",
"howMuchWouldYouLikeToPay": "How much would you like to pay?",
"confirm": "Confirm",
"totalBill": "Total Bill",
"remainingToPay": "Remaining to Pay"
} }
} }

View File

@@ -1,7 +1,7 @@
.quantityControls { .quantityControls {
display: flex; display: flex;
align-items: center; align-items: center;
background-color: #ffb70014; background-color: var(--background);
border-radius: 888px; border-radius: 888px;
width: fit-content; width: fit-content;
} }
@@ -15,7 +15,7 @@
.quantityInputContainer { .quantityInputContainer {
display: flex; display: flex;
align-items: center; align-items: center;
padding: 8px; padding: 0 1px;
border-radius: 888px; border-radius: 888px;
width: 100px; width: 100px;
height: 32px; height: 32px;
@@ -77,10 +77,15 @@
} }
.plusIcon { .plusIcon {
margin-bottom: 1px; margin-bottom: 1px;
color: var(--secondary-background);
}
.minusIcon {
color: var(--secondary-foreground);
} }
.deleteIcon { .deleteIcon {
position: relative; position: relative;
right: 1px; right: 1px;
} }

View File

@@ -1,7 +1,6 @@
import { MinusOutlined } from "@ant-design/icons"; import { MinusOutlined, PlusOutlined } from "@ant-design/icons";
import { Button, Grid, InputNumber, Popconfirm } from "antd"; import { Button, Grid, InputNumber, Popconfirm } from "antd";
import DeleteIcon from "components/Icons/DeleteIcon"; import DeleteIcon from "components/Icons/DeleteIcon";
import PlusIcon from "components/Icons/PlusIcon";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAppSelector } from "redux/hooks"; import { useAppSelector } from "redux/hooks";
import { colors } from "../../ThemeConstants"; import { colors } from "../../ThemeConstants";
@@ -51,14 +50,19 @@ export default function ActionsButtons({
<div className={styles.quantityInputContainer}> <div className={styles.quantityInputContainer}>
{quantity > 0 ? ( {quantity > 0 ? (
<Button <Button
type="text" shape="circle"
iconPlacement="start"
icon={<MinusOutlined title="add" className={styles.minusIcon} />}
size="small" size="small"
onClick={() => setQuantity(Math.max(1, quantity - 1))} onClick={() => setQuantity(Math.max(1, quantity - 1))}
className={styles.quantityButton} className={styles.quantityButton}
{...(min && { disabled: quantity === min })} {...(min && { disabled: quantity === min })}
> style={{
<MinusOutlined style={{ fontSize: 16, color: colors.primary }} /> width: 28,
</Button> height: 28,
border: "none",
}}
/>
) : ( ) : (
<Popconfirm <Popconfirm
title={t("cart.deleteConfirmation.title")} title={t("cart.deleteConfirmation.title")}
@@ -70,17 +74,20 @@ export default function ActionsButtons({
placement={isRTL ? "left" : "right"} placement={isRTL ? "left" : "right"}
styles={{ styles={{
root: getPopconfirmOverlayStyle(), root: getPopconfirmOverlayStyle(),
body: {
padding: xs ? "12px" : "16px",
},
}} }}
> >
<Button <Button
type="text" shape="circle"
iconPlacement="start"
icon={<DeleteIcon />}
size="small" size="small"
danger className={styles.addButton}
icon={<DeleteIcon className={styles.deleteIcon} />} style={{
className={styles.removeButton} background: "#FEF2F2",
width: 28,
height: 28,
border: "none",
}}
/> />
</Popconfirm> </Popconfirm>
)} )}
@@ -88,21 +95,27 @@ export default function ActionsButtons({
min={min || 1} min={min || 1}
max={max || 100} max={max || 100}
value={quantity || 1} value={quantity || 1}
onChange={(value) => setQuantity(value || 1)} onChange={(value: number | null) => setQuantity(value || 1)}
size="small" size="small"
controls={false} controls={false}
className={styles.quantityInput} className={styles.quantityInput}
name="id" name="id"
/> />
<Button <Button
type="text" shape="circle"
iconPlacement="start"
icon={<PlusOutlined title="add" className={styles.plusIcon} />}
size="small" size="small"
onClick={() => setQuantity(Math.min(100, quantity + 1))} onClick={() => setQuantity(Math.min(100, quantity + 1))}
className={styles.quantityButton} className={styles.quantityButton}
{...(max && { disabled: quantity >= max })} {...(max && { disabled: quantity >= max })}
> style={{
<PlusIcon className={styles.plusIcon} /> backgroundColor: colors.primary,
</Button> width: 28,
height: 28,
border: "none",
}}
/>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -40,6 +40,7 @@
box-shadow: none; box-shadow: none;
font-size: 16px; font-size: 16px;
font-weight: 600; font-weight: 600;
padding: 0;
} }
.removeButton { .removeButton {
@@ -55,7 +56,6 @@
position: absolute; position: absolute;
top: 12px; top: 12px;
right: 12px; right: 12px;
background-color: #ffb70014;
border-radius: 50%; border-radius: 50%;
padding: 8px; padding: 8px;
cursor: pointer; cursor: pointer;

View File

@@ -46,7 +46,7 @@ export default function CartActionsButtons({ item }: { item: CartItem }) {
{item.quantity > 1 ? ( {item.quantity > 1 ? (
<Button <Button
shape="circle" shape="circle"
iconPosition="start" iconPlacement="start"
icon={<MinusOutlined title="add" className={styles.minusIcon} />} icon={<MinusOutlined title="add" className={styles.minusIcon} />}
size="small" size="small"
onClick={() => onClick={() =>
@@ -76,14 +76,11 @@ export default function CartActionsButtons({ item }: { item: CartItem }) {
placement={isRTL ? "left" : "right"} placement={isRTL ? "left" : "right"}
styles={{ styles={{
root: getPopconfirmOverlayStyle(), root: getPopconfirmOverlayStyle(),
body: {
padding: isMobile ? "12px" : "16px",
},
}} }}
> >
<Button <Button
shape="circle" shape="circle"
iconPosition="start" iconPlacement="start"
icon={<DeleteIcon />} icon={<DeleteIcon />}
size="small" size="small"
onClick={() => onClick={() =>
@@ -109,7 +106,7 @@ export default function CartActionsButtons({ item }: { item: CartItem }) {
min={1} min={1}
max={100} max={100}
value={item.quantity || 1} value={item.quantity || 1}
onChange={(value) => onChange={(value: number | null) =>
dispatch( dispatch(
updateQuantity({ updateQuantity({
id: item.id, id: item.id,
@@ -125,7 +122,7 @@ export default function CartActionsButtons({ item }: { item: CartItem }) {
/> />
<Button <Button
shape="circle" shape="circle"
iconPosition="start" iconPlacement="start"
icon={<PlusOutlined title="add" className={styles.plusIcon} />} icon={<PlusOutlined title="add" className={styles.plusIcon} />}
size="small" size="small"
onClick={() => onClick={() =>

View File

@@ -110,7 +110,7 @@ export function GiftBottomSheet({
<ProPhoneInput <ProPhoneInput
propName="senderPhone" propName="senderPhone"
label={t("address.receiverPhone")} label={t("address.senderPhone")}
/> />
<Form.Item <Form.Item

View File

@@ -6,20 +6,17 @@ interface DeleteIconType {
const DeleteIcon = ({ className, onClick }: DeleteIconType) => { const DeleteIcon = ({ className, onClick }: DeleteIconType) => {
return ( return (
<svg <svg
width="16" width="12"
height="16" height="12"
viewBox="0 0 16 16" viewBox="0 0 12 12"
fill="none" fill="none"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
className={className} className={className}
onClick={onClick} onClick={onClick}
> >
<path <path
d="M6 2H10M2 4H14M12.6667 4L12.1991 11.0129C12.129 12.065 12.0939 12.5911 11.8667 12.99C11.6666 13.3412 11.3648 13.6235 11.0011 13.7998C10.588 14 10.0607 14 9.00623 14H6.99377C5.93927 14 5.41202 14 4.99889 13.7998C4.63517 13.6235 4.33339 13.3412 4.13332 12.99C3.90607 12.5911 3.871 12.065 3.80086 11.0129L3.33333 4M6.66667 7V10.3333M9.33333 7V10.3333" d="M3 2.4V0.6C3 0.44087 3.06321 0.288258 3.17574 0.175736C3.28826 0.0632141 3.44087 0 3.6 0H8.4C8.55913 0 8.71174 0.0632141 8.82426 0.175736C8.93679 0.288258 9 0.44087 9 0.6V2.4H12V3.6H10.8V11.4C10.8 11.5591 10.7368 11.7117 10.6243 11.8243C10.5117 11.9368 10.3591 12 10.2 12H1.8C1.64087 12 1.48826 11.9368 1.37574 11.8243C1.26321 11.7117 1.2 11.5591 1.2 11.4V3.6H0V2.4H3ZM6.8484 7.2L7.9092 6.1392L7.0608 5.2908L6 6.3516L4.9392 5.2908L4.0908 6.1392L5.1516 7.2L4.0908 8.2608L4.9392 9.1092L6 8.0484L7.0608 9.1092L7.9092 8.2608L6.8484 7.2ZM4.2 1.2V2.4H7.8V1.2H4.2Z"
stroke="#FF6F59" fill="#DC2626"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/> />
</svg> </svg>
); );

View File

@@ -43,7 +43,7 @@ export default function OrderSummary() {
<Card className={`${styles.orderSummary}`}> <Card className={`${styles.orderSummary}`}>
<ProTitle style={{ fontSize: 18 }}>{t("cart.orderSummary")}</ProTitle> <ProTitle style={{ fontSize: 18 }}>{t("cart.orderSummary")}</ProTitle>
<Divider style={{ margin: "15px 0 15px 0" }} /> <Divider style={{ margin: "15px 0 15px 0" }} />
<Space direction="vertical" style={{ width: "100%" }}> <Space orientation="vertical" style={{ width: "100%" }}>
<div className={styles.summaryRow}> <div className={styles.summaryRow}>
<ProText type="secondary">{t("cart.basketTotal")}</ProText> <ProText type="secondary">{t("cart.basketTotal")}</ProText>
<ArabicPrice price={subtotal} /> <ArabicPrice price={subtotal} />

View File

@@ -88,7 +88,7 @@ const PaymentMethods = () => {
}} }}
size="large" size="large"
> >
<Space direction="vertical" style={{ width: "100%" }}> <Space orientation="vertical" style={{ width: "100%" }}>
{options.map((option) => ( {options.map((option) => (
<div key={option.value}> <div key={option.value}>
<Radio <Radio

View File

@@ -16,6 +16,7 @@ interface ProBottomSheetProps {
initialSnap?: number; initialSnap?: number;
className?: string; className?: string;
themeName?: "light" | "dark"; themeName?: "light" | "dark";
contentStyle?: React.CSSProperties;
} }
export function ProBottomSheet({ export function ProBottomSheet({
@@ -30,6 +31,7 @@ export function ProBottomSheet({
snapPoints = [500], snapPoints = [500],
initialSnap = 0, initialSnap = 0,
className = "", className = "",
contentStyle = {},
}: ProBottomSheetProps) { }: ProBottomSheetProps) {
const [currentSnap, setCurrentSnap] = useState(initialSnap); const [currentSnap, setCurrentSnap] = useState(initialSnap);
const [isDragging, setIsDragging] = useState(false); const [isDragging, setIsDragging] = useState(false);
@@ -231,12 +233,13 @@ export function ProBottomSheet({
backdropFilter: themeName === "dark" ? "blur(8px)" : "none", backdropFilter: themeName === "dark" ? "blur(8px)" : "none",
}; };
const contentStyle: React.CSSProperties = { const contentWrapperStyle: React.CSSProperties = {
flex: 1, flex: 1,
overflow: "auto", overflow: "auto",
padding: "0 20px", padding: "0 20px",
backgroundColor: themeName === "dark" ? "#0a0a0a" : "#ffffff", backgroundColor: themeName === "dark" ? "#0a0a0a" : "#ffffff",
color: themeName === "dark" ? "#ffffff" : "#000000", color: themeName === "dark" ? "#ffffff" : "#000000",
...contentStyle,
}; };
const closeButtonStyle: React.CSSProperties = { const closeButtonStyle: React.CSSProperties = {
@@ -315,7 +318,7 @@ export function ProBottomSheet({
</div> </div>
)} )}
<div style={contentStyle}>{children}</div> <div style={contentWrapperStyle}>{children}</div>
</div> </div>
</> </>
); );

View File

@@ -69,10 +69,9 @@ export default function HeaderMenuDrawer() {
maskClosable={false} maskClosable={false}
onClose={closeMobileMenu} onClose={closeMobileMenu}
open={mobileMenuOpen} open={mobileMenuOpen}
width={isMobile ? "50%" : "25%"}
styles={{ styles={{
body: { body: {
padding: 0, padding: 0,
}, },
header: { header: {
padding: "5px 24px", padding: "5px 24px",
@@ -80,6 +79,9 @@ export default function HeaderMenuDrawer() {
themeName === "dark" ? "#374151" : "#e5e7eb" themeName === "dark" ? "#374151" : "#e5e7eb"
}`, }`,
}, },
wrapper: {
width: isMobile ? "50%" : "25%",
},
}} }}
closeIcon={null} closeIcon={null}
> >

View File

@@ -169,6 +169,7 @@
gap: 1rem; gap: 1rem;
background-color: var(--secondary-background); background-color: var(--secondary-background);
box-shadow: none; box-shadow: none;
z-index: 999;
} }
.splitBillButton { .splitBillButton {

View File

@@ -69,7 +69,7 @@ export default function CartMobileTabletLayout({
className={`${styles.cartContainer} '${styles.cartLayout}' ${getResponsiveClass()}`} className={`${styles.cartContainer} '${styles.cartLayout}' ${getResponsiveClass()}`}
> >
<Space <Space
direction="vertical" orientation="vertical"
size={isMobile ? "middle" : isTablet ? "large" : "large"} size={isMobile ? "middle" : isTablet ? "large" : "large"}
style={{ width: "100%", gap: 16 }} style={{ width: "100%", gap: 16 }}
> >
@@ -124,7 +124,7 @@ export default function CartMobileTabletLayout({
<Divider style={{ margin: "0px 0px 10px 0px" }} /> <Divider style={{ margin: "0px 0px 10px 0px" }} />
)} )}
{items.map((item, index) => ( {items.map((item, index) => (
<div key={index}> <div key={index} style={{ position: "relative" }}>
<Space <Space
size="middle" size="middle"
style={{ style={{
@@ -134,12 +134,14 @@ export default function CartMobileTabletLayout({
height: "100%", height: "100%",
}} }}
> >
<Space <Space orientation="vertical" size="small">
direction="vertical" <div
size="small" style={{
style={{ flex: 1, gap: isMobile ? 32 : isTablet ? 24 : 32 }} position: "absolute",
> top: 0,
<div> [isRTL ? "right" : "left"]: 0,
}}
>
<ProText <ProText
style={{ style={{
margin: 0, margin: 0,
@@ -155,8 +157,10 @@ export default function CartMobileTabletLayout({
}} }}
> >
{isRTL {isRTL
? (item.variant as Variant)?.optionsAR?.[0]?.value ? (item.variant as Variant)?.optionsAR?.[0]
: (item.variant as Variant)?.options?.[0]?.value} ?.value
: (item.variant as Variant)?.options?.[0]
?.value}
</span> </span>
</ProText> </ProText>
<br /> <br />
@@ -176,9 +180,14 @@ export default function CartMobileTabletLayout({
wordWrap: "break-word", wordWrap: "break-word",
overflowWrap: "break-word", overflowWrap: "break-word",
lineHeight: "1.4", lineHeight: "1.4",
maxHeight: isMobile ? "2.8em" : isTablet ? "4.8em" : "6.8em", maxHeight: isMobile
? "2.8em"
: isTablet
? "4.8em"
: "6.8em",
fontWeight: 500, fontWeight: 500,
letterSpacing: "0.01em", letterSpacing: "0.01em",
width: "65%",
}} }}
> >
{item.description} {item.description}
@@ -186,20 +195,15 @@ export default function CartMobileTabletLayout({
</div> </div>
<div <div
style={{ style={{
display: "flex", position: "absolute",
flexDirection: "row", bottom: index !== items.length - 1 ? 16 : 6,
justifyContent: "start", [isRTL ? "right" : "left"]: 0,
gap: isMobile ? 20 : 24,
}} }}
> >
<ProText <ArabicPrice
strong price={item.price}
style={{ style={{ fontStyle: "bold" }}
fontSize: isMobile ? 14 : isTablet ? 16 : 18, />
}}
>
<ArabicPrice price={item.price} />
</ProText>
</div> </div>
</Space> </Space>
<div style={{ position: "relative" }}> <div style={{ position: "relative" }}>

View File

@@ -73,6 +73,7 @@ export default function TableNumberCard() {
width: "100%", width: "100%",
height: 50, height: 50,
fontSize: 12, fontSize: 12,
borderRadius: 888,
}} }}
onChange={(value) => { onChange={(value) => {
console.log(value); console.log(value);

View File

@@ -56,7 +56,7 @@
outline-offset: 4px; outline-offset: 4px;
} }
.youMightAlsoLikeContainer { .youMightAlsoLikeContainer {
height: 160px !important; height: 130px !important;
} }
.itemDescriptionIconsContainer { .itemDescriptionIconsContainer {
@@ -70,7 +70,7 @@
@media (min-width: 768px) and (max-width: 1024px) { @media (min-width: 768px) and (max-width: 1024px) {
.youMightAlsoLikeContainer { .youMightAlsoLikeContainer {
height: 210px !important; height: 190px !important;
} }
.itemDescriptionIconsContainer { .itemDescriptionIconsContainer {

View File

@@ -239,14 +239,6 @@ export default function YouMightAlsoLike() {
fallbackSrc={default_image} fallbackSrc={default_image}
/> />
<div
className={styles.itemDescriptionIconsContainer}
>
<ItemDescriptionIcons
className={styles.itemDescriptionIcons}
/>
</div>
<Space <Space
direction="vertical" direction="vertical"
size="small" size="small"
@@ -265,7 +257,11 @@ export default function YouMightAlsoLike() {
fontSize: isMobile ? 12 : isTablet ? 14 : 16, fontSize: isMobile ? 12 : isTablet ? 14 : 16,
width: isMobile ? 80 : isTablet ? 100 : 120, width: isMobile ? 80 : isTablet ? 100 : 120,
display: "inline-block", display: "inline-block",
fontWeight: 600, fontWeight: 500,
fontStyle: "Medium",
lineHeight: "140%",
letterSpacing: "0%",
marginTop: 8,
}} }}
> >
{item.name} {item.name}
@@ -282,7 +278,11 @@ export default function YouMightAlsoLike() {
textOverflow: "ellipsis", textOverflow: "ellipsis",
padding: isMobile ? 3 : isTablet ? "0 8px" : "0 10px", padding: isMobile ? 3 : isTablet ? "0 8px" : "0 10px",
fontSize: isMobile ? 12 : isTablet ? 14 : 16, fontSize: isMobile ? 12 : isTablet ? 14 : 16,
fontWeight: 500, fontWeight: 600,
fontStyle: "SemiBold",
lineHeight: "140%",
letterSpacing: "0%",
marginTop: 4,
}} }}
/> />
</Space> </Space>

View File

@@ -14,101 +14,99 @@ export function GiftCard() {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
return ( return (
<> <>
<ProInputCard title={t("address.giftDetails")}> <ProInputCard title={t("address.giftDetails")}>
<ProPhoneInput
propName="receiverPhone"
<ProPhoneInput label={t("address.receiverPhone")}
propName="receiverPhone" value={order?.receiverPhone}
label={t("address.receiverPhone")}
value={order?.receiverPhone}
onChange={(e) => {
dispatch(updateOrder({ ...order, receiverPhone: e }));
}}
/>
<Form.Item name="message" label={t("address.message")}>
<TextArea
placeholder={t("address.message")}
size="large"
style={{
fontSize: 14,
borderRadius: 10,
}}
rows={2}
autoFocus={false}
value={order?.senderName}
onChange={(e) => { onChange={(e) => {
dispatch(updateOrder({ ...order, senderName: e.target.value })); dispatch(updateOrder({ ...order, receiverPhone: e }));
}} }}
/> />
</Form.Item>
<Form.Item <Form.Item name="message" label={t("address.message")}>
name="senderName" <TextArea
label={t("address.senderName")} placeholder={t("address.message")}
rules={[{ required: true, message: "" }]} size="large"
colon={false} style={{
> fontSize: 14,
<Input borderRadius: 10,
placeholder={t("address.senderName")} }}
size="large" rows={2}
style={{ autoFocus={false}
fontSize: 14, value={order?.message}
height: 50, onChange={(e) => {
}} dispatch(updateOrder({ ...order, message: e.target.value }));
autoFocus={false} }}
/>
</Form.Item>
<Form.Item
name="senderName"
label={t("address.senderName")}
rules={[{ required: true, message: "" }]}
colon={false}
>
<Input
placeholder={t("address.senderName")}
size="large"
style={{
fontSize: 14,
height: 50,
}}
autoFocus={false}
value={order?.senderName}
onChange={(e) => {
dispatch(updateOrder({ ...order, senderName: e.target.value }));
}}
/>
</Form.Item>
<ProPhoneInput
propName="senderPhone"
label={t("address.senderPhone")}
value={order?.senderPhone} value={order?.senderPhone}
onChange={(e) => { onChange={(e) => {
dispatch(updateOrder({ ...order, senderPhone: e.target.value })); dispatch(updateOrder({ ...order, senderPhone: e }));
}} }}
/> />
</Form.Item>
<ProPhoneInput <Form.Item
propName="senderPhone" name="senderEmail"
label={t("address.receiverPhone")} label={t("address.senderEmail")}
/> rules={[{ required: true, message: "" }]}
colon={false}
<Form.Item
name="senderEmail"
label={t("address.senderEmail")}
rules={[{ required: true, message: "" }]}
colon={false}
>
<Input
placeholder={t("address.senderEmail")}
size="large"
style={{
fontSize: 14,
height: 50,
}}
autoFocus={false}
value={order?.senderEmail}
onChange={(e) => {
dispatch(updateOrder({ ...order, senderEmail: e.target.value }));
}}
/>
</Form.Item>
<Form.Item
name="isSecret"
rules={[{ required: true, message: "" }]}
colon={false}
>
<Checkbox
style={{
fontSize: 14,
}}
autoFocus={false}
checked={order?.isSecret}
onChange={(e) => {
dispatch(updateOrder({ ...order, isSecret: e.target.checked }));
}}
> >
<ProText>{t("address.keepMyNameSecret")}</ProText> <Input
</Checkbox> placeholder={t("address.senderEmail")}
</Form.Item> size="large"
</ProInputCard> style={{
fontSize: 14,
height: 50,
}}
autoFocus={false}
value={order?.senderEmail}
onChange={(e) => {
dispatch(updateOrder({ ...order, senderEmail: e.target.value }));
}}
/>
</Form.Item>
<Form.Item name="isSecret" colon={false}>
<Checkbox
style={{
fontSize: 14,
}}
autoFocus={false}
checked={order?.isSecret}
onChange={(e) => {
dispatch(updateOrder({ ...order, isSecret: e.target.checked }));
}}
>
<ProText>{t("address.keepMyNameSecret")}</ProText>
</Checkbox>
</Form.Item>
</ProInputCard>
</> </>
); );
} }

View File

@@ -8,7 +8,7 @@ import styles from "./AddToCartButton.module.css";
import { useAppSelector, useAppDispatch } from "redux/hooks"; import { useAppSelector, useAppDispatch } from "redux/hooks";
import { Product } from "utils/types/appTypes"; import { Product } from "utils/types/appTypes";
import NextIcon from "components/Icons/NextIcon"; import NextIcon from "components/Icons/NextIcon";
import { addItem, updateQuantity, removeItem } from "features/order/orderSlice"; import { addItem, removeItem, updateQuantity } from "features/order/orderSlice";
import ProText from "components/ProText"; import ProText from "components/ProText";
export function AddToCartButton({ item }: { item: Product }) { export function AddToCartButton({ item }: { item: Product }) {
@@ -26,7 +26,7 @@ export function AddToCartButton({ item }: { item: Product }) {
const cartItemsForProduct = items.filter((i) => i.id === item.id); const cartItemsForProduct = items.filter((i) => i.id === item.id);
const totalQuantity = cartItemsForProduct.reduce( const totalQuantity = cartItemsForProduct.reduce(
(total, item) => total + item.quantity, (total, item) => total + item.quantity,
0 0,
); );
const isInCart = totalQuantity > 0; const isInCart = totalQuantity > 0;
@@ -41,7 +41,7 @@ export function AddToCartButton({ item }: { item: Product }) {
(cartItem) => (cartItem) =>
(!cartItem.variant || cartItem.variant === "None") && (!cartItem.variant || cartItem.variant === "None") &&
(!cartItem.extras || cartItem.extras.length === 0) && (!cartItem.extras || cartItem.extras.length === 0) &&
(!cartItem.extrasgroupnew || cartItem.extrasgroupnew.length === 0) (!cartItem.extrasgroupnew || cartItem.extrasgroupnew.length === 0),
); );
const handleClick = () => { const handleClick = () => {
@@ -90,7 +90,7 @@ export function AddToCartButton({ item }: { item: Product }) {
id: basicCartItem.id, id: basicCartItem.id,
uniqueId: basicCartItem.uniqueId, uniqueId: basicCartItem.uniqueId,
quantity: basicCartItem.quantity - 1, quantity: basicCartItem.quantity - 1,
}) }),
); );
} else { } else {
// Remove item if quantity is 1 // Remove item if quantity is 1
@@ -106,7 +106,7 @@ export function AddToCartButton({ item }: { item: Product }) {
id: firstItem.id, id: firstItem.id,
uniqueId: firstItem.uniqueId, uniqueId: firstItem.uniqueId,
quantity: firstItem.quantity - 1, quantity: firstItem.quantity - 1,
}) }),
); );
} else { } else {
dispatch(removeItem(firstItem.uniqueId)); dispatch(removeItem(firstItem.uniqueId));
@@ -128,7 +128,7 @@ export function AddToCartButton({ item }: { item: Product }) {
id: basicCartItem.id, id: basicCartItem.id,
uniqueId: basicCartItem.uniqueId, uniqueId: basicCartItem.uniqueId,
quantity: basicCartItem.quantity + 1, quantity: basicCartItem.quantity + 1,
}) }),
); );
} else if (!hasOptions) { } else if (!hasOptions) {
// Add new basic item if no options // Add new basic item if no options
@@ -153,42 +153,24 @@ export function AddToCartButton({ item }: { item: Product }) {
} }
}; };
return isInCart ? ( return isInCart && !hasOptions ? (
<> <>
<div <div
className={styles.addButton} className={styles.addButton}
style={{ style={{
width: 107, width: 90,
height: 45, height: 30,
position: "absolute", position: "absolute",
bottom: -5, bottom: 3,
[isRTL ? "left" : "right"]: -4, [isRTL ? "left" : "right"]: 1,
backgroundColor: "var(--secondary-background)",
borderRadius: 888,
opacity: 0.8,
}} }}
> >
<svg
width="107"
height="45"
viewBox="0 0 107 45"
fill="none"
xmlns="http://www.w3.org/2000/svg"
style={{
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: "100%",
}}
>
<rect
width="107"
height="45"
rx="22.5"
className={styles.actionRect}
/>
</svg>
<Button <Button
shape="circle" shape="circle"
iconPosition="start" iconPlacement="start"
icon={<MinusOutlined title="minus" style={{ color: "black" }} />} icon={<MinusOutlined title="minus" style={{ color: "black" }} />}
size="small" size="small"
onClick={handleMinusClick} onClick={handleMinusClick}
@@ -198,16 +180,17 @@ export function AddToCartButton({ item }: { item: Product }) {
width: 28, width: 28,
height: 28, height: 28,
position: "absolute", position: "absolute",
bottom: 9, bottom: 1,
[isRTL ? "left" : "right"]: 70, [isRTL ? "left" : "right"]: 60,
minWidth: 28, minWidth: 28,
border: "none",
}} }}
/> />
<ProText <ProText
style={{ style={{
position: "absolute", position: "absolute",
bottom: 17, bottom: 7,
[isRTL ? "left" : "right"]: 50, [isRTL ? "left" : "right"]: 45,
fontSize: 14, fontSize: 14,
fontWeight: 700, fontWeight: 700,
fontStyle: "Bold", fontStyle: "Bold",
@@ -221,7 +204,7 @@ export function AddToCartButton({ item }: { item: Product }) {
</ProText> </ProText>
<Button <Button
shape="circle" shape="circle"
iconPosition="start" iconPlacement="start"
icon={<PlusOutlined title="plus" />} icon={<PlusOutlined title="plus" />}
size="small" size="small"
onClick={handlePlusClick} onClick={handlePlusClick}
@@ -231,53 +214,45 @@ export function AddToCartButton({ item }: { item: Product }) {
width: 28, width: 28,
height: 28, height: 28,
position: "absolute", position: "absolute",
bottom: 9, bottom: 1,
[isRTL ? "left" : "right"]: 10, [isRTL ? "left" : "right"]: 3,
minWidth: 28, minWidth: 28,
}} }}
/> />
</div> </div>
</> </>
) : ( ) : (
<> <div
<div style={{
position: "absolute",
bottom: -11,
[isRTL ? "left" : "right"]: -2,
borderRadius: "50%",
}}
>
<Button
shape="circle"
iconPlacement="start"
size="small"
icon={
hasOptions ? (
<NextIcon iconColor="#fff" iconSize={16} />
) : (
<PlusOutlined title="add" />
)
}
onClick={handleClick}
className={styles.addButton}
style={{ style={{
width: 48, backgroundColor: colors.primary,
height: 48, width: 28,
height: 28,
position: "absolute", position: "absolute",
bottom: -11, bottom: 16,
[isRTL ? "left" : "right"]: -2, [isRTL ? "left" : "right"]: 7,
backgroundColor: "var(--background)", minWidth: 28,
borderRadius: "50%",
}} }}
> />
<Button </div>
shape="circle"
iconPosition="start"
icon={
hasOptions ? (
<NextIcon
className={styles.plusIcon}
iconColor="#fff"
iconSize={16}
/>
) : (
<PlusOutlined title="add" className={styles.plusIcon} />
)
}
size="small"
onClick={handleClick}
className={styles.addButton}
style={{
backgroundColor: colors.primary,
width: 36,
height: 36,
position: "absolute",
bottom: 6,
[isRTL ? "left" : "right"]: 6,
}}
/>
</div>
</>
); );
} }

View File

@@ -48,7 +48,7 @@ export default function ProductCard({ item }: Props) {
key={item.id} key={item.id}
style={{ style={{
borderRadius: 8, borderRadius: 8,
height: 148, height: item.description ? 148 : 120,
overflow: "hide", overflow: "hide",
width: "100%", width: "100%",
boxShadow: "none", boxShadow: "none",
@@ -188,13 +188,13 @@ export default function ProductCard({ item }: Props) {
? styles.popularMenuItemImageTablet ? styles.popularMenuItemImageTablet
: styles.popularMenuItemImageDesktop : styles.popularMenuItemImageDesktop
}`} }`}
width={90} width={92}
height={90} height={92}
/> />
<AddToCartButton item={item} />
</Badge> </Badge>
</div> </div>
</div> </div>
<AddToCartButton item={item} />
</Card> </Card>
</div> </div>

View File

@@ -1,4 +1,4 @@
import { Button, Card, Divider, Image } from "antd"; import { Button, Card, Divider, Flex, Image, Progress, Tooltip } from "antd";
import Ads2 from "components/Ads/Ads2"; import Ads2 from "components/Ads/Ads2";
import { CancelOrderBottomSheet } from "components/CustomBottomSheet/CancelOrderBottomSheet"; import { CancelOrderBottomSheet } from "components/CustomBottomSheet/CancelOrderBottomSheet";
import LocationIcon from "components/Icons/LocationIcon"; import LocationIcon from "components/Icons/LocationIcon";
@@ -11,7 +11,7 @@ import ProInputCard from "components/ProInputCard/ProInputCard";
import ProText from "components/ProText"; import ProText from "components/ProText";
import ProTitle from "components/ProTitle"; import ProTitle from "components/ProTitle";
import dayjs from "dayjs"; import dayjs from "dayjs";
import { useEffect, useRef } from "react"; import { useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import { import {
@@ -74,6 +74,147 @@ export default function OrderPage() {
} }
}, [orderDetails?.status, restaurantSubdomain, refetchRestaurantDetails]); }, [orderDetails?.status, restaurantSubdomain, refetchRestaurantDetails]);
// Check if order is in progress (check last status alias)
const lastStatus = orderDetails?.status?.[orderDetails.status.length - 1];
const isInProgress = lastStatus?.alias === "accepted_by_restaurant";
// Calculate timer and progress
const [remainingSeconds, setRemainingSeconds] = useState<number>(0);
const [progressPercent, setProgressPercent] = useState<number>(0);
useEffect(() => {
if (
!isInProgress ||
!orderDetails?.order?.time_to_prepare ||
!orderDetails?.order?.created_at
) {
return;
}
const updateTimer = () => {
const orderCreatedAt = dayjs(orderDetails.order.created_at);
const now = dayjs();
const elapsedSeconds = now.diff(orderCreatedAt, "second");
// time_to_prepare is in minutes, convert to seconds
const totalSeconds =
(Number(orderDetails.order.time_to_prepare) || 0) * 60;
const remaining = Math.max(0, totalSeconds - elapsedSeconds);
setRemainingSeconds(remaining);
// Calculate progress as remaining time percentage (starts at 100%, decreases to 0%)
const percent =
totalSeconds > 0
? Math.min(100, Math.max(0, (remaining / totalSeconds) * 100))
: 100;
setProgressPercent(percent);
};
updateTimer();
const interval = setInterval(updateTimer, 1000);
return () => clearInterval(interval);
}, [
isInProgress,
orderDetails?.order?.time_to_prepare,
orderDetails?.status,
]);
// Format remaining time with Min and Sec labels
const formatTimer = (totalSeconds: number) => {
const mins = Math.floor(totalSeconds / 60);
const secs = Math.floor(totalSeconds % 60);
return (
<div
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
gap: 8,
}}
>
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
gap: 2,
}}
>
<ProText
style={{
fontWeight: 600,
fontStyle: "SemiBold",
fontSize: 28,
lineHeight: "100%",
letterSpacing: "0%",
color: "#CC9300",
}}
>
{mins.toString().padStart(2, "0")}
</ProText>
<ProText
style={{
fontWeight: 400,
fontStyle: "Regular",
fontSize: 12,
lineHeight: "140%",
letterSpacing: "0%",
color: "#CC9300",
}}
>
{t("order.min")}
</ProText>
</div>
<ProText
style={{
fontWeight: 600,
fontStyle: "SemiBold",
fontSize: 28,
lineHeight: "100%",
letterSpacing: "0%",
color: "#CC9300",
}}
>
:
</ProText>
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
gap: 2,
}}
>
<ProText
style={{
fontWeight: 600,
fontStyle: "SemiBold",
fontSize: 28,
lineHeight: "100%",
letterSpacing: "0%",
color: "#CC9300",
}}
>
{secs.toString().padStart(2, "0")}
</ProText>
<ProText
style={{
fontWeight: 400,
fontStyle: "Regular",
fontSize: 12,
lineHeight: "140%",
letterSpacing: "0%",
color: "#CC9300",
}}
>
{t("order.sec")}
</ProText>
</div>
</div>
);
};
return ( return (
<> <>
<ProHeader>{t("order.title")}</ProHeader> <ProHeader>{t("order.title")}</ProHeader>
@@ -126,7 +267,51 @@ export default function OrderPage() {
</div> </div>
</div> </div>
<OrderDishIcon className={styles.orderDishIcon} /> {isInProgress ? (
<Flex gap="small" wrap justify="center">
<Tooltip title="3 done / 3 in progress / 4 to do">
<div
style={{
transform: "scaleX(-1)",
}}
>
<Progress
percent={progressPercent}
format={() => (
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
gap: 4,
transform: "scaleX(-1)",
}}
>
<ProText
style={{
fontWeight: 400,
fontStyle: "Regular",
fontSize: 18,
lineHeight: "140%",
letterSpacing: "0%",
}}
>
{t("order.remainingTime")}
</ProText>
{formatTimer(remainingSeconds)}
</div>
)}
strokeColor="#FFB700"
size={200}
type="dashboard"
/>
</div>
</Tooltip>
</Flex>
) : (
<OrderDishIcon className={styles.orderDishIcon} />
)}
<div> <div>
<ProTitle <ProTitle

View File

@@ -9,7 +9,9 @@ import {
updateSplitBillAmount, updateSplitBillAmount,
} from "features/order/orderSlice"; } from "features/order/orderSlice";
import { useAppDispatch, useAppSelector } from "redux/hooks"; import { useAppDispatch, useAppSelector } from "redux/hooks";
import ProInputCard from "components/ProInputCard/ProInputCard"; import ProText from "components/ProText";
import ArabicPrice from "components/ArabicPrice";
import styles from "./SplitBill.module.css";
interface SplitBillChoiceBottomSheetProps { interface SplitBillChoiceBottomSheetProps {
isOpen: boolean; isOpen: boolean;
@@ -50,6 +52,14 @@ export function CustomAmountChoiceBottomSheet({
onClose(); onClose();
}; };
// Calculate preview values using local amount state for real-time updates
const currentAmount = parseFloat(amount) || 0;
// Original total bill (before split) = grandTotal + splitBillAmount (from Redux)
const originalTotalBill = grandTotal + splitBillAmount;
// Preview: total bill stays the same, remaining = original - current amount being typed
const previewTotalBill = originalTotalBill;
const previewRemaining = originalTotalBill - currentAmount;
return ( return (
<ProBottomSheet <ProBottomSheet
isOpen={isOpen} isOpen={isOpen}
@@ -57,56 +67,129 @@ export function CustomAmountChoiceBottomSheet({
title={t("splitBill.payAsCustomAmount")} title={t("splitBill.payAsCustomAmount")}
showCloseButton={true} showCloseButton={true}
initialSnap={1} initialSnap={1}
height={400} height={430}
snapPoints={[400]} snapPoints={[430]}
contentStyle={{
padding: 0,
}}
> >
<div <div
style={{ style={{
padding: "20px 0", padding: "20px",
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
gap: 20, gap: 20,
}} }}
> >
<div> <div>
<ProInputCard title={t("splitBill.payAsCustomAmount")}> <ProText
<Form.Item style={{
label={t("splitBill.amount")} fontWeight: 400,
name="amount" fontStyle: "Regular",
style={{ position: "relative", top: -5 }} fontSize: 16,
> lineHeight: "140%",
<InputNumber letterSpacing: "0%",
value={amount} }}
onChange={(value) => setAmount(value?.toString() || "")}
placeholder={t("splitBill.amount")}
max={grandTotal.toString()}
min={"0"}
style={{ width: "100%", fontSize:"1rem" }}
/>
</Form.Item>
</ProInputCard>
</div>
<div
style={{
display: "flex",
gap: 12,
marginTop: 20,
}}
>
<Button style={{ flex: 1 }} onClick={handleRemoveSplitWay}>
{t("splitBill.removeSplitWay")}
</Button>
<Button
type="primary"
style={{ flex: 1, boxShadow: "none" }}
onClick={handleSave}
disabled={!amount || parseFloat(amount) <= 0}
> >
{t("cart.save")} {t("splitBill.howMuchWouldYouLikeToPay")}
</Button> </ProText>
<Form.Item
label={t("splitBill.amount")}
name="amount"
style={{ position: "relative", top: -5 }}
>
<InputNumber
value={amount}
onChange={(value) => {
setAmount(value?.toString() || "");
dispatch(updateSplitBillAmount(Number(value) || 0));
}}
placeholder={t("splitBill.amount")}
max={(grandTotal + splitBillAmount).toString()}
min={"0"}
style={{ width: "100%", fontSize: "1rem" }}
/>
</Form.Item>
</div> </div>
</div> </div>
<div
style={{
display: "flex",
flexDirection: "column",
backgroundColor: "var(--background)",
padding: "20px",
opacity: 1,
gap: 8,
borderTopLeftRadius: 24,
borderTopRightRadius: 24,
paddingTop: 12,
paddingRight: 24,
paddingBottom: 24,
paddingLeft: 24,
}}
>
<div className={styles.summaryRow}>
<ProText
style={{
fontWeight: 400,
fontStyle: "Regular",
fontSize: 14,
lineHeight: "140%",
letterSpacing: "0%",
}}
>
{t("splitBill.totalBill")}
</ProText>
<ArabicPrice price={previewTotalBill} />
</div>
<div className={styles.summaryRow}>
<ProText
style={{
fontWeight: 400,
fontStyle: "Regular",
fontSize: 14,
lineHeight: "140%",
letterSpacing: "0%",
}}
>
{t("splitBill.remainingToPay")}
</ProText>
<ArabicPrice price={Math.max(0, previewRemaining)} />
</div>
</div>
<div
style={{
display: "flex",
gap: 12,
margin: 20,
}}
>
<Button
style={{
flex: 1,
backgroundColor: "#FEEDED",
color: "#DD4143",
boxShadow: "none",
border: "none",
}}
onClick={handleRemoveSplitWay}
>
{t("splitBill.removeSplit")}
</Button>
<Button
type="primary"
style={{
flex: 1,
boxShadow: "none",
}}
onClick={handleSave}
disabled={!amount || parseFloat(amount) <= 0}
>
{t("splitBill.confirm")}
</Button>
</div>
</ProBottomSheet> </ProBottomSheet>
); );
} }

View File

@@ -3,8 +3,8 @@ import { ProBottomSheet } from "components/ProBottomSheet/ProBottomSheet.tsx";
import { useMemo } from "react"; import { useMemo } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import PeopleIcon from "components/Icons/PeopleIcon";
import ProText from "components/ProText"; import ProText from "components/ProText";
import ArabicPrice from "components/ArabicPrice";
import { import {
selectCart, selectCart,
selectGrandTotal, selectGrandTotal,
@@ -14,6 +14,7 @@ import { useAppDispatch, useAppSelector } from "redux/hooks";
import { ProGray1 } from "ThemeConstants"; import { ProGray1 } from "ThemeConstants";
import PayForActions from "../../../split-bill/components/PayForActions"; import PayForActions from "../../../split-bill/components/PayForActions";
import TotalPeopleActions from "../../../split-bill/components/TotalPeopleActions"; import TotalPeopleActions from "../../../split-bill/components/TotalPeopleActions";
import styles from "./SplitBill.module.css";
interface SplitBillChoiceBottomSheetProps { interface SplitBillChoiceBottomSheetProps {
isOpen: boolean; isOpen: boolean;
@@ -34,20 +35,23 @@ export function EqualltyChoiceBottomSheet({
}: SplitBillChoiceBottomSheetProps) { }: SplitBillChoiceBottomSheetProps) {
const { t } = useTranslation(); const { t } = useTranslation();
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const { tmp } = useAppSelector(selectCart); const { tmp, splitBillAmount } = useAppSelector(selectCart);
const grandTotal = useAppSelector(selectGrandTotal); const grandTotal = useAppSelector(selectGrandTotal);
const splitBillTmp = tmp as SplitBillTmp; const splitBillTmp = tmp as SplitBillTmp;
const totalPeople = splitBillTmp?.totalPeople || 2; const totalPeople = splitBillTmp?.totalPeople || 2;
const payFor = splitBillTmp?.payFor || 1; const payFor = splitBillTmp?.payFor || 1;
// Calculate split amount // Calculate original total bill (grandTotal already subtracts splitBillAmount)
const originalTotalBill = grandTotal + splitBillAmount;
// Calculate split amount based on original total bill
const splitAmount = useMemo(() => { const splitAmount = useMemo(() => {
if (totalPeople > 0) { if (totalPeople > 0) {
return (grandTotal / totalPeople) * payFor; return (originalTotalBill / totalPeople) * payFor;
} }
return 0; return 0;
}, [grandTotal, totalPeople, payFor]); }, [originalTotalBill, totalPeople, payFor]);
const handleSave = () => { const handleSave = () => {
dispatch(updateSplitBillAmount(splitAmount)); dispatch(updateSplitBillAmount(splitAmount));
@@ -67,8 +71,11 @@ export function EqualltyChoiceBottomSheet({
title={t("splitBill.divideTheBillEqually")} title={t("splitBill.divideTheBillEqually")}
showCloseButton={true} showCloseButton={true}
initialSnap={1} initialSnap={1}
height={610} height={630}
snapPoints={[610]} snapPoints={[630]}
contentStyle={{
padding: 0,
}}
> >
<div <div
style={{ style={{
@@ -77,96 +84,6 @@ export function EqualltyChoiceBottomSheet({
marginTop: 20, marginTop: 20,
}} }}
> >
<div
style={{
display: "flex",
flexDirection: "column",
gap: "1rem",
}}
>
<div
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
gap: "1rem",
padding: 8,
}}
>
<div
style={{
display: "flex",
flexDirection: "row",
gap: "1rem",
}}
>
<Button
type="text"
shape="circle"
style={{
backgroundColor: "rgba(95, 108, 123, 0.05)",
position: "relative",
top: -10,
}}
>
<PeopleIcon />
</Button>
<ProText
style={{
fontSize: "1rem",
marginTop: 3,
color: ProGray1,
}}
>
{t("checkout.totalPeople")}
</ProText>
</div>
<TotalPeopleActions />
</div>
<div
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
gap: "1rem",
padding: 8,
}}
>
<div
style={{
display: "flex",
flexDirection: "row",
gap: "1rem",
}}
>
<Button
type="text"
shape="circle"
style={{
backgroundColor: "rgba(95, 108, 123, 0.05)",
position: "relative",
top: -10,
}}
>
<PeopleIcon />
</Button>
<ProText
style={{
fontSize: "1rem",
marginTop: 2,
color: ProGray1,
}}
>
{t("checkout.payFor")}
</ProText>
</div>
<PayForActions />
</div>
</div>
{/* Spinner Visualization - Blank Spin Wheel */} {/* Spinner Visualization - Blank Spin Wheel */}
{totalPeople > 0 && ( {totalPeople > 0 && (
<div <div
@@ -203,7 +120,7 @@ export function EqualltyChoiceBottomSheet({
const startAngleRad = (startAngle * Math.PI) / 180; const startAngleRad = (startAngle * Math.PI) / 180;
const endAngleRad = (endAngle * Math.PI) / 180; const endAngleRad = (endAngle * Math.PI) / 180;
// Calculate path for pie slice // Calculate path for pie slice (fit 200x200 viewBox)
const radius = 90; const radius = 90;
const centerX = 100; const centerX = 100;
const centerY = 100; const centerY = 100;
@@ -230,57 +147,189 @@ export function EqualltyChoiceBottomSheet({
isSelected ? "var(--primary)" : "rgba(0, 0, 0, 0.1)" isSelected ? "var(--primary)" : "rgba(0, 0, 0, 0.1)"
} }
stroke="#fff" stroke="#fff"
strokeWidth="2" strokeWidth="5"
/> />
); );
})} })}
</svg> </svg>
{/* Center circle to make it look like a blank wheel */} {/* Center circle with total bill amount */}
<div <div
style={{ style={{
position: "absolute", position: "absolute",
top: "50%", top: "50%",
left: "50%", left: "50%",
transform: "translate(-50%, -50%)", transform: "translate(-50%, -50%)",
width: 60, // Keep the SVG at 200x200, but make the center content smaller
height: 60, // so the wheel remains visible around it.
width: 160,
height: 160,
borderRadius: "50%", borderRadius: "50%",
backgroundColor: "var(--background)", backgroundColor: "var(--secondary-background)",
border: "3px solid var(--primary)",
display: "flex", display: "flex",
flexDirection: "column",
alignItems: "center", alignItems: "center",
justifyContent: "center", justifyContent: "center",
fontSize: 18,
fontWeight: 600,
color: "var(--primary)",
zIndex: 10, zIndex: 10,
padding: 10,
}} }}
> >
{payFor} <div
style={{
fontSize: 20,
fontWeight: 600,
color: "var(--primary)",
lineHeight: 1.1,
textAlign: "center",
}}
>
<ArabicPrice
price={originalTotalBill}
style={{
fontSize: 20,
fontWeight: 600,
}}
/>
</div>
<ProText
style={{
fontSize: 11,
color: ProGray1,
marginTop: 6,
textAlign: "center",
lineHeight: 1.2,
fontWeight: 400,
}}
>
{t("splitBill.totalBill")}
</ProText>
</div> </div>
</div> </div>
<ProText
style={{
textAlign: "center",
marginTop: 12,
fontSize: 16,
fontWeight: 600,
}}
>
{t("splitBill.yourAmount")}: {splitAmount.toFixed(2)}
</ProText>
</div> </div>
)} )}
<div <div
style={{ style={{
display: "flex", display: "flex",
gap: 12, flexDirection: "column",
marginTop: 20, gap: "1rem",
padding: 20,
}} }}
> >
<Button style={{ flex: 1 }} onClick={handleRemoveSplitWay}> <div
{t("splitBill.removeSplitWay")} style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
gap: "1rem",
padding: 8,
}}
>
<ProText
style={{
fontSize: "1rem",
marginTop: 3,
color: ProGray1,
}}
>
{t("checkout.totalPeople")}
</ProText>
<TotalPeopleActions />
<ProText
style={{
fontSize: "1rem",
marginTop: 3,
color: ProGray1,
}}
>
{t("checkout.totalPeople")}
</ProText>
</div>
<div
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
gap: "1rem",
padding: 8,
}}
>
<ProText
style={{
fontSize: "1rem",
marginTop: 2,
color: ProGray1,
}}
>
{t("checkout.payFor")}
</ProText>
<PayForActions />
<ProText
style={{
fontSize: "1rem",
marginTop: 2,
color: ProGray1,
}}
>
{t("checkout.payFor")}
</ProText>
</div>
</div>
<div
style={{
display: "flex",
flexDirection: "column",
backgroundColor: "var(--background)",
padding: 20,
opacity: 1,
gap: 8,
borderTopLeftRadius: 24,
borderTopRightRadius: 24,
paddingTop: 12,
paddingRight: 24,
paddingBottom: 24,
paddingLeft: 24,
}}
>
<div className={styles.summaryRow}>
<ProText
style={{
fontWeight: 400,
fontStyle: "Regular",
fontSize: 14,
lineHeight: "140%",
letterSpacing: "0%",
}}
>
{t("splitBill.yourShare")}
</ProText>
<ArabicPrice price={splitAmount} />
</div>
</div>
<div
style={{
display: "flex",
gap: 12,
margin: 20,
}}
>
<Button
style={{
flex: 1,
backgroundColor: "#FEEDED",
color: "#DD4143",
boxShadow: "none",
border: "none",
}}
onClick={handleRemoveSplitWay}
>
{t("splitBill.removeSplit")}
</Button> </Button>
<Button <Button
type="primary" type="primary"

View File

@@ -1,4 +1,4 @@
import { Button, Card, Image } from "antd"; import { Button, Card, Checkbox, Divider, Image } from "antd";
import { ProBottomSheet } from "components/ProBottomSheet/ProBottomSheet.tsx"; import { ProBottomSheet } from "components/ProBottomSheet/ProBottomSheet.tsx";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -7,6 +7,7 @@ import ArabicPrice from "components/ArabicPrice";
import ProText from "components/ProText"; import ProText from "components/ProText";
import { selectCart, updateSplitBillAmount } from "features/order/orderSlice"; import { selectCart, updateSplitBillAmount } from "features/order/orderSlice";
import { useAppDispatch, useAppSelector } from "redux/hooks"; import { useAppDispatch, useAppSelector } from "redux/hooks";
import styles from "./SplitBill.module.css";
interface SplitBillChoiceBottomSheetProps { interface SplitBillChoiceBottomSheetProps {
isOpen: boolean; isOpen: boolean;
@@ -72,13 +73,13 @@ export function PayForYourItemsChoiceBottomSheet({
title={t("splitBill.payForYourItems")} title={t("splitBill.payForYourItems")}
showCloseButton={true} showCloseButton={true}
initialSnap={1} initialSnap={1}
height={745} height={720}
snapPoints={[745]} snapPoints={[720]}
contentStyle={{ padding: 0 }}
> >
<div <div
style={{ style={{
padding: "0 20px", padding: 20,
margin: "20px 0",
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
gap: 12, gap: 12,
@@ -101,65 +102,71 @@ export function PayForYourItemsChoiceBottomSheet({
const itemTotal = item.price * item.quantity; const itemTotal = item.price * item.quantity;
return ( return (
<Card <>
key={itemId} <Card
style={{ key={itemId}
border: "none",
cursor: "pointer",
}}
onClick={() => handleItemToggle(itemId)}
>
<div
style={{ style={{
display: "flex", border: "none",
flexDirection: "row", cursor: "pointer",
gap: 12, padding: 0,
alignItems: "center",
}} }}
onClick={() => handleItemToggle(itemId)}
> >
<Image
src={item.image}
alt={item.name}
width={60}
height={60}
preview={false}
style={{
borderRadius: 8,
objectFit: "cover",
}}
/>
<div <div
style={{ style={{
flex: 1,
display: "flex",
flexDirection: "column",
gap: 4,
}}
>
<ProText style={{ fontSize: 14, fontWeight: 500 }}>
{item.name}
</ProText>
<ProText type="secondary" style={{ fontSize: 12 }}>
{t("cart.quantity")}: {item.quantity}
</ProText>
<ArabicPrice price={itemTotal} />
</div>
<Button
type={isSelected ? "primary" : "default"}
shape="circle"
style={{
width: 32,
height: 32,
minWidth: 32,
display: "flex", display: "flex",
flexDirection: "row",
gap: 12,
alignItems: "center", alignItems: "center",
justifyContent: "center",
}} }}
> >
{isSelected ? "✓" : "+"} <Image
</Button> src={item.image}
</div> alt={item.name}
</Card> width={60}
height={60}
preview={false}
style={{
borderRadius: 8,
objectFit: "cover",
}}
/>
<div
style={{
flex: 1,
display: "flex",
flexDirection: "column",
gap: 4,
}}
>
<ProText style={{ fontSize: 14, fontWeight: 500 }}>
{item.name}
</ProText>
<ArabicPrice price={itemTotal} />
</div>
<div
style={{
width: 32,
height: 32,
minWidth: 32,
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
onClick={(e) => e.stopPropagation()}
>
<Checkbox
className={styles.circleCheckbox}
checked={isSelected}
onChange={() => handleItemToggle(itemId)}
/>
</div>
</div>
</Card>
{item !== items[items.length - 1] && (
<Divider style={{ margin: "0" }} />
)}
</>
); );
}) })
)} )}
@@ -189,11 +196,20 @@ export function PayForYourItemsChoiceBottomSheet({
style={{ style={{
display: "flex", display: "flex",
gap: 12, gap: 12,
marginTop: 20, margin: 20,
}} }}
> >
<Button style={{ flex: 1 }} onClick={handleRemoveSplitWay}> <Button
{t("splitBill.removeSplitWay")} style={{
flex: 1,
backgroundColor: "#FEEDED",
color: "#DD4143",
boxShadow: "none",
border: "none",
}}
onClick={handleRemoveSplitWay}
>
{t("splitBill.removeSplit")}
</Button> </Button>
<Button <Button
type="primary" type="primary"

View File

@@ -19,7 +19,6 @@
height: 48px !important; height: 48px !important;
} }
.backToHomePage { .backToHomePage {
width: 100%; width: 100%;
height: 48px; height: 48px;
@@ -46,3 +45,45 @@
width: 24px; width: 24px;
height: 24px; height: 24px;
} }
.summaryRow {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 16px;
}
/* Make AntD checkbox look like a circular check indicator (scoped via CSS modules) */
.circleCheckbox :global(.ant-checkbox-inner) {
width: 24px;
height: 24px;
border-radius: 50% !important;
border: 1.5px solid #D5D8DA;
background: transparent;
}
.circleCheckbox :global(.ant-checkbox-checked .ant-checkbox-inner) {
border-radius: 50% !important;
background: transparent;
border-color: #ffb700;
}
/* Replace AntD checkmark with a filled inner circle when checked (match SVG) */
.circleCheckbox :global(.ant-checkbox-inner::after) {
content: "";
border: 0 !important;
transform: none !important;
width: 0;
height: 0;
left: 50%;
top: 50%;
}
.circleCheckbox :global(.ant-checkbox-checked .ant-checkbox-inner::after) {
width: 18px;
height: 18px;
margin-left: -9px;
margin-top: -9px;
border-radius: 50%;
background: #ffb700;
}

View File

@@ -0,0 +1,90 @@
.quantityControls {
display: flex;
align-items: center;
border-radius: 888px;
width: fit-content;
}
.quantityLabel {
font-size: 14px;
color: var(--secondary-color);
font-weight: 500;
}
.quantityInputContainer {
display: flex;
align-items: center;
padding: 0 1px;
border-radius: 888px;
width: 140px;
height: 48px;
}
.quantityButton {
padding: 0;
width: 25px;
height: 48px;
display: flex;
align-items: center;
justify-content: center;
color: var(--secondary-color);
transition: all 0.2s ease;
}
.quantityInput {
text-align: center;
border: none;
box-shadow: none;
font-size: 16px;
font-weight: 600;
}
.removeButton {
padding: 4px 0;
height: 48px;
display: flex;
align-items: center;
gap: 4px;
width: 30px;
}
.deleteButtonContainer {
position: absolute;
top: 12px;
right: 12px;
background-color: var(--primary);
border-radius: 50%;
padding: 8px;
cursor: pointer;
transition: all 0.3s ease;
}
.deleteIcon {
font-size: 18px;
color: var(--secondary-color);
}
.cartItemActions :global(.ant-input-number-outlined) {
border: none;
width: 40px;
background-color: inherit;
text-align: center;
}
.cartItemActions :global(.ant-input-number-input) {
text-align: center !important;
}
.plusIcon {
margin-bottom: 1px;
color: #1F1C2E;
}
.minusIcon {
color: var(--secondary-foreground);
}
.deleteIcon {
position: relative;
right: 1px;
}

View File

@@ -0,0 +1,125 @@
import { MinusOutlined, PlusOutlined } from "@ant-design/icons";
import { Button, Grid, InputNumber, Popconfirm } from "antd";
import DeleteIcon from "components/Icons/DeleteIcon";
import { useTranslation } from "react-i18next";
import { useAppSelector } from "redux/hooks";
import styles from "./ActionsButtons.module.css";
import { colors } from "ThemeConstants";
const { useBreakpoint } = Grid;
export default function ActionsButtons({
quantity,
setQuantity,
max,
min,
}: {
quantity: number;
setQuantity: (quantity: number) => void;
max?: number;
min?: number;
}) {
const { t } = useTranslation();
const { xs } = useBreakpoint(); // Default to desktop
const { isRTL } = useAppSelector((state) => state.locale); // Default to LTR
const getPopconfirmOverlayStyle = () => ({
width: xs ? "280px" : "auto",
maxWidth: "320px",
".antPopconfirmMessageTitle": {
fontSize: xs ? "14px" : "16px",
paddingRight: xs ? "24px" : "0",
},
".antPopconfirmMessageContent": {
fontSize: xs ? "13px" : "14px",
marginTop: "4px",
},
".antPopconfirmButtons": {
marginTop: "12px",
".ant-btn": {
fontSize: xs ? "13px" : "14px",
height: xs ? "28px" : "32px",
padding: xs ? "0 12px" : "4px 15px",
},
},
});
return (
<div className={styles.cartItemActions}>
<div className={styles.quantityControls}>
<div className={styles.quantityInputContainer}>
{quantity > 0 ? (
<Button
shape="circle"
iconPlacement="start"
icon={<MinusOutlined title="add" className={styles.minusIcon} />}
size="small"
onClick={() => setQuantity(Math.max(1, quantity - 1))}
className={styles.quantityButton}
{...(min && { disabled: quantity === min })}
style={{
width: 48,
height: 48,
minWidth: 48,
borderColor: "#DEDEE0",
}}
/>
) : (
<Popconfirm
title={t("cart.deleteConfirmation.title")}
description={t("cart.deleteConfirmation.content")}
onConfirm={() => setQuantity(0)}
okText={t("cart.deleteConfirmation.confirm")}
cancelText={t("cart.deleteConfirmation.cancel")}
okButtonProps={{ danger: true }}
placement={isRTL ? "left" : "right"}
styles={{
root: getPopconfirmOverlayStyle(),
}}
>
<Button
shape="circle"
iconPlacement="start"
icon={<DeleteIcon />}
size="small"
className={styles.addButton}
style={{
background: "#FEF2F2",
width: 48,
height: 48,
border: "none",
minWidth: 48,
}}
/>
</Popconfirm>
)}
<InputNumber
min={min || 1}
max={max || 100}
value={quantity || 1}
onChange={(value: number | null) => setQuantity(value || 1)}
size="small"
controls={false}
className={styles.quantityInput}
name="id"
/>
<Button
shape="circle"
iconPlacement="start"
icon={<PlusOutlined title="add" className={styles.plusIcon} />}
size="small"
onClick={() => setQuantity(Math.min(100, quantity + 1))}
className={styles.quantityButton}
{...(max && { disabled: quantity >= max })}
style={{
width: 48,
height: 48,
borderColor: "#DEDEE0",
minWidth: 48,
}}
/>
</div>
</div>
</div>
);
}

View File

@@ -1,12 +1,7 @@
import { import { ShoppingCartOutlined } from "@ant-design/icons";
LeftOutlined, import { Button, Form, message, Row } from "antd";
RightOutlined,
ShoppingCartOutlined,
} from "@ant-design/icons";
import { Button, Form, Input, message, Row } from "antd";
import { addItem } from "features/order/orderSlice"; import { addItem } from "features/order/orderSlice";
import useBreakPoint from "hooks/useBreakPoint"; import useBreakPoint from "hooks/useBreakPoint";
import { BottomSheet } from "pages/cart/components/specialRequest/BottomSheet.tsx";
import { useMemo, useState } from "react"; 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";
@@ -15,6 +10,9 @@ import { Extra, Product, Variant } from "utils/types/appTypes";
import styles from "../product.module.css"; import styles from "../product.module.css";
import { useGetRestaurantDetailsQuery } from "redux/api/others"; import { useGetRestaurantDetailsQuery } from "redux/api/others";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import TextArea from "antd/es/input/TextArea";
import ProText from "components/ProText";
import ActionsButtons from "./ActionsButtons/ActionsButtons";
export default function ProductFooter({ export default function ProductFooter({
product, product,
@@ -24,6 +22,7 @@ export default function ProductFooter({
selectedGroups, selectedGroups,
quantity, quantity,
onClose, onClose,
setQuantity,
}: { }: {
product: Product; product: Product;
isValid?: boolean; isValid?: boolean;
@@ -32,11 +31,11 @@ export default function ProductFooter({
selectedGroups: Record<number, string[]>; selectedGroups: Record<number, string[]>;
quantity: number; quantity: number;
onClose?: () => void; onClose?: () => void;
setQuantity: (quantity: number) => void;
}) { }) {
const { t } = useTranslation(); const { t } = useTranslation();
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const { themeName } = useAppSelector((state) => state.theme); const { themeName } = useAppSelector((state) => state.theme);
const [isSpecialRequestOpen, setIsSpecialRequestOpen] = useState(false);
const { isMobile, isDesktop } = useBreakPoint(); const { isMobile, isDesktop } = useBreakPoint();
const { isRTL } = useAppSelector((state) => state.locale); const { isRTL } = useAppSelector((state) => state.locale);
const [specialRequest, setSpecialRequest] = useState(""); const [specialRequest, setSpecialRequest] = useState("");
@@ -122,14 +121,6 @@ export default function ProductFooter({
} }
}; };
const handleSpecialRequestSave = (value: string) => {
setSpecialRequest(value);
};
const handleSpecialRequestClose = () => {
setIsSpecialRequestOpen(false);
};
return ( return (
<> <>
<Row <Row
@@ -149,7 +140,7 @@ export default function ProductFooter({
[isRTL ? "right" : "left"]: 0, [isRTL ? "right" : "left"]: 0,
width: hasCustomizationOptions ? "50%" : "100%", width: hasCustomizationOptions ? "50%" : "100%",
}), }),
height: "135px", height: "195px",
}} }}
> >
<div <div
@@ -160,84 +151,79 @@ export default function ProductFooter({
gap: "12px", gap: "12px",
}} }}
> >
<ProText>{t("cart.specialRequest")}</ProText>
<Form.Item style={{ position: "relative", top: -5, width: "100%" }}>
<TextArea
value={specialRequest}
rows={2}
placeholder={t("cart.specialRequest")}
size="large"
autoFocus={false}
className={styles.inputField}
onChange={(e) => setSpecialRequest(e.target.value)}
/>
</Form.Item>
<div <div
style={{ style={{
display: "flex", display: "flex",
flexDirection: "row",
justifyContent: "space-between",
gap: "12px", gap: "12px",
width: "100%", width: "100%",
}} }}
> >
<Form.Item style={{ position: "relative", top: -5, width: "100%" }}> <ActionsButtons
<Input quantity={quantity}
value={specialRequest} setQuantity={setQuantity}
placeholder={t("cart.specialRequest")} max={100}
size="large" min={1}
autoFocus={false}
className={styles.inputField}
onChange={(e) => setSpecialRequest(e.target.value)}
suffix={
<div
className={styles.editButton}
onClick={() => setIsSpecialRequestOpen(true)}
>
<u>{t("cart.editNote")}</u>{" "}
{isRTL ? <LeftOutlined /> : <RightOutlined />}
</div>
}
/> />
</Form.Item> <Button
</div> type="primary"
<div icon={<ShoppingCartOutlined />}
style={{ onClick={handleAddToCart}
display: "flex", disabled={!isValid}
gap: "12px", style={{
width: "100%", flex: 1,
}} height: 48,
> fontSize: isMobile ? "1rem" : "16px",
<Button transition: "all 0.3s ease",
type="primary" width: "100%",
icon={<ShoppingCartOutlined />} borderRadius: 888,
onClick={handleAddToCart} boxShadow: "none",
disabled={!isValid} backgroundColor: isValid
style={{ ? colors.primary
flex: 1, : "rgba(233, 233, 233, 1)",
height: "48px", color: isValid ? "#FFF" : "#999",
fontSize: isMobile ? "1rem" : "16px", cursor: isValid ? "pointer" : "not-allowed",
transition: "all 0.3s ease", }}
width: "100%", onMouseEnter={(e) => {
borderRadius: 888, if (!isMobile && isValid) {
boxShadow: "none", e.currentTarget.style.transform = "translateY(-2px)";
backgroundColor: isValid }
? colors.primary }}
: "rgba(233, 233, 233, 1)", onMouseLeave={(e) => {
color: isValid ? "#FFF" : "#999", if (!isMobile) {
cursor: isValid ? "pointer" : "not-allowed", e.currentTarget.style.transform = "translateY(0)";
}} }
onMouseEnter={(e) => { }}
if (!isMobile && isValid) { >
e.currentTarget.style.transform = "translateY(-2px)"; {isValid
} ? t("menu.addToCart")
}} : t("menu.selectRequiredOptions")}
onMouseLeave={(e) => { </Button>
if (!isMobile) {
e.currentTarget.style.transform = "translateY(0)";
}
}}
>
{isValid ? t("menu.addToCart") : t("menu.selectRequiredOptions")}
</Button>
</div> </div>
</div> </div>
</Row> </Row>
{!isDesktop && isSpecialRequestOpen && ( {/* {!isDesktop && isSpecialRequestOpen && (
<BottomSheet <BottomSheet
isOpen={isSpecialRequestOpen} isOpen={isSpecialRequestOpen}
onClose={handleSpecialRequestClose} onClose={handleSpecialRequestClose}
initialValue={specialRequest} initialValue={specialRequest}
onSave={handleSpecialRequestSave} onSave={handleSpecialRequestSave}
/> />
)} )} */}
</> </>
); );
} }

View File

@@ -110,7 +110,7 @@ export default function Variants({
<> <>
{variantsList?.length > 0 && variantLevels.length > 0 && ( {variantsList?.length > 0 && variantLevels.length > 0 && (
<> <>
{!isDesktop && <Divider style={{ margin: "0" }} />} {!isDesktop && <Divider style={{ margin: "0 0 10px 0" }} />}
<div> <div>
<div <div
style={{ style={{

View File

@@ -1,4 +1,3 @@
import ActionsButtons from "components/ActionsButtons/ActionsButtons";
import ImageWithFallback from "components/ImageWithFallback"; import ImageWithFallback from "components/ImageWithFallback";
import { ItemDescriptionIcons } from "components/ItemDescriptionIcons/ItemDescriptionIcons"; import { ItemDescriptionIcons } from "components/ItemDescriptionIcons/ItemDescriptionIcons";
import ProText from "components/ProText"; import ProText from "components/ProText";
@@ -177,7 +176,7 @@ export default function ProductDetailPage({
return ( return (
<div <div
style={{ style={{
height: "80vh", height: "75vh",
overflow: "auto", overflow: "auto",
scrollbarWidth: "none", scrollbarWidth: "none",
}} }}
@@ -221,12 +220,16 @@ export default function ProductDetailPage({
<div className={styles.productHeader}> <div className={styles.productHeader}>
<div className={styles.productDetails}> <div className={styles.productDetails}>
<ProText <ProText
strong style={{
style={{ fontSize: isDesktop ? "1.5rem" : "1.25rem" }} fontWeight: 400,
fontStyle: "Regular",
fontSize: "14px",
lineHeight: "140%",
letterSpacing: "0%",
}}
> >
{isRTL ? product?.nameOther : product?.name} {isRTL ? product?.nameOther : product?.name}
</ProText> </ProText>
<br />
{product?.description && ( {product?.description && (
<ProText <ProText
type="secondary" type="secondary"
@@ -239,24 +242,19 @@ export default function ProductDetailPage({
textOverflow: "ellipsis", textOverflow: "ellipsis",
wordWrap: "break-word", wordWrap: "break-word",
overflowWrap: "break-word", overflowWrap: "break-word",
lineHeight: "1.4",
maxHeight: "2.8em", maxHeight: "2.8em",
fontWeight: "500", fontWeight: 400,
letterSpacing: "0.01em", fontStyle: "Regular",
fontSize: "1rem", fontSize: "12px",
lineHeight: "140%",
letterSpacing: "0%",
marginTop: 10,
}} }}
> >
{isRTL ? product?.descriptionAR : product?.description} {isRTL ? product?.descriptionAR : product?.description}
</ProText> </ProText>
)} )}
<ArabicPrice
price={product?.price}
style={{
fontSize: isDesktop ? "1.2rem" : "1rem",
color: colors.primary,
marginTop: "12px",
}}
/>
<div <div
style={{ style={{
display: "flex", display: "flex",
@@ -271,14 +269,13 @@ export default function ProductDetailPage({
className={styles.itemDescriptionIcons} className={styles.itemDescriptionIcons}
/> />
</div> </div>
</div> <ArabicPrice
price={product?.price}
<div className={styles.quantitySection}> style={{
<ActionsButtons fontSize: isDesktop ? "1.2rem" : "1rem",
quantity={quantity} color: colors.primary,
setQuantity={(quantity) => setQuantity(quantity)} marginTop: "12px",
max={100} }}
min={1}
/> />
</div> </div>
</div> </div>
@@ -293,6 +290,7 @@ export default function ProductDetailPage({
selectedGroups={selectedExtrasByGroup} selectedGroups={selectedExtrasByGroup}
quantity={quantity} quantity={quantity}
onClose={onClose} onClose={onClose}
setQuantity={(quantity: number) => setQuantity(quantity)}
/> />
)} )}
</div> </div>
@@ -301,7 +299,7 @@ export default function ProductDetailPage({
{hasCustomizationOptions && ( {hasCustomizationOptions && (
<div className={isDesktop ? styles.rightColumn : styles.fullWidth}> <div className={isDesktop ? styles.rightColumn : styles.fullWidth}>
<Space <Space
direction="vertical" orientation="vertical"
size="middle" size="middle"
style={{ width: "100%", padding: "0 1rem" }} style={{ width: "100%", padding: "0 1rem" }}
> >
@@ -341,6 +339,7 @@ export default function ProductDetailPage({
selectedExtras={selectedExtras} selectedExtras={selectedExtras}
selectedGroups={selectedExtrasByGroup} selectedGroups={selectedExtrasByGroup}
quantity={quantity} quantity={quantity}
setQuantity={(quantity: number) => setQuantity(quantity)}
/> />
)} )}
</div> </div>

View File

@@ -232,7 +232,7 @@
align-items: center; align-items: center;
justify-content: flex-end; justify-content: flex-end;
position: relative; position: relative;
top: 5px top: 5px;
} }
/* Dark mode desktop styles */ /* Dark mode desktop styles */
@@ -320,8 +320,9 @@
} }
.inputField { .inputField {
height: 50px; height: 100px;
width: 100% !important; width: 100% !important;
border-radius: 6px;
} }
.editButton { .editButton {
@@ -329,4 +330,3 @@
font-size: 14px; font-size: 14px;
cursor: pointer; cursor: pointer;
} }