This commit is contained in:
KarimAldeen 2024-03-28 14:44:49 +03:00
parent 231b4dc913
commit 469ab0f3b3
34 changed files with 438 additions and 620 deletions

View File

@ -32,7 +32,7 @@ const StatisticsCard = (props :StatisticsCardProps) => {
} = props;
return (
<Card className="p-4 gomecards" {...rest} onClick={()=>navigate(pathWhenClick , {replace:true})}>
<Card className="p-4 gomecards" {...rest} onClick={()=>navigate(pathWhenClick )}>
<CardBody
className={`${
className ? className : "stats-card-body"

View File

@ -1,18 +1,28 @@
import { Form, DatePicker } from 'antd'
import React from 'react'
import { Form, DatePicker } from 'antd';
import React from 'react';
import useFormField from '../../../Hooks/useFormField';
import dayjs from 'dayjs';
const Date = ({ name, label,picker="date" ,isDisabled,props,onChange,placeholder ,className,Format}: any) => {
const DateField = ({ name, label, picker = "date", isDisabled, props, onChange, placeholder, className, Format }: any) => {
const { errorMsg, isError, t, formik } = useFormField(name, props);
const { errorMsg, isError, t, formik } = useFormField(name, props)
const onCalendarChange = (value: any) => {
console.log(value,"value");
formik.setFieldValue(name, value)
formik.setFieldValue(name, value);
};
return (
// Function to check if a date is valid
const isValidDate = (date: any) => {
return date && !isNaN(date.valueOf()) && dayjs(date).isValid();
};
// Set a default invalid date if the provided defaultValue is invalid
const getDefaultDate = () => {
const defaultValue = formik.values[name];
return isValidDate(defaultValue) ? defaultValue : null; // Set to null or any other default invalid date
};
return (
<div className='ValidationField'>
<label htmlFor={name} className="text">
{t(`${label ? label : name}`)}
@ -27,18 +37,15 @@ const Date = ({ name, label,picker="date" ,isDisabled,props,onChange,placeholder
placeholder={placeholder}
allowClear
className={`${className} w-100`}
defaultValue={formik.values[name]}
defaultValue={getDefaultDate()}
size="large"
onChange={onChange || onCalendarChange}
disabled={isDisabled}
format={Format}
/>
</Form.Item>
</div>
)
);
}
export default Date
export default DateField;

View File

@ -11,7 +11,7 @@ function useNavigateOnSuccess(isSuccess :boolean , to_path:string , callbackAfte
if (typeof callbackAfterSuccess === 'function') {
callbackAfterSuccess()
}
navigate(to_path , {replace:true})
navigate(to_path )
}
},[isSuccess])

View File

@ -3,7 +3,7 @@ import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useLocation, useNavigate } from 'react-router-dom';
const SelectField = ({ selectBy, submiteBy, lebel, option }: any) => {
const SelectField = ({ selectBy, lebel, option }: any) => {
const [searchQuery, setSearchQuery] = useState<string>('');
const location = useLocation();
const navigate = useNavigate();
@ -14,23 +14,13 @@ const SelectField = ({ selectBy, submiteBy, lebel, option }: any) => {
setSearchQuery(searchParams.get('search') || '');
}, []);
const handleSearchChange = (value: any) => {
if (value || value !== "") {
navigate(`${location.pathname}?${selectBy}=${value}`, { replace: true });
} else {
const params = new URLSearchParams(location.search);
params.delete(selectBy ?? "search");
navigate(`${location.pathname}?${params.toString()}`, { replace: true });
}
};
const handleSelectChange = (value: any) => {
if (value) {
console.log(`${location.pathname}?${submiteBy}=${value}`);
navigate(`${location.pathname}?${submiteBy}=${value}`, { replace: true });
console.log(`${location.pathname}?${selectBy}=${value}`);
navigate(`${location.pathname}?${selectBy}=${value}`, { replace: true });
}
}
}
return (
<div className='SelectField'>
@ -41,9 +31,6 @@ const SelectField = ({ selectBy, submiteBy, lebel, option }: any) => {
className={`w-100`}
allowClear
onChange={handleSelectChange}
showSearch
optionFilterProp="label"
onSearch={handleSearchChange}
/>
</div>
);

View File

@ -0,0 +1,52 @@
import { Select } from 'antd';
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useLocation, useNavigate } from 'react-router-dom';
const SelectWSearchField = ({ selectBy, submiteBy, lebel, option }: any) => {
const [searchQuery, setSearchQuery] = useState<string>('');
const location = useLocation();
const navigate = useNavigate();
const [t] = useTranslation();
useEffect(() => {
const searchParams = new URLSearchParams(location.search);
setSearchQuery(searchParams.get('search') || '');
}, []);
const handleSearchChange = (value: any) => {
if (value || value !== "") {
navigate(`${location.pathname}?${selectBy}=${value}`, { replace: true });
} else {
const params = new URLSearchParams(location.search);
params.delete(selectBy ?? "search");
navigate(`${location.pathname}?${params.toString()}`, { replace: true });
}
};
const handleSelectChange = (value: any) => {
if (value) {
console.log(`${location.pathname}?${submiteBy}=${value}`);
navigate(`${location.pathname}?${submiteBy}=${value}`, { replace: true });
}
}
return (
<div className='SelectWSearchField'>
<Select
placeholder={t(`${lebel}`)}
options={option}
size="large"
className={`w-100`}
allowClear
onChange={handleSelectChange}
showSearch
optionFilterProp="label"
onSearch={handleSearchChange}
/>
</div>
);
};
export default React.memo(SelectWSearchField);

View File

@ -3,7 +3,7 @@ import { Card, CardHeader, CardTitle, CardBody, Button } from "reactstrap";
import { Formik, Form } from "formik";
import { LoadingButton } from "../../Components/Ui/LoadingButton";
import ProgressBar from "../../Components/Ui/ProgressBar";
import { useNavigate } from "react-router-dom";
import { useLocation, useNavigate } from "react-router-dom";
import { usePageState } from "../../lib/state mangment/LayoutPagestate";
import { useTranslation } from "react-i18next";
@ -24,13 +24,29 @@ const ViewPage: React.FC<TViewPage>= ({children,getInitialValues, getValidation
const navigate = useNavigate();
// console.log(BarStatus);
const location = useLocation();
const navigateToParent = () => {
// // Get the current path
// const currentPath = window.location.pathname;
// // Find the index of the second '/' in the current path
// const secondSlashIndex = currentPath.indexOf('/', 1);
// // Extract the parent path
// const parentPath = secondSlashIndex !== -1 ? currentPath.substring(0, secondSlashIndex) : currentPath;
// // Navigate to the parent path
// navigate(parentPath);
navigate(-1)
};
return (
<Card className="ViewTapPage">
<CardHeader className="CardHeader" >
<CardTitle className="View_information">
{t("View_information")}
</CardTitle>
<Button onClick={() => { navigate(-1);}}> {t("back")} </Button>
<Button onClick={() => { navigateToParent()}}> {t("back")} </Button>
</CardHeader>
<CardBody>
{

View File

@ -8,7 +8,7 @@ function NotFoundPage() {
<div className='container-not-found'>
<p>404 <h6>|</h6>This page could not be found</p>
<div> <button onClick={()=>navigate('/' , {replace:true})}>Home</button></div>
<div> <button onClick={()=>navigate('/' )}>Home</button></div>
</div>
</div>
)

View File

@ -8,7 +8,7 @@ import { useGetProduct } from '../../api/product'
import { useNavigate } from 'react-router-dom'
import AddButton from '../../Layout/Dashboard/AddButton/AddButton'
import SearchField from '../../Layout/Dashboard/SearchField'
import SelectField from '../../Layout/Dashboard/SelectField'
import SelectField from '../../Layout/Dashboard/SelectWSearchField'
import { useGetCategories } from '../../api/Categories'
function ProductsPage() {

View File

@ -8,9 +8,8 @@ import { QueryStatusEnum } from '../../config/QueryStatus'
import { useGetUsers } from '../../api/users'
import SearchField from '../../Layout/Dashboard/SearchField'
import { useNavigate } from 'react-router-dom'
import AddButton from '../../Layout/Dashboard/AddButton/AddButton'
import { useTranslation } from 'react-i18next'
import SelectField from '../../Layout/Dashboard/SelectField'
import AddButtonNotification from './ui/AddButtonNotification'
function Page() {
@ -18,36 +17,29 @@ function Page() {
const {data ,status } = useGetUsers()
const totalRows = data?.meta?.total;
const navigate = useNavigate()
const [t] = useTranslation()
const typeData = [{label:"admin",value:"admin"},{value:"user",label:"user"}]
const statusData = [{label:"active",value:"active"},{label:"inActive",value:"inActive"}]
return (
// Pass Status to Layout
<DashBody status={status as QueryStatusEnum} >
<DashHeader showAddButton={false} title={'users'}>
<div className='RightSide d-flex gap-2 align-center '>
<SearchField searchBy={"name"} />
<div className='FillterSection'>
<AddButtonNotification/>
<SearchField searchBy={"email"} />
<SelectField selectBy="type" lebel="type" option={typeData} />
<SelectField selectBy="status" lebel="status" option={statusData} />
<div className='Add_Button_notification' onClick={()=>navigate('/notification/add')} >
<button >
<span >
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width={24}
height={24}
>
<path fill="none" d="M0 0h24v24H0z" />
<path fill="currentColor" d="M11 11V5h2v6h6v2h-6v6h-2v-6H5v-2z" />
</svg>{" "}
{t("create_notification")}
</span>
</button>
</div>
</div>
</DashHeader>
<LyTable
data={data?.data}
isLoading={false}

View File

@ -0,0 +1,27 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
import { useNavigate } from 'react-router-dom'
const AddButtonNotification = () => {
const navigate = useNavigate()
const [t] = useTranslation()
return (
<div className='Add_Button_notification' onClick={()=>navigate('/notification/add')} >
<button >
<span >
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width={24}
height={24}
>
<path fill="none" d="M0 0h24v24H0z" />
<path fill="currentColor" d="M11 11V5h2v6h6v2h-6v6h-2v-6H5v-2z" />
</svg>{" "}
{t("create_notification")}
</span>
</button>
</div> )
}
export default AddButtonNotification

View File

@ -2,14 +2,11 @@
import React from 'react'
import { Col, Row } from 'reactstrap';
import ValidationField from '../../../Components/ValidationField/ValidationField';
import { useFormikContext } from 'formik';
import { FaCheck, FaTimes, FaClock, FaBan } from 'react-icons/fa';
import { useTranslation } from 'react-i18next';
function Form() {
const formik = useFormikContext<any>();
const [t] = useTranslation();
// 'pending_approve', 'approved', 'rejected', 'pending_cancellation', 'cancelled'
const stateSelect = [

View File

@ -3,23 +3,7 @@ import * as Yup from "yup";
import { buildFormData } from "../../../api/helper/buildFormData";
import * as dayjs from 'dayjs'
interface formUtilCommon {
number:number,
value:number
}
interface ObjectToEdit extends formUtilCommon {
id?:number,
}
interface InitialValues extends ObjectToEdit {
}
interface ValidateSchema extends formUtilCommon{
}
export const getInitialValues = (objectToEdit: any | null = null): any => {
// console.log(objectToEdit,"objectToEdit");
return {

View File

@ -1,17 +1,20 @@
import React, { useEffect } from 'react'
import { getInitialValues, getDataToSend } from './formUtil'
import { getInitialValues, getDataToSend } from './Edit/formUtil'
import { Tab, TabList, TabPanel as TabBody, Tabs } from 'react-tabs'
import 'react-tabs/style/react-tabs.css';
import { MdLanguage } from 'react-icons/md'
import ViewPage from '../../../Layout/Dashboard/ViewPage';
import ViewPage from '../../Layout/Dashboard/ViewPage';
import { Spin } from 'antd';
import { usePageState } from '../../../lib/state mangment/LayoutPagestate';
import { usePageState } from '../../lib/state mangment/LayoutPagestate';
import { useParams } from 'react-router-dom';
import LoadingPage from '../../../Layout/app/LoadingPage';
import LoadingPage from '../../Layout/app/LoadingPage';
import { useTranslation } from 'react-i18next';
import useNavigateOnSuccess from '../../../Hooks/useNavigateOnSuccess';
import Form from './EditForm';
import { useGetOneOrder, useUpdateOrder } from '../../../api/order';
import useNavigateOnSuccess from '../../Hooks/useNavigateOnSuccess';
import { useGetOneOrder, useUpdateOrder } from '../../api/order';
import { FaEdit, FaFirstOrderAlt } from 'react-icons/fa';
import ProductsPage from './Products/ProductsPage';
import Form from './Edit/EditForm';
import ViewForm from './View/ViewForm';
@ -35,6 +38,10 @@ const EditPage = () => {
cleanedValues.deliviration_estimated_time = cleanedValues.deliviration_estimated_time.format('YYYY-MM-DD HH:mm:ss');
}
if(cleanedValues.deliviration_estimated_time === "Invalid Date"){
delete cleanedValues["deliviration_estimated_time"]
}
// Log the formatted deliviration_estimated_time
console.log(cleanedValues.deliviration_estimated_time);
@ -64,19 +71,29 @@ const EditPage = () => {
}
return (
<div className='ViewPage'>
{objectToEdit && data?.data ?
<ViewPage {...ViewProps}>
<Tabs>
<TabList>
<Tab><div className='SignleDriverContainer'><span className='SignleDriverInfoIcon'><FaEdit size={20} /></span> <h6 className='SingleDriverInfo'>{t("EditDetails")}</h6></div></Tab>
<Tab><div className='SignleDriverContainer'><span className='SignleDriverInfoIcon'><MdLanguage size={20} /></span> <h6 className='SingleDriverInfo'>{t("BasicInfo")}</h6></div></Tab>
<Tab><div className='SignleDriverContainer'><span className='SignleDriverInfoIcon'><FaFirstOrderAlt size={20} /></span> <h6 className='SingleDriverInfo'>{t("OrderItems")}</h6></div></Tab>
</TabList>
<TabBody >
<div className=" mt-4"><Form /></div>
</TabBody>
<TabBody >
<div className=" mt-4"><ViewForm /></div>
</TabBody>
<TabBody >
<div className=" mt-4"><ProductsPage /></div>
</TabBody>
</Tabs>
</ViewPage>

View File

@ -4,35 +4,50 @@ import DashBody from "../../Layout/Dashboard/DashBody";
import DashHeader from "../../Layout/Dashboard/DashHeader";
import { QueryStatusEnum } from "../../config/QueryStatus";
import LyTable from "../../Layout/Dashboard/LyTable";
import { useTranslation } from "react-i18next";
import { useGetOrder } from "../../api/order";
import SearchField from "../../Layout/Dashboard/SearchField";
import SelectField from "../../Layout/Dashboard/SelectField";
import { useGetCoupon } from "../../api/Coupon";
import SelectWSearchField from "../../Layout/Dashboard/SelectWSearchField";
// import SearchField from "../../Components/ValidationField/View/SearchField";
import CustomDateRange from "./ui/CustomDateRange";
const OrderPage = () => {
const [t] = useTranslation();
//filters
const [search, setSearchText] = React.useState("");
const filterIsApplied = search !== "";
//Table Content -- Data + Columns
const { data, isLoading, status } = useGetOrder({ search });
const { data, status } = useGetOrder();
const totalRows = data?.pagination?.total || 0;
const columns = useTableColumns();
/// Coupon status Created from -> to Price from => to
const statusData = [{label:"active",value:"active"},{label:"inActive",value:"inActive"}]
const { data:Coupon } = useGetCoupon()
const SelectData = Coupon?.coupons?.map((item:any)=>(
{
label : item?.name,
value : item?.id
}
))
return (
<>
<DashBody status={status as QueryStatusEnum} >
<DashHeader title="orders" showAddButton={false}>
<div className='RightSide d-flex gap-2 align-center '>
<SearchField searchBy="username" />
<div className='FillterSection'>
<SearchField searchBy={"username"} />
<SelectWSearchField selectBy="coupon" submiteBy="coupon_id" lebel="Coupon" option={SelectData} />
<SelectField selectBy="status" lebel="status" option={statusData} />
<CustomDateRange/>
</div>
</DashHeader>
<LyTable
data={data?.Orders}
total={totalRows}

View File

@ -0,0 +1,44 @@
import DashBody from '../../../Layout/Dashboard/DashBody'
import DashHeader from '../../../Layout/Dashboard/DashHeader'
import LyTable from '../../../Layout/Dashboard/LyTable'
import useTableColumns from './useTableColumns'
import { QueryStatusEnum } from '../../../config/QueryStatus'
import { useParams } from 'react-router-dom'
import { useGetOneOrder } from '../../../api/order'
import { Spin } from 'antd'
function ProductsPage() {
const column =useTableColumns()
const {id} = useParams()
const { data, status,isLoading } = useGetOneOrder({id: id })
const order = data?.data || {};
const items = order?.products ;
if(isLoading){
return <Spin/>
}
console.log(items,"items");
return (
<DashBody status={status as QueryStatusEnum} >
<DashHeader showAddButton={false} title={'products'}>
</DashHeader>
<LyTable
data={items}
isLoading={false}
columns={column}
is_pagination={false}
/>
</DashBody>
)
}
export default ProductsPage

View File

@ -0,0 +1,49 @@
import { useMemo } from "react";
import { useTranslation } from "react-i18next";
const useTableColumns :any = () => {
const [t] = useTranslation();
const language = localStorage.getItem("language") ?? "en"
return useMemo(
() => [
{
name: t("id"),
sortable: true, // Enable sorting for id column
center: true,
selector: (row: any) => row.id, // Specify selector function for sorting
}, {
name: t("name"),
sortable: false,
center: true,
selector:(row:any) => row?.name?.[language],
},
{
name: t("product_count"),
sortable: false,
center: true,
selector:(row:any) => row?.product_count,
},
{
name: t("category"),
sortable: false,
center: true,
cell: (row:any) => (
row?.category?.name?.[language]
),
},
],
[language, t]
);
};
export default useTableColumns;

View File

@ -1,51 +0,0 @@
import React, { useState } from 'react';
import {
Dropdown,
DropdownToggle,
DropdownMenu,
DropdownItem,
} from 'reactstrap';
// import PropTypes from 'prop-types';
import {BsArrowDownShort} from 'react-icons/bs'
import { useTranslation } from 'utility/language';
function SelectType({ direction, title , setSelectType,setRefreshPage}) {
const t = useTranslation()
const [dropdownOpen, setDropdownOpen] = useState(false);
const toggle = () => setDropdownOpen((prevState) => !prevState);
return (
<div className="d-flex " style={{marginInline:10 }}>
<Dropdown isOpen={dropdownOpen} toggle={toggle} direction={direction} size={30}
>
<DropdownToggle outline style={{color:"black" , width:"100%" , border:"gray solid 2px" , borderRadius:"10px" , padding:"8px"}} nav caret >{t(localStorage.getItem('order_status') || 'all')} <BsArrowDownShort size={17} style={{height:20}} /></DropdownToggle>
<DropdownMenu >
<DropdownItem onClick={()=>{
setRefreshPage(v => !v)
setSelectType('status')
localStorage.setItem('order_status','')
}} style={{width:"100%", }}>{t('all')}</DropdownItem>
<DropdownItem onClick={()=>{
setRefreshPage(v => !v)
setSelectType('complete')
localStorage.setItem('order_status','complete')
}} style={{color:"black", width:"100%"}}>{t('complete')}</DropdownItem>
<DropdownItem onClick={()=>{
setRefreshPage(v => !v)
setSelectType('canceled')
localStorage.setItem('order_status','canceled')
}} style={{color:"black", width:"100%"}}>{t('canceled')}</DropdownItem>
</DropdownMenu>
</Dropdown>
</div>
);
}
// SelectType.propTypes = {
// direction: PropTypes.string,
// };
export default SelectType;

View File

@ -0,0 +1,50 @@
import React from 'react'
import { useTranslation } from 'react-i18next';
import { Col, Row } from 'reactstrap';
import { useGetOneOrder } from '../../../api/order';
import { useParams } from 'react-router-dom';
import { ChangeformatDate } from '../../../utils/Date/ChangeFormat';
import { Spin } from 'antd';
function Form() {
const [t] = useTranslation()
const { id } = useParams()
const { data, isLoading } = useGetOneOrder({ id: id })
const order = data?.data || {};
if (isLoading) {
return <Spin />
}
return (
<>
<Row xs={1} sm={1} md={2} lg={2} xl={2} className='OrderDetails'>
<Col >
<p >{t("customer_name")}{" : "}{order.user?.name??"null"}</p>
<p >{t("customer_phone_number")}{" : "}{order.user?.phone??"null"}</p>
<p >{t("order_created_at")}{" : "}{ChangeformatDate(order.created_at)}</p>
<p >{t("address")}{" : "}{order?.form?.address}</p>
<p >{t("country")}{" : "}{order?.form?.country}</p>
<p >{t("note")}{" : "}{order?.form?.note}</p>
</Col>
<Col >
<p >{t("sub_total")}{" : "}{order?.total}</p>
<p >{t("delivery_fee")}{" : "}{0}</p>
<p >{t("overall_total")}{" : "}{order?.total}</p>
</Col>
</Row>
</>
)
}
export default Form

View File

@ -1,61 +0,0 @@
import * as Yup from "yup";
import { buildFormData } from "api/helpers";
export const getInitialValues = (objectToEdit = null) => {
if (!objectToEdit) {
return {
driver_name:"",
driver_id_number: "",
driver_car_back_side:""
};
}
return {
driver_name:objectToEdit.driver_name,
driver_id_number: objectToEdit.driver_id_numbert,
customer_image: "",
driver_car_back_side:""
};
};
export const getValidationSchema = (editMode = false) => {
return Yup.object().shape({
customer_name:Yup.string().required("required"),
driver_id_number: Yup.number().required("required"),
...(!editMode && {
subcategory_image: Yup.mixed().required("required"),
}),
});
};
export const getDataToSend = (values) => {
const data = { ...values };
if (values.subcategory_image === "") {
delete data["subcategory_image"];
}
const formData = new FormData();
buildFormData(formData, data);
return formData;
};
export const selectFailGender = [
{value : "female" , label:"female"},
{value:"male" , label:"male"}
]
export const ChangePointShape = (array_of_points)=>{
let my_new_array = [];
for (let index = 0; index < array_of_points.length; index+=5) {
const my_latlong =(array_of_points[index]).split(',')
my_new_array.push({
lat:+ my_latlong[0],
lng:+my_latlong[1]
})
}
return my_new_array ;
}

View File

@ -0,0 +1,27 @@
import React from 'react'
import { DatePicker } from 'antd'
const { RangePicker } = DatePicker;
const CustomDateRange = () => {
const dateFormat = 'YYYY-MM-DD';
const onCalendarChange = (value: any) => {
const FromData = value[0]?.format(dateFormat)
const ToData = value[1]?.format(dateFormat)
console.log(FromData,"FromData");
console.log(ToData,"ToData");
};
return (
<RangePicker
size="large"
allowClear
format={dateFormat}
onChange={onCalendarChange}
className="CustomDateRange"
/>
)
}
export default CustomDateRange

View File

@ -22,14 +22,14 @@ const useTableColumns = () => {
name: t("name"),
sortable: false,
center:true,
selector:(row:any) => row?.user?.name,
selector:(row:any) => row?.user?.name ?? "null",
},
{
name: t("email"),
sortable: false,
center:true,
selector:(row:any) => row?.user?.email,
selector:(row:any) => row?.user?.email?? "null",
},
@ -86,8 +86,9 @@ const useTableColumns = () => {
objectToEdit={row}
onDelete={() => deleteMutation.mutate({order_id:row.id })}
showEdit={true}
onView={()=>navigate(`/order/view/${row?.id}` , {replace:true})}
onEdit={()=>navigate(`/order/${row?.id}` , {replace:true})}
showView={false}
onView={()=>navigate(`/order/view/${row?.id}` )}
onEdit={()=>navigate(`/order/${row?.id}` )}
/>

View File

@ -1,90 +0,0 @@
import Reac from 'react'
import { useNavigate, useParams } from 'react-router-dom';
import { Button, Card, CardBody, CardFooter, CardHeader, CardTitle } from 'reactstrap';
import OrderForm from './OrderForm';
import DataTable from 'react-data-table-component';
import useTableColumns from './useTableColumns';
import { useTranslation } from 'react-i18next';
import { useGetOneOrder } from '../../../api/order';
import LoadingPage from '../../../Layout/app/LoadingPage';
import { history } from '../../../ProviderContainer';
import StatusOrderController from './StatusOrderController';
export default function Order() {
const { id } = useParams();
const [t] = useTranslation();
const navigate = useNavigate()
const { data, isLoading, notFound } = useGetOneOrder({id: id })
const order = data?.data || {};
const columns = useTableColumns();
const items = order?.products ;
if (isLoading) {
return (<LoadingPage />)
}
return (
<Card style={{paddingBottom:"2.5rem"}}>
<CardHeader style={{display:"flex" , justifyContent:"space-between" , margin:"20px"}}>
<CardTitle>
<p>{t("order_id")} : {order?.id}</p>
</CardTitle>
<span style={{display:"flex" , height:37, marginRight:7,justifyContent:"space-between" }}>
<Button
onClick={() => navigate(-1)}
color="danger"
>
{t("back")}
</Button>
</span>
</CardHeader>
{/* <div style={{padding:"1.5rem",display:"flex",alignItems:"center",justifyContent:"space-between"}}>
<div>
</div>
</div> */}
<CardBody style={{padding:" 1.5rem"}}>
<OrderForm order={order} />
<DataTable
columns={columns}
data={items}
progressPending={isLoading}
// noDataComponent={<h6 className="my-4">{("no_records")}</h6>}
// noHeader
/>
</CardBody>
</Card>
)
}

View File

@ -1,39 +0,0 @@
import React from 'react'
import { Row, Col } from 'reactstrap'
import classes from './OrderForm.module.scss';
import { useTranslation } from 'react-i18next';
import { ChangeformatDate } from '../../../utils/Date/ChangeFormat';
export default function OrderForm({ order }) {
const [t] = useTranslation();
return (
<>
<Row xs={1} sm={1} md={2} lg={3} xl={3}>
<Col className={classes.test} >
<p >{t("customer_name")}{" : "}{order.user?.name}</p>
<p >{t("customer_phone_number")}{" : "}{order.user?.phone}</p>
<p >{t("order_created_at")}{" : "}{ChangeformatDate(order.created_at)}</p>
</Col>
<Col className={classes.test} >
<p >{t("address")}{" : "}{order?.form?.address}</p>
<p >{t("country")}{" : "}{order?.form?.country}</p>
<p >{t("note")}{" : "}{order?.form?.note}</p>
</Col>
</Row>
<Row className={classes.Wrapper}>
<div className={classes.totalsForm}>
<h1 >{t("totals")}</h1>
<p >{t("sub_total")}{" : "}{order?.total}</p>
<p >{t("delivery_fee")}{" : "}{0}</p>
<p >{t("overall_total")}{" : "}{order?.total}</p>
</div>
</Row>
</>
)
}

View File

@ -1,36 +0,0 @@
.totalsForm {
width: 60%;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 1rem;
border-radius: 10px;
border: 3px solid #122236;
margin-bottom: 10px;
}
.Wrapper {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 1rem;
}
.Wrapper h1{
color: #122236;
}
.test {
padding: 1rem;
display: flex;
align-items: flex-start;
justify-content: center;
flex-direction: column;
}
p {
font-weight: 600;
}

View File

@ -1,31 +0,0 @@
import React from "react";
import { Badge } from "reactstrap";
import PropTypes from "prop-types";
import { useTranslation } from "react-i18next";
const OrderStatus = ({ order_status }) => {
const [t] = useTranslation();
const all={
pending:{color:"secondary"},
accepted:{color:"success"},
accept:{color:"success"},
delivering:{color:"primary"},
delivered:{color:"success"},
canceled:{color:"danger"}
}
return (
<Badge color={all[order_status].color}>
{t(order_status)}
</Badge>
);
};
OrderStatus.propTypes = {
order_status: PropTypes.string.isRequired,
};
export default OrderStatus;

View File

@ -1,80 +0,0 @@
import React from 'react'
import OrderStatus from './OrderStatus';
import { useTranslation } from 'react-i18next';
import { useAcceptOrder, useCancelOrder, useDeliverOrder, useDeliveredOrder } from '../../../api/order';
import { LoadingButton } from '../../../Components/Ui/LoadingButton';
export default function StatusOrderController({ order_status, order_id }) {
const acceptMutation = useAcceptOrder();
const cancelMutation = useCancelOrder();
const deliverMutation = useDeliverOrder();
const deliveredMutation = useDeliveredOrder();
const [t] = useTranslation();
const controll = {
pending: {
nextMutation: acceptMutation,
nextLabel: "accept",
nextColor: "primary",
prevMutation: cancelMutation,
prevLabel: "cancel",
prevColor: "danger",
},
accepted: {
nextMutation: deliverMutation,
nextLabel: "deliver",
nextColor: "primary",
prevMutation: cancelMutation,
prevLabel: 'cancel',
prevColor: "danger",
},
delivering: {
nextMutation: deliveredMutation,
nextLabel: "delivered",
nextColor: "primary",
prevMutation: cancelMutation,
prevLabel: 'cancel',
prevColor: "danger",
},
delivered: {
nextMutation: null,
nextLabel: null,
prevMutation: null,
prevLabel: null
},
canceled: {
nextMutation: null,
nextLabel: null,
prevMutation: null,
prevLabel: null
},
}
return (
<div >
<div className="d-flex align-items-center justify-content-start m-1" style={{gap:"10px"}}>
<p >{t("order_status")}{" : "}{<OrderStatus order_status={order_status} />}</p>
{
controll[order_status].nextMutation && controll[order_status].nextLabel && <LoadingButton
style={{ margin: "10px" }}
color={controll[order_status].nextColor}
isLoading={controll[order_status].nextMutation.isLoading}
onClick={() => controll[order_status].nextMutation.mutate({ order_id: order_id })}
>
{t(controll[order_status].nextLabel)}
</LoadingButton>
}
{
controll[order_status].prevMutation && controll[order_status].prevLabel && <LoadingButton
color={controll[order_status].prevColor}
isLoading={controll[order_status].prevMutation.isLoading}
onClick={() => controll[order_status].prevMutation.mutate({ order_id: order_id })}
>
{t(controll[order_status].prevLabel)}
</LoadingButton>
}
</div>
</div>
)
}

View File

@ -1,20 +0,0 @@
.print-source {
display: none;
}
body > .print-source {
display: block;
}
.inner{
display: flex;
align-items: center;
justify-content: space-between;
}
@media print {
.print-source {
display: block;
}
}

View File

@ -1,59 +0,0 @@
import React from 'react'
import { useTranslation } from 'react-i18next';
import ColumnsImage from '../../../Components/Columns/ColumnsImage';
import { mapTranslatedProperties } from '../../../utils/language/mapTranslatedProperties';
export default function useTableColumns() {
const [t] = useTranslation();
const language = localStorage.getItem("language") ?? "en"
return [
{
name: t("id"),
sortable: true,
center: true,
cell:(row) => row.id
},
{
name: `${t('name')}`,
sortable: true,
center: true,
cell:(row) => row.name[language]
},
{
name: `${t("image")}`,
sortable: false,
center: true,
cell: (row) => {
const imgSource = row?.main_photo
return (
<ColumnsImage
src={imgSource}
/>
);
},
},
{
name: t("quantity"),
sortable: true,
center: true,
cell:(row)=>row?.quantity
},
{
name: t("price"),
sortable: true,
center: true,
cell:(row)=>row?.price
},
]
}

View File

@ -17,9 +17,8 @@ import EditCategories from "./Pages/Categories/View/EditPage";
import ProductsPage from "./Pages/Products/ProductsPage";
import AddProductPage from "./Pages/Products/View/AddPage";
import EditProduct from "./Pages/Products/View/EditPage";
import Order from "./Pages/order/view-one/Order";
import OrderPage from "./Pages/order/OrderPage";
import EditOrder from "./Pages/order/Edit/EditPage";
import EditOrder from "./Pages/order/EditPage";
import CouponPage from "./Pages/Coupon/Page";
@ -120,13 +119,7 @@ export const RoutesLinks: RoutesLinksType[] = [
hidden:true
},
{
name: "view_order",
element: <Order />,
href: "/order/view/:id",
hidden:true
},
{
name: "Coupon",
element: <CouponPage />,

View File

@ -15,6 +15,7 @@
@import '../component/DriverInfoSocket.scss';
@import '../component/radio.scss';
@import '../Layout/FillterSection.scss';

View File

@ -0,0 +1,18 @@
.FillterSection{
display: flex;
gap: 20px;
flex-wrap: wrap;
margin-bottom: 20px;
align-items: center;
flex-direction: row-reverse;
.SelectField{
width: 150px;
}
}
@media screen and (max-width: 600px) {
.SelectField{
display: none;
}
}

View File

@ -503,7 +503,7 @@ padding: 10px 40px;
@media screen and (max-width: 600px) {
.SearchField,.SelectField{
.SearchField,.SelectWSearchField{
display: none;
}
}
@ -573,7 +573,7 @@ padding: 10px 40px;
// gap: 30px;
// }
// }
.SelectField{
.SelectWSearchField{
width: 200px;
}
.ant-drawer .ant-drawer-body{
@ -606,3 +606,9 @@ padding: 10px 40px;
}
}
.CustomDateRange{
width: 300px;
}
.OrderDetails{
padding: 20px 4vw ;
}

View File

@ -16,7 +16,7 @@ const API = {
const KEY = "Order"
export const useGetOrder = (params?:any) => useGetQueryPagination(KEY, API.GET_ALL,params);
export const useGetOrder = (params?:any) => useGetQueryPagination(KEY, API.GET_ALL,params,{},"coupon");
export const useGetOneOrder = (params?:any) => useGetOneQuery(KEY, API.GET_ALL,params);
export const useAddOrder = () => useAddMutation(KEY, API.ADD);

View File

@ -6,3 +6,5 @@ whatsApp
subject
message
SupportMessages
EditDetails
OrderItems