order page: integration
This commit is contained in:
@@ -335,6 +335,7 @@
|
|||||||
"cancelOrder": "إلغاء الطلب",
|
"cancelOrder": "إلغاء الطلب",
|
||||||
"areYouSureYouWantToCancelThisOrder?": "هل أنت متأكد أنك تريد إلغاء هذا الطلب؟",
|
"areYouSureYouWantToCancelThisOrder?": "هل أنت متأكد أنك تريد إلغاء هذا الطلب؟",
|
||||||
"keepOrder": "الاحتفاظ بالطلب",
|
"keepOrder": "الاحتفاظ بالطلب",
|
||||||
"thisActionCannotBeUndone": "هذا الإجراء لا يمكن التراجع عنه."
|
"thisActionCannotBeUndone": "هذا الإجراء لا يمكن التراجع عنه.",
|
||||||
|
"createOrderFailed": "فشل إنشاء الطلب"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -346,6 +346,7 @@
|
|||||||
"cancelOrder": "Cancel Order",
|
"cancelOrder": "Cancel Order",
|
||||||
"areYouSureYouWantToCancelThisOrder?": "Are you sure you want to cancel this order?",
|
"areYouSureYouWantToCancelThisOrder?": "Are you sure you want to cancel this order?",
|
||||||
"keepOrder": "Keep Order",
|
"keepOrder": "Keep Order",
|
||||||
"thisActionCannotBeUndone": "This action cannot be undone."
|
"thisActionCannotBeUndone": "This action cannot be undone.",
|
||||||
|
"createOrderFailed": "Create Order Failed"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,13 @@
|
|||||||
import { Card, Divider, Space } from "antd";
|
import { Card, Divider, Space } from "antd";
|
||||||
import ArabicPrice from "components/ArabicPrice";
|
import ArabicPrice from "components/ArabicPrice";
|
||||||
import { selectCartTotal } from "features/order/orderSlice";
|
import { Order } from "pages/checkout/hooks/types";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useAppSelector } from "redux/hooks";
|
|
||||||
import ProText from "../ProText";
|
import ProText from "../ProText";
|
||||||
import ProTitle from "../ProTitle";
|
import ProTitle from "../ProTitle";
|
||||||
import styles from "./PaymentDetails.module.css";
|
import styles from "./PaymentDetails.module.css";
|
||||||
|
|
||||||
export default function PaymentDetails() {
|
export default function PaymentDetails({ order }: { order?: Order }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const total = useAppSelector(selectCartTotal);
|
|
||||||
const { isRTL } = useAppSelector((state) => state.locale);
|
|
||||||
|
|
||||||
const subtotal = total;
|
|
||||||
const tax = subtotal * 0.1; // 10% tax
|
|
||||||
const finalTotal = subtotal + tax;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -26,7 +19,7 @@ export default function PaymentDetails() {
|
|||||||
<div className={`${styles.summaryRow} ${styles.totalRow}`}>
|
<div className={`${styles.summaryRow} ${styles.totalRow}`}>
|
||||||
<ProText strong>{t("cart.totalAmount")}</ProText>
|
<ProText strong>{t("cart.totalAmount")}</ProText>
|
||||||
<ArabicPrice
|
<ArabicPrice
|
||||||
price={finalTotal}
|
price={order?.total_price || 0}
|
||||||
strong
|
strong
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,17 +3,18 @@ import { Group } from "antd/es/radio";
|
|||||||
import ArabicPrice from "components/ArabicPrice";
|
import ArabicPrice from "components/ArabicPrice";
|
||||||
import DifferentCardIcon from "components/Icons/paymentMethods/DifferentCardIcon";
|
import DifferentCardIcon from "components/Icons/paymentMethods/DifferentCardIcon";
|
||||||
import ProText from "components/ProText";
|
import ProText from "components/ProText";
|
||||||
|
import { selectCart, updatePaymentMethod } from "features/order/orderSlice";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useAppDispatch, useAppSelector } from "redux/hooks";
|
||||||
import { colors, ProGray1 } from "../../ThemeConstants";
|
import { colors, ProGray1 } from "../../ThemeConstants";
|
||||||
import ProInputCard from "../ProInputCard/ProInputCard";
|
import ProInputCard from "../ProInputCard/ProInputCard";
|
||||||
import styles from "./PaymentMethods.module.css";
|
import styles from "./PaymentMethods.module.css";
|
||||||
|
|
||||||
interface PaymentMethodsProps {
|
|
||||||
onPaymentSelect?: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const PaymentMethods = ({ onPaymentSelect, ...props }: PaymentMethodsProps) => {
|
const PaymentMethods = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { paymentMethod } = useAppSelector(selectCart);
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
const options: {
|
const options: {
|
||||||
label: string;
|
label: string;
|
||||||
@@ -48,6 +49,10 @@ const PaymentMethods = ({ onPaymentSelect, ...props }: PaymentMethodsProps) => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const onPaymentSelect = (value: string) => {
|
||||||
|
dispatch(updatePaymentMethod(value));
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ProInputCard title={t("checkout.selectedPaymentMethod")}>
|
<ProInputCard title={t("checkout.selectedPaymentMethod")}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
@@ -56,13 +61,13 @@ const PaymentMethods = ({ onPaymentSelect, ...props }: PaymentMethodsProps) => {
|
|||||||
rules={[
|
rules={[
|
||||||
{ required: true, message: t("checkout.pleaseSelectPaymentMethod") },
|
{ required: true, message: t("checkout.pleaseSelectPaymentMethod") },
|
||||||
]}
|
]}
|
||||||
|
initialValue={paymentMethod}
|
||||||
>
|
>
|
||||||
<Group
|
<Group
|
||||||
className={styles.paymentMethods}
|
className={styles.paymentMethods}
|
||||||
style={{
|
style={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
}}
|
}}
|
||||||
{...props}
|
|
||||||
size="large"
|
size="large"
|
||||||
>
|
>
|
||||||
<Space direction="vertical" style={{ width: "100%" }}>
|
<Space direction="vertical" style={{ width: "100%" }}>
|
||||||
@@ -71,7 +76,7 @@ const PaymentMethods = ({ onPaymentSelect, ...props }: PaymentMethodsProps) => {
|
|||||||
<Radio
|
<Radio
|
||||||
key={option.value}
|
key={option.value}
|
||||||
value={option.value}
|
value={option.value}
|
||||||
onClick={onPaymentSelect}
|
onClick={() => onPaymentSelect(option.value)}
|
||||||
style={{
|
style={{
|
||||||
height: 50,
|
height: 50,
|
||||||
borderRadius: 888,
|
borderRadius: 888,
|
||||||
|
|||||||
@@ -49,10 +49,11 @@ interface CartState {
|
|||||||
estimateTimeTime: string;
|
estimateTimeTime: string;
|
||||||
collectionMethod: string;
|
collectionMethod: string;
|
||||||
phone: string;
|
phone: string;
|
||||||
|
paymentMethod: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// localStorage keys
|
// localStorage keys
|
||||||
const CART_STORAGE_KEYS = {
|
export const CART_STORAGE_KEYS = {
|
||||||
ITEMS: 'fascano_cart_items',
|
ITEMS: 'fascano_cart_items',
|
||||||
SPECIAL_REQUEST: 'fascano_special_request',
|
SPECIAL_REQUEST: 'fascano_special_request',
|
||||||
COUPON: 'fascano_coupon',
|
COUPON: 'fascano_coupon',
|
||||||
@@ -67,6 +68,7 @@ const CART_STORAGE_KEYS = {
|
|||||||
ESTIMATE_TIME_TIME: 'fascano_estimate_time_time',
|
ESTIMATE_TIME_TIME: 'fascano_estimate_time_time',
|
||||||
COLLECTION_METHOD: 'fascano_collection_method',
|
COLLECTION_METHOD: 'fascano_collection_method',
|
||||||
PHONE: 'fascano_phone',
|
PHONE: 'fascano_phone',
|
||||||
|
PAYMENT_METHOD: 'fascano_payment_method',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
// Utility functions for localStorage
|
// Utility functions for localStorage
|
||||||
@@ -98,6 +100,7 @@ const initialState: CartState = {
|
|||||||
estimateTimeTime: getFromLocalStorage(CART_STORAGE_KEYS.ESTIMATE_TIME_TIME, ""),
|
estimateTimeTime: getFromLocalStorage(CART_STORAGE_KEYS.ESTIMATE_TIME_TIME, ""),
|
||||||
collectionMethod: getFromLocalStorage(CART_STORAGE_KEYS.COLLECTION_METHOD, ""),
|
collectionMethod: getFromLocalStorage(CART_STORAGE_KEYS.COLLECTION_METHOD, ""),
|
||||||
phone: getFromLocalStorage(CART_STORAGE_KEYS.PHONE, ""),
|
phone: getFromLocalStorage(CART_STORAGE_KEYS.PHONE, ""),
|
||||||
|
paymentMethod: getFromLocalStorage(CART_STORAGE_KEYS.PAYMENT_METHOD, ""),
|
||||||
};
|
};
|
||||||
|
|
||||||
const orderSlice = createSlice({
|
const orderSlice = createSlice({
|
||||||
@@ -146,6 +149,7 @@ const orderSlice = createSlice({
|
|||||||
clearCart(state) {
|
clearCart(state) {
|
||||||
state.items = [];
|
state.items = [];
|
||||||
state.specialRequest = "";
|
state.specialRequest = "";
|
||||||
|
state.phone = "";
|
||||||
state.coupon = "";
|
state.coupon = "";
|
||||||
state.tip = "";
|
state.tip = "";
|
||||||
state.tables = [];
|
state.tables = [];
|
||||||
@@ -157,7 +161,7 @@ const orderSlice = createSlice({
|
|||||||
state.estimateTimeDate = new Date();
|
state.estimateTimeDate = new Date();
|
||||||
state.estimateTimeTime = "";
|
state.estimateTimeTime = "";
|
||||||
state.collectionMethod = "";
|
state.collectionMethod = "";
|
||||||
|
state.paymentMethod = "";
|
||||||
// Clear all cart data from localStorage
|
// Clear all cart data from localStorage
|
||||||
if (typeof window !== 'undefined') {
|
if (typeof window !== 'undefined') {
|
||||||
Object.values(CART_STORAGE_KEYS).forEach(key => {
|
Object.values(CART_STORAGE_KEYS).forEach(key => {
|
||||||
@@ -198,7 +202,7 @@ const orderSlice = createSlice({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
updateTables(state, action: PayloadAction<string[]>) {
|
updateTables(state, action: PayloadAction<string[]>) {
|
||||||
state.tables = [...state.tables, ...action.payload];
|
state.tables = action.payload;
|
||||||
|
|
||||||
// Sync to localStorage
|
// Sync to localStorage
|
||||||
if (typeof window !== 'undefined') {
|
if (typeof window !== 'undefined') {
|
||||||
@@ -284,6 +288,14 @@ const orderSlice = createSlice({
|
|||||||
localStorage.setItem(CART_STORAGE_KEYS.PHONE, JSON.stringify(state.phone));
|
localStorage.setItem(CART_STORAGE_KEYS.PHONE, JSON.stringify(state.phone));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
updatePaymentMethod(state, action: PayloadAction<string>) {
|
||||||
|
state.paymentMethod = action.payload;
|
||||||
|
|
||||||
|
// Sync to localStorage
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
localStorage.setItem(CART_STORAGE_KEYS.PAYMENT_METHOD, JSON.stringify(state.paymentMethod));
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -307,6 +319,7 @@ export const {
|
|||||||
updateEstimateTime,
|
updateEstimateTime,
|
||||||
updateCollectionMethod,
|
updateCollectionMethod,
|
||||||
updatePhone,
|
updatePhone,
|
||||||
|
updatePaymentMethod,
|
||||||
reset,
|
reset,
|
||||||
} = orderSlice.actions;
|
} = orderSlice.actions;
|
||||||
|
|
||||||
|
|||||||
228
src/pages/checkout/hooks/types.ts
Normal file
228
src/pages/checkout/hooks/types.ts
Normal file
@@ -0,0 +1,228 @@
|
|||||||
|
import { Variant } from "pages/orders/types"
|
||||||
|
import { Extra3 } from "utils/types/appTypes"
|
||||||
|
|
||||||
|
export interface OrderDetails {
|
||||||
|
orderItems: OrderItem[]
|
||||||
|
order: Order
|
||||||
|
status: Status[]
|
||||||
|
laststatus: Status2[]
|
||||||
|
restaurant: string
|
||||||
|
restaurantAR: string
|
||||||
|
restaurantID: number
|
||||||
|
global_currency: string
|
||||||
|
local_currency: string
|
||||||
|
address: string
|
||||||
|
phone: string
|
||||||
|
restaurant_iimage: string
|
||||||
|
itemsImagePrefixOld: string
|
||||||
|
itemsImagePrefix: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderItem {
|
||||||
|
id: number
|
||||||
|
is_loyalty_used: number
|
||||||
|
no_of_stamps_give: number
|
||||||
|
isHasLoyalty: boolean
|
||||||
|
is_vat_disabled: number
|
||||||
|
name: string
|
||||||
|
price: number
|
||||||
|
qty: number
|
||||||
|
variant_price: string
|
||||||
|
image: string
|
||||||
|
imageName: string
|
||||||
|
variantName: string
|
||||||
|
variantLocalName?: string
|
||||||
|
extras: any[]
|
||||||
|
itemline: string
|
||||||
|
itemlineAR: string
|
||||||
|
itemlineAREN: string
|
||||||
|
extrasgroups: any[]
|
||||||
|
itemComment: string
|
||||||
|
variant?: Variant
|
||||||
|
itemExtras: any[]
|
||||||
|
AvaiilableVariantExtras: Extra3[]
|
||||||
|
isPrinted: number
|
||||||
|
category_id: number
|
||||||
|
pos_order_id: string
|
||||||
|
updated_at: string
|
||||||
|
created_at: string
|
||||||
|
old_qty: number
|
||||||
|
new_qty: number
|
||||||
|
last_printed_qty: number
|
||||||
|
deleted_qty: number
|
||||||
|
discount_value: any
|
||||||
|
discount_type_id: any
|
||||||
|
original_price: number
|
||||||
|
pricing_method: string
|
||||||
|
is_already_paid: number
|
||||||
|
hash_item: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Order {
|
||||||
|
id: number
|
||||||
|
pos_order_id: string
|
||||||
|
created_at: string
|
||||||
|
updated_at: string
|
||||||
|
table: string
|
||||||
|
phone: string
|
||||||
|
user_name: string
|
||||||
|
restaurant_name: string
|
||||||
|
lat: string
|
||||||
|
lng: string
|
||||||
|
restaurant_icon: string
|
||||||
|
location: any
|
||||||
|
status: string
|
||||||
|
status_id: number
|
||||||
|
delivery_method: number
|
||||||
|
orderItems: OrderItem2[]
|
||||||
|
discount: string
|
||||||
|
vat: number
|
||||||
|
total_price: number
|
||||||
|
comment: string
|
||||||
|
pickup_comments: any
|
||||||
|
car_plate: string
|
||||||
|
pickup_time: any
|
||||||
|
pickup_date: any
|
||||||
|
delivery_pickup_interval: any
|
||||||
|
office_no: any
|
||||||
|
room_no: any
|
||||||
|
time_to_prepare: any
|
||||||
|
last_status_id: number
|
||||||
|
currency: string
|
||||||
|
gift_id: any
|
||||||
|
is_loyalty_used: number
|
||||||
|
payment_status: string
|
||||||
|
created_by: string
|
||||||
|
split_order_group_id: any
|
||||||
|
split_sequence: any
|
||||||
|
is_split_order: number
|
||||||
|
split_at: any
|
||||||
|
split_by_user_id: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderItem2 {
|
||||||
|
id: number
|
||||||
|
is_loyalty_used: number
|
||||||
|
no_of_stamps_give: number
|
||||||
|
isHasLoyalty: boolean
|
||||||
|
is_vat_disabled: number
|
||||||
|
name: string
|
||||||
|
price: number
|
||||||
|
qty: number
|
||||||
|
variant_price: string
|
||||||
|
image: string
|
||||||
|
imageName: string
|
||||||
|
variantName: string
|
||||||
|
variantLocalName?: string
|
||||||
|
extras: any[]
|
||||||
|
itemline: string
|
||||||
|
itemlineAR: string
|
||||||
|
itemlineAREN: string
|
||||||
|
extrasgroups: any[]
|
||||||
|
itemComment: string
|
||||||
|
variant?: Variant2
|
||||||
|
itemExtras: any[]
|
||||||
|
AvaiilableVariantExtras: AvaiilableVariantExtra2[]
|
||||||
|
isPrinted: number
|
||||||
|
category_id: number
|
||||||
|
pos_order_id: string
|
||||||
|
updated_at: string
|
||||||
|
created_at: string
|
||||||
|
old_qty: number
|
||||||
|
new_qty: number
|
||||||
|
last_printed_qty: number
|
||||||
|
deleted_qty: number
|
||||||
|
discount_value: any
|
||||||
|
discount_type_id: any
|
||||||
|
original_price: number
|
||||||
|
pricing_method: string
|
||||||
|
is_already_paid: number
|
||||||
|
hash_item: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Status {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
alias: string
|
||||||
|
pivot: Pivot5
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Pivot5 {
|
||||||
|
order_id: number
|
||||||
|
status_id: number
|
||||||
|
user_id: number
|
||||||
|
created_at: string
|
||||||
|
comment: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Status2 {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
alias: string
|
||||||
|
pivot: Pivot6
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Pivot6 {
|
||||||
|
order_id: number
|
||||||
|
status_id: number
|
||||||
|
user_id: number
|
||||||
|
created_at: string
|
||||||
|
comment: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Variant2 {
|
||||||
|
id: number
|
||||||
|
price: number
|
||||||
|
options: string
|
||||||
|
local_name: any
|
||||||
|
optionsArray: OptionsArray2[]
|
||||||
|
OptionsList: string
|
||||||
|
extras: Extra2[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OptionsArray2 {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Extra2 {
|
||||||
|
id: number
|
||||||
|
item_id: number
|
||||||
|
price: number
|
||||||
|
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
|
||||||
|
pivot: Pivot3
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Pivot3 {
|
||||||
|
variant_id: number
|
||||||
|
extra_id: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AvaiilableVariantExtra2 {
|
||||||
|
id: number
|
||||||
|
item_id: number
|
||||||
|
price: number
|
||||||
|
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
|
||||||
|
pivot: Pivot4
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Pivot4 {
|
||||||
|
variant_id: number
|
||||||
|
extra_id: number
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
|
import { message } from "antd";
|
||||||
import { clearCart, selectCart } from "features/order/orderSlice";
|
import { clearCart, selectCart } from "features/order/orderSlice";
|
||||||
import { useCallback } from "react";
|
import { useCallback } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import { useCreateOrderMutation } from "redux/api/others";
|
import { useCreateOrderMutation } from "redux/api/others";
|
||||||
import { useAppDispatch, useAppSelector } from "redux/hooks";
|
import { useAppDispatch, useAppSelector } from "redux/hooks";
|
||||||
@@ -8,6 +10,7 @@ import { Customer } from "../../otp/types";
|
|||||||
export default function useOrder() {
|
export default function useOrder() {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const router = useNavigate();
|
const router = useNavigate();
|
||||||
|
const { t } = useTranslation();
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const restaurantID = localStorage.getItem("restaurantID");
|
const restaurantID = localStorage.getItem("restaurantID");
|
||||||
const { mobilenumber, user_uuid } = JSON.parse(
|
const { mobilenumber, user_uuid } = JSON.parse(
|
||||||
@@ -59,11 +62,15 @@ export default function useOrder() {
|
|||||||
useWallet: 0,
|
useWallet: 0,
|
||||||
tip,
|
tip,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then((res: any) => {
|
||||||
|
if (res.error)
|
||||||
|
message.error(res.error.data.message || t("order.createOrderFailed"));
|
||||||
|
else {
|
||||||
dispatch(clearCart());
|
dispatch(clearCart());
|
||||||
router(`/${id}/order`);
|
router(`/${id}/order/${res.data.result.orderID}`);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error: any) => {
|
||||||
console.error("Create Order failed:", error);
|
console.error("Create Order failed:", error);
|
||||||
});
|
});
|
||||||
}, [
|
}, [
|
||||||
@@ -80,6 +87,7 @@ export default function useOrder() {
|
|||||||
user_uuid,
|
user_uuid,
|
||||||
estimateTime,
|
estimateTime,
|
||||||
tip,
|
tip,
|
||||||
|
t,
|
||||||
dispatch,
|
dispatch,
|
||||||
router,
|
router,
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ import { Form } from "antd";
|
|||||||
import OrderSummary from "components/OrderSummary/OrderSummary";
|
import OrderSummary from "components/OrderSummary/OrderSummary";
|
||||||
import PaymentMethods from "components/PaymentMethods/PaymentMethods";
|
import PaymentMethods from "components/PaymentMethods/PaymentMethods";
|
||||||
import ProHeader from "components/ProHeader/ProHeader";
|
import ProHeader from "components/ProHeader/ProHeader";
|
||||||
|
import { selectCart } from "features/order/orderSlice";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useAppSelector } from "redux/hooks";
|
||||||
import styles from "../address/address.module.css";
|
import styles from "../address/address.module.css";
|
||||||
import { AddressSummary } from "./components/AddressSummary";
|
import { AddressSummary } from "./components/AddressSummary";
|
||||||
import BriefMenu from "./components/BriefMenu";
|
import BriefMenu from "./components/BriefMenu";
|
||||||
@@ -15,10 +17,15 @@ import PhoneCard from "./components/phoneCard";
|
|||||||
export default function CheckoutPage() {
|
export default function CheckoutPage() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
const { phone } = useAppSelector(selectCart);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Form form={form}>
|
<Form
|
||||||
|
form={form}
|
||||||
|
initialValues={{
|
||||||
|
phone,
|
||||||
|
}}
|
||||||
|
>
|
||||||
<ProHeader>{t("checkout.title")}</ProHeader>
|
<ProHeader>{t("checkout.title")}</ProHeader>
|
||||||
<div className={styles.checkoutContainer}>
|
<div className={styles.checkoutContainer}>
|
||||||
<AddressSummary />
|
<AddressSummary />
|
||||||
|
|||||||
@@ -2,6 +2,12 @@
|
|||||||
padding: 16px !important;
|
padding: 16px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.profileImage {
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Enhanced responsive order summary */
|
/* Enhanced responsive order summary */
|
||||||
@media (min-width: 769px) and (max-width: 1024px) {
|
@media (min-width: 769px) and (max-width: 1024px) {
|
||||||
.orderSummary {
|
.orderSummary {
|
||||||
@@ -9,7 +15,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.fascanoIcon {
|
.fascanoIcon {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 3px;
|
top: 3px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { Button, Card, Divider } from "antd";
|
import { Button, Card, Divider, Image } 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 Fascano50X50Icon from "components/Icons/fascano/Fascano50X50Icon";
|
|
||||||
import LocationIcon from "components/Icons/LocationIcon";
|
import LocationIcon from "components/Icons/LocationIcon";
|
||||||
import InvoiceIcon from "components/Icons/order/InvoiceIcon";
|
import InvoiceIcon from "components/Icons/order/InvoiceIcon";
|
||||||
import TimeIcon from "components/Icons/order/TimeIcon";
|
import TimeIcon from "components/Icons/order/TimeIcon";
|
||||||
@@ -12,15 +11,28 @@ 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 { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
import { useGetOrderDetailsQuery } from "redux/api/others";
|
||||||
|
import { useAppSelector } from "redux/hooks";
|
||||||
import Stepper from "./components/Stepper";
|
import Stepper from "./components/Stepper";
|
||||||
import styles from "./order.module.css";
|
import styles from "./order.module.css";
|
||||||
|
|
||||||
export default function OrderPage() {
|
export default function OrderPage() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { orderId } = useParams();
|
||||||
|
const { isRTL } = useAppSelector((state) => state.locale);
|
||||||
|
|
||||||
// const subtotal = getTotal();
|
const { data: orderDetails } = useGetOrderDetailsQuery(
|
||||||
// const tax = subtotal * 0.1; // 10% tax
|
{
|
||||||
// const total = subtotal + tax;
|
orderID: orderId || "",
|
||||||
|
restaurantID: localStorage.getItem("restaurantID") || "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skip: !orderId,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(orderDetails);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -54,7 +66,12 @@ export default function OrderPage() {
|
|||||||
backgroundColor: "rgba(255, 183, 0, 0.08)",
|
backgroundColor: "rgba(255, 183, 0, 0.08)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Fascano50X50Icon className={styles.fascanoIcon} />
|
<Image
|
||||||
|
src={orderDetails?.restaurant_iimage}
|
||||||
|
className={styles.profileImage}
|
||||||
|
width={50}
|
||||||
|
height={50}
|
||||||
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
<div>
|
<div>
|
||||||
<ProText style={{ fontSize: "1rem" }}>
|
<ProText style={{ fontSize: "1rem" }}>
|
||||||
@@ -63,7 +80,7 @@ export default function OrderPage() {
|
|||||||
<br />
|
<br />
|
||||||
<ProText type="secondary">
|
<ProText type="secondary">
|
||||||
<LocationIcon className={styles.locationIcon} />{" "}
|
<LocationIcon className={styles.locationIcon} />{" "}
|
||||||
{t("order.muscat")}
|
{isRTL ? orderDetails?.restaurantAR : orderDetails?.restaurant}
|
||||||
</ProText>
|
</ProText>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -84,11 +101,11 @@ export default function OrderPage() {
|
|||||||
<div style={{ display: "flex", flexDirection: "row", gap: 8 }}>
|
<div style={{ display: "flex", flexDirection: "row", gap: 8 }}>
|
||||||
<InvoiceIcon className={styles.invoiceIcon} />
|
<InvoiceIcon className={styles.invoiceIcon} />
|
||||||
<ProText type="secondary" style={{ fontSize: "14px" }}>
|
<ProText type="secondary" style={{ fontSize: "14px" }}>
|
||||||
#A54363
|
#{orderDetails?.order.id}
|
||||||
</ProText>
|
</ProText>
|
||||||
<TimeIcon className={styles.timeIcon} />
|
<TimeIcon className={styles.timeIcon} />
|
||||||
<ProText type="secondary" style={{ fontSize: "14px" }}>
|
<ProText type="secondary" style={{ fontSize: "14px" }}>
|
||||||
ordered :- Today - 13:55 PM
|
ordered :- Today - {orderDetails?.status[0]?.pivot?.created_at.split(" ")[1]} PM
|
||||||
</ProText>
|
</ProText>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -117,11 +134,7 @@ export default function OrderPage() {
|
|||||||
<div
|
<div
|
||||||
style={{ display: "flex", flexDirection: "column", gap: "1rem" }}
|
style={{ display: "flex", flexDirection: "column", gap: "1rem" }}
|
||||||
>
|
>
|
||||||
{[
|
{orderDetails?.orderItems.map((item, index) => (
|
||||||
{ id: 1, name: "Lazord Grill - half kilo" },
|
|
||||||
{ id: 2, name: "Lazord Grill - half kilo" },
|
|
||||||
{ id: 3, name: "Lazord Grill - half kilo" },
|
|
||||||
].map((item, index) => (
|
|
||||||
<div key={item.id}>
|
<div key={item.id}>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@@ -153,7 +166,7 @@ export default function OrderPage() {
|
|||||||
</div>
|
</div>
|
||||||
</ProInputCard>
|
</ProInputCard>
|
||||||
|
|
||||||
<PaymentDetails />
|
<PaymentDetails order={orderDetails?.order} />
|
||||||
|
|
||||||
<CancelOrderBottomSheet />
|
<CancelOrderBottomSheet />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
import {
|
import {
|
||||||
CREATE_ORDER_URL,
|
CREATE_ORDER_URL,
|
||||||
|
ORDER_DETAILS_URL,
|
||||||
ORDERS_URL,
|
ORDERS_URL,
|
||||||
PRODUCTS_AND_CATEGORIES_URL,
|
PRODUCTS_AND_CATEGORIES_URL,
|
||||||
RESTAURANT_DETAILS_URL,
|
RESTAURANT_DETAILS_URL,
|
||||||
|
TABLES_URL,
|
||||||
} from "utils/constants";
|
} from "utils/constants";
|
||||||
|
|
||||||
|
import { OrderDetails } from "pages/checkout/hooks/types";
|
||||||
import menuParser from "pages/menu/helper";
|
import menuParser from "pages/menu/helper";
|
||||||
import { RestaurantDetails } from "utils/types/appTypes";
|
import { RestaurantDetails } from "utils/types/appTypes";
|
||||||
import { baseApi } from "./apiSlice";
|
import { baseApi } from "./apiSlice";
|
||||||
@@ -43,6 +46,40 @@ export const branchApi = baseApi.injectEndpoints({
|
|||||||
}),
|
}),
|
||||||
invalidatesTags: ["Orders"],
|
invalidatesTags: ["Orders"],
|
||||||
}),
|
}),
|
||||||
|
getTables: builder.query<
|
||||||
|
any,
|
||||||
|
{ restaurantID: string; tableType: string }
|
||||||
|
>({
|
||||||
|
query: ({
|
||||||
|
restaurantID,
|
||||||
|
tableType,
|
||||||
|
}: {
|
||||||
|
restaurantID: string;
|
||||||
|
tableType: string;
|
||||||
|
}) => ({
|
||||||
|
url: TABLES_URL,
|
||||||
|
method: "POST",
|
||||||
|
body: {
|
||||||
|
restaurantID,
|
||||||
|
tableType,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
transformResponse: (response: any) => {
|
||||||
|
return response.result.data;
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
getOrderDetails: builder.query<OrderDetails, { orderID: string; restaurantID: string }>({
|
||||||
|
query: ({ orderID, restaurantID }: { orderID: string; restaurantID: string }) => ({
|
||||||
|
url: `${ORDER_DETAILS_URL}/${orderID}`,
|
||||||
|
method: "POST",
|
||||||
|
body: {
|
||||||
|
restaurantID,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
transformResponse: (response: any) => {
|
||||||
|
return response.result;
|
||||||
|
},
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
export const {
|
export const {
|
||||||
@@ -50,4 +87,6 @@ export const {
|
|||||||
useGetMenuQuery,
|
useGetMenuQuery,
|
||||||
useCreateOrderMutation,
|
useCreateOrderMutation,
|
||||||
useGetOrdersQuery,
|
useGetOrdersQuery,
|
||||||
|
useGetTablesQuery,
|
||||||
|
useGetOrderDetailsQuery,
|
||||||
} = branchApi;
|
} = branchApi;
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ export const router = createHashRouter([
|
|||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: "/:id/order",
|
path: "/:id/order/:orderId",
|
||||||
element: <PageWrapper children={<OrderPage />} />,
|
element: <PageWrapper children={<OrderPage />} />,
|
||||||
errorElement: <ErrorPage />,
|
errorElement: <ErrorPage />,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -95,12 +95,9 @@ export const RESTAURANT_DETAILS_URL = `${BASE_URL}restaurant/selectLanguage/`;
|
|||||||
export const PRODUCTS_AND_CATEGORIES_URL = `${BASE_URL}getRestaurantItems/`;
|
export const PRODUCTS_AND_CATEGORIES_URL = `${BASE_URL}getRestaurantItems/`;
|
||||||
export const PRODUCT_DETAILS_URL = `${BASE_URL}getOptionsForItem/`;
|
export const PRODUCT_DETAILS_URL = `${BASE_URL}getOptionsForItem/`;
|
||||||
export const ORDERS_URL = `${BASE_URL}customer_orders`;
|
export const ORDERS_URL = `${BASE_URL}customer_orders`;
|
||||||
|
export const ORDER_DETAILS_URL = `${BASE_URL}restaurant/getOneOrderForWebmenu`;
|
||||||
export const CREATE_ORDER_URL = `${BASE_URL}create_order_webmenu`;
|
export const CREATE_ORDER_URL = `${BASE_URL}create_order_webmenu`;
|
||||||
|
export const TABLES_URL = `${BASE_URL}restaurant/getTables`;
|
||||||
export const LOGIN_URL = `${API_BASE_URL}login`;
|
export const LOGIN_URL = `${API_BASE_URL}login`;
|
||||||
export const SEND_OTP_URL = `${API_BASE_URL}sendOtp`;
|
export const SEND_OTP_URL = `${API_BASE_URL}sendOtp`;
|
||||||
export const CONFIRM_OTP_URL = `${API_BASE_URL}confirmOtp`;
|
export const CONFIRM_OTP_URL = `${API_BASE_URL}confirmOtp`;
|
||||||
export const USERS_DATA_URL = `${API_BASE_URL}users`;
|
|
||||||
export const TABLE_HEADERS = `${API_BASE_URL}tableheader`;
|
|
||||||
export const PERMISSIONS_DATA_URL = `${API_BASE_URL}permissions`;
|
|
||||||
export const SINGED_USER_INFO_URL = `${API_BASE_URL}users/authenticated`;
|
|
||||||
export const ROLES_DATA_URL = `${API_BASE_URL}roles`;
|
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
// zero value may be considered an undefined ... donn't use in enums
|
// zero value may be considered an undefined ... donn't use in enums
|
||||||
import { ColumnType } from "antd/es/table";
|
import { ColumnType } from "antd/es/table";
|
||||||
import { PermissionType } from "modules/system/rolesManagement/types";
|
|
||||||
import { TaxType } from "modules/system/taxes/types";
|
|
||||||
import { QrCode } from "pages/pos/orders/components/order-panel/types";
|
|
||||||
import { ItemType, OrderType } from "pages/pos/orders/types";
|
|
||||||
|
|
||||||
export enum AlignType {
|
export enum AlignType {
|
||||||
"left" = "left",
|
"left" = "left",
|
||||||
@@ -148,25 +144,6 @@ export type LoginUserType = {
|
|||||||
password?: string;
|
password?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UserType = {
|
|
||||||
id?: number;
|
|
||||||
first_name?: string;
|
|
||||||
last_name?: string;
|
|
||||||
password?: string;
|
|
||||||
phone_number?: string;
|
|
||||||
salary?: any;
|
|
||||||
employment_date?: any;
|
|
||||||
email?: string;
|
|
||||||
username?: string;
|
|
||||||
personal_image?: any;
|
|
||||||
identity_card_front?: any;
|
|
||||||
identity_card_back?: any;
|
|
||||||
driving_license_front?: any;
|
|
||||||
driving_license_back?: any;
|
|
||||||
roles?: RolesType[];
|
|
||||||
menus: string[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export enum Mode {
|
export enum Mode {
|
||||||
Edit = 1,
|
Edit = 1,
|
||||||
New = 2,
|
New = 2,
|
||||||
@@ -297,33 +274,6 @@ export enum TableStatus {
|
|||||||
requestPayment = "PENDING_INVOICE",
|
requestPayment = "PENDING_INVOICE",
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ReservationType {
|
|
||||||
id: number;
|
|
||||||
start_datetime: string;
|
|
||||||
end_datetime: any;
|
|
||||||
seats_reserved: number;
|
|
||||||
orders: OrderType[];
|
|
||||||
invoice: InvoiceType;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface InvoiceType {
|
|
||||||
id: number;
|
|
||||||
number: number;
|
|
||||||
uuid: string;
|
|
||||||
sub_total: number;
|
|
||||||
grand_total: number;
|
|
||||||
discount_amount: number;
|
|
||||||
taxes_total: number;
|
|
||||||
print_times: number;
|
|
||||||
start_datetime: string;
|
|
||||||
end_datetime: string;
|
|
||||||
printed_at: string;
|
|
||||||
remaining_amount: number;
|
|
||||||
qr_code: QrCode;
|
|
||||||
taxes: TaxType[];
|
|
||||||
items: ItemType[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RegisterType {
|
export interface RegisterType {
|
||||||
id: number;
|
id: number;
|
||||||
opening_balance: number;
|
opening_balance: number;
|
||||||
@@ -339,12 +289,6 @@ export interface SessionPayload {
|
|||||||
total_expenses?: number;
|
total_expenses?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RolesType {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
permissions: PermissionType[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum Roles {
|
export enum Roles {
|
||||||
SuperUser = "super-admin",
|
SuperUser = "super-admin",
|
||||||
Admin = "admin",
|
Admin = "admin",
|
||||||
@@ -399,14 +343,6 @@ export interface User {
|
|||||||
role: "admin" | "user";
|
role: "admin" | "user";
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Order {
|
|
||||||
id: string;
|
|
||||||
userId: string;
|
|
||||||
items: CartItem[];
|
|
||||||
total: number;
|
|
||||||
status: "pending" | "confirmed" | "completed" | "cancelled";
|
|
||||||
createdAt: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Locale = "en" | "ar";
|
export type Locale = "en" | "ar";
|
||||||
export type Theme = "light" | "dark";
|
export type Theme = "light" | "dark";
|
||||||
|
|||||||
Reference in New Issue
Block a user