Initial commit
This commit is contained in:
160
src/pages/orders/OrdersList.tsx
Normal file
160
src/pages/orders/OrdersList.tsx
Normal file
@@ -0,0 +1,160 @@
|
||||
import { Button, Card, Divider } from "antd";
|
||||
import EmptyOrdersIcon from "components/Icons/EmptyOrdersIcon";
|
||||
import RateIcon from "components/Icons/RateIcon";
|
||||
import ReOrderIcon from "components/Icons/ReOrderIcon";
|
||||
import LoadingSpinner from "components/LoadingSpinner";
|
||||
import ProText from "components/ProText";
|
||||
import ProTitle from "components/ProTitle";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useGetOrdersQuery } from "redux/api/others";
|
||||
import { colors } from "ThemeConstants";
|
||||
import styles from "./orders.module.css";
|
||||
|
||||
// Utility function to format date
|
||||
const formatDate = (dateString: string): string => {
|
||||
const date = new Date(dateString);
|
||||
|
||||
// Format: "14 December 2022 18:45"
|
||||
const options: Intl.DateTimeFormatOptions = {
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
hour12: false,
|
||||
};
|
||||
|
||||
return date.toLocaleDateString("en-GB", options);
|
||||
};
|
||||
|
||||
export default function OrdersList() {
|
||||
const { data: orders = [], isLoading, error, refetch } = useGetOrdersQuery();
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
if (isLoading) {
|
||||
return <LoadingSpinner />;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
height: "90vh",
|
||||
}}
|
||||
>
|
||||
<ProTitle level={4}>{t("orders.errorLoadingOrders")}</ProTitle>
|
||||
<Button onClick={refetch}>{t("orders.retry")}</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{orders.length === 0 ? (
|
||||
// Empty state
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
height: "90vh",
|
||||
padding: "1rem"
|
||||
}}
|
||||
>
|
||||
<EmptyOrdersIcon />
|
||||
<ProTitle level={4}>{t("orders.noOrdersFound")}</ProTitle>
|
||||
<ProText>
|
||||
{t("orders.youHavenTPlacedAnyOrdersYet")}
|
||||
</ProText>
|
||||
</div>
|
||||
) : (
|
||||
// Orders list
|
||||
<div style={{ padding: "16px" }}>
|
||||
{orders.map((order: any) => (
|
||||
<Card
|
||||
key={order.id}
|
||||
style={{
|
||||
borderRadius: "12px",
|
||||
boxShadow: "0 2px 8px rgba(0, 0, 0, 0.1)",
|
||||
marginBottom: 12,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
justifyContent: "flex-start",
|
||||
gap: "1rem",
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
type="text"
|
||||
shape="circle"
|
||||
style={{
|
||||
backgroundColor: "rgba(255, 183, 0, 0.08)",
|
||||
}}
|
||||
>
|
||||
{order.restaurant_name[0]}
|
||||
</Button>
|
||||
<div
|
||||
style={{ display: "flex", flexDirection: "column", gap: 8 }}
|
||||
>
|
||||
<ProText style={{ fontSize: "1rem" }}>
|
||||
{order.restaurant_name}
|
||||
</ProText>
|
||||
<ProText type="secondary">
|
||||
{formatDate(order?.created_at)}
|
||||
</ProText>
|
||||
<ProText type="secondary">
|
||||
{t("orders.orderID")} {order.id}
|
||||
</ProText>
|
||||
<Button
|
||||
style={{
|
||||
borderRadius: 888,
|
||||
height: 24,
|
||||
border: "none",
|
||||
backgroundColor: colors.primary,
|
||||
color: "white",
|
||||
padding: "0 8px",
|
||||
width: "fit-content",
|
||||
}}
|
||||
>
|
||||
{order.status}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<Divider style={{ margin: "15px 0 10px 0" }} />
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-around",
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<ProText style={{ fontSize: "1rem", color: colors.primary }}>
|
||||
<RateIcon className={styles.rateIcon} />
|
||||
{t("orders.rateOrder")}
|
||||
</ProText>{" "}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<ProText style={{ fontSize: "1rem", color: colors.primary }}>
|
||||
<ReOrderIcon className={styles.reorderIcon} />
|
||||
{t("orders.reOrder")}
|
||||
</ProText>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
67
src/pages/orders/orders.module.css
Normal file
67
src/pages/orders/orders.module.css
Normal file
@@ -0,0 +1,67 @@
|
||||
.productContainer :global(.ant-radio-wrapper:last-child) {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.productContainer :global(.ant-radio-label) {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
/* radio.module.css */
|
||||
.productContainer :global(.ant-radio-inner) {
|
||||
width: 24px !important;
|
||||
height: 24px !important;
|
||||
border-radius: 30px !important;
|
||||
}
|
||||
|
||||
.productContainer :global(.ant-radio) {
|
||||
width: 24px !important;
|
||||
height: 24px !important;
|
||||
}
|
||||
|
||||
.productContainer :global(.ant-radio-checked .ant-radio-inner) {
|
||||
border-radius: 30px !important;
|
||||
}
|
||||
|
||||
.productContainer :global(.ant-checkbox-wrapper:last-child) {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.productContainer :global(.ant-checkbox-label) {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
/* .productContainer :global(.ant-checkbox-input) {
|
||||
margin-top: 5px !important;
|
||||
} */
|
||||
|
||||
.productContainer :global(.ant-checkbox-inner) {
|
||||
border-radius: 40px !important;
|
||||
}
|
||||
|
||||
/* CheckboxGroup.module.css */
|
||||
.productContainer :global(.ant-checkbox-inner) {
|
||||
width: 24px !important;
|
||||
height: 24px !important;
|
||||
border-radius: 30px !important;
|
||||
}
|
||||
|
||||
.productContainer :global(.ant-checkbox) {
|
||||
width: 24px !important;
|
||||
height: 24px !important;
|
||||
}
|
||||
|
||||
.productContainer :global(.ant-checkbox-checked .ant-checkbox-inner) {
|
||||
border-radius: 30px !important;
|
||||
}
|
||||
|
||||
.rateIcon{
|
||||
position: relative;
|
||||
top: 2px;
|
||||
margin:0 5px;
|
||||
}
|
||||
|
||||
.reorderIcon{
|
||||
position: relative;
|
||||
top: 2px;
|
||||
margin:0 5px;
|
||||
}
|
||||
42
src/pages/orders/page.tsx
Normal file
42
src/pages/orders/page.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import { Button, Row } from "antd";
|
||||
import ProHeader from "components/ProHeader/ProHeader";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link, useParams } from "react-router-dom";
|
||||
import { useAppSelector } from "redux/hooks";
|
||||
import { ProBlack2 } from "ThemeConstants";
|
||||
import OrdersList from "./OrdersList";
|
||||
|
||||
export default function OrdersPage() {
|
||||
const { t } = useTranslation();
|
||||
const { id } = useParams();
|
||||
const { themeName } = useAppSelector((state) => state.theme);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ProHeader>{t("orders.title")}</ProHeader>
|
||||
<OrdersList />
|
||||
<Row
|
||||
style={{
|
||||
width: "100%",
|
||||
padding: "16px 16px 0",
|
||||
position: "fixed",
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
boxShadow: "0px -1px 3px rgba(0, 0, 0, 0.1)",
|
||||
backgroundColor: themeName === "light" ? "white" : ProBlack2,
|
||||
|
||||
}}
|
||||
>
|
||||
<Link to={`/${id}/menu`} style={{ width: "100%" }}>
|
||||
<Button
|
||||
type="primary"
|
||||
shape="round"
|
||||
style={{ width: "100%", height: 48, marginBottom: 16 }}
|
||||
>
|
||||
{t('orders.browseMenu')}
|
||||
</Button>
|
||||
</Link>
|
||||
</Row>
|
||||
</>
|
||||
);
|
||||
}
|
||||
92
src/pages/orders/types.ts
Normal file
92
src/pages/orders/types.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
export interface ProductDetails {
|
||||
data: Daum[]
|
||||
name: string
|
||||
nameAR: string
|
||||
image: string
|
||||
price: number
|
||||
variants: Variant[]
|
||||
theExtrasGroups: TheExtrasGroup[]
|
||||
discount: number
|
||||
options: Option[]
|
||||
hasVariants: number
|
||||
currency: string
|
||||
short_description: string
|
||||
short_descriptionAR: string
|
||||
}
|
||||
|
||||
export interface Daum {
|
||||
id: number
|
||||
name: string
|
||||
data: string[]
|
||||
prices: string[]
|
||||
pricesNew: string[]
|
||||
nameAR: string
|
||||
dataAR: string[]
|
||||
}
|
||||
|
||||
export interface Variant {
|
||||
id: number
|
||||
price: number
|
||||
options: string
|
||||
image: string
|
||||
qty: number
|
||||
enable_qty: number
|
||||
order: number
|
||||
item_id: number
|
||||
created_at: string
|
||||
updated_at: string
|
||||
deleted_at: any
|
||||
available: string
|
||||
OptionsList: string
|
||||
extras: any[]
|
||||
}
|
||||
|
||||
export interface TheExtrasGroup {
|
||||
id: number
|
||||
name: string
|
||||
nameAR: string
|
||||
label: string
|
||||
labelAR: string
|
||||
limit: number
|
||||
item_id: number
|
||||
created_at: string
|
||||
updated_at: string
|
||||
deleted_at: any
|
||||
force_limit_selection: number
|
||||
extras: Extra[]
|
||||
}
|
||||
|
||||
export interface Extra {
|
||||
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: Pivot
|
||||
}
|
||||
|
||||
export interface Pivot {
|
||||
group_id: number
|
||||
extra_id: number
|
||||
}
|
||||
|
||||
export interface Option {
|
||||
id: number
|
||||
item_id: number
|
||||
name: string
|
||||
nameAR: string
|
||||
options: string
|
||||
optionsAR: string
|
||||
optionprices: string
|
||||
created_at: string
|
||||
updated_at: string
|
||||
deleted_at: any
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user