diff --git a/src/assets/locals/ar.json b/src/assets/locals/ar.json index 89ae429..03081f8 100644 --- a/src/assets/locals/ar.json +++ b/src/assets/locals/ar.json @@ -221,7 +221,8 @@ "inYourCart": "في سلة المشتريات", "updatedSuccessfully": "تم التحديث بنجاح", "editNote": "تعديل الملاحظة", - "selectTimeEstimate": "أدخل وقت التقديم" + "selectTimeEstimate": "أدخل وقت التقديم", + "pleaseAddItemsToCart": "يرجى إضافة عناصر إلى السلة" }, "checkout": { "title": "الدفع", @@ -238,7 +239,8 @@ "totalAmount": "المبلغ الكلي", "items": "العناصر", "expiresIn": "تنتهي في", - "expiresInDescription": "تنتهي في:12/26" + "expiresInDescription": "تنتهي في:12/26", + "phoneNumber": "رقم الهاتف" }, "address": { "title": "العنوان", diff --git a/src/assets/locals/en.json b/src/assets/locals/en.json index 0525b15..1a5b873 100644 --- a/src/assets/locals/en.json +++ b/src/assets/locals/en.json @@ -231,7 +231,8 @@ "plateNumber": "Plate Number", "plateNumberPlaceholder": "Enter plate number", "editNote": "Edit Note", - "selectTimeEstimate": "Select Estimate Time" + "selectTimeEstimate": "Select Estimate Time", + "pleaseAddItemsToCart": "Please add items to your cart" }, "checkout": { "title": "Checkout", @@ -248,7 +249,8 @@ "totalAmount": "Total Amount", "items": "Items", "expiresIn": "Expires in", - "expiresInDescription": "Expires in:12/26" + "expiresInDescription": "Expires in:12/26", + "phoneNumber": "Phone Number" }, "address": { "title": "Address", diff --git a/src/components/PaymentMethods/PaymentMethods.tsx b/src/components/PaymentMethods/PaymentMethods.tsx index 32786b7..a5fc897 100644 --- a/src/components/PaymentMethods/PaymentMethods.tsx +++ b/src/components/PaymentMethods/PaymentMethods.tsx @@ -1,4 +1,4 @@ -import { Radio, Space } from "antd"; +import { Form, Radio, Space } from "antd"; import { Group } from "antd/es/radio"; import ArabicPrice from "components/ArabicPrice"; import DifferentCardIcon from "components/Icons/paymentMethods/DifferentCardIcon"; @@ -50,67 +50,69 @@ const PaymentMethods = ({ onPaymentSelect, ...props }: PaymentMethodsProps) => { return ( - - - {options.map((option) => ( -
- -
+ + + {options.map((option) => ( +
+ - - {option.label} - - {!option.icon ? ( - - ) : ( - <>{option.icon} - )} -
- -
- ))} - - + > + {option.label} + + {!option.icon ? ( + + ) : ( + <>{option.icon} + )} +
+ + + ))} +
+
+
); }; diff --git a/src/features/order/orderSlice.ts b/src/features/order/orderSlice.ts index 0bdb863..ea9e502 100644 --- a/src/features/order/orderSlice.ts +++ b/src/features/order/orderSlice.ts @@ -48,6 +48,7 @@ interface CartState { estimateTimeDate: Date; estimateTimeTime: string; collectionMethod: string; + phone: string; } // localStorage keys @@ -65,6 +66,7 @@ const CART_STORAGE_KEYS = { ESTIMATE_TIME_DATE: 'fascano_estimate_time_date', ESTIMATE_TIME_TIME: 'fascano_estimate_time_time', COLLECTION_METHOD: 'fascano_collection_method', + PHONE: 'fascano_phone', } as const; // Utility functions for localStorage @@ -95,6 +97,7 @@ const initialState: CartState = { estimateTimeDate: new Date(getFromLocalStorage(CART_STORAGE_KEYS.ESTIMATE_TIME_DATE, new Date().toISOString())), estimateTimeTime: getFromLocalStorage(CART_STORAGE_KEYS.ESTIMATE_TIME_TIME, ""), collectionMethod: getFromLocalStorage(CART_STORAGE_KEYS.COLLECTION_METHOD, ""), + phone: getFromLocalStorage(CART_STORAGE_KEYS.PHONE, ""), }; const orderSlice = createSlice({ @@ -273,6 +276,14 @@ const orderSlice = createSlice({ localStorage.setItem(CART_STORAGE_KEYS.COLLECTION_METHOD, JSON.stringify(state.collectionMethod)); } }, + updatePhone(state, action: PayloadAction) { + state.phone = action.payload; + + // Sync to localStorage + if (typeof window !== 'undefined') { + localStorage.setItem(CART_STORAGE_KEYS.PHONE, JSON.stringify(state.phone)); + } + }, }, }); @@ -295,6 +306,7 @@ export const { updateGiftDetails, updateEstimateTime, updateCollectionMethod, + updatePhone, reset, } = orderSlice.actions; diff --git a/src/pages/cart/components/CartMobileTabletLayout.tsx b/src/pages/cart/components/CartMobileTabletLayout.tsx index 289b4c1..689a2db 100644 --- a/src/pages/cart/components/CartMobileTabletLayout.tsx +++ b/src/pages/cart/components/CartMobileTabletLayout.tsx @@ -1,5 +1,5 @@ import { PlusOutlined } from "@ant-design/icons"; -import { Card, Divider, Space } from "antd"; +import { Card, Divider, Form, Space } from "antd"; import ArabicPrice from "components/ArabicPrice"; import CartActionsButtons from "components/CartActionsButtons/CartActionsButtons.tsx"; import ImageWithFallback from "components/ImageWithFallback"; @@ -35,7 +35,9 @@ interface CartMobileTabletLayoutProps { form: FormInstance; } -export default function CartMobileTabletLayout({ form }: CartMobileTabletLayoutProps) { +export default function CartMobileTabletLayout({ + form, +}: CartMobileTabletLayoutProps) { const { t } = useTranslation(); const { items, collectionMethod } = useAppSelector(selectCart); const { id } = useParams(); @@ -235,24 +237,30 @@ export default function CartMobileTabletLayout({ form }: CartMobileTabletLayoutP {/* Collection Method */} {orderType === "pickup" && ( - { - if (value === "cod") { - updateCollectionMethod(value); - } else { - updateCollectionMethod(value); - } - }} - /> + + { + if (value === "cod") { + updateCollectionMethod(value); + } else { + updateCollectionMethod(value); + } + }} + /> + )} diff --git a/src/pages/cart/components/cartFooter/CartFooter.tsx b/src/pages/cart/components/cartFooter/CartFooter.tsx index 5797963..efb1ea8 100644 --- a/src/pages/cart/components/cartFooter/CartFooter.tsx +++ b/src/pages/cart/components/cartFooter/CartFooter.tsx @@ -1,5 +1,5 @@ import { colors } from "ThemeConstants.ts"; -import { Button, FormInstance } from "antd"; +import { Button, FormInstance, message } from "antd"; import { selectCart } from "features/order/orderSlice.ts"; import { useTranslation } from "react-i18next"; import { Link, useNavigate, useParams } from "react-router-dom"; @@ -17,15 +17,15 @@ export default function CartFooter({ form }: CartFooterProps) { const orderType = localStorage.getItem("orderType"); const navigate = useNavigate(); - // Check if checkout should be disabled - const isCheckoutDisabled = items.length === 0; - const handleCheckoutClick = async () => { - try { - await form.validateFields(); - navigate(`/${id}/checkout`); - } catch (error) { - console.log("Form validation failed:", error); + if (items.length === 0) message.warning(t("cart.pleaseAddItemsToCart")); + else { + try { + await form.validateFields(); + navigate(`/${id}/checkout`); + } catch (error) { + console.log("Form validation failed:", error); + } } }; @@ -60,7 +60,6 @@ export default function CartFooter({ form }: CartFooterProps) { color: "white", width: "100%", }} - disabled={isCheckoutDisabled} onClick={handleCheckoutClick} > {t("cart.checkout")} diff --git a/src/pages/cart/components/timeEstimate/TimeEstimateCard.tsx b/src/pages/cart/components/timeEstimate/TimeEstimateCard.tsx index 2162897..a096765 100644 --- a/src/pages/cart/components/timeEstimate/TimeEstimateCard.tsx +++ b/src/pages/cart/components/timeEstimate/TimeEstimateCard.tsx @@ -1,3 +1,4 @@ +import { Form } from "antd"; import ProInputCard from "components/ProInputCard/ProInputCard.tsx"; import ProRatioGroups from "components/ProRatioGroups/ProRatioGroups.tsx"; import { selectCart, updateEstimateTime } from "features/order/orderSlice.ts"; @@ -27,22 +28,24 @@ export default function TimeEstimateCard() { return ( <> - { - if (value === "now") { - setEstimateWay(value); - handleEstimateTimeSave(new Date(), "now"); - } else { - setEstimateWay(value); - setIsEstimateTimeOpen(true); - } - }} - /> + + { + if (value === "now") { + setEstimateWay(value); + handleEstimateTimeSave(new Date(), "now"); + } else { + setEstimateWay(value); + setIsEstimateTimeOpen(true); + } + }} + /> + {isDesktop ? ( -
+
localStorage.getItem("orderType"), []); const navigate = useNavigate(); @@ -16,13 +16,18 @@ export default function CheckoutButton() { navigate(`/${id}/split-bill`); }, [navigate, id]); - const handlePlaceOrderClick = useCallback(() => { - handleCreateOrder(); - }, [handleCreateOrder]); + const handlePlaceOrderClick = useCallback(async () => { + try { + await form.validateFields(); + handleCreateOrder(); + } catch (error) { + console.log(error); + } + }, [handleCreateOrder, form]); const shouldShowSplitBill = useMemo( () => orderType === "dine-in", - [orderType] + [orderType], ); return ( diff --git a/src/pages/checkout/components/phoneCard.tsx b/src/pages/checkout/components/phoneCard.tsx new file mode 100644 index 0000000..7f0b67d --- /dev/null +++ b/src/pages/checkout/components/phoneCard.tsx @@ -0,0 +1,27 @@ +import { Form, Input } from "antd"; +import ProInputCard from "components/ProInputCard/ProInputCard.tsx"; +import { selectCart, updatePhone } from "features/order/orderSlice"; +import { useTranslation } from "react-i18next"; +import { useAppDispatch, useAppSelector } from "redux/hooks"; + +export default function PhoneCard() { + const { t } = useTranslation(); + const dispatch = useAppDispatch(); + const { phone } = useAppSelector(selectCart); + return ( + <> + + + dispatch(updatePhone(e.target.value))} + /> + + + + ); +} diff --git a/src/pages/checkout/hooks/useOrder.ts b/src/pages/checkout/hooks/useOrder.ts index 43eba72..8a2bd60 100644 --- a/src/pages/checkout/hooks/useOrder.ts +++ b/src/pages/checkout/hooks/useOrder.ts @@ -13,14 +13,14 @@ export default function useOrder() { const { mobilenumber, user_uuid } = JSON.parse( localStorage.getItem("customer") || "{}" ) as Customer; - const { items, coupon, tip, tables, specialRequest } = + const { items, coupon, tip, tables, specialRequest, phone } = useAppSelector(selectCart); const [createOrder] = useCreateOrderMutation(); const handleCreateOrder = useCallback(() => { createOrder({ - phone: mobilenumber, + phone: mobilenumber || phone, couponID: coupon, discountAmount: 0, comment: specialRequest, diff --git a/src/pages/checkout/page.tsx b/src/pages/checkout/page.tsx index 6ce0b4e..d0b05f4 100644 --- a/src/pages/checkout/page.tsx +++ b/src/pages/checkout/page.tsx @@ -1,3 +1,4 @@ +import { Form } from "antd"; import OrderSummary from "components/OrderSummary/OrderSummary"; import PaymentMethods from "components/PaymentMethods/PaymentMethods"; import ProHeader from "components/ProHeader/ProHeader"; @@ -9,12 +10,15 @@ import CheckoutButton from "./components/CheckoutButton"; import { GiftDetails } from "./components/GiftDetails"; import { OfficeDetails } from "./components/OfficeDetails"; import { RoomDetails } from "./components/RoomDetails"; +import PhoneCard from "./components/phoneCard"; export default function CheckoutPage() { const { t } = useTranslation(); + const [form] = Form.useForm(); return ( <> +
{t("checkout.title")}
@@ -22,11 +26,13 @@ export default function CheckoutPage() { +
- + + ); }