Done
This commit is contained in:
parent
086116119c
commit
82c7c0d09b
BIN
public/Logo.png
Normal file
BIN
public/Logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
|
|
@ -8,7 +8,7 @@
|
||||||
content="Web site created using create-react-app"
|
content="Web site created using create-react-app"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<title>Etaxi - App</title>
|
<title>Hijab - App</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ const App = () => {
|
||||||
{/* 404 Page */}
|
{/* 404 Page */}
|
||||||
<Route path="*" element={<Suspense fallback={<Loading />}> <Page404 /></Suspense>} />
|
<Route path="*" element={<Suspense fallback={<Loading />}> <Page404 /></Suspense>} />
|
||||||
{/* Login Page */}
|
{/* Login Page */}
|
||||||
{/* <Route path="/auth" element={<Suspense fallback={<Loading />}> <Auth /></Suspense>} /> */}
|
<Route path="/auth" element={<Suspense fallback={<Loading />}> <Auth /></Suspense>} />
|
||||||
|
|
||||||
{/* route not in navigation */}
|
{/* route not in navigation */}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import React from "react";
|
||||||
import "./KarimField.scss";
|
import "./KarimField.scss";
|
||||||
import { Date, Time, File, DataRange, SelectField, Default, CheckboxField } from './View';
|
import { Date, Time, File, DataRange, SelectField, Default, CheckboxField } from './View';
|
||||||
import { KarimFieldProps } from "./types";
|
import { KarimFieldProps } from "./types";
|
||||||
|
import MaltyFile from "./View/MaltyFile";
|
||||||
|
|
||||||
const KarimField: React.FC<KarimFieldProps> = ({type = "text", ...otherProps}) => {
|
const KarimField: React.FC<KarimFieldProps> = ({type = "text", ...otherProps}) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|
@ -15,6 +16,8 @@ const KarimField: React.FC<KarimFieldProps> = ({type = "text", ...otherProps}) =
|
||||||
return <Time {...otherProps} />;
|
return <Time {...otherProps} />;
|
||||||
case "File":
|
case "File":
|
||||||
return <File {...otherProps} />;
|
return <File {...otherProps} />;
|
||||||
|
case "MaltyFile":
|
||||||
|
return <MaltyFile {...otherProps} />;
|
||||||
case "Checkbox":
|
case "Checkbox":
|
||||||
return <CheckboxField {...otherProps} />;
|
return <CheckboxField {...otherProps} />;
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { Form, Input } from 'antd'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import useFormField from '../../../Hooks/useFormField';
|
import useFormField from '../../../Hooks/useFormField';
|
||||||
|
|
||||||
const Default = ({ name, label, placeholder, isDisabled, onChange, props }: any) => {
|
const Default = ({ name, label, placeholder, isDisabled, onChange, props,type="text" }: any) => {
|
||||||
const { Field, formik, isError, errorMsg, t } = useFormField(name, props);
|
const { Field, formik, isError, errorMsg, t } = useFormField(name, props);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -18,11 +18,12 @@ const Default = ({ name, label, placeholder, isDisabled, onChange, props }: any)
|
||||||
>
|
>
|
||||||
<Field
|
<Field
|
||||||
as={Input}
|
as={Input}
|
||||||
type="text"
|
type={type}
|
||||||
placeholder={t(`${placeholder ?placeholder : name}`)}
|
placeholder={t(`${placeholder ?placeholder : name}`)}
|
||||||
name={name}
|
name={name}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
size="large"
|
size="large"
|
||||||
|
|
||||||
// onChange={onChange ? onChange : handleChange}
|
// onChange={onChange ? onChange : handleChange}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
|
||||||
52
src/Components/Karimalden/View/MaltyFile.tsx
Normal file
52
src/Components/Karimalden/View/MaltyFile.tsx
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
import { Button, Upload } from 'antd';
|
||||||
|
import { UploadOutlined } from '@ant-design/icons';
|
||||||
|
import { ImageBaseURL } from '../../../api/config';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import useFormField from '../../../Hooks/useFormField';
|
||||||
|
|
||||||
|
const MaltyFile = ({ name, label, onChange, isDisabled, placholder, className, props }: any) => {
|
||||||
|
const { formik, t, isError } = useFormField(name, props);
|
||||||
|
const imageUrl = formik.values[name] ? ImageBaseURL + formik.values[name] : '';
|
||||||
|
const fileList = formik.values[name] ? formik.values[name].map((file: any, index: number) => ({
|
||||||
|
uid: index,
|
||||||
|
name: file.name,
|
||||||
|
status: 'done',
|
||||||
|
url: file.url || '',
|
||||||
|
thumbUrl: file.url || '',
|
||||||
|
})) : [];
|
||||||
|
|
||||||
|
const FilehandleChange = ({ file, fileList }: any) => {
|
||||||
|
formik.setFieldValue(name, fileList.map((file: any) => file.originFileObj));
|
||||||
|
};
|
||||||
|
|
||||||
|
const customRequest = async ({ onSuccess }: any) => {
|
||||||
|
// Perform any necessary actions before onSuccess is called
|
||||||
|
onSuccess();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="KarimField">
|
||||||
|
<label htmlFor={name} className="text">
|
||||||
|
{t(`${label || name}`)}
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<Upload
|
||||||
|
disabled={isDisabled}
|
||||||
|
listType="picture"
|
||||||
|
defaultFileList={[...fileList]}
|
||||||
|
onChange={onChange || FilehandleChange}
|
||||||
|
customRequest={customRequest}
|
||||||
|
className={`${className} w-100`}
|
||||||
|
multiple // Allow multiple files to be selected
|
||||||
|
|
||||||
|
>
|
||||||
|
<Button className={isError ? "isError w-100" : " w-100"} icon={<UploadOutlined />}>
|
||||||
|
{placholder ?? t("upload_image")}
|
||||||
|
</Button>
|
||||||
|
<div className='Error_color'> {isError ? "required" : ""}</div>
|
||||||
|
</Upload>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MaltyFile;
|
||||||
|
|
@ -77,7 +77,7 @@
|
||||||
|
|
||||||
export interface KarimFieldPropsFile {
|
export interface KarimFieldPropsFile {
|
||||||
name: string;
|
name: string;
|
||||||
type: "File";
|
type: "File" | "MaltyFile";
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
label?: string;
|
label?: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,15 @@ import { useTranslation } from "react-i18next";
|
||||||
interface ToggleStatusProps {
|
interface ToggleStatusProps {
|
||||||
|
|
||||||
}
|
}
|
||||||
export const ToggleStatus = ({ object, toggleMutation, ...props }:any) => {
|
export const ToggleStatus = ({ object, handleSwitch, toggleMutation, ...props }:any) => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
|
||||||
const handleSwitch = () => {
|
// const handleSwitch = () => {
|
||||||
toggleMutation.mutate({
|
// toggleMutation.mutate({
|
||||||
id: object.id,
|
// id: object.id,
|
||||||
new_status: !object.is_active,
|
// new_status: !object.is_active,
|
||||||
});
|
// });
|
||||||
};
|
// };
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,15 @@ import React, { useEffect } from 'react'
|
||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
|
|
||||||
|
|
||||||
function useNavigateOnSuccess(isSuccess :boolean , to_path:string , callbackAfterSuccess:any) {
|
function useNavigateOnSuccess(isSuccess :boolean , to_path:string , callbackAfterSuccess?:any) {
|
||||||
|
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
|
|
||||||
if(isSuccess){
|
if(isSuccess){
|
||||||
|
if (typeof callbackAfterSuccess === 'function') {
|
||||||
callbackAfterSuccess()
|
callbackAfterSuccess()
|
||||||
|
}
|
||||||
navigate(to_path , {replace:true})
|
navigate(to_path , {replace:true})
|
||||||
}
|
}
|
||||||
},[isSuccess])
|
},[isSuccess])
|
||||||
|
|
|
||||||
33
src/Layout/Dashboard/AddButton/AddButton.tsx
Normal file
33
src/Layout/Dashboard/AddButton/AddButton.tsx
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
import React from 'react'
|
||||||
|
import './Add_Button.scss'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { usePageState } from '../../../lib/state mangment/LayoutPagestate'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const AddButton = (props :any) => {
|
||||||
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='Add_Button' {...props} >
|
||||||
|
<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("Add")}
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AddButton
|
||||||
77
src/Layout/Dashboard/ViewPage.tsx
Normal file
77
src/Layout/Dashboard/ViewPage.tsx
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
import React from "react";
|
||||||
|
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 { usePageState } from "../../lib/state mangment/LayoutPagestate";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
type TViewPage ={
|
||||||
|
children: React.ReactNode,
|
||||||
|
getInitialValues:any,
|
||||||
|
getValidationSchema:any,
|
||||||
|
getDataToSend:any,
|
||||||
|
handleSubmit:any,
|
||||||
|
// BarStatus:any,
|
||||||
|
showProgressBar?:boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
const ViewPage: React.FC<TViewPage>= ({children,getInitialValues, getValidationSchema,handleSubmit,showProgressBar = true})=> {
|
||||||
|
|
||||||
|
const {objectToEdit} = usePageState()
|
||||||
|
const {t} = useTranslation();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
// console.log(BarStatus);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card className="ViewTapPage">
|
||||||
|
<CardHeader className="CardHeader" >
|
||||||
|
<CardTitle className="View_information">
|
||||||
|
{t("View_information")}
|
||||||
|
</CardTitle>
|
||||||
|
<Button onClick={() => { navigate(-1);}}> {t("back")} </Button>
|
||||||
|
</CardHeader>
|
||||||
|
<CardBody>
|
||||||
|
{
|
||||||
|
<Formik
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
initialValues={getInitialValues(objectToEdit)}
|
||||||
|
validationSchema={getValidationSchema()}
|
||||||
|
>
|
||||||
|
{(formik) => (
|
||||||
|
<Form>
|
||||||
|
{/* <HeadTabs tabs={tabs} /> */}
|
||||||
|
{children}
|
||||||
|
{showProgressBar &&
|
||||||
|
<>
|
||||||
|
{/* <ProgressBar
|
||||||
|
value={BarStatus?.value}
|
||||||
|
isLoading={BarStatus?.isLoading}
|
||||||
|
isError={BarStatus?.isError}
|
||||||
|
isSuccess={BarStatus?.isSuccess}
|
||||||
|
/> */}
|
||||||
|
<div className="d-flex mt-4 justify-content-center align-items-center">
|
||||||
|
{/* <LoadingButton
|
||||||
|
type="submit"
|
||||||
|
color="primary"
|
||||||
|
// isLoading={BarStatus?.isLoading}
|
||||||
|
>
|
||||||
|
{t("save")}
|
||||||
|
</LoadingButton> */}
|
||||||
|
<Button type="submit" color="primary"> {t("save")} </Button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
</Form>
|
||||||
|
)}
|
||||||
|
</Formik>
|
||||||
|
}
|
||||||
|
|
||||||
|
</CardBody>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export default ViewPage;
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import LoadingSpinner from '../../Components/Ui/LoadingSpinner'
|
import LoadingSpinner from '../../Components/Ui/LoadingSpinner'
|
||||||
|
import { Spin } from 'antd'
|
||||||
|
|
||||||
function LoadingPage() {
|
function LoadingPage() {
|
||||||
return (
|
return (
|
||||||
<div style={{height:"80vh", width:"100%" , display:"flex" , justifyContent:"center" , alignItems:"center"}}>
|
<div style={{height:"80vh", width:"100%" , display:"flex" , justifyContent:"center" , alignItems:"center"}}>
|
||||||
<LoadingSpinner/>
|
<Spin/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { FaAngleDown, FaAngleRight } from 'react-icons/fa';
|
import { FaAngleDown, FaAngleRight } from 'react-icons/fa';
|
||||||
import { GiHamburgerMenu } from 'react-icons/gi';
|
import { GiHamburgerMenu } from 'react-icons/gi';
|
||||||
import { Link, useLocation } from 'react-router-dom';
|
import { Link, useLocation } from 'react-router-dom';
|
||||||
|
|
@ -7,11 +7,24 @@ import { useTranslation } from 'react-i18next';
|
||||||
import KarimLogo from './KarimLogo';
|
import KarimLogo from './KarimLogo';
|
||||||
import { useWindowSize } from '../../Hooks/useWindowSize';
|
import { useWindowSize } from '../../Hooks/useWindowSize';
|
||||||
import Etaxi from './Etaxi';
|
import Etaxi from './Etaxi';
|
||||||
|
import { usePageState } from '../../lib/state mangment/LayoutPagestate';
|
||||||
|
|
||||||
interface SidebarProps {}
|
interface SidebarProps {}
|
||||||
|
|
||||||
const Sidebar: React.FC<SidebarProps> = () => {
|
const Sidebar: React.FC<SidebarProps> = () => {
|
||||||
const { pathname } = useLocation();
|
const { pathname } = useLocation();
|
||||||
|
// const {isOpenAddModel ,isOpenEditModel} = usePageState(state => state)
|
||||||
|
// useEffect(() => {
|
||||||
|
// if(isOpenAddModel || isOpenEditModel){
|
||||||
|
// setIsOpenSide(true);
|
||||||
|
// document.getElementById('DashboardLayout_Body')?.classList.add('DashboardLayout_Body_Open');
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// }, [isOpenAddModel ,isOpenEditModel])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const [isOpenSide, setIsOpenSide] = useState<boolean>(false);
|
const [isOpenSide, setIsOpenSide] = useState<boolean>(false);
|
||||||
const [openDropdown, setOpenDropdown] = useState<number | null>(null);
|
const [openDropdown, setOpenDropdown] = useState<number | null>(null);
|
||||||
|
|
@ -37,8 +50,8 @@ const Sidebar: React.FC<SidebarProps> = () => {
|
||||||
<div className={isOpenSide ? 'SideBar SideBar_Open' : 'SideBar noOpen'}>
|
<div className={isOpenSide ? 'SideBar SideBar_Open' : 'SideBar noOpen'}>
|
||||||
<div className='SideBar_Top'>
|
<div className='SideBar_Top'>
|
||||||
<div onClick={handleImg}>
|
<div onClick={handleImg}>
|
||||||
{/* <img src="../Layout/logorayan.png" width={isOpenSide ? 70 : 150} alt="" /> */}
|
<img src="../Logo.png" width={isOpenSide ? 70 : 150} alt="" />
|
||||||
<Etaxi/>
|
{/* <Etaxi/> */}
|
||||||
</div>
|
</div>
|
||||||
<div className='HamburgerMenu' onClick={handleHamburgerMenu}>
|
<div className='HamburgerMenu' onClick={handleHamburgerMenu}>
|
||||||
<GiHamburgerMenu />
|
<GiHamburgerMenu />
|
||||||
|
|
|
||||||
|
|
@ -2,23 +2,23 @@ import React from 'react'
|
||||||
import { Formik, Form, Field } from 'formik';
|
import { Formik, Form, Field } from 'formik';
|
||||||
import Translate from '../../Components/Utils/Translate';
|
import Translate from '../../Components/Utils/Translate';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useNavigate } from 'react-router-dom';
|
|
||||||
import { TOKEN_KEY } from '../../config/AppKey';
|
|
||||||
import { useLoginAdmin } from '../../api/auth';
|
import { useLoginAdmin } from '../../api/auth';
|
||||||
|
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
import { getInitialValues, getValidationSchema } from './formUtil';
|
import { getInitialValues, getValidationSchema } from './formUtil';
|
||||||
import KarimField from '../../Components/Karimalden/KarimField';
|
|
||||||
import { LoadingButton } from '../../Components/Ui/LoadingButton';
|
import { LoadingButton } from '../../Components/Ui/LoadingButton';
|
||||||
import useNavigateOnSuccess from '../../Hooks/useNavigateOnSuccess';
|
import useNavigateOnSuccess from '../../Hooks/useNavigateOnSuccess';
|
||||||
import useAuthState from '../../lib/state mangment/AuthState';
|
import useAuthState from '../../lib/state mangment/AuthState';
|
||||||
|
import KarimField from '../../Components/Karimalden/KarimField';
|
||||||
|
|
||||||
const LoginForm = () => {
|
const LoginForm = () => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
|
||||||
const {mutate , isLoading , isSuccess, data} = useLoginAdmin()
|
const {mutate , isLoading , isSuccess, data} = useLoginAdmin()
|
||||||
const {login} = useAuthState()
|
const {login} = useAuthState()
|
||||||
|
const OnSuccess = ()=>{
|
||||||
|
|
||||||
|
}
|
||||||
useNavigateOnSuccess(isSuccess , '/' , ()=>login(data?.data as any ))
|
useNavigateOnSuccess(isSuccess , '/' , ()=>login(data?.data as any ))
|
||||||
|
|
||||||
const handelSubmit = (values:any)=>{
|
const handelSubmit = (values:any)=>{
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ const Auth = () => {
|
||||||
<div className='Auth' style={{ background: `url(${LoginBg})` }}>
|
<div className='Auth' style={{ background: `url(${LoginBg})` }}>
|
||||||
<div className='In_Auth'>
|
<div className='In_Auth'>
|
||||||
<div className="Left_Col">
|
<div className="Left_Col">
|
||||||
<img className='Logo' src="/Layout/etaxlogo.svg" alt="Logo" />
|
<img className='Logo' src="../Logo.png" alt="Logo" />
|
||||||
</div>
|
</div>
|
||||||
<div className=" Right_Col ">
|
<div className=" Right_Col ">
|
||||||
<LoginForm />
|
<LoginForm />
|
||||||
|
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
import React from 'react'
|
|
||||||
import LayoutModal from '../../Layout/Dashboard/LayoutModal'
|
|
||||||
import AddForm from './AddForm'
|
|
||||||
import { useAddCategories } from '../../api/Categories'
|
|
||||||
import { getDataToSend, getInitialValues, getValidationSchema } from './formUtil'
|
|
||||||
import { QueryStatusEnum } from '../../config/QueryStatus'
|
|
||||||
import { useTranslation } from 'react-i18next'
|
|
||||||
|
|
||||||
function AddCategoriesModal() {
|
|
||||||
|
|
||||||
|
|
||||||
const [t] = useTranslation()
|
|
||||||
const {mutate , status} = useAddCategories()
|
|
||||||
const handelSubmit = (values:any )=>{
|
|
||||||
values['name'] = {
|
|
||||||
"en" : values.name_en,
|
|
||||||
"ar" : values.name_ar,
|
|
||||||
"de" : values.name_de,
|
|
||||||
}
|
|
||||||
console.log(values);
|
|
||||||
mutate(values)
|
|
||||||
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<LayoutModal
|
|
||||||
|
|
||||||
isAddModal={true}
|
|
||||||
getInitialValues={getInitialValues()}
|
|
||||||
handleSubmit={handelSubmit}
|
|
||||||
status={status as QueryStatusEnum}
|
|
||||||
headerText={t('Add') +t('Categories')}
|
|
||||||
|
|
||||||
getValidationSchema={getValidationSchema()}>
|
|
||||||
|
|
||||||
<AddForm />
|
|
||||||
</LayoutModal>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AddCategoriesModal
|
|
||||||
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import FormPage from '../../../Layout/Dashboard/FormPage';
|
|
||||||
import EditForm from './EditForm';
|
|
||||||
import { getInitialValues, getValidationSchema } from '../formUtil';
|
|
||||||
import { useParams } from 'react-router-dom';
|
|
||||||
import KarimSpinner from '../../../Components/Karimalden/Ui/KarimSpinner';
|
|
||||||
import { useAddCategories, useGetOneCategories } from '../../../api/Categories';
|
|
||||||
|
|
||||||
const EditPage = () => {
|
|
||||||
|
|
||||||
const { id } = useParams()
|
|
||||||
const { data,isLoading } = useGetOneCategories({id})
|
|
||||||
const {mutate} = useAddCategories()
|
|
||||||
const handleSubmit = (values: any) => {
|
|
||||||
const newdata = {} as any;
|
|
||||||
|
|
||||||
for (const key in data) {
|
|
||||||
if (values[key] !== data[key]) {
|
|
||||||
newdata[key] = values[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mutate(newdata);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<KarimSpinner loading={isLoading}>
|
|
||||||
<FormPage
|
|
||||||
handleSubmit={(values: any) => handleSubmit(values)}
|
|
||||||
initialValues={getInitialValues(data)}
|
|
||||||
validationSchema={getValidationSchema}
|
|
||||||
title='Edit Categories'
|
|
||||||
>
|
|
||||||
<EditForm />
|
|
||||||
|
|
||||||
</FormPage>
|
|
||||||
</KarimSpinner>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default EditPage;
|
|
||||||
|
|
@ -4,37 +4,39 @@ import DashBody from '../../Layout/Dashboard/DashBody'
|
||||||
import DashHeader from '../../Layout/Dashboard/DashHeader'
|
import DashHeader from '../../Layout/Dashboard/DashHeader'
|
||||||
import LyTable from '../../Layout/Dashboard/LyTable'
|
import LyTable from '../../Layout/Dashboard/LyTable'
|
||||||
import useTableColumns from './useTableColumns'
|
import useTableColumns from './useTableColumns'
|
||||||
|
import { QueryStatusEnum } from '../../config/QueryStatus'
|
||||||
|
import { useGetProduct } from '../../api/product'
|
||||||
|
import { Button } from 'antd'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { useNavigate } from 'react-router-dom'
|
||||||
|
import AddButton from '../../Layout/Dashboard/AddButton/AddButton'
|
||||||
import { useGetCategories } from '../../api/Categories'
|
import { useGetCategories } from '../../api/Categories'
|
||||||
|
|
||||||
import { useTranslation } from 'react-i18next'
|
function Page() {
|
||||||
import AddCategoriesModal from './AddCategoriesModal'
|
|
||||||
import { QueryStatusEnum } from '../../config/QueryStatus'
|
|
||||||
// import * as XLSX from 'ts-xlsx';
|
|
||||||
|
|
||||||
function CategoriesPage() {
|
|
||||||
|
|
||||||
const column =useTableColumns()
|
const column =useTableColumns()
|
||||||
const {data ,status } = useGetCategories()
|
const {data ,status } = useGetCategories()
|
||||||
const {t} = useTranslation();
|
console.log(data);
|
||||||
|
const [t] = useTranslation()
|
||||||
|
const navigate = useNavigate()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
// Pass Status to Layout
|
||||||
<DashBody status={status as QueryStatusEnum} >
|
<DashBody status={status as QueryStatusEnum} >
|
||||||
<DashHeader title={'Categories'}>
|
<DashHeader showAddButton={false} title={'categories'}>
|
||||||
|
<AddButton onClick={()=>navigate('/categories/add')}></AddButton>
|
||||||
</DashHeader>
|
</DashHeader>
|
||||||
|
|
||||||
<LyTable
|
<LyTable
|
||||||
data={data?.categories}
|
data={data?.categories}
|
||||||
isLoading={false}
|
isLoading={false}
|
||||||
columns={column}
|
columns={column}
|
||||||
// is_pagination={true}
|
|
||||||
// total={data?.meta?.total}
|
|
||||||
|
|
||||||
/>
|
/>
|
||||||
<AddCategoriesModal />
|
|
||||||
|
|
||||||
</DashBody>
|
</DashBody>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CategoriesPage
|
export default Page
|
||||||
|
|
||||||
|
|
@ -1,17 +1,15 @@
|
||||||
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Col, Row } from 'reactstrap';
|
import { Col, Row } from 'reactstrap';
|
||||||
import KarimField from '../../Components/Karimalden/KarimField';
|
import KarimField from '../../../Components/Karimalden/KarimField';
|
||||||
import { FakeSelectData } from '../../Layout/app/Const';
|
|
||||||
import { useFormikContext } from 'formik';
|
import { useFormikContext } from 'formik';
|
||||||
|
|
||||||
import { DatePicker } from 'antd';
|
import { DatePicker } from 'antd';
|
||||||
import { useGetCategories } from '../../api/Categories';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
function AddForm() {
|
function Form() {
|
||||||
const formik = useFormikContext<any>();
|
const formik = useFormikContext<any>();
|
||||||
const {data } = useGetCategories()
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row xs={1} sm={1} md={1} lg={2} xl={2}>
|
<Row xs={1} sm={1} md={1} lg={2} xl={2}>
|
||||||
|
|
@ -28,10 +26,11 @@ function AddForm() {
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</Row>
|
</Row>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AddForm
|
export default Form
|
||||||
|
|
||||||
|
|
||||||
62
src/Pages/Categories/View/AddPage.tsx
Normal file
62
src/Pages/Categories/View/AddPage.tsx
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { getInitialValues, getValidationSchema, getDataToSend } from '../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 { useTranslation } from 'react-i18next';
|
||||||
|
import { BsInfoCircle } from 'react-icons/bs';
|
||||||
|
import useNavigateOnSuccess from '../../../Hooks/useNavigateOnSuccess';
|
||||||
|
import { useAddCategories } from '../../../api/Categories';
|
||||||
|
import Form from './AddForm';
|
||||||
|
|
||||||
|
const AddcategoriesPage = () => {
|
||||||
|
|
||||||
|
|
||||||
|
const {mutate , isLoading , isSuccess} = useAddCategories()
|
||||||
|
const handleSubmit = (values:any)=>{
|
||||||
|
|
||||||
|
values['name'] = {
|
||||||
|
"en" : values.name_en,
|
||||||
|
"ar" : values.name_ar,
|
||||||
|
"de" : values.name_de,
|
||||||
|
}
|
||||||
|
mutate(values)
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
const {t} = useTranslation();
|
||||||
|
|
||||||
|
useNavigateOnSuccess(isSuccess , '/categories' )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const ViewProps = { getInitialValues, getValidationSchema, getDataToSend, handleSubmit };
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='ViewPage'>
|
||||||
|
|
||||||
|
<ViewPage {...ViewProps}>
|
||||||
|
<Tabs>
|
||||||
|
<TabList>
|
||||||
|
<Tab><div className='SignleDriverContainer'><span className='SignleDriverInfoIcon'><MdLanguage size={20} /></span> <h6 className='SingleDriverInfo'>{t("BasicInfo")}</h6></div></Tab>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</TabList>
|
||||||
|
<TabBody >
|
||||||
|
<div className=" mt-4"><Form /></div>
|
||||||
|
</TabBody>
|
||||||
|
|
||||||
|
</Tabs>
|
||||||
|
</ViewPage>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AddcategoriesPage
|
||||||
32
src/Pages/Categories/View/EditForm.tsx
Normal file
32
src/Pages/Categories/View/EditForm.tsx
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
|
||||||
|
import React from 'react'
|
||||||
|
import { Col, Row } from 'reactstrap';
|
||||||
|
import KarimField from '../../../Components/Karimalden/KarimField';
|
||||||
|
import { useFormikContext } from 'formik';
|
||||||
|
|
||||||
|
import { DatePicker } from 'antd';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
function Form() {
|
||||||
|
const formik = useFormikContext<any>();
|
||||||
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Row xs={1} sm={1} md={1} lg={2} xl={2}>
|
||||||
|
|
||||||
|
<Col>
|
||||||
|
<KarimField name="name" />
|
||||||
|
<KarimField name="parent_id" type="Select" option={[]} />
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<KarimField name="photo" type="File" />
|
||||||
|
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
</Row>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Form
|
||||||
|
|
||||||
|
|
||||||
86
src/Pages/Categories/View/EditPage.tsx
Normal file
86
src/Pages/Categories/View/EditPage.tsx
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { getInitialValues, getDataToSend } from '../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 { FaSadCry } from 'react-icons/fa'
|
||||||
|
import ViewPage from '../../../Layout/Dashboard/ViewPage';
|
||||||
|
import { Rate } from 'antd';
|
||||||
|
import { usePageState } from '../../../lib/state mangment/LayoutPagestate';
|
||||||
|
import { useParams } from 'react-router-dom';
|
||||||
|
import LoadingPage from '../../../Layout/app/LoadingPage';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { BsInfoCircle } from 'react-icons/bs';
|
||||||
|
import { useGetOneCategories, useUpdateCategories } from '../../../api/Categories';
|
||||||
|
import useNavigateOnSuccess from '../../../Hooks/useNavigateOnSuccess';
|
||||||
|
import Form from './EditForm';
|
||||||
|
|
||||||
|
const EditPage = () => {
|
||||||
|
const { setObjectToEdit, objectToEdit } = usePageState()
|
||||||
|
const {t} = useTranslation();
|
||||||
|
const { data } = useGetOneCategories()
|
||||||
|
const {mutate ,isSuccess} = useUpdateCategories()
|
||||||
|
const FormatedData = data?.category ;
|
||||||
|
const handleSubmit = (values:any)=>{
|
||||||
|
|
||||||
|
const newData = {} as any;
|
||||||
|
|
||||||
|
for (const key in FormatedData) {
|
||||||
|
if (values[key] !== FormatedData[key]) {
|
||||||
|
newData[key] = values[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
const language = localStorage.getItem("language") ?? "en";
|
||||||
|
|
||||||
|
newData['name'] = {
|
||||||
|
[language]: values.name,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return mutate(newData);
|
||||||
|
}
|
||||||
|
|
||||||
|
useNavigateOnSuccess(isSuccess , '/categories')
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
|
setObjectToEdit(data?.category);
|
||||||
|
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
|
||||||
|
const getValidationSchema = () => {
|
||||||
|
return null
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const ViewProps = { getInitialValues, getValidationSchema, getDataToSend, handleSubmit };
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='ViewPage'>
|
||||||
|
{objectToEdit && data ?
|
||||||
|
<ViewPage {...ViewProps}>
|
||||||
|
<Tabs>
|
||||||
|
<TabList>
|
||||||
|
<Tab><div className='SignleDriverContainer'><span className='SignleDriverInfoIcon'><MdLanguage size={20} /></span> <h6 className='SingleDriverInfo'>{t("BasicInfo")}</h6></div></Tab>
|
||||||
|
|
||||||
|
</TabList>
|
||||||
|
<TabBody >
|
||||||
|
<div className=" mt-4"><Form /></div>
|
||||||
|
</TabBody>
|
||||||
|
|
||||||
|
|
||||||
|
</Tabs>
|
||||||
|
</ViewPage>
|
||||||
|
: <LoadingPage />}
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EditPage
|
||||||
|
|
@ -20,9 +20,10 @@ interface ValidateSchema extends formUtilCommon{
|
||||||
|
|
||||||
}
|
}
|
||||||
export const getInitialValues = (objectToEdit: any | null = null): any => {
|
export const getInitialValues = (objectToEdit: any | null = null): any => {
|
||||||
|
console.log(objectToEdit,"objectToEdit");
|
||||||
return {
|
return {
|
||||||
id: objectToEdit?.id ?? 0,
|
id: objectToEdit?.id ?? 0,
|
||||||
name: "",
|
name:objectToEdit?.name ?? "",
|
||||||
name_ar: objectToEdit?.name?.ar ?? '',
|
name_ar: objectToEdit?.name?.ar ?? '',
|
||||||
name_en: objectToEdit?.name?.en ?? '',
|
name_en: objectToEdit?.name?.en ?? '',
|
||||||
name_de: objectToEdit?.name?.de ?? '',
|
name_de: objectToEdit?.name?.de ?? '',
|
||||||
|
|
@ -35,7 +36,6 @@ export const getInitialValues = (objectToEdit: any | null = null): any => {
|
||||||
export const getValidationSchema = (editMode: boolean = false): Yup.Schema<any> => {
|
export const getValidationSchema = (editMode: boolean = false): Yup.Schema<any> => {
|
||||||
// Validate input
|
// Validate input
|
||||||
return Yup.object().shape({
|
return Yup.object().shape({
|
||||||
name : Yup.string().required('Required'),
|
|
||||||
name_ar: Yup.string().required('Required'),
|
name_ar: Yup.string().required('Required'),
|
||||||
name_en: Yup.string().required('Required'),
|
name_en: Yup.string().required('Required'),
|
||||||
name_de: Yup.string().required('Required'),
|
name_de: Yup.string().required('Required'),
|
||||||
|
|
@ -45,6 +45,7 @@ export const getValidationSchema = (editMode: boolean = false): Yup.Schema<any>
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const getDataToSend = (values: any): FormData => {
|
export const getDataToSend = (values: any): FormData => {
|
||||||
const data = { ...values };
|
const data = { ...values };
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
import { Col, Row } from "reactstrap";
|
|
||||||
import KarimField from '../../../Components/Karimalden/KarimField';
|
|
||||||
|
|
||||||
const CreateForm = () => {
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
|
||||||
|
|
||||||
<Row>
|
|
||||||
<Col>
|
|
||||||
<KarimField name="name" />
|
|
||||||
<KarimField name="parent_id" type="Select" option={[]} />
|
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
<KarimField name="photo" type="File" />
|
|
||||||
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default CreateForm
|
|
||||||
55
src/Pages/Coupon/FormProducts.tsx
Normal file
55
src/Pages/Coupon/FormProducts.tsx
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
|
||||||
|
import React from 'react'
|
||||||
|
import { Col, Row } from 'reactstrap';
|
||||||
|
import KarimField from '../../Components/Karimalden/KarimField';
|
||||||
|
import { useFormikContext } from 'formik';
|
||||||
|
|
||||||
|
import { DatePicker } from 'antd';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
function FormProduct() {
|
||||||
|
const formik = useFormikContext<any>();
|
||||||
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Row xs={1} sm={1} md={1} lg={2} xl={2}>
|
||||||
|
<Col>
|
||||||
|
<KarimField
|
||||||
|
name="translated_fields[1][product_name]"
|
||||||
|
label={`${t("product_name")} (${t("en")})`}
|
||||||
|
placeholder={`${t("product_name")} (${t("en")})`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<KarimField
|
||||||
|
name="translated_fields[1][product_description]"
|
||||||
|
label={`${t("product_description")} (${t("en")})`}
|
||||||
|
placeholder={`${t("product_description")} (${t("en")})`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<KarimField
|
||||||
|
dir="rtl"
|
||||||
|
name="translated_fields[2][product_name]"
|
||||||
|
label={`${t("product_name")} (${t("ar")})`}
|
||||||
|
placeholder={`${t("product_name")} (${t("ar")})`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<KarimField
|
||||||
|
dir="rtl"
|
||||||
|
name="translated_fields[2][product_description]"
|
||||||
|
label={`${t("product_description")} (${t("ar")})`}
|
||||||
|
placeholder={`${t("product_description")} (${t("ar")})`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</Row>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FormProduct
|
||||||
|
|
||||||
|
|
||||||
41
src/Pages/Coupon/ProductsPage.tsx
Normal file
41
src/Pages/Coupon/ProductsPage.tsx
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
|
||||||
|
import React from 'react'
|
||||||
|
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 { useGetProduct } from '../../api/product'
|
||||||
|
import { Button } from 'antd'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { useNavigate } from 'react-router-dom'
|
||||||
|
import AddButton from '../../Layout/Dashboard/AddButton/AddButton'
|
||||||
|
|
||||||
|
function ProductsPage() {
|
||||||
|
|
||||||
|
const column =useTableColumns()
|
||||||
|
const {data ,status } = useGetProduct("")
|
||||||
|
console.log(data);
|
||||||
|
const [t] = useTranslation()
|
||||||
|
const navigate = useNavigate()
|
||||||
|
|
||||||
|
return (
|
||||||
|
// Pass Status to Layout
|
||||||
|
<DashBody status={status as QueryStatusEnum} >
|
||||||
|
<DashHeader showAddButton={false} title={'products'}>
|
||||||
|
<AddButton onClick={()=>navigate('/products/add')}></AddButton>
|
||||||
|
</DashHeader>
|
||||||
|
|
||||||
|
<LyTable
|
||||||
|
data={data?.products}
|
||||||
|
isLoading={false}
|
||||||
|
columns={column}
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
</DashBody>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ProductsPage
|
||||||
|
|
||||||
72
src/Pages/Coupon/View/AddPage.tsx
Normal file
72
src/Pages/Coupon/View/AddPage.tsx
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { getInitialValues, getValidationSchema, getDataToSend } from '../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 { FaSadCry } from 'react-icons/fa'
|
||||||
|
import ViewPage from '../../../Layout/Dashboard/ViewPage';
|
||||||
|
import { Rate } from 'antd';
|
||||||
|
import BasicInfo from './BasicInfo';
|
||||||
|
import { usePageState } from '../../../lib/state mangment/LayoutPagestate';
|
||||||
|
import { useParams } from 'react-router-dom';
|
||||||
|
import LoadingPage from '../../../Layout/app/LoadingPage';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { BsInfoCircle } from 'react-icons/bs';
|
||||||
|
import BasicInfo2 from './BasicInfo2';
|
||||||
|
import useNavigateOnSuccess from '../../../Hooks/useNavigateOnSuccess';
|
||||||
|
import { useAddProduct } from '../../../api/product';
|
||||||
|
|
||||||
|
const AddProductPage = () => {
|
||||||
|
|
||||||
|
|
||||||
|
const {mutate , isLoading , isSuccess} = useAddProduct()
|
||||||
|
const [BarStatus, setBarStatus] = useState({ value: 0, isLoading: false, isError: false, isSuccess: false })
|
||||||
|
const handleSubmit = (values:any)=>{
|
||||||
|
|
||||||
|
console.log(values);
|
||||||
|
|
||||||
|
const formToSend = getDataToSend(values)
|
||||||
|
|
||||||
|
|
||||||
|
mutate(formToSend);
|
||||||
|
|
||||||
|
}
|
||||||
|
const {t} = useTranslation();
|
||||||
|
|
||||||
|
useNavigateOnSuccess(isSuccess , '/products' )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const ViewProps = { getInitialValues, getValidationSchema, getDataToSend, handleSubmit, BarStatus };
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='ViewPage'>
|
||||||
|
|
||||||
|
<ViewPage {...ViewProps}>
|
||||||
|
<Tabs>
|
||||||
|
<TabList>
|
||||||
|
<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'><BsInfoCircle size={20} /></span> <h6 className='SingleDriverInfo'>{t("BasicInfo2")}</h6></div></Tab>
|
||||||
|
|
||||||
|
|
||||||
|
</TabList>
|
||||||
|
<TabBody >
|
||||||
|
<div className=" mt-4"><BasicInfo /></div>
|
||||||
|
</TabBody>
|
||||||
|
<TabBody >
|
||||||
|
<div className=" mt-4"><BasicInfo2 /></div>
|
||||||
|
</TabBody>
|
||||||
|
|
||||||
|
</Tabs>
|
||||||
|
</ViewPage>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AddProductPage
|
||||||
47
src/Pages/Coupon/View/BasicInfo.tsx
Normal file
47
src/Pages/Coupon/View/BasicInfo.tsx
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { Col, Row } from 'reactstrap'
|
||||||
|
import KarimField from '../../../Components/Karimalden/KarimField'
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
const BasicInfo = () => {
|
||||||
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Row xs={1} sm={1} md={1} lg={2} xl={2}>
|
||||||
|
<Col>
|
||||||
|
<KarimField
|
||||||
|
name="translated_fields[1][product_name]"
|
||||||
|
label={`${t("product_name")} (${t("en")})`}
|
||||||
|
placeholder={`${t("product_name")} (${t("en")})`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<KarimField
|
||||||
|
name="translated_fields[1][product_description]"
|
||||||
|
label={`${t("product_description")} (${t("en")})`}
|
||||||
|
placeholder={`${t("product_description")} (${t("en")})`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<KarimField
|
||||||
|
dir="rtl"
|
||||||
|
name="translated_fields[2][product_name]"
|
||||||
|
label={`${t("product_name")} (${t("ar")})`}
|
||||||
|
placeholder={`${t("product_name")} (${t("ar")})`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<KarimField
|
||||||
|
dir="rtl"
|
||||||
|
name="translated_fields[2][product_description]"
|
||||||
|
label={`${t("product_description")} (${t("ar")})`}
|
||||||
|
placeholder={`${t("product_description")} (${t("ar")})`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
|
||||||
|
</Row>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BasicInfo
|
||||||
87
src/Pages/Coupon/View/BasicInfo2.tsx
Normal file
87
src/Pages/Coupon/View/BasicInfo2.tsx
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { Col, Row } from 'reactstrap'
|
||||||
|
import KarimField from '../../../Components/Karimalden/KarimField'
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
const BasicInfo2 = () => {
|
||||||
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
const categoryOption = [] as any
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Row xs={1} sm={1} md={1} lg={2} xl={2}>
|
||||||
|
<Col>
|
||||||
|
<KarimField name="product_main_image" type="File" label='image' placeholder='image' />
|
||||||
|
|
||||||
|
<KarimField
|
||||||
|
type='Select'
|
||||||
|
option={categoryOption}
|
||||||
|
name="category_id"
|
||||||
|
label={`${t("category")}`}
|
||||||
|
placeholder={`${t("category")}`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{/* <KarimField
|
||||||
|
name="is_cheapest"
|
||||||
|
label={t("is_cheapest")}
|
||||||
|
placeholder={t("is_cheapest")}
|
||||||
|
type="Checkbox"
|
||||||
|
|
||||||
|
/> */}
|
||||||
|
<KarimField
|
||||||
|
name="is_most_purchase"
|
||||||
|
label={t("is_most_purchase")}
|
||||||
|
// placeholder={t("is_most_purchase")}
|
||||||
|
type="Checkbox"
|
||||||
|
|
||||||
|
/>
|
||||||
|
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<KarimField
|
||||||
|
name="product_price"
|
||||||
|
label={t("price")}
|
||||||
|
placeholder={t("price")}
|
||||||
|
type="number"
|
||||||
|
|
||||||
|
/>
|
||||||
|
<KarimField
|
||||||
|
name="product_quantity"
|
||||||
|
label={t("product_quantity")}
|
||||||
|
placeholder={t("product_quantity")}
|
||||||
|
type="number"
|
||||||
|
|
||||||
|
/>
|
||||||
|
{/*
|
||||||
|
<KarimField
|
||||||
|
name="is_latest"
|
||||||
|
label={t("is_latest")}
|
||||||
|
placeholder={t("is_latest")}
|
||||||
|
type="Checkbox"
|
||||||
|
|
||||||
|
/>
|
||||||
|
*/}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<KarimField
|
||||||
|
name="is_highlight"
|
||||||
|
label={t("is_highlight")}
|
||||||
|
// placeholder={t("is_highlight")}
|
||||||
|
type="Checkbox"
|
||||||
|
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
|
||||||
|
</Row>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BasicInfo2
|
||||||
91
src/Pages/Coupon/View/Page.tsx
Normal file
91
src/Pages/Coupon/View/Page.tsx
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { getInitialValues, getValidationSchema, getDataToSend } from '../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 { FaSadCry } from 'react-icons/fa'
|
||||||
|
import ViewPage from '../../../Layout/Dashboard/ViewPage';
|
||||||
|
import { Rate } from 'antd';
|
||||||
|
import BasicInfo from './BasicInfo';
|
||||||
|
import { usePageState } from '../../../lib/state mangment/LayoutPagestate';
|
||||||
|
import { useParams } from 'react-router-dom';
|
||||||
|
import LoadingPage from '../../../Layout/app/LoadingPage';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { BsInfoCircle } from 'react-icons/bs';
|
||||||
|
import { useGetOneProduct, useUpdateProduct } from '../../../api/product';
|
||||||
|
import BasicInfo2 from './BasicInfo2';
|
||||||
|
import useNavigateOnSuccess from '../../../Hooks/useNavigateOnSuccess';
|
||||||
|
|
||||||
|
const ViewProduct = () => {
|
||||||
|
const { setObjectToEdit, objectToEdit } = usePageState()
|
||||||
|
const {t} = useTranslation();
|
||||||
|
const { id } = useParams()
|
||||||
|
const { data } = useGetOneProduct({id:id})
|
||||||
|
const [BarStatus, setBarStatus] = useState({ value: 0, isLoading: false, isError: false, isSuccess: false })
|
||||||
|
const {mutate ,isSuccess} = useUpdateProduct()
|
||||||
|
const handleSubmit = (values:any)=>{
|
||||||
|
|
||||||
|
values['product_id'] = id
|
||||||
|
|
||||||
|
values['is_highlight'] =values['is_highlight'] == true ?1 :0
|
||||||
|
values['is_most_purchase'] =values['is_most_purchase'] == true ?1 :0
|
||||||
|
|
||||||
|
const formToSend = getDataToSend(values)
|
||||||
|
|
||||||
|
mutate(formToSend)
|
||||||
|
}
|
||||||
|
|
||||||
|
useNavigateOnSuccess(isSuccess , '/products')
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
|
setObjectToEdit(data);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
|
||||||
|
|
||||||
|
return ()=>{
|
||||||
|
setObjectToEdit(null)
|
||||||
|
|
||||||
|
}
|
||||||
|
},[])
|
||||||
|
|
||||||
|
const ViewProps = { getInitialValues, getValidationSchema, getDataToSend, handleSubmit, BarStatus };
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='ViewPage'>
|
||||||
|
{objectToEdit && data ?
|
||||||
|
<ViewPage {...ViewProps}>
|
||||||
|
<Tabs>
|
||||||
|
<TabList>
|
||||||
|
<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'><BsInfoCircle size={20} /></span> <h6 className='SingleDriverInfo'>{t("BasicInfo2")}</h6></div></Tab>
|
||||||
|
|
||||||
|
|
||||||
|
</TabList>
|
||||||
|
<TabBody >
|
||||||
|
<div className=" mt-4"><BasicInfo /></div>
|
||||||
|
</TabBody>
|
||||||
|
<TabBody >
|
||||||
|
<div className=" mt-4"><BasicInfo2 /></div>
|
||||||
|
</TabBody>
|
||||||
|
|
||||||
|
</Tabs>
|
||||||
|
</ViewPage>
|
||||||
|
: <LoadingPage />}
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ViewProduct
|
||||||
|
|
@ -1,65 +1,70 @@
|
||||||
|
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
import { buildFormData } from "../../api/helper/buildFormData";
|
import { buildFormData } from "../../api/helper/buildFormData";
|
||||||
|
import { mapTranslatedProperties } from "../../utils/language/mapTranslatedProperties";
|
||||||
|
|
||||||
interface formUtilCommon {
|
|
||||||
number:number,
|
|
||||||
value:number
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ObjectToEdit extends formUtilCommon {
|
|
||||||
|
|
||||||
id?:number,
|
export const getInitialValues = (objectToEdit: any | null = null) => {
|
||||||
|
|
||||||
}
|
// console.log(objectToEdit);
|
||||||
|
|
||||||
interface InitialValues extends ObjectToEdit {
|
|
||||||
|
|
||||||
}
|
|
||||||
interface ValidateSchema extends formUtilCommon{
|
|
||||||
|
|
||||||
}
|
|
||||||
export const getInitialValues = (objectToEdit: any | null = null): any => {
|
|
||||||
return {
|
return {
|
||||||
id: objectToEdit?.id ?? 0,
|
product_price:objectToEdit?.product_price??0,
|
||||||
name: "",
|
product_quantity:objectToEdit?.product_quantity??0,
|
||||||
name_ar: objectToEdit?.name?.ar ?? '',
|
product_main_image:objectToEdit?.product_main_image??'',
|
||||||
name_en: objectToEdit?.name?.en ?? '',
|
translated_fields: {
|
||||||
name_de: objectToEdit?.name?.de ?? '',
|
1: {
|
||||||
parent_id: objectToEdit?.parent_id ?? 1,
|
product_name: mapTranslatedProperties(objectToEdit?.product_translations ,'name', 1) ??'',
|
||||||
photo: objectToEdit?.photo ?? '',
|
product_description: mapTranslatedProperties(objectToEdit?.product_translations ,'description', 1) ?? '',
|
||||||
};
|
|
||||||
|
},
|
||||||
|
2: {
|
||||||
|
product_name: mapTranslatedProperties(objectToEdit?.product_translations ,'name', 2) ?? '',
|
||||||
|
product_description: mapTranslatedProperties(objectToEdit?.product_translations ,'description', 2) ?? '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
category_id:objectToEdit?.category_id ?? null,
|
||||||
|
is_highlight:objectToEdit?.is_highlight??false,
|
||||||
|
is_most_purchase:objectToEdit?.is_most_purchase??false,
|
||||||
|
is_cheapest:objectToEdit?.is_cheapest??false
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getValidationSchema = (editMode: boolean = false) => {
|
||||||
export const getValidationSchema = (editMode: boolean = false): Yup.Schema<any> => {
|
// validate input
|
||||||
// Validate input
|
|
||||||
return Yup.object().shape({
|
return Yup.object().shape({
|
||||||
name : Yup.string().required('Required'),
|
translated_fields : Yup.object().shape({
|
||||||
name_ar: Yup.string().required('Required'),
|
1: Yup.object().shape({
|
||||||
name_en: Yup.string().required('Required'),
|
product_name :Yup.string().required("required"),
|
||||||
name_de: Yup.string().required('Required'),
|
product_description :Yup.string().required("required")
|
||||||
parent_id: Yup.string().required('Required'),
|
}),
|
||||||
photo: Yup.string().required('Required'),
|
2: Yup.object().shape({
|
||||||
|
product_name :Yup.string().required("required"),
|
||||||
|
product_description :Yup.string().required("required")
|
||||||
|
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
category_id :Yup.string().required("required"),
|
||||||
|
|
||||||
|
...(!editMode && {
|
||||||
|
product_main_image: Yup.mixed().required('required'),
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export const getDataToSend = (values: any): FormData => {
|
export const getDataToSend = (values: any): FormData => {
|
||||||
const data = { ...values };
|
const data = { ...values };
|
||||||
|
// console.log(data);
|
||||||
|
|
||||||
|
if(typeof data['product_main_image'] == 'string') delete data['product_main_image']
|
||||||
|
|
||||||
|
data['en_product_name'] = values['translated_fields']['1']['product_name']
|
||||||
|
data['ar_product_name'] =values['translated_fields']['2']['product_name']
|
||||||
|
data['ar_product_description'] =values['translated_fields']['2']['product_description']
|
||||||
|
data['en_product_description'] =values['translated_fields']['1']['product_description']
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
buildFormData(formData, data);
|
buildFormData(formData, data);
|
||||||
return formData;
|
return formData;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ChangeDataToPrint = (data:any)=>{
|
|
||||||
|
|
||||||
let new_array = data
|
|
||||||
for(let i =0 ; i<data.length ; i++){
|
|
||||||
new_array[i]['status'] =!data[i]['deleted_at'] ?'available':'unavailable'
|
|
||||||
delete new_array[i]['deleted_at']
|
|
||||||
}
|
|
||||||
return new_array
|
|
||||||
}
|
|
||||||
|
|
@ -2,81 +2,87 @@
|
||||||
import React, { useMemo } from "react";
|
import React, { useMemo } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import Actions from "../../Components/Ui/tables/Actions";
|
import Actions from "../../Components/Ui/tables/Actions";
|
||||||
|
import { HovarableImage } from "../../Components/Ui";
|
||||||
|
import { BaseURL } from "../../api/config";
|
||||||
|
import { ToggleStatus } from "../../Components/Ui/ToggleStatus";
|
||||||
import ColumnsImage from "../../Components/Columns/ColumnsImage";
|
import ColumnsImage from "../../Components/Columns/ColumnsImage";
|
||||||
import { useDeleteCoupon } from "../../api/Coupon";
|
import LoadingSpinner from "../../Components/Ui/LoadingSpinner";
|
||||||
|
import { Switch } from "antd";
|
||||||
|
import { mapTranslatedProperties } from "../../utils/language/mapTranslatedProperties";
|
||||||
|
// import { useDeleteProduct, useUpdateProductStatus } from "../../api/owner_products";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { useDeleteProduct, useUpdateProductStatus } from "../../api/product";
|
||||||
|
|
||||||
function fnDelete(props :any ){}
|
|
||||||
|
|
||||||
const useTableColumns :any = () => {
|
const useTableColumns :any = () => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
const deleteMutation = useDeleteCoupon()
|
const toggleMutation = useUpdateProductStatus();
|
||||||
|
const deleteMutation = useDeleteProduct();
|
||||||
|
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
const handleChange = (row:any)=> {
|
||||||
|
const status = row?.favorite ;
|
||||||
|
toggleMutation.mutate({id:row?.id,new_status:status})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return useMemo(
|
return useMemo(
|
||||||
() => [
|
() => [
|
||||||
|
|
||||||
|
{
|
||||||
|
name: t("image"),
|
||||||
|
center: "true",
|
||||||
|
cell: (row: any) => {
|
||||||
|
return (
|
||||||
|
<ColumnsImage src={row?.main_photo} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: t("name"),
|
name: t("name"),
|
||||||
sortable: false,
|
sortable: false,
|
||||||
center: "true",
|
center: true,
|
||||||
cell: (row:any) => row?.name
|
selector:(row:any) => row?.name,
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: t("image"),
|
name: t("price"),
|
||||||
sortable: false,
|
sortable: false,
|
||||||
center: "true",
|
center: true,
|
||||||
cell: (row:any) => <ColumnsImage src={row?.photo} />
|
selector:(row:any) => row?.price,
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: t("parent_id"),
|
name: t("description"),
|
||||||
sortable: false,
|
sortable: false,
|
||||||
center: "true",
|
center: true,
|
||||||
cell: (row:any) => row?.parent_id
|
cell: (row:any) => (
|
||||||
|
row?.description
|
||||||
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: t("product_count"),
|
name: t("favorite"),
|
||||||
sortable: false,
|
sortable: false,
|
||||||
center: "true",
|
center: true,
|
||||||
cell: (row:any) => row?.product_count
|
cell: (row:any) => (
|
||||||
|
<ToggleStatus handleSwitch={handleChange} object={row} toggleMutation={toggleMutation} />
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "#",
|
name: "#",
|
||||||
sortable: false,
|
sortable: false,
|
||||||
center: true,
|
center: "true",
|
||||||
cell: (row:any) => (
|
cell: (row:any) => (
|
||||||
<Actions
|
<Actions
|
||||||
|
onEdit={()=> navigate('/products/'+row.id)}
|
||||||
objectToEdit={row}
|
objectToEdit={row}
|
||||||
showEdit
|
showEdit={true}
|
||||||
onEdit={()=> navigate(`/Coupon/${row.id}`) }
|
|
||||||
showView={false}
|
showView={false}
|
||||||
onDelete={() => deleteMutation.mutate({ id: row.id })}
|
onDelete={() => deleteMutation.mutate({ product_id: row.id })}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
// {
|
|
||||||
// name: t("status"),
|
|
||||||
// sortable: false,
|
|
||||||
// center: "true",
|
|
||||||
// cell: (row:any) => {
|
|
||||||
|
|
||||||
// return(
|
|
||||||
// <p style={{
|
|
||||||
// background:!row.deleted_at ?'#19ab27':'#ea5454',
|
|
||||||
// color:"white",
|
|
||||||
// padding:6,
|
|
||||||
// borderRadius:10,
|
|
||||||
// position:"relative",
|
|
||||||
// top:'7px'
|
|
||||||
// }}>
|
|
||||||
// {
|
|
||||||
// !row.deleted_at ? t('available') : t('unavailable')
|
|
||||||
|
|
||||||
// }
|
|
||||||
// </p>
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
|
|
||||||
],
|
],
|
||||||
[t]
|
[t]
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,11 @@ import { FakeSelectData } from '../../Layout/app/Const';
|
||||||
import { useFormikContext } from 'formik';
|
import { useFormikContext } from 'formik';
|
||||||
|
|
||||||
import { DatePicker } from 'antd';
|
import { DatePicker } from 'antd';
|
||||||
import { useGetCoupon } from '../../api/Coupon';
|
import { useGetSlider } from '../../api/Slider';
|
||||||
|
|
||||||
function AddForm() {
|
function AddForm() {
|
||||||
const formik = useFormikContext<any>();
|
const formik = useFormikContext<any>();
|
||||||
const {data } = useGetCoupon()
|
const {data } = useGetSlider()
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -24,7 +24,7 @@ function CouponPage() {
|
||||||
</DashHeader>
|
</DashHeader>
|
||||||
|
|
||||||
<LyTable
|
<LyTable
|
||||||
data={data?.Coupon}
|
data={data?.coupons}
|
||||||
isLoading={false}
|
isLoading={false}
|
||||||
columns={column}
|
columns={column}
|
||||||
// is_pagination={true}
|
// is_pagination={true}
|
||||||
|
|
@ -27,7 +27,7 @@ const EditPage = () => {
|
||||||
<KarimSpinner loading={isLoading}>
|
<KarimSpinner loading={isLoading}>
|
||||||
<FormPage
|
<FormPage
|
||||||
handleSubmit={(values: any) => handleSubmit(values)}
|
handleSubmit={(values: any) => handleSubmit(values)}
|
||||||
initialValues={getInitialValues(data)}
|
initialValues={getInitialValues(data?.coupons)}
|
||||||
validationSchema={getValidationSchema}
|
validationSchema={getValidationSchema}
|
||||||
title='Edit Coupon'
|
title='Edit Coupon'
|
||||||
>
|
>
|
||||||
76
src/Pages/Coupon2/formUtil.ts
Normal file
76
src/Pages/Coupon2/formUtil.ts
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
|
||||||
|
import * as Yup from "yup";
|
||||||
|
import { buildFormData } from "../../api/helper/buildFormData";
|
||||||
|
|
||||||
|
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 => {
|
||||||
|
return {
|
||||||
|
id: objectToEdit?.id ?? 0,
|
||||||
|
name: objectToEdit?.name??"",
|
||||||
|
code: objectToEdit?.code??"",
|
||||||
|
coupon_value: objectToEdit?.coupon_value??"",
|
||||||
|
status: objectToEdit?.status??"",
|
||||||
|
active_to: objectToEdit?.active_to??"",
|
||||||
|
discount_type: objectToEdit?.discount_type??"",
|
||||||
|
coupon_type: objectToEdit?.coupon_type??"",
|
||||||
|
minimum_total_to_order: objectToEdit?.minimum_total_to_order??"",
|
||||||
|
maximum_number_of_uses: objectToEdit?.maximum_number_of_uses??"",
|
||||||
|
useable_by_guest: objectToEdit?.useable_by_guest??"",
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export const getValidationSchema = (editMode: boolean = false): Yup.Schema<any> => {
|
||||||
|
// Validate input
|
||||||
|
return Yup.object().shape({
|
||||||
|
name : Yup.string().required('Required'),
|
||||||
|
code : Yup.number().required('Required'),
|
||||||
|
coupon_value : Yup.number().required('Required'),
|
||||||
|
status : Yup.string().required('Required'),
|
||||||
|
active_to : Yup.string().required('Required'),
|
||||||
|
discount_type : Yup.string().required('Required'),
|
||||||
|
coupon_type : Yup.string().required('Required'),
|
||||||
|
minimum_total_to_order : Yup.number().required('Required'),
|
||||||
|
maximum_number_of_uses : Yup.number().required('Required'),
|
||||||
|
useable_by_guest : Yup.string().required('Required'),
|
||||||
|
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export const getDataToSend = (values: any): FormData => {
|
||||||
|
const data = { ...values };
|
||||||
|
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
buildFormData(formData, data);
|
||||||
|
return formData;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ChangeDataToPrint = (data:any)=>{
|
||||||
|
|
||||||
|
let new_array = data
|
||||||
|
for(let i =0 ; i<data.length ; i++){
|
||||||
|
new_array[i]['status'] =!data[i]['deleted_at'] ?'available':'unavailable'
|
||||||
|
delete new_array[i]['deleted_at']
|
||||||
|
}
|
||||||
|
return new_array
|
||||||
|
}
|
||||||
104
src/Pages/Coupon2/useTableColumns.tsx
Normal file
104
src/Pages/Coupon2/useTableColumns.tsx
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
|
||||||
|
import React, { useMemo } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import Actions from "../../Components/Ui/tables/Actions";
|
||||||
|
import ColumnsImage from "../../Components/Columns/ColumnsImage";
|
||||||
|
import { useDeleteCoupon } from "../../api/Coupon";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { Button } from "antd";
|
||||||
|
|
||||||
|
function fnDelete(props :any ){}
|
||||||
|
|
||||||
|
const useTableColumns :any = () => {
|
||||||
|
const [t] = useTranslation();
|
||||||
|
const deleteMutation = useDeleteCoupon()
|
||||||
|
const navigate = useNavigate()
|
||||||
|
return useMemo(
|
||||||
|
() => [
|
||||||
|
|
||||||
|
{
|
||||||
|
name: t("name"),
|
||||||
|
sortable: false,
|
||||||
|
center: "true",
|
||||||
|
cell: (row:any) => row?.name
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: t("code"),
|
||||||
|
sortable: false,
|
||||||
|
center: "true",
|
||||||
|
cell: (row:any) => row?.code
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: t("coupon_value"),
|
||||||
|
sortable: false,
|
||||||
|
center: "true",
|
||||||
|
cell: (row:any) => row?.coupon_value
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
name: t("status"),
|
||||||
|
sortable: false,
|
||||||
|
center: true,
|
||||||
|
cell: (row:any) => {
|
||||||
|
return <Button type="primary" style={{ backgroundColor: row.status === 'active' ? 'green' : 'red' }}>{row.status}</Button>
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: t("discount_type"),
|
||||||
|
sortable: false,
|
||||||
|
center: "true",
|
||||||
|
cell: (row:any) => row?.discount_type
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: t("coupon_type"),
|
||||||
|
sortable: false,
|
||||||
|
center: "true",
|
||||||
|
cell: (row:any) => row?.coupon_type
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "#",
|
||||||
|
sortable: false,
|
||||||
|
center: true,
|
||||||
|
cell: (row:any) => (
|
||||||
|
<Actions
|
||||||
|
objectToEdit={row}
|
||||||
|
showEdit
|
||||||
|
onEdit={()=> navigate(`/Coupon/${row.id}`) }
|
||||||
|
showView={false}
|
||||||
|
onDelete={() => deleteMutation.mutate({ id: row.id })}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// name: t("status"),
|
||||||
|
// sortable: false,
|
||||||
|
// center: "true",
|
||||||
|
// cell: (row:any) => {
|
||||||
|
|
||||||
|
// return(
|
||||||
|
// <p style={{
|
||||||
|
// background:!row.deleted_at ?'#19ab27':'#ea5454',
|
||||||
|
// color:"white",
|
||||||
|
// padding:6,
|
||||||
|
// borderRadius:10,
|
||||||
|
// position:"relative",
|
||||||
|
// top:'7px'
|
||||||
|
// }}>
|
||||||
|
// {
|
||||||
|
// !row.deleted_at ? t('available') : t('unavailable')
|
||||||
|
|
||||||
|
// }
|
||||||
|
// </p>
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
|
||||||
|
],
|
||||||
|
[t]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useTableColumns;
|
||||||
|
|
||||||
40
src/Pages/Products/ProductsPage.tsx
Normal file
40
src/Pages/Products/ProductsPage.tsx
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
|
||||||
|
import React from 'react'
|
||||||
|
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 { useGetProduct } from '../../api/product'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { useNavigate } from 'react-router-dom'
|
||||||
|
import AddButton from '../../Layout/Dashboard/AddButton/AddButton'
|
||||||
|
|
||||||
|
function ProductsPage() {
|
||||||
|
|
||||||
|
const column =useTableColumns()
|
||||||
|
const {data ,status } = useGetProduct()
|
||||||
|
console.log(data);
|
||||||
|
const [t] = useTranslation()
|
||||||
|
const navigate = useNavigate()
|
||||||
|
|
||||||
|
return (
|
||||||
|
// Pass Status to Layout
|
||||||
|
<DashBody status={status as QueryStatusEnum} >
|
||||||
|
<DashHeader showAddButton={false} title={'products'}>
|
||||||
|
<AddButton onClick={()=>navigate('/products/add')}></AddButton>
|
||||||
|
</DashHeader>
|
||||||
|
|
||||||
|
<LyTable
|
||||||
|
data={data?.products}
|
||||||
|
isLoading={false}
|
||||||
|
columns={column}
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
</DashBody>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ProductsPage
|
||||||
|
|
||||||
91
src/Pages/Products/View/AddPage.tsx
Normal file
91
src/Pages/Products/View/AddPage.tsx
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { getInitialValues, getValidationSchema, getDataToSend } from '../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 { FaCheck, FaSadCry } from 'react-icons/fa'
|
||||||
|
import ViewPage from '../../../Layout/Dashboard/ViewPage';
|
||||||
|
import { Rate } from 'antd';
|
||||||
|
import BasicInfo from './BasicInfo';
|
||||||
|
import { usePageState } from '../../../lib/state mangment/LayoutPagestate';
|
||||||
|
import { useParams } from 'react-router-dom';
|
||||||
|
import LoadingPage from '../../../Layout/app/LoadingPage';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { BsInfoCircle } from 'react-icons/bs';
|
||||||
|
import BasicInfo2 from './BasicInfo2';
|
||||||
|
import useNavigateOnSuccess from '../../../Hooks/useNavigateOnSuccess';
|
||||||
|
import { useAddProduct } from '../../../api/product';
|
||||||
|
import VarianInfo from './VarianInfo';
|
||||||
|
|
||||||
|
const AddProductPage = () => {
|
||||||
|
|
||||||
|
|
||||||
|
const { mutate, isLoading, isSuccess } = useAddProduct()
|
||||||
|
const [BarStatus, setBarStatus] = useState({ value: 0, isLoading: false, isError: false, isSuccess: false })
|
||||||
|
const [IsValed, setIsValed] = useState(1)
|
||||||
|
const handleSubmit = (values: any) => {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
values['name'] = {
|
||||||
|
"en" : values.name_en,
|
||||||
|
"ar" : values.name_ar,
|
||||||
|
"de" : values.name_de,
|
||||||
|
}
|
||||||
|
values['description'] = {
|
||||||
|
"en" : values.description_en,
|
||||||
|
"ar" : values.description_ar,
|
||||||
|
"de" : values.description_de,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const infoArray = Object.entries(values.info).map(([key, value]: [string, any]) => ({
|
||||||
|
[key.split('.')[1]]: value
|
||||||
|
}));
|
||||||
|
values["info"]= infoArray
|
||||||
|
|
||||||
|
console.log(infoArray);
|
||||||
|
|
||||||
|
// mutate(values);
|
||||||
|
// console.log(values);
|
||||||
|
|
||||||
|
}
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
useNavigateOnSuccess(isSuccess, '/products')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const ViewProps = { getInitialValues, getValidationSchema, getDataToSend, handleSubmit, BarStatus };
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='ViewPage'>
|
||||||
|
|
||||||
|
<ViewPage {...ViewProps}>
|
||||||
|
<Tabs>
|
||||||
|
<TabList>
|
||||||
|
<Tab><div className='SignleDriverContainer'><span className='SignleDriverInfoIcon'><MdLanguage size={20} /></span> <h6 className='SingleInfo'>{t("Base_info")} {IsValed ? <FaCheck />: "" } </h6></div></Tab>
|
||||||
|
|
||||||
|
<Tab disabled={IsValed === 0}><div className='SignleDriverContainer'><span className='SignleDriverInfoIcon'><BsInfoCircle size={20} /></span> <h6 className='SingleInfo'>{t("VarianInfo")}</h6></div></Tab>
|
||||||
|
|
||||||
|
|
||||||
|
</TabList>
|
||||||
|
<TabBody >
|
||||||
|
<div className=" mt-4"><BasicInfo setIsValed={setIsValed} /></div>
|
||||||
|
</TabBody>
|
||||||
|
<TabBody >
|
||||||
|
<div className=" mt-4"><VarianInfo /></div>
|
||||||
|
</TabBody>
|
||||||
|
|
||||||
|
</Tabs>
|
||||||
|
</ViewPage>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AddProductPage
|
||||||
42
src/Pages/Products/View/BasicInfo.tsx
Normal file
42
src/Pages/Products/View/BasicInfo.tsx
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { Col, Row } from 'reactstrap'
|
||||||
|
import KarimField from '../../../Components/Karimalden/KarimField'
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { useFormikContext } from 'formik';
|
||||||
|
|
||||||
|
const BasicInfo = ({setIsValed}:any) => {
|
||||||
|
const [t] = useTranslation();
|
||||||
|
const formikContext = useFormikContext();
|
||||||
|
const { values, submitForm,isValid } = formikContext;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
//@ts-ignore
|
||||||
|
if (values.name_ar !== "" && values.name_en !== "" && values.name_de !== "" && values.main_photo !== "" && values.category_id !== "" ) {
|
||||||
|
setIsValed(1);
|
||||||
|
console.log(isValid, 'isValid');
|
||||||
|
} else {
|
||||||
|
console.log(values);
|
||||||
|
}
|
||||||
|
}, [isValid,values]);
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Row xs={1} sm={1} md={1} lg={2} xl={2}>
|
||||||
|
<Col>
|
||||||
|
<KarimField name="name_ar" />
|
||||||
|
<KarimField name="name_en" />
|
||||||
|
<KarimField name="name_de" />
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<KarimField name="main_photo" type='File' />
|
||||||
|
<KarimField name="category_id" type='Select' option={[]} label='category' placeholder='category' />
|
||||||
|
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</Row>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BasicInfo
|
||||||
32
src/Pages/Products/View/BasicInfo2.tsx
Normal file
32
src/Pages/Products/View/BasicInfo2.tsx
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { Col, Row } from 'reactstrap'
|
||||||
|
import KarimField from '../../../Components/Karimalden/KarimField'
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import ObjectField from './ObjectField';
|
||||||
|
|
||||||
|
const BasicInfo2 = () => {
|
||||||
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
const categoryOption = [] as any
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Row xs={1} sm={1} md={1} lg={2} xl={2}>
|
||||||
|
<Col>
|
||||||
|
{/* <KarimField name="images" type='MaltyFile' /> */}
|
||||||
|
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
{/* <KarimField name="price" /> */}
|
||||||
|
{/* <KarimField name="quantity" type='number' /> */}
|
||||||
|
{/* <KarimField name="info" /> */}
|
||||||
|
<ObjectField/>
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
|
||||||
|
</Row>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BasicInfo2
|
||||||
92
src/Pages/Products/View/ObjectField.tsx
Normal file
92
src/Pages/Products/View/ObjectField.tsx
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { CloseOutlined } from '@ant-design/icons';
|
||||||
|
import { Button, Card, Form, Input, Space, Typography } from 'antd';
|
||||||
|
import { useFormikContext } from 'formik';
|
||||||
|
|
||||||
|
const ObjectField: React.FC = () => {
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
const formik = useFormikContext<any>();
|
||||||
|
const [FieldItems, setFieldItems] = useState<any>([])
|
||||||
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const { name, value } = e.target;
|
||||||
|
setFieldItems((prevState:any) => ({
|
||||||
|
...prevState,
|
||||||
|
[name]: value
|
||||||
|
}));
|
||||||
|
formik.setFieldValue("info", FieldItems)
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
form.setFieldsValue({
|
||||||
|
items: [{ list: [{ Attribute: '', Description: '' }] }]
|
||||||
|
});
|
||||||
|
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Form
|
||||||
|
labelCol={{ span: 6 }}
|
||||||
|
wrapperCol={{ span: 18 }}
|
||||||
|
form={form}
|
||||||
|
name="dynamic_form_complex"
|
||||||
|
style={{ width: '100%' }} // Set width to 100%
|
||||||
|
autoComplete="off"
|
||||||
|
>
|
||||||
|
<Form.List name="items">
|
||||||
|
{(fields, { add, remove }) => (
|
||||||
|
<div style={{ display: 'flex', rowGap: 16, flexDirection: 'column' }}>
|
||||||
|
{fields.map((field, index) => (
|
||||||
|
<div key={field.key}>
|
||||||
|
<Typography.Text strong style={{ marginBottom: 8 }}>
|
||||||
|
Information
|
||||||
|
</Typography.Text>
|
||||||
|
|
||||||
|
{/* Nested Form.List for sub-items */}
|
||||||
|
<Form.Item>
|
||||||
|
<Form.List name={[field.name, 'list']}>
|
||||||
|
{(subFields, subOpt) => (
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column', rowGap: 16 }}>
|
||||||
|
{subFields.map((subField) => (
|
||||||
|
<Space key={subField.key}>
|
||||||
|
<Form.Item noStyle name={[subField.name, 'Attribute']}>
|
||||||
|
<Input
|
||||||
|
placeholder="Attribute"
|
||||||
|
|
||||||
|
onChange={handleChange} // Assign onChange handler
|
||||||
|
name={`${subField.name}.Attribute`} // Ensure proper name for dynamic state update
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item noStyle name={[subField.name, 'Description']}>
|
||||||
|
<Input
|
||||||
|
placeholder="Description"
|
||||||
|
|
||||||
|
onChange={handleChange} // Assign onChange handler
|
||||||
|
name={`${subField.name}.Description`} // Ensure proper name for dynamic state update
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<CloseOutlined
|
||||||
|
onClick={() => {
|
||||||
|
subOpt.remove(subField.name);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Space>
|
||||||
|
))}
|
||||||
|
<Button type="dashed" onClick={() => subOpt.add()} block>
|
||||||
|
+ Add Another Item
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Form.List>
|
||||||
|
</Form.Item>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Form.List>
|
||||||
|
</Form>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ObjectField;
|
||||||
92
src/Pages/Products/View/Page.tsx
Normal file
92
src/Pages/Products/View/Page.tsx
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { getInitialValues, getValidationSchema, getDataToSend } from '../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 { FaSadCry } from 'react-icons/fa'
|
||||||
|
import ViewPage from '../../../Layout/Dashboard/ViewPage';
|
||||||
|
import { Rate } from 'antd';
|
||||||
|
import BasicInfo from './BasicInfo';
|
||||||
|
import { usePageState } from '../../../lib/state mangment/LayoutPagestate';
|
||||||
|
import { useParams } from 'react-router-dom';
|
||||||
|
import LoadingPage from '../../../Layout/app/LoadingPage';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { BsInfoCircle } from 'react-icons/bs';
|
||||||
|
import { useGetOneProduct, useUpdateProduct } from '../../../api/product';
|
||||||
|
import BasicInfo2 from './BasicInfo2';
|
||||||
|
import useNavigateOnSuccess from '../../../Hooks/useNavigateOnSuccess';
|
||||||
|
import VarianInfo from './VarianInfo';
|
||||||
|
|
||||||
|
const ViewProduct = () => {
|
||||||
|
const { setObjectToEdit, objectToEdit } = usePageState()
|
||||||
|
const {t} = useTranslation();
|
||||||
|
const { id } = useParams()
|
||||||
|
const { data } = useGetOneProduct({id:id})
|
||||||
|
const [BarStatus, setBarStatus] = useState({ value: 0, isLoading: false, isError: false, isSuccess: false })
|
||||||
|
const {mutate ,isSuccess} = useUpdateProduct()
|
||||||
|
const handleSubmit = (values:any)=>{
|
||||||
|
|
||||||
|
values['product_id'] = id
|
||||||
|
|
||||||
|
values['is_highlight'] =values['is_highlight'] == true ?1 :0
|
||||||
|
values['is_most_purchase'] =values['is_most_purchase'] == true ?1 :0
|
||||||
|
|
||||||
|
const formToSend = getDataToSend(values)
|
||||||
|
|
||||||
|
mutate(formToSend)
|
||||||
|
}
|
||||||
|
|
||||||
|
useNavigateOnSuccess(isSuccess , '/products')
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
|
setObjectToEdit(data);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
|
||||||
|
|
||||||
|
return ()=>{
|
||||||
|
setObjectToEdit(null)
|
||||||
|
|
||||||
|
}
|
||||||
|
},[])
|
||||||
|
|
||||||
|
const ViewProps = { getInitialValues, getValidationSchema, getDataToSend, handleSubmit, BarStatus };
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='ViewPage'>
|
||||||
|
{objectToEdit && data ?
|
||||||
|
<ViewPage {...ViewProps}>
|
||||||
|
<Tabs>
|
||||||
|
<TabList>
|
||||||
|
<Tab><div className='SignleDriverContainer'><span className='SignleDriverInfoIcon'><MdLanguage size={20} /></span> <h6 className='SingleDriverInfo'>{t("Base_info")}</h6></div></Tab>
|
||||||
|
|
||||||
|
<Tab><div className='SignleDriverContainer'><span className='SignleDriverInfoIcon'><BsInfoCircle size={20} /></span> <h6 className='SingleDriverInfo'>{t("VarianInfo")}</h6></div></Tab>
|
||||||
|
|
||||||
|
|
||||||
|
</TabList>
|
||||||
|
<TabBody >
|
||||||
|
<div className=" mt-4"><BasicInfo /></div>
|
||||||
|
</TabBody>
|
||||||
|
<TabBody >
|
||||||
|
<div className=" mt-4"><VarianInfo /></div>
|
||||||
|
</TabBody>
|
||||||
|
|
||||||
|
</Tabs>
|
||||||
|
</ViewPage>
|
||||||
|
: <LoadingPage />}
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ViewProduct
|
||||||
13
src/Pages/Products/View/VarianInfo.tsx
Normal file
13
src/Pages/Products/View/VarianInfo.tsx
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
import React, { useState } from 'react'
|
||||||
|
import ResposiveTabs from './taps/ResposiveTabs'
|
||||||
|
|
||||||
|
const VarianInfo = () => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='VarianInfo'>
|
||||||
|
<ResposiveTabs/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default VarianInfo
|
||||||
14
src/Pages/Products/View/taps/NewTabs.tsx
Normal file
14
src/Pages/Products/View/taps/NewTabs.tsx
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
const NewTabs = () => {
|
||||||
|
function handelClick(){
|
||||||
|
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div onClick={handelClick}>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NewTabs
|
||||||
152
src/Pages/Products/View/taps/ResposiveTabs.tsx
Normal file
152
src/Pages/Products/View/taps/ResposiveTabs.tsx
Normal file
|
|
@ -0,0 +1,152 @@
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Tabs, Space, Input } from 'antd';
|
||||||
|
import { CopyOutlined } from '@ant-design/icons';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
const { TabPane } = Tabs;
|
||||||
|
|
||||||
|
interface TabItem {
|
||||||
|
label: string;
|
||||||
|
children: string;
|
||||||
|
key: string;
|
||||||
|
closable: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialItemShape: TabItem = {
|
||||||
|
label: 'variable 1',
|
||||||
|
children: 'Content of Tab 1',
|
||||||
|
key: '1',
|
||||||
|
closable: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const App: React.FC = () => {
|
||||||
|
const [activeKey, setActiveKey] = useState(initialItemShape.key);
|
||||||
|
const [items, setItems] = useState([initialItemShape]);
|
||||||
|
const [inputValues, setInputValues] = useState<{ [key: string]: string[] }>({});
|
||||||
|
const onChange = (newActiveKey: string) => {
|
||||||
|
setActiveKey(newActiveKey);
|
||||||
|
};
|
||||||
|
|
||||||
|
const add = () => {
|
||||||
|
const newActiveKey = `${items.length + 1}`;
|
||||||
|
const newItem: TabItem = {
|
||||||
|
...initialItemShape,
|
||||||
|
key: newActiveKey,
|
||||||
|
label: `variable ${newActiveKey}`,
|
||||||
|
};
|
||||||
|
const newPanes = [...items, newItem];
|
||||||
|
setItems(newPanes);
|
||||||
|
setActiveKey(newActiveKey);
|
||||||
|
};
|
||||||
|
|
||||||
|
const duplicate = (targetKey: string) => {
|
||||||
|
const targetItem = items.find((item) => item.key === targetKey);
|
||||||
|
if (targetItem) {
|
||||||
|
const newActiveKey = `${items.length + 1}`;
|
||||||
|
const newItem: TabItem = {
|
||||||
|
...targetItem,
|
||||||
|
key: newActiveKey,
|
||||||
|
label: `variable ${newActiveKey}`,
|
||||||
|
};
|
||||||
|
const newPanes = [...items, newItem];
|
||||||
|
setItems(newPanes);
|
||||||
|
setActiveKey(newActiveKey);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const remove = (targetKey: string) => {
|
||||||
|
let newActiveKey = activeKey;
|
||||||
|
let lastIndex = -1;
|
||||||
|
items.forEach((item, i) => {
|
||||||
|
if (item.key === targetKey) {
|
||||||
|
lastIndex = i - 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const newPanes = items.filter((item) => item.key !== targetKey);
|
||||||
|
if (newPanes.length && newActiveKey === targetKey) {
|
||||||
|
if (lastIndex >= 0) {
|
||||||
|
newActiveKey = newPanes[lastIndex].key;
|
||||||
|
} else {
|
||||||
|
newActiveKey = newPanes[0].key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setItems(newPanes);
|
||||||
|
setActiveKey(newActiveKey);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleInputChange = (key: string, values: string[]) => {
|
||||||
|
setInputValues((prevInputValues) => ({
|
||||||
|
...prevInputValues,
|
||||||
|
[key]: values,
|
||||||
|
}));
|
||||||
|
console.log(inputValues);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onEdit = (
|
||||||
|
targetKey: string | React.MouseEvent | React.KeyboardEvent,
|
||||||
|
action: 'add' | 'remove'
|
||||||
|
) => {
|
||||||
|
if (action === 'add') {
|
||||||
|
add();
|
||||||
|
} else {
|
||||||
|
remove(targetKey as string);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tabs
|
||||||
|
type="editable-card"
|
||||||
|
onChange={onChange}
|
||||||
|
activeKey={activeKey}
|
||||||
|
onEdit={onEdit}
|
||||||
|
tabPosition="left"
|
||||||
|
>
|
||||||
|
{items.map((item) => (
|
||||||
|
<TabPane
|
||||||
|
key={item.key}
|
||||||
|
tab={
|
||||||
|
<Space>
|
||||||
|
{item.label}
|
||||||
|
<CopyOutlined onClick={() => duplicate(item.key)} />
|
||||||
|
</Space>
|
||||||
|
}
|
||||||
|
closable={item.closable}
|
||||||
|
>
|
||||||
|
<VariableTabs
|
||||||
|
value={inputValues[item.key] || ['', '', '', '']}
|
||||||
|
onChange={(values: string[]) => handleInputChange(item.key, values)}
|
||||||
|
/>
|
||||||
|
</TabPane>
|
||||||
|
))}
|
||||||
|
</Tabs>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
interface VariableTabsProps {
|
||||||
|
value: string[];
|
||||||
|
onChange: (value: string[]) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const VariableTabs: React.FC<VariableTabsProps> = ({ value, onChange }) => {
|
||||||
|
const handleInputChange = (index: number) => (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const newValues = [...value];
|
||||||
|
newValues[index] = e.target.value;
|
||||||
|
onChange(newValues);
|
||||||
|
};
|
||||||
|
const [t] = useTranslation()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<label className="text">
|
||||||
|
{t(`Name`)}
|
||||||
|
</label>
|
||||||
|
<Input value={value[0]} onChange={handleInputChange(0)} />
|
||||||
|
|
||||||
|
<Input value={value[1]} onChange={handleInputChange(1)} />
|
||||||
|
<Input value={value[2]} onChange={handleInputChange(2)} />
|
||||||
|
<Input value={value[3]} onChange={handleInputChange(3)} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default App;
|
||||||
26
src/Pages/Products/View/varianForm.tsx
Normal file
26
src/Pages/Products/View/varianForm.tsx
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { Col, Row } from 'reactstrap'
|
||||||
|
import KarimField from '../../../Components/Karimalden/KarimField'
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
const varianForm = () => {
|
||||||
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Row xs={1} sm={1} md={1} lg={2} xl={2}>
|
||||||
|
<Col>
|
||||||
|
<KarimField name="name" />
|
||||||
|
<KarimField name="description" />
|
||||||
|
<KarimField name="images" type='MaltyFile' />
|
||||||
|
|
||||||
|
{/* <KarimField name="quantity" type='number' /> */}
|
||||||
|
{/* <KarimField name="info" /> */}
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</Row>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default varianForm
|
||||||
61
src/Pages/Products/formUtil.ts
Normal file
61
src/Pages/Products/formUtil.ts
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
|
||||||
|
import * as Yup from "yup";
|
||||||
|
import { buildFormData } from "../../api/helper/buildFormData";
|
||||||
|
import { mapTranslatedProperties } from "../../utils/language/mapTranslatedProperties";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const getInitialValues = (objectToEdit: any | null = null) => {
|
||||||
|
|
||||||
|
// console.log(objectToEdit);
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: objectToEdit?.id ?? 0,
|
||||||
|
name:objectToEdit?.name ?? "",
|
||||||
|
name_ar: objectToEdit?.name?.ar ?? '',
|
||||||
|
name_en: objectToEdit?.name?.en ?? '',
|
||||||
|
name_de: objectToEdit?.name?.de ?? '',
|
||||||
|
description: objectToEdit?.description ?? '',
|
||||||
|
price:objectToEdit?.price??"",
|
||||||
|
main_photo:objectToEdit?.main_photo??"",
|
||||||
|
images:objectToEdit?.images??"",
|
||||||
|
category_id:objectToEdit?.category_id??1,
|
||||||
|
variable:[],
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getValidationSchema = (editMode: boolean = false) => {
|
||||||
|
// validate input
|
||||||
|
return Yup.object().shape({
|
||||||
|
// name_ar: Yup.string().required('Required'),
|
||||||
|
// name_en: Yup.string().required('Required'),
|
||||||
|
// name_de: Yup.string().required('Required'),
|
||||||
|
// description_ar: Yup.string().required('Required'),
|
||||||
|
// description_en: Yup.string().required('Required'),
|
||||||
|
// description_de: Yup.string().required('Required'),
|
||||||
|
// price: Yup.number().required('Required'),
|
||||||
|
// // info: Yup.string().required('Required'),
|
||||||
|
// main_photo: Yup.string().required('Required'),
|
||||||
|
// // images: Yup.string().required('Required'),
|
||||||
|
// category_id: Yup.string().required('Required'),
|
||||||
|
// quantity: Yup.number().required('Required'),
|
||||||
|
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getDataToSend = (values: any): FormData => {
|
||||||
|
const data = { ...values };
|
||||||
|
// console.log(data);
|
||||||
|
|
||||||
|
if(typeof data['product_main_image'] == 'string') delete data['product_main_image']
|
||||||
|
|
||||||
|
data['en_product_name'] = values['translated_fields']['1']['product_name']
|
||||||
|
data['ar_product_name'] =values['translated_fields']['2']['product_name']
|
||||||
|
data['ar_product_description'] =values['translated_fields']['2']['product_description']
|
||||||
|
data['en_product_description'] =values['translated_fields']['1']['product_description']
|
||||||
|
const formData = new FormData();
|
||||||
|
buildFormData(formData, data);
|
||||||
|
return formData;
|
||||||
|
};
|
||||||
|
|
||||||
92
src/Pages/Products/useTableColumns.tsx
Normal file
92
src/Pages/Products/useTableColumns.tsx
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
|
||||||
|
import React, { useMemo } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import Actions from "../../Components/Ui/tables/Actions";
|
||||||
|
import { HovarableImage } from "../../Components/Ui";
|
||||||
|
import { BaseURL } from "../../api/config";
|
||||||
|
import { ToggleStatus } from "../../Components/Ui/ToggleStatus";
|
||||||
|
import ColumnsImage from "../../Components/Columns/ColumnsImage";
|
||||||
|
import LoadingSpinner from "../../Components/Ui/LoadingSpinner";
|
||||||
|
import { Switch } from "antd";
|
||||||
|
import { mapTranslatedProperties } from "../../utils/language/mapTranslatedProperties";
|
||||||
|
// import { useDeleteProduct, useUpdateProductStatus } from "../../api/owner_products";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { useDeleteProduct, useUpdateProductStatus } from "../../api/product";
|
||||||
|
|
||||||
|
|
||||||
|
const useTableColumns :any = () => {
|
||||||
|
const [t] = useTranslation();
|
||||||
|
const toggleMutation = useUpdateProductStatus();
|
||||||
|
const deleteMutation = useDeleteProduct();
|
||||||
|
|
||||||
|
const navigate = useNavigate()
|
||||||
|
const handleChange = (row:any)=> {
|
||||||
|
const status = row?.favorite ;
|
||||||
|
toggleMutation.mutate({id:row?.id,new_status:status})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return useMemo(
|
||||||
|
() => [
|
||||||
|
|
||||||
|
{
|
||||||
|
name: t("image"),
|
||||||
|
center: "true",
|
||||||
|
cell: (row: any) => {
|
||||||
|
return (
|
||||||
|
<ColumnsImage src={row?.main_photo} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: t("name"),
|
||||||
|
sortable: false,
|
||||||
|
center: true,
|
||||||
|
selector:(row:any) => row?.name,
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: t("price"),
|
||||||
|
sortable: false,
|
||||||
|
center: true,
|
||||||
|
selector:(row:any) => row?.price,
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: t("description"),
|
||||||
|
sortable: false,
|
||||||
|
center: true,
|
||||||
|
cell: (row:any) => (
|
||||||
|
row?.description
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: t("favorite"),
|
||||||
|
sortable: false,
|
||||||
|
center: true,
|
||||||
|
cell: (row:any) => (
|
||||||
|
<ToggleStatus handleSwitch={handleChange} object={row} toggleMutation={toggleMutation} />
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "#",
|
||||||
|
sortable: false,
|
||||||
|
center: "true",
|
||||||
|
cell: (row:any) => (
|
||||||
|
<Actions
|
||||||
|
onEdit={()=> navigate('/products/'+row.id)}
|
||||||
|
objectToEdit={row}
|
||||||
|
showEdit={true}
|
||||||
|
showView={false}
|
||||||
|
onDelete={() => deleteMutation.mutate({ product_id: row.id })}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[t]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useTableColumns;
|
||||||
|
|
||||||
52
src/Pages/order/OrderPage.tsx
Normal file
52
src/Pages/order/OrderPage.tsx
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
import React from "react";
|
||||||
|
import useTableColumns from "./useTableColumns";
|
||||||
|
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 "../../Components/Karimalden/View/SearchField";
|
||||||
|
const OrderPage = () => {
|
||||||
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//filters
|
||||||
|
const [search, setSearchText] = React.useState("");
|
||||||
|
|
||||||
|
|
||||||
|
const filterIsApplied = search !== "";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//Table Content -- Data + Columns
|
||||||
|
const { data, isLoading , status } = useGetOrder({search});
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
|
const totalRows = data?.pagination?.total || 0;
|
||||||
|
|
||||||
|
const columns = useTableColumns();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<DashBody status={status as QueryStatusEnum} >
|
||||||
|
<DashHeader title="orders" showAddButton={false}>
|
||||||
|
{/* <SearchField/> */}
|
||||||
|
</DashHeader>
|
||||||
|
<LyTable
|
||||||
|
data={data?.Orders}
|
||||||
|
total={totalRows}
|
||||||
|
column={columns}
|
||||||
|
is_pagination={true}
|
||||||
|
|
||||||
|
|
||||||
|
/>
|
||||||
|
</DashBody>
|
||||||
|
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OrderPage;
|
||||||
51
src/Pages/order/Select.js
Normal file
51
src/Pages/order/Select.js
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
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;
|
||||||
61
src/Pages/order/form/formUtils.js
Normal file
61
src/Pages/order/form/formUtils.js
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
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 ;
|
||||||
|
}
|
||||||
113
src/Pages/order/useTableColumns.tsx
Normal file
113
src/Pages/order/useTableColumns.tsx
Normal file
|
|
@ -0,0 +1,113 @@
|
||||||
|
import React, { useMemo } from "react";
|
||||||
|
// import { history } from "../../../history";
|
||||||
|
// import { GrView } from "react-icons/gr";
|
||||||
|
// import OrderStatus from "components/OrderStatus";
|
||||||
|
// import Actions from "components/table/TableActions";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useDeleteOrder } from "../../api/order";
|
||||||
|
import { GrView } from "react-icons/gr";
|
||||||
|
import Actions from "../../Components/Ui/tables/Actions";
|
||||||
|
import { history } from "../../ProviderContainer";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import ColumnsImage from "../../Components/Columns/ColumnsImage";
|
||||||
|
|
||||||
|
const useTableColumns = () => {
|
||||||
|
const [t] = useTranslation();
|
||||||
|
const navigate = useNavigate()
|
||||||
|
const deleteMutation = useDeleteOrder()
|
||||||
|
|
||||||
|
let column = [
|
||||||
|
{
|
||||||
|
name: t("order_code"),
|
||||||
|
sortable: false,
|
||||||
|
center:true,
|
||||||
|
selector:(row:any) => row?.id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: t("image"),
|
||||||
|
sortable: false,
|
||||||
|
center:true,
|
||||||
|
selector:(row:any) => {
|
||||||
|
const {avatar} = row.user
|
||||||
|
return(
|
||||||
|
<ColumnsImage src={avatar} />
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: t("name"),
|
||||||
|
sortable: false,
|
||||||
|
center:true,
|
||||||
|
selector:(row:any) => row?.user?.name,
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: t("email"),
|
||||||
|
sortable: false,
|
||||||
|
center:true,
|
||||||
|
selector:(row:any) => row?.user?.email,
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: t("status"),
|
||||||
|
center: true,
|
||||||
|
|
||||||
|
cell:(row:any)=>{
|
||||||
|
|
||||||
|
return row?.order_status;
|
||||||
|
// return <OrderStatus order_status={row?.order_status}/>
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: t("payment_method"),
|
||||||
|
selector: "payment_method",
|
||||||
|
center: true,
|
||||||
|
cell:(row:any)=>{
|
||||||
|
return t(row?.payment_method)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: t("price"),
|
||||||
|
center: true,
|
||||||
|
cell:(row:any)=>{
|
||||||
|
console.log(row);
|
||||||
|
|
||||||
|
return (row?.order_total)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "#",
|
||||||
|
center: true,
|
||||||
|
cell: (row:any) =>
|
||||||
|
<span style={{display:"flex" , alignItems:"center" , justifyContent:"space-around" , width:"100px" }} >
|
||||||
|
|
||||||
|
<Actions
|
||||||
|
showDelete={false}
|
||||||
|
objectToEdit={row}
|
||||||
|
onDelete={() => deleteMutation.mutate({order_id:row.id })}
|
||||||
|
showEdit={false}
|
||||||
|
onView={()=>navigate(`/order/${row?.id}` , {replace:true})}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</span>
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return column
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useTableColumns;
|
||||||
93
src/Pages/order/view-one/Order.js
Normal file
93
src/Pages/order/view-one/Order.js
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
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 ;
|
||||||
|
|
||||||
|
console.log(items);
|
||||||
|
|
||||||
|
console.log(order);
|
||||||
|
|
||||||
|
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>
|
||||||
|
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
39
src/Pages/order/view-one/OrderForm.js
Normal file
39
src/Pages/order/view-one/OrderForm.js
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
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>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
36
src/Pages/order/view-one/OrderForm.module.scss
Normal file
36
src/Pages/order/view-one/OrderForm.module.scss
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
.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;
|
||||||
|
}
|
||||||
31
src/Pages/order/view-one/OrderStatus.js
Normal file
31
src/Pages/order/view-one/OrderStatus.js
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
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;
|
||||||
80
src/Pages/order/view-one/StatusOrderController.js
Normal file
80
src/Pages/order/view-one/StatusOrderController.js
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
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>
|
||||||
|
)
|
||||||
|
}
|
||||||
20
src/Pages/order/view-one/index.css
Normal file
20
src/Pages/order/view-one/index.css
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
.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;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
57
src/Pages/order/view-one/useTableColumns.js
Normal file
57
src/Pages/order/view-one/useTableColumns.js
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
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();
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: t("id"),
|
||||||
|
sortable: true,
|
||||||
|
center: true,
|
||||||
|
cell:(row) => row.id
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: `${t('name')}`,
|
||||||
|
sortable: true,
|
||||||
|
center: true,
|
||||||
|
cell:(row) => row.name
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -1,18 +1,26 @@
|
||||||
import { ReactNode, lazy } from "react";
|
import { ReactNode, lazy } from "react";
|
||||||
|
|
||||||
// Icons Import
|
// Icons Import
|
||||||
|
import { FaCartArrowDown, FaImages } from "react-icons/fa";
|
||||||
|
|
||||||
import { FaUser, FaHome, FaSadCry } from "react-icons/fa"
|
import { FaUser, FaHome, FaSadCry } from "react-icons/fa"
|
||||||
|
import { BiSolidCategory } from "react-icons/bi";
|
||||||
|
import { BiSolidCoupon } from "react-icons/bi";
|
||||||
|
|
||||||
|
|
||||||
// Pages Import
|
// Pages Import
|
||||||
|
|
||||||
import HomePage from "./Pages/Home/HomePage";
|
import AddCategoriesPage from "./Pages/Categories/View/AddPage";
|
||||||
import CategoriesPage from "./Pages/Categories/CategoriesPage";
|
import EditCategories from "./Pages/Categories/View/EditPage";
|
||||||
import EditCategories from "./Pages/Categories/EditCategories/Page";
|
import CategoriesPage from "./Pages/Categories/Page";
|
||||||
import EditCoupon from "./Pages/Coupon/EditCoupon/Page";
|
|
||||||
|
|
||||||
import CouponPage from "./Pages/Coupon/CouponPage";
|
import HomePage from "./Pages/Home/HomePage";
|
||||||
|
|
||||||
|
import ProductsPage from "./Pages/Products/ProductsPage";
|
||||||
|
import AddProductPage from "./Pages/Products/View/AddPage";
|
||||||
|
import EditProduct from "./Pages/Products/View/Page";
|
||||||
|
import Order from "./Pages/order/view-one/Order";
|
||||||
|
import OrderPage from "./Pages/order/OrderPage";
|
||||||
|
|
||||||
|
|
||||||
interface RoutesLinksType {
|
interface RoutesLinksType {
|
||||||
|
|
@ -38,18 +46,31 @@ export const RoutesLinks: RoutesLinksType[] = [
|
||||||
{
|
{
|
||||||
name: "Categories",
|
name: "Categories",
|
||||||
element: <CategoriesPage />,
|
element: <CategoriesPage />,
|
||||||
icon: <FaHome />,
|
icon: <BiSolidCategory />
|
||||||
|
,
|
||||||
href: "/categories",
|
href: "/categories",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// {
|
||||||
|
// name: "Coupon",
|
||||||
|
// element: <CouponPage />,
|
||||||
|
// icon: <BiSolidCoupon /> ,
|
||||||
|
// href: "/Coupon",
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
name: "Coupon",
|
name: "products",
|
||||||
element: <CouponPage />,
|
element: <ProductsPage />,
|
||||||
icon: <FaUser />,
|
icon: <BiSolidCoupon /> ,
|
||||||
href: "/Coupon",
|
href: "/products",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "Order",
|
||||||
|
element: <OrderPage />,
|
||||||
|
icon: <BiSolidCoupon /> ,
|
||||||
|
href: "/order",
|
||||||
},
|
},
|
||||||
|
|
||||||
/////////////// hidden route
|
|
||||||
|
|
||||||
{
|
{
|
||||||
href: "/categories/:id",
|
href: "/categories/:id",
|
||||||
|
|
@ -57,8 +78,33 @@ export const RoutesLinks: RoutesLinksType[] = [
|
||||||
hidden:true
|
hidden:true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: "/coupon/:id",
|
href: "/categories/add",
|
||||||
element: <EditCoupon />,
|
element: <AddCategoriesPage />,
|
||||||
hidden:true
|
hidden:true
|
||||||
}
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "add_products",
|
||||||
|
element: <AddProductPage />,
|
||||||
|
// icon: <BiSolidCoupon /> ,
|
||||||
|
href: "/products/add",
|
||||||
|
hidden:true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "edit_products",
|
||||||
|
element: <EditProduct />,
|
||||||
|
// icon: <BiSolidCoupon /> ,
|
||||||
|
href: "/products/:id",
|
||||||
|
hidden:true
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "view_order",
|
||||||
|
element: <Order />,
|
||||||
|
href: "/order/:id",
|
||||||
|
hidden:true
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap');
|
||||||
|
|
||||||
|
|
||||||
html,body {
|
html,body {
|
||||||
background: var(--bg2)
|
background: var(--bg2);
|
||||||
|
font-family: 'Poppins', sans-serif;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
:root {
|
:root {
|
||||||
--primary:#fcb04f ;
|
--primary:#E57DB1 ;
|
||||||
--secondary : #304a7e;
|
--secondary : #2D9CDB;
|
||||||
--text: #565656;
|
--text: #565656;
|
||||||
--bg: #ffffff;
|
--bg: #ffffff;
|
||||||
--bg2: #f8f8f8;
|
--bg2: #f8f8f8;
|
||||||
--shadow: rgba(0, 0, 0, 0.15);
|
--shadow: rgba(0, 0, 0, 0.15);
|
||||||
--gray : rgb(207, 210, 214);
|
--gray : rgb(207, 210, 214);
|
||||||
--linear : linear-gradient(118deg, #fcb04f, #f78c3f)
|
--linear : linear-gradient(118deg, #2D9CDB, #2D9CDB)
|
||||||
}
|
}
|
||||||
|
|
||||||
:root:has(.dark) {
|
:root:has(.dark) {
|
||||||
|
|
|
||||||
|
|
@ -361,3 +361,29 @@ background: var(--bg);
|
||||||
background: var(--bg);
|
background: var(--bg);
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
}
|
}
|
||||||
|
.SingleInfo{
|
||||||
|
svg{
|
||||||
|
color: green !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ResposiveTabs{
|
||||||
|
padding-block: 20px;
|
||||||
|
min-height: 300px;
|
||||||
|
}
|
||||||
|
/* Ant tabs tab active */
|
||||||
|
.ant-tabs-nav-wrap .ant-tabs-nav-list .ant-tabs-tab-active{
|
||||||
|
display:inline-block;
|
||||||
|
transform:translatex(0px) translatey(0px) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ant tabs content holder */
|
||||||
|
.VarianInfo .ant-tabs-left .ant-tabs-content-holder{
|
||||||
|
transform:translatex(0px) translatey(0px);
|
||||||
|
|
||||||
|
}
|
||||||
|
.ant-tabs-nav-wrap .ant-tabs-nav-list .ant-tabs-tab{
|
||||||
|
align-self: center !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -84,7 +84,7 @@ overflow-x: hidden;
|
||||||
background: var(--primary);
|
background: var(--primary);
|
||||||
color: var(--bg);
|
color: var(--bg);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
box-shadow: 2px 2px 7px 0 var(--primary);
|
box-shadow: 2px 2px 7px 0 var(--shadow);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transform: scale(1.01);
|
transform: scale(1.01);
|
||||||
@include Shadow;
|
@include Shadow;
|
||||||
|
|
@ -149,7 +149,7 @@ overflow-x: hidden;
|
||||||
background: var(--linear);
|
background: var(--linear);
|
||||||
color: var(--bg);
|
color: var(--bg);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
box-shadow: 2px 2px 7px 0 var(--primary);
|
box-shadow: 2px 2px 7px 0 var(--shadow);
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
|
|
||||||
|
|
@ -54,3 +54,27 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.ImageWname{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ant form item control */
|
||||||
|
#dynamic_form_complex div .ant-form-item-control{
|
||||||
|
transform:translatex(0px) translatey(0px);
|
||||||
|
min-width:93%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ant form item row */
|
||||||
|
#dynamic_form_complex div .ant-form-item-row{
|
||||||
|
transform:translatex(0px) translatey(0px);
|
||||||
|
overflow:hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ant space item */
|
||||||
|
#dynamic_form_complex div .ant-space-item{
|
||||||
|
min-width:47%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -17,7 +17,7 @@ const KEY = "CATEGORIES"
|
||||||
|
|
||||||
|
|
||||||
export const useGetCategories = (params?:any) => useGetQueryPagination(KEY, API.GET_ALL,params);
|
export const useGetCategories = (params?:any) => useGetQueryPagination(KEY, API.GET_ALL,params);
|
||||||
export const useGetOneCategories = (params?:any) => useGetOneQuery(KEY, API.GET_ALL,params);
|
export const useGetOneCategories = () => useGetOneQuery(KEY, API.GET_ALL);
|
||||||
|
|
||||||
export const useAddCategories = () => useAddMutation(KEY, API.ADD);
|
export const useAddCategories = () => useAddMutation(KEY, API.ADD);
|
||||||
export const useUpdateCategories = () => useUpdateMutation(KEY, API.UPDATE);
|
export const useUpdateCategories = () => useUpdateMutation(KEY, API.UPDATE);
|
||||||
|
|
|
||||||
25
src/api/Slider.ts
Normal file
25
src/api/Slider.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
|
||||||
|
import useGetQueryPagination from "./helper/ueGetPagination";
|
||||||
|
import useAddMutation from "./helper/useAddMutation"
|
||||||
|
import useDeleteMutation from "./helper/useDeleteMutation"
|
||||||
|
import useGetOneQuery from "./helper/useGetOneQuery";
|
||||||
|
import useGetQuery from "./helper/useGetQuery"
|
||||||
|
import useUpdateMutation from "./helper/useUpdateMutation";
|
||||||
|
|
||||||
|
const API = {
|
||||||
|
ADD: `slider`,
|
||||||
|
GET_ALL: `slider`,
|
||||||
|
DELETE: `slider`,
|
||||||
|
UPDATE: `slider`,
|
||||||
|
|
||||||
|
};
|
||||||
|
const KEY = "SLIDER"
|
||||||
|
|
||||||
|
|
||||||
|
export const useGetSlider = (params?:any) => useGetQueryPagination(KEY, API.GET_ALL,params);
|
||||||
|
export const useGetOneSlider = (params?:any) => useGetOneQuery(KEY, API.GET_ALL,params);
|
||||||
|
|
||||||
|
export const useAddSlider = () => useAddMutation(KEY, API.ADD);
|
||||||
|
export const useUpdateSlider = () => useUpdateMutation(KEY, API.UPDATE);
|
||||||
|
|
||||||
|
export const useDeleteSlider = () =>useDeleteMutation(KEY, API.DELETE);
|
||||||
|
|
@ -5,7 +5,7 @@ import useAddMutation from "./helper/useAddMutation";
|
||||||
|
|
||||||
const KEY = "AUTH"
|
const KEY = "AUTH"
|
||||||
const API = {
|
const API = {
|
||||||
LOGIN: `/api/admin/login`,
|
LOGIN: `admin/login`,
|
||||||
LOGOUT: `/api/admin/logout`,
|
LOGOUT: `/api/admin/logout`,
|
||||||
};
|
};
|
||||||
export const useLoginAdmin = ()=>useAddMutation(KEY , API.LOGIN)
|
export const useLoginAdmin = ()=>useAddMutation(KEY , API.LOGIN)
|
||||||
|
|
@ -1,12 +1,16 @@
|
||||||
import { useQuery } from 'react-query';
|
import { useQuery } from 'react-query';
|
||||||
import useAxios from './useAxios';
|
import useAxios from './useAxios';
|
||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation, useNavigate } from 'react-router-dom';
|
||||||
|
import useAuthState from '../../lib/state mangment/AuthState';
|
||||||
|
|
||||||
export default function useGetQueryPagination(KEY:string , Api: string , params:any={},options:any={}) {
|
export default function useGetQueryPagination(KEY:string , Api: string , params:any={},options:any={}) {
|
||||||
const axios = useAxios();
|
const axios = useAxios();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const pagination = location?.search || '';
|
const pagination = location?.search || '';
|
||||||
// console.log(params);
|
// console.log(params);
|
||||||
|
const {logout} = useAuthState()
|
||||||
|
const language = localStorage.getItem("language") ?? "en"
|
||||||
|
const navigate = useNavigate()
|
||||||
|
|
||||||
return useQuery(
|
return useQuery(
|
||||||
[KEY, pagination], async () => {
|
[KEY, pagination], async () => {
|
||||||
|
|
@ -14,14 +18,19 @@ export default function useGetQueryPagination(KEY:string , Api: string , params
|
||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...options
|
onError: (error:any) => {
|
||||||
|
if(error.response.status == 401 || error.response.status == 403){
|
||||||
|
logout()
|
||||||
|
navigate("/auth")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
refetchOnWindowFocus: false,
|
||||||
|
|
||||||
|
...options
|
||||||
|
|
||||||
}
|
}
|
||||||
// {
|
|
||||||
// onError: (error) => {
|
|
||||||
// console.error('An error occurred:', error);
|
|
||||||
// },
|
|
||||||
// refetchOnWindowFocus: false,
|
|
||||||
// }
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,7 @@ function useAxios() {
|
||||||
|
|
||||||
if(isAuthenticated){
|
if(isAuthenticated){
|
||||||
|
|
||||||
buildAxios.withHeaders({ Authorization: 'Bearer '+
|
buildAxios.withHeaders({ Authorization: 'Bearer '+ token })
|
||||||
"31|wDE4pbzJitVVrHhYlBnRIQjIJpkDfwOjqM8Yhbmdb0a4e257"
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,20 @@
|
||||||
import { useQuery } from 'react-query';
|
import { useQuery } from 'react-query';
|
||||||
import useAxios from './useAxios';
|
import useAxios from './useAxios';
|
||||||
import useAuthState from '../../lib/state mangment/AuthState';
|
import useAuthState from '../../lib/state mangment/AuthState';
|
||||||
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
|
|
||||||
function useGetOneQuery(key: string, url: string , params:any={},options:any={}) {
|
function useGetOneQuery(key: string, url: string , params:any={},options:any={}) {
|
||||||
const axios = useAxios();
|
const axios = useAxios();
|
||||||
const {logout} = useAuthState()
|
const {logout} = useAuthState()
|
||||||
const language = localStorage.getItem("language") ?? "en"
|
const language = localStorage.getItem("language") ?? "en"
|
||||||
|
const navigate = useNavigate()
|
||||||
|
const {id} = useParams()
|
||||||
|
|
||||||
return useQuery(
|
return useQuery(
|
||||||
params ? [key, params] : key,
|
[id, key],
|
||||||
async () => {
|
async () => {
|
||||||
const response = await axios.get(url+"/"+ params?.id+`?lang=${language}`);
|
const response = await axios.get(url+"/"+ id+`?lang=${language}`);
|
||||||
return response.data.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -18,6 +22,7 @@ function useGetOneQuery(key: string, url: string , params:any={},options:any={})
|
||||||
onError: (error:any) => {
|
onError: (error:any) => {
|
||||||
if(error.response.status == 401 || error.response.status == 403){
|
if(error.response.status == 401 || error.response.status == 403){
|
||||||
logout()
|
logout()
|
||||||
|
navigate("/auth")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
import { useQuery } from 'react-query';
|
import { useQuery } from 'react-query';
|
||||||
import useAxios from './useAxios';
|
import useAxios from './useAxios';
|
||||||
import useAuthState from '../../lib/state mangment/AuthState';
|
import useAuthState from '../../lib/state mangment/AuthState';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
function useGetQuery(key: string, url: string , params:any={},options:any={}) {
|
function useGetQuery(key: string, url: string , params:any={},options:any={}) {
|
||||||
const axios = useAxios();
|
const axios = useAxios();
|
||||||
const {logout} = useAuthState()
|
const {logout} = useAuthState()
|
||||||
|
const navigate = useNavigate()
|
||||||
return useQuery(
|
return useQuery(
|
||||||
params ? [key, params] : key,
|
params ? [key, params] : key,
|
||||||
async () => {
|
async () => {
|
||||||
|
|
@ -15,8 +17,13 @@ function useGetQuery(key: string, url: string , params:any={},options:any={}) {
|
||||||
|
|
||||||
{
|
{
|
||||||
onError: (error:any) => {
|
onError: (error:any) => {
|
||||||
|
console.log('====================================');
|
||||||
|
console.log(error.response.status);
|
||||||
|
console.log('====================================');
|
||||||
if(error.response.status == 401 || error.response.status == 403){
|
if(error.response.status == 401 || error.response.status == 403){
|
||||||
logout()
|
logout()
|
||||||
|
navigate("/auth")
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { useQueryClient, useMutation, UseMutationResult } from "react-query";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import useAxios from "./useAxios";
|
import useAxios from "./useAxios";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
|
||||||
type AxiosResponse = {
|
type AxiosResponse = {
|
||||||
message: string;
|
message: string;
|
||||||
|
|
@ -16,10 +17,11 @@ const useUpdateMutation = (
|
||||||
const axios = useAxios();
|
const axios = useAxios();
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
const {id}= useParams()
|
||||||
|
|
||||||
return useMutation<AxiosResponse, unknown, unknown>(
|
return useMutation<AxiosResponse, unknown, unknown>(
|
||||||
async (dataToSend) => {
|
async (dataToSend) => {
|
||||||
const { data } = await axios.post(url, dataToSend);
|
const { data } = await axios.post(url+"/"+id, dataToSend);
|
||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
32
src/api/order.ts
Normal file
32
src/api/order.ts
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
|
||||||
|
import useGetQueryPagination from "./helper/ueGetPagination";
|
||||||
|
import useAddMutation from "./helper/useAddMutation"
|
||||||
|
import useDeleteMutation from "./helper/useDeleteMutation"
|
||||||
|
import useGetOneQuery from "./helper/useGetOneQuery";
|
||||||
|
import useGetQuery from "./helper/useGetQuery"
|
||||||
|
import useUpdateMutation from "./helper/useUpdateMutation";
|
||||||
|
|
||||||
|
const API = {
|
||||||
|
ADD: `order`,
|
||||||
|
GET_ALL: `order`,
|
||||||
|
DELETE: `order`,
|
||||||
|
UPDATE: `order`,
|
||||||
|
|
||||||
|
};
|
||||||
|
const KEY = "Order"
|
||||||
|
|
||||||
|
|
||||||
|
export const useGetOrder = (params?:any) => useGetQueryPagination(KEY, API.GET_ALL,params);
|
||||||
|
export const useGetOneOrder = (params?:any) => useGetOneQuery(KEY, API.GET_ALL,params);
|
||||||
|
|
||||||
|
export const useAddOrder = () => useAddMutation(KEY, API.ADD);
|
||||||
|
export const useUpdateOrder = () => useUpdateMutation(KEY, API.UPDATE);
|
||||||
|
|
||||||
|
export const useDeleteOrder = () =>useDeleteMutation(KEY, API.DELETE);
|
||||||
|
|
||||||
|
|
||||||
|
export const useAcceptOrder = ()=> useAddMutation(KEY, API.ADD)
|
||||||
|
export const useCancelOrder = ()=> useAddMutation(KEY, API.ADD)
|
||||||
|
export const useDeliverOrder = ()=> useAddMutation(KEY, API.ADD)
|
||||||
|
export const useDeliveredOrder = ()=> useAddMutation(KEY, API.ADD)
|
||||||
|
|
||||||
26
src/api/product.ts
Normal file
26
src/api/product.ts
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
import useGetQueryPagination from "./helper/ueGetPagination";
|
||||||
|
import useAddMutation from "./helper/useAddMutation"
|
||||||
|
import useDeleteMutation from "./helper/useDeleteMutation"
|
||||||
|
import useGetOneQuery from "./helper/useGetOneQuery";
|
||||||
|
import useGetQuery from "./helper/useGetQuery"
|
||||||
|
import useUpdateMutation from "./helper/useUpdateMutation";
|
||||||
|
|
||||||
|
const API = {
|
||||||
|
ADD: `product`,
|
||||||
|
GET_ALL: `product`,
|
||||||
|
DELETE: `product`,
|
||||||
|
UPDATE: `product`,
|
||||||
|
|
||||||
|
};
|
||||||
|
const KEY = "Product"
|
||||||
|
|
||||||
|
|
||||||
|
export const useGetProduct = (params?:any) => useGetQueryPagination(KEY, API.GET_ALL,params);
|
||||||
|
export const useGetOneProduct = (params?:any) => useGetOneQuery(KEY, API.GET_ALL,params);
|
||||||
|
|
||||||
|
export const useAddProduct = () => useAddMutation(KEY, API.ADD);
|
||||||
|
export const useUpdateProduct = () => useUpdateMutation(KEY, API.UPDATE);
|
||||||
|
export const useUpdateProductStatus = () => useUpdateMutation(KEY, API.UPDATE);
|
||||||
|
|
||||||
|
export const useDeleteProduct = () =>useDeleteMutation(KEY, API.DELETE);
|
||||||
25
src/api/users.ts
Normal file
25
src/api/users.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
|
||||||
|
import useGetQueryPagination from "./helper/ueGetPagination";
|
||||||
|
import useAddMutation from "./helper/useAddMutation"
|
||||||
|
import useDeleteMutation from "./helper/useDeleteMutation"
|
||||||
|
import useGetOneQuery from "./helper/useGetOneQuery";
|
||||||
|
import useGetQuery from "./helper/useGetQuery"
|
||||||
|
import useUpdateMutation from "./helper/useUpdateMutation";
|
||||||
|
|
||||||
|
const API = {
|
||||||
|
ADD: `user`,
|
||||||
|
GET_ALL: `user`,
|
||||||
|
DELETE: `user`,
|
||||||
|
UPDATE: `user`,
|
||||||
|
|
||||||
|
};
|
||||||
|
const KEY = "User"
|
||||||
|
|
||||||
|
|
||||||
|
export const useGetUsers = (params?:any) => useGetQueryPagination(KEY, API.GET_ALL,params);
|
||||||
|
export const useGetOneUser = (params?:any) => useGetOneQuery(KEY, API.GET_ALL,params);
|
||||||
|
|
||||||
|
export const useAddUsers = () => useAddMutation(KEY, API.ADD);
|
||||||
|
export const useUpdateUsers = () => useUpdateMutation(KEY, API.UPDATE);
|
||||||
|
|
||||||
|
export const useDeleteUsers = () =>useDeleteMutation(KEY, API.DELETE);
|
||||||
|
|
@ -1,15 +1,14 @@
|
||||||
import create from 'zustand';
|
import create from 'zustand';
|
||||||
import { TOKEN_KEY, TOKEN_KEY_SOCKET, USER_KEY } from '../../config/AppKey';
|
import { TOKEN_KEY, TOKEN_KEY_SOCKET, USER_KEY } from '../../config/AppKey';
|
||||||
import { IUser } from '../../types/User';
|
|
||||||
|
|
||||||
interface LoginResponse {
|
interface LoginResponse {
|
||||||
token:string ,
|
token:string ,
|
||||||
"user": IUser,
|
"admin": any,
|
||||||
token_node:string
|
token_node:string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AuthStore {
|
interface AuthStore {
|
||||||
user: IUser | null |undefined;
|
user: any | null |undefined;
|
||||||
token:string |null | undefined;
|
token:string |null | undefined;
|
||||||
isAuthenticated: boolean;
|
isAuthenticated: boolean;
|
||||||
login: (userData: LoginResponse) => Promise<void>;
|
login: (userData: LoginResponse) => Promise<void>;
|
||||||
|
|
@ -25,16 +24,15 @@ const useAuthState = create<AuthStore>((set) => {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
user: initialUser,
|
user: initialUser,
|
||||||
isAuthenticated: true,
|
isAuthenticated: !!storedToken,
|
||||||
token:storedToken,
|
token:storedToken,
|
||||||
login: async (userData) => {
|
login: async (userData) => {
|
||||||
// console.log(userData);
|
console.log(userData);
|
||||||
localStorage.setItem(TOKEN_KEY , userData.token)
|
localStorage.setItem(TOKEN_KEY , userData.token)
|
||||||
|
|
||||||
localStorage.setItem(TOKEN_KEY_SOCKET , userData.token_node)
|
localStorage.setItem(USER_KEY , JSON.stringify(userData.admin))
|
||||||
localStorage.setItem(USER_KEY , JSON.stringify(userData.user))
|
|
||||||
|
|
||||||
set((state)=>({user:userData.user , isAuthenticated:true , token:userData.token}))
|
set((state)=>({user:userData.admin , isAuthenticated:true , token:userData.token}))
|
||||||
|
|
||||||
},
|
},
|
||||||
logout: async () => {
|
logout: async () => {
|
||||||
|
|
|
||||||
5
src/utils/Date/ChangeFormat.ts
Normal file
5
src/utils/Date/ChangeFormat.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
export function ChangeformatDate(dateString:string) {
|
||||||
|
const dateObject = new Date(dateString);
|
||||||
|
const formattedDate = `${dateObject.toLocaleDateString()} ${dateObject.toLocaleTimeString()}`;
|
||||||
|
return formattedDate;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user