Initial commit

This commit is contained in:
2025-10-04 18:22:24 +03:00
commit 2852c2c054
291 changed files with 38109 additions and 0 deletions

View 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>
)}
</>
);
}

View 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
View 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
View 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
}