diff --git a/src/Pages/Categories/AddCategoriesModal.tsx b/src/Pages/Categories/AddCategoriesModal.tsx
deleted file mode 100644
index 08cdbe1..0000000
--- a/src/Pages/Categories/AddCategoriesModal.tsx
+++ /dev/null
@@ -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 (
-
-
-
-
- )
-}
-
-export default AddCategoriesModal
-
diff --git a/src/Pages/Categories/EditCategories/Page.tsx b/src/Pages/Categories/EditCategories/Page.tsx
deleted file mode 100644
index c883658..0000000
--- a/src/Pages/Categories/EditCategories/Page.tsx
+++ /dev/null
@@ -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 (
-
- handleSubmit(values)}
- initialValues={getInitialValues(data)}
- validationSchema={getValidationSchema}
- title='Edit Categories'
- >
-
-
-
-
- );
-};
-
-export default EditPage;
diff --git a/src/Pages/Categories/CategoriesPage.tsx b/src/Pages/Categories/Page.tsx
similarity index 52%
rename from src/Pages/Categories/CategoriesPage.tsx
rename to src/Pages/Categories/Page.tsx
index 6d31781..dae9843 100644
--- a/src/Pages/Categories/CategoriesPage.tsx
+++ b/src/Pages/Categories/Page.tsx
@@ -4,37 +4,39 @@ import DashBody from '../../Layout/Dashboard/DashBody'
import DashHeader from '../../Layout/Dashboard/DashHeader'
import LyTable from '../../Layout/Dashboard/LyTable'
import useTableColumns from './useTableColumns'
-import { useGetCategories} from '../../api/Categories'
-
-import { useTranslation } from 'react-i18next'
-import AddCategoriesModal from './AddCategoriesModal'
import { QueryStatusEnum } from '../../config/QueryStatus'
-// import * as XLSX from 'ts-xlsx';
+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'
-function CategoriesPage() {
+function Page() {
const column =useTableColumns()
const {data ,status } = useGetCategories()
- const {t} = useTranslation();
+ console.log(data);
+ const [t] = useTranslation()
+ const navigate = useNavigate()
-
return (
+ // Pass Status to Layout
-
+
+ navigate('/categories/add')}>
-
-
+ />
+
+
)
}
-export default CategoriesPage
+export default Page
diff --git a/src/Pages/Categories/AddForm.tsx b/src/Pages/Categories/View/AddForm.tsx
similarity index 67%
rename from src/Pages/Categories/AddForm.tsx
rename to src/Pages/Categories/View/AddForm.tsx
index 7dc0f6f..a0b2f06 100644
--- a/src/Pages/Categories/AddForm.tsx
+++ b/src/Pages/Categories/View/AddForm.tsx
@@ -1,17 +1,15 @@
import React from 'react'
import { Col, Row } from 'reactstrap';
-import KarimField from '../../Components/Karimalden/KarimField';
-import { FakeSelectData } from '../../Layout/app/Const';
+import KarimField from '../../../Components/Karimalden/KarimField';
import { useFormikContext } from 'formik';
import { DatePicker } from 'antd';
-import { useGetCategories } from '../../api/Categories';
+import { useTranslation } from 'react-i18next';
-function AddForm() {
+function Form() {
const formik = useFormikContext
();
- const {data } = useGetCategories()
-
+ const [t] = useTranslation();
return (
@@ -27,11 +25,12 @@ function AddForm() {
+
)
}
-export default AddForm
+export default Form
diff --git a/src/Pages/Categories/View/AddPage.tsx b/src/Pages/Categories/View/AddPage.tsx
new file mode 100644
index 0000000..ff09d8d
--- /dev/null
+++ b/src/Pages/Categories/View/AddPage.tsx
@@ -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 (
+
+
+
+
+
+
{t("BasicInfo")}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+
+}
+
+export default AddcategoriesPage
\ No newline at end of file
diff --git a/src/Pages/Categories/View/EditForm.tsx b/src/Pages/Categories/View/EditForm.tsx
new file mode 100644
index 0000000..02a973d
--- /dev/null
+++ b/src/Pages/Categories/View/EditForm.tsx
@@ -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();
+ const [t] = useTranslation();
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default Form
+
+
diff --git a/src/Pages/Categories/View/EditPage.tsx b/src/Pages/Categories/View/EditPage.tsx
new file mode 100644
index 0000000..52c1d74
--- /dev/null
+++ b/src/Pages/Categories/View/EditPage.tsx
@@ -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 (
+
+ {objectToEdit && data ?
+
+
+
+
{t("BasicInfo")}
+
+
+
+
+
+
+
+
+
+ :
}
+
+
+
+ )
+
+}
+
+export default EditPage
\ No newline at end of file
diff --git a/src/Pages/Categories/formUtil.ts b/src/Pages/Categories/formUtil.ts
index 7d73b6c..b585f4a 100644
--- a/src/Pages/Categories/formUtil.ts
+++ b/src/Pages/Categories/formUtil.ts
@@ -20,9 +20,10 @@ interface ValidateSchema extends formUtilCommon{
}
export const getInitialValues = (objectToEdit: any | null = null): any => {
+ console.log(objectToEdit,"objectToEdit");
return {
id: objectToEdit?.id ?? 0,
- name: "",
+ name:objectToEdit?.name ?? "",
name_ar: objectToEdit?.name?.ar ?? '',
name_en: objectToEdit?.name?.en ?? '',
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 => {
// Validate input
return Yup.object().shape({
- name : Yup.string().required('Required'),
name_ar: Yup.string().required('Required'),
name_en: Yup.string().required('Required'),
name_de: Yup.string().required('Required'),
@@ -45,6 +45,7 @@ export const getValidationSchema = (editMode: boolean = false): Yup.Schema
};
+
export const getDataToSend = (values: any): FormData => {
const data = { ...values };
diff --git a/src/Pages/Coupon/EditCoupon/EditForm.tsx b/src/Pages/Coupon/EditCoupon/EditForm.tsx
deleted file mode 100644
index 690cbe2..0000000
--- a/src/Pages/Coupon/EditCoupon/EditForm.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import React from 'react'
-import { Col, Row } from "reactstrap";
-import KarimField from '../../../Components/Karimalden/KarimField';
-
-const CreateForm = () => {
-
-
- return (
-
-
-
-
-
-
-
-
-
-
-
- )
-}
-
-export default CreateForm
\ No newline at end of file
diff --git a/src/Pages/Coupon/FormProducts.tsx b/src/Pages/Coupon/FormProducts.tsx
new file mode 100644
index 0000000..22cd08d
--- /dev/null
+++ b/src/Pages/Coupon/FormProducts.tsx
@@ -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();
+ const [t] = useTranslation();
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default FormProduct
+
+
diff --git a/src/Pages/Coupon/ProductsPage.tsx b/src/Pages/Coupon/ProductsPage.tsx
new file mode 100644
index 0000000..29a62f2
--- /dev/null
+++ b/src/Pages/Coupon/ProductsPage.tsx
@@ -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
+
+
+ navigate('/products/add')}>
+
+
+
+
+
+
+ )
+}
+
+export default ProductsPage
+
diff --git a/src/Pages/Coupon/View/AddPage.tsx b/src/Pages/Coupon/View/AddPage.tsx
new file mode 100644
index 0000000..6247fe6
--- /dev/null
+++ b/src/Pages/Coupon/View/AddPage.tsx
@@ -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 (
+
+
+
+
+
+
{t("BasicInfo")}
+
+
{t("BasicInfo2")}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+
+}
+
+export default AddProductPage
\ No newline at end of file
diff --git a/src/Pages/Coupon/View/BasicInfo.tsx b/src/Pages/Coupon/View/BasicInfo.tsx
new file mode 100644
index 0000000..1ba9e67
--- /dev/null
+++ b/src/Pages/Coupon/View/BasicInfo.tsx
@@ -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 (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default BasicInfo
\ No newline at end of file
diff --git a/src/Pages/Coupon/View/BasicInfo2.tsx b/src/Pages/Coupon/View/BasicInfo2.tsx
new file mode 100644
index 0000000..378d320
--- /dev/null
+++ b/src/Pages/Coupon/View/BasicInfo2.tsx
@@ -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 (
+
+
+
+
+
+
+
+
+ {/* */}
+
+
+
+
+
+
+{/*
+
+ */}
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default BasicInfo2
\ No newline at end of file
diff --git a/src/Pages/Coupon/View/Page.tsx b/src/Pages/Coupon/View/Page.tsx
new file mode 100644
index 0000000..6fa9f43
--- /dev/null
+++ b/src/Pages/Coupon/View/Page.tsx
@@ -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 (
+
+ {objectToEdit && data ?
+
+
+
+
{t("BasicInfo")}
+
+
{t("BasicInfo2")}
+
+
+
+
+
+
+
+
+
+
+
+
+ :
}
+
+
+
+ )
+
+}
+
+export default ViewProduct
\ No newline at end of file
diff --git a/src/Pages/Coupon/formUtil.ts b/src/Pages/Coupon/formUtil.ts
index 7d73b6c..fd6fa77 100644
--- a/src/Pages/Coupon/formUtil.ts
+++ b/src/Pages/Coupon/formUtil.ts
@@ -1,65 +1,70 @@
import * as Yup from "yup";
import { buildFormData } from "../../api/helper/buildFormData";
+import { mapTranslatedProperties } from "../../utils/language/mapTranslatedProperties";
-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 => {
+export const getInitialValues = (objectToEdit: any | null = null) => {
+
+ // console.log(objectToEdit);
+
return {
- id: objectToEdit?.id ?? 0,
- name: "",
- name_ar: objectToEdit?.name?.ar ?? '',
- name_en: objectToEdit?.name?.en ?? '',
- name_de: objectToEdit?.name?.de ?? '',
- parent_id: objectToEdit?.parent_id ?? 1,
- photo: objectToEdit?.photo ?? '',
- };
+ product_price:objectToEdit?.product_price??0,
+ product_quantity:objectToEdit?.product_quantity??0,
+ product_main_image:objectToEdit?.product_main_image??'',
+ translated_fields: {
+ 1: {
+ product_name: mapTranslatedProperties(objectToEdit?.product_translations ,'name', 1) ??'',
+ 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): Yup.Schema => {
- // Validate input
+export const getValidationSchema = (editMode: boolean = false) => {
+ // validate input
return Yup.object().shape({
- name : Yup.string().required('Required'),
- name_ar: Yup.string().required('Required'),
- name_en: Yup.string().required('Required'),
- name_de: Yup.string().required('Required'),
- parent_id: Yup.string().required('Required'),
- photo: Yup.string().required('Required'),
+ translated_fields : Yup.object().shape({
+ 1: Yup.object().shape({
+ product_name :Yup.string().required("required"),
+ product_description :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 => {
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;
};
-export const ChangeDataToPrint = (data:any)=>{
-
- let new_array = data
- for(let i =0 ; i {
const [t] = useTranslation();
- const deleteMutation = useDeleteCoupon()
- const navigate = useNavigate()
+ 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 (
+
+ )
+ }
+ },
{
name: t("name"),
sortable: false,
- center: "true",
- cell: (row:any) => row?.name
+ center: true,
+ selector:(row:any) => row?.name,
+
},
{
- name: t("image"),
+ name: t("price"),
sortable: false,
- center: "true",
- cell: (row:any) =>
+ center: true,
+ selector:(row:any) => row?.price,
+
},
{
- name: t("parent_id"),
+ name: t("description"),
sortable: false,
- center: "true",
- cell: (row:any) => row?.parent_id
+ center: true,
+ cell: (row:any) => (
+ row?.description
+ ),
},
+
{
- name: t("product_count"),
+ name: t("favorite"),
sortable: false,
- center: "true",
- cell: (row:any) => row?.product_count
+ center: true,
+ cell: (row:any) => (
+
+ ),
},
{
name: "#",
sortable: false,
- center: true,
+ center: "true",
cell: (row:any) => (
- navigate(`/Coupon/${row.id}`) }
- showView={false}
- onDelete={() => deleteMutation.mutate({ id: row.id })}
- />
+ navigate('/products/'+row.id)}
+ objectToEdit={row}
+ showEdit={true}
+ showView={false}
+ onDelete={() => deleteMutation.mutate({ product_id: row.id })}
+ />
),
},
- // {
- // name: t("status"),
- // sortable: false,
- // center: "true",
- // cell: (row:any) => {
-
- // return(
- //
- // {
- // !row.deleted_at ? t('available') : t('unavailable')
-
- // }
- //
- // )
- // }
- // },
-
],
[t]
);
diff --git a/src/Pages/Coupon/AddCouponModal.tsx b/src/Pages/Coupon2/AddCouponModal.tsx
similarity index 100%
rename from src/Pages/Coupon/AddCouponModal.tsx
rename to src/Pages/Coupon2/AddCouponModal.tsx
diff --git a/src/Pages/Coupon/AddForm.tsx b/src/Pages/Coupon2/AddForm.tsx
similarity index 89%
rename from src/Pages/Coupon/AddForm.tsx
rename to src/Pages/Coupon2/AddForm.tsx
index 2d4036d..2556b20 100644
--- a/src/Pages/Coupon/AddForm.tsx
+++ b/src/Pages/Coupon2/AddForm.tsx
@@ -6,11 +6,11 @@ import { FakeSelectData } from '../../Layout/app/Const';
import { useFormikContext } from 'formik';
import { DatePicker } from 'antd';
-import { useGetCoupon } from '../../api/Coupon';
+import { useGetSlider } from '../../api/Slider';
function AddForm() {
const formik = useFormikContext();
- const {data } = useGetCoupon()
+ const {data } = useGetSlider()
return (
diff --git a/src/Pages/Coupon/CouponPage.tsx b/src/Pages/Coupon2/CouponPage.tsx
similarity index 97%
rename from src/Pages/Coupon/CouponPage.tsx
rename to src/Pages/Coupon2/CouponPage.tsx
index 45a0235..cffad89 100644
--- a/src/Pages/Coupon/CouponPage.tsx
+++ b/src/Pages/Coupon2/CouponPage.tsx
@@ -24,7 +24,7 @@ function CouponPage() {
{
handleSubmit(values)}
- initialValues={getInitialValues(data)}
+ initialValues={getInitialValues(data?.coupons)}
validationSchema={getValidationSchema}
title='Edit Coupon'
>
diff --git a/src/Pages/Coupon2/formUtil.ts b/src/Pages/Coupon2/formUtil.ts
new file mode 100644
index 0000000..1c5bf86
--- /dev/null
+++ b/src/Pages/Coupon2/formUtil.ts
@@ -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 => {
+ // 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 {
+ 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
+
+ }
+ },
+ {
+ 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) => (
+ navigate(`/Coupon/${row.id}`) }
+ showView={false}
+ onDelete={() => deleteMutation.mutate({ id: row.id })}
+ />
+ ),
+ },
+ // {
+ // name: t("status"),
+ // sortable: false,
+ // center: "true",
+ // cell: (row:any) => {
+
+ // return(
+ //
+ // {
+ // !row.deleted_at ? t('available') : t('unavailable')
+
+ // }
+ //
+ // )
+ // }
+ // },
+
+ ],
+ [t]
+ );
+};
+
+export default useTableColumns;
+
diff --git a/src/Pages/Products/ProductsPage.tsx b/src/Pages/Products/ProductsPage.tsx
new file mode 100644
index 0000000..b615214
--- /dev/null
+++ b/src/Pages/Products/ProductsPage.tsx
@@ -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
+
+
+ navigate('/products/add')}>
+
+
+
+
+
+
+ )
+}
+
+export default ProductsPage
+
diff --git a/src/Pages/Products/View/AddPage.tsx b/src/Pages/Products/View/AddPage.tsx
new file mode 100644
index 0000000..e409562
--- /dev/null
+++ b/src/Pages/Products/View/AddPage.tsx
@@ -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 (
+
+
+
+
+
+
{t("Base_info")} {IsValed ? : "" }
+
+
{t("VarianInfo")}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+
+}
+
+export default AddProductPage
\ No newline at end of file
diff --git a/src/Pages/Products/View/BasicInfo.tsx b/src/Pages/Products/View/BasicInfo.tsx
new file mode 100644
index 0000000..83f4035
--- /dev/null
+++ b/src/Pages/Products/View/BasicInfo.tsx
@@ -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 (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default BasicInfo
\ No newline at end of file
diff --git a/src/Pages/Products/View/BasicInfo2.tsx b/src/Pages/Products/View/BasicInfo2.tsx
new file mode 100644
index 0000000..30b91f9
--- /dev/null
+++ b/src/Pages/Products/View/BasicInfo2.tsx
@@ -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 (
+
+
+ {/* */}
+
+
+
+ {/* */}
+ {/* */}
+ {/* */}
+
+
+
+
+
+ )
+}
+
+export default BasicInfo2
\ No newline at end of file
diff --git a/src/Pages/Products/View/ObjectField.tsx b/src/Pages/Products/View/ObjectField.tsx
new file mode 100644
index 0000000..01b8b4a
--- /dev/null
+++ b/src/Pages/Products/View/ObjectField.tsx
@@ -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();
+ const [FieldItems, setFieldItems] = useState([])
+ const handleChange = (e: React.ChangeEvent) => {
+ const { name, value } = e.target;
+ setFieldItems((prevState:any) => ({
+ ...prevState,
+ [name]: value
+ }));
+ formik.setFieldValue("info", FieldItems)
+
+ };
+
+ useEffect(() => {
+ form.setFieldsValue({
+ items: [{ list: [{ Attribute: '', Description: '' }] }]
+ });
+
+ }, []);
+
+ return (
+
+ {(fields, { add, remove }) => (
+
+ {fields.map((field, index) => (
+
+ ))}
+
+ )}
+
+
+ );
+};
+
+export default ObjectField;
diff --git a/src/Pages/Products/View/Page.tsx b/src/Pages/Products/View/Page.tsx
new file mode 100644
index 0000000..95d9b89
--- /dev/null
+++ b/src/Pages/Products/View/Page.tsx
@@ -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 (
+
+ {objectToEdit && data ?
+
+
+
+
{t("Base_info")}
+
+
{t("VarianInfo")}
+
+
+
+
+
+
+
+
+
+
+
+
+ :
}
+
+
+
+ )
+
+}
+
+export default ViewProduct
\ No newline at end of file
diff --git a/src/Pages/Products/View/VarianInfo.tsx b/src/Pages/Products/View/VarianInfo.tsx
new file mode 100644
index 0000000..a26110d
--- /dev/null
+++ b/src/Pages/Products/View/VarianInfo.tsx
@@ -0,0 +1,13 @@
+import React, { useState } from 'react'
+import ResposiveTabs from './taps/ResposiveTabs'
+
+const VarianInfo = () => {
+
+ return (
+
+
+
+ )
+}
+
+export default VarianInfo
\ No newline at end of file
diff --git a/src/Pages/Products/View/taps/NewTabs.tsx b/src/Pages/Products/View/taps/NewTabs.tsx
new file mode 100644
index 0000000..548973c
--- /dev/null
+++ b/src/Pages/Products/View/taps/NewTabs.tsx
@@ -0,0 +1,14 @@
+import React from 'react'
+
+const NewTabs = () => {
+ function handelClick(){
+
+ }
+ return (
+
+
+
+ )
+}
+
+export default NewTabs
\ No newline at end of file
diff --git a/src/Pages/Products/View/taps/ResposiveTabs.tsx b/src/Pages/Products/View/taps/ResposiveTabs.tsx
new file mode 100644
index 0000000..e1f87f5
--- /dev/null
+++ b/src/Pages/Products/View/taps/ResposiveTabs.tsx
@@ -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 (
+
+ {items.map((item) => (
+
+ {item.label}
+ duplicate(item.key)} />
+
+ }
+ closable={item.closable}
+ >
+ handleInputChange(item.key, values)}
+ />
+
+ ))}
+
+ );
+};
+
+interface VariableTabsProps {
+ value: string[];
+ onChange: (value: string[]) => void;
+}
+
+const VariableTabs: React.FC = ({ value, onChange }) => {
+ const handleInputChange = (index: number) => (e: React.ChangeEvent) => {
+ const newValues = [...value];
+ newValues[index] = e.target.value;
+ onChange(newValues);
+ };
+ const [t] = useTranslation()
+
+ return (
+
+
+
+
+
+
+
+
+ );
+};
+
+export default App;
diff --git a/src/Pages/Products/View/varianForm.tsx b/src/Pages/Products/View/varianForm.tsx
new file mode 100644
index 0000000..5505375
--- /dev/null
+++ b/src/Pages/Products/View/varianForm.tsx
@@ -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 (
+
+
+
+
+
+
+ {/* */}
+ {/* */}
+
+
+
+
+
+ )
+}
+
+export default varianForm
\ No newline at end of file
diff --git a/src/Pages/Products/formUtil.ts b/src/Pages/Products/formUtil.ts
new file mode 100644
index 0000000..f0d0889
--- /dev/null
+++ b/src/Pages/Products/formUtil.ts
@@ -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;
+};
+
diff --git a/src/Pages/Products/useTableColumns.tsx b/src/Pages/Products/useTableColumns.tsx
new file mode 100644
index 0000000..c827704
--- /dev/null
+++ b/src/Pages/Products/useTableColumns.tsx
@@ -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 (
+
+ )
+ }
+ },
+ {
+ 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) => (
+
+ ),
+ },
+ {
+ name: "#",
+ sortable: false,
+ center: "true",
+ cell: (row:any) => (
+ navigate('/products/'+row.id)}
+ objectToEdit={row}
+ showEdit={true}
+ showView={false}
+ onDelete={() => deleteMutation.mutate({ product_id: row.id })}
+ />
+ ),
+ },
+ ],
+ [t]
+ );
+};
+
+export default useTableColumns;
+
diff --git a/src/Pages/order/OrderPage.tsx b/src/Pages/order/OrderPage.tsx
new file mode 100644
index 0000000..1a4d5ad
--- /dev/null
+++ b/src/Pages/order/OrderPage.tsx
@@ -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 (
+ <>
+
+
+ {/* */}
+
+
+
+
+ >
+ );
+};
+
+export default OrderPage;
diff --git a/src/Pages/order/Select.js b/src/Pages/order/Select.js
new file mode 100644
index 0000000..0071fb7
--- /dev/null
+++ b/src/Pages/order/Select.js
@@ -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 (
+
+
+ {t(localStorage.getItem('order_status') || 'all')}
+
+ {
+ setRefreshPage(v => !v)
+ setSelectType('status')
+ localStorage.setItem('order_status','')
+ }} style={{width:"100%", }}>{t('all')}
+ {
+ setRefreshPage(v => !v)
+ setSelectType('complete')
+ localStorage.setItem('order_status','complete')
+ }} style={{color:"black", width:"100%"}}>{t('complete')}
+ {
+ setRefreshPage(v => !v)
+ setSelectType('canceled')
+ localStorage.setItem('order_status','canceled')
+ }} style={{color:"black", width:"100%"}}>{t('canceled')}
+
+
+
+
+ );
+}
+
+SelectType.propTypes = {
+ direction: PropTypes.string,
+};
+
+export default SelectType;
diff --git a/src/Pages/order/form/formUtils.js b/src/Pages/order/form/formUtils.js
new file mode 100644
index 0000000..2df2197
--- /dev/null
+++ b/src/Pages/order/form/formUtils.js
@@ -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 ;
+}
\ No newline at end of file
diff --git a/src/Pages/order/useTableColumns.tsx b/src/Pages/order/useTableColumns.tsx
new file mode 100644
index 0000000..44eceff
--- /dev/null
+++ b/src/Pages/order/useTableColumns.tsx
@@ -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(
+
+
+ )
+ }
+ },
+
+ {
+ 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
+
+ }
+ },
+ {
+ 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) =>
+
+
+ deleteMutation.mutate({order_id:row.id })}
+ showEdit={false}
+ onView={()=>navigate(`/order/${row?.id}` , {replace:true})}
+ />
+
+
+
+
+ },
+
+
+
+
+ ]
+
+
+
+
+
+ return column
+
+};
+
+export default useTableColumns;
diff --git a/src/Pages/order/view-one/Order.js b/src/Pages/order/view-one/Order.js
new file mode 100644
index 0000000..959523b
--- /dev/null
+++ b/src/Pages/order/view-one/Order.js
@@ -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 ()
+ }
+
+ return (
+
+
+
+
+ {t("order_id")} : {order?.id}
+
+
+
+
+
+
+
+
+
+ {/* */}
+
+
+
+
+ {("no_records")}}
+ // noHeader
+
+ />
+
+
+
+
+
+
+ )
+}
diff --git a/src/Pages/order/view-one/OrderForm.js b/src/Pages/order/view-one/OrderForm.js
new file mode 100644
index 0000000..b022f1c
--- /dev/null
+++ b/src/Pages/order/view-one/OrderForm.js
@@ -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 (
+ <>
+
+
+ {t("customer_name")}{" : "}{order.user?.name}
+ {t("customer_phone_number")}{" : "}{order.user?.phone}
+ {t("order_created_at")}{" : "}{ChangeformatDate(order.created_at)}
+
+
+ {t("address")}{" : "}{order?.form?.address}
+ {t("country")}{" : "}{order?.form?.country}
+ {t("note")}{" : "}{order?.form?.note}
+
+
+
+
+
+
+
+
+
+
{t("totals")}
+
{t("sub_total")}{" : "}{order?.total}
+
{t("delivery_fee")}{" : "}{0}
+
{t("overall_total")}{" : "}{order?.total}
+
+
+
+ >
+ )
+}
diff --git a/src/Pages/order/view-one/OrderForm.module.scss b/src/Pages/order/view-one/OrderForm.module.scss
new file mode 100644
index 0000000..4e64eee
--- /dev/null
+++ b/src/Pages/order/view-one/OrderForm.module.scss
@@ -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;
+}
diff --git a/src/Pages/order/view-one/OrderStatus.js b/src/Pages/order/view-one/OrderStatus.js
new file mode 100644
index 0000000..0a90a8f
--- /dev/null
+++ b/src/Pages/order/view-one/OrderStatus.js
@@ -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 (
+
+ {t(order_status)}
+
+ );
+};
+
+OrderStatus.propTypes = {
+ order_status: PropTypes.string.isRequired,
+};
+
+export default OrderStatus;
diff --git a/src/Pages/order/view-one/StatusOrderController.js b/src/Pages/order/view-one/StatusOrderController.js
new file mode 100644
index 0000000..e2330bd
--- /dev/null
+++ b/src/Pages/order/view-one/StatusOrderController.js
@@ -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 (
+
+
+
{t("order_status")}{" : "}{}
+ {
+ controll[order_status].nextMutation && controll[order_status].nextLabel &&
controll[order_status].nextMutation.mutate({ order_id: order_id })}
+ >
+ {t(controll[order_status].nextLabel)}
+
+ }
+
+ {
+ controll[order_status].prevMutation && controll[order_status].prevLabel &&
controll[order_status].prevMutation.mutate({ order_id: order_id })}
+ >
+ {t(controll[order_status].prevLabel)}
+
+ }
+
+
+
+ )
+}
diff --git a/src/Pages/order/view-one/index.css b/src/Pages/order/view-one/index.css
new file mode 100644
index 0000000..cee3e2d
--- /dev/null
+++ b/src/Pages/order/view-one/index.css
@@ -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;
+
+ }
+ }
\ No newline at end of file
diff --git a/src/Pages/order/view-one/useTableColumns.js b/src/Pages/order/view-one/useTableColumns.js
new file mode 100644
index 0000000..73b00fc
--- /dev/null
+++ b/src/Pages/order/view-one/useTableColumns.js
@@ -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 (
+
+ );
+ },
+ },
+
+
+ {
+ name: t("quantity"),
+ sortable: true,
+ center: true,
+ cell:(row)=>row?.quantity
+
+ },
+
+ {
+ name: t("price"),
+ sortable: true,
+ center: true,
+ cell:(row)=>row?.price
+
+
+ },
+
+
+ ]
+}
diff --git a/src/Routes.tsx b/src/Routes.tsx
index 0bc9583..6b9424e 100644
--- a/src/Routes.tsx
+++ b/src/Routes.tsx
@@ -1,18 +1,26 @@
import { ReactNode, lazy } from "react";
// Icons Import
+import { FaCartArrowDown, FaImages } 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
-import HomePage from "./Pages/Home/HomePage";
-import CategoriesPage from "./Pages/Categories/CategoriesPage";
-import EditCategories from "./Pages/Categories/EditCategories/Page";
-import EditCoupon from "./Pages/Coupon/EditCoupon/Page";
+import AddCategoriesPage from "./Pages/Categories/View/AddPage";
+import EditCategories from "./Pages/Categories/View/EditPage";
+import CategoriesPage from "./Pages/Categories/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 {
@@ -38,18 +46,31 @@ export const RoutesLinks: RoutesLinksType[] = [
{
name: "Categories",
element: ,
- icon: ,
+ icon:
+ ,
href: "/categories",
},
+ // {
+ // name: "Coupon",
+ // element: ,
+ // icon: ,
+ // href: "/Coupon",
+ // },
{
- name: "Coupon",
- element: ,
- icon: ,
- href: "/Coupon",
+ name: "products",
+ element: ,
+ icon: ,
+ href: "/products",
+ },
+
+ {
+ name: "Order",
+ element: ,
+ icon: ,
+ href: "/order",
},
-/////////////// hidden route
{
href: "/categories/:id",
@@ -57,8 +78,33 @@ export const RoutesLinks: RoutesLinksType[] = [
hidden:true
},
{
- href: "/coupon/:id",
- element: ,
+ href: "/categories/add",
+ element: ,
hidden:true
- }
+ },
+
+ {
+ name: "add_products",
+ element: ,
+ // icon: ,
+ href: "/products/add",
+ hidden:true
+ },
+ {
+ name: "edit_products",
+ element: ,
+ // icon: ,
+ href: "/products/:id",
+ hidden:true
+
+ },
+ {
+ name: "view_order",
+ element: ,
+ href: "/order/:id",
+ hidden:true
+
+ },
+
+
]
\ No newline at end of file
diff --git a/src/Styles/AppStyle/App.scss b/src/Styles/AppStyle/App.scss
index e43d661..d9efda0 100644
--- a/src/Styles/AppStyle/App.scss
+++ b/src/Styles/AppStyle/App.scss
@@ -1,6 +1,10 @@
+@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap');
+
+
html,body {
- background: var(--bg2)
-
+ background: var(--bg2);
+ font-family: 'Poppins', sans-serif;
+
}
*{
diff --git a/src/Styles/AppStyle/Varibils.scss b/src/Styles/AppStyle/Varibils.scss
index 3f3cd98..ae6688b 100644
--- a/src/Styles/AppStyle/Varibils.scss
+++ b/src/Styles/AppStyle/Varibils.scss
@@ -1,12 +1,12 @@
:root {
- --primary:#fcb04f ;
- --secondary : #304a7e;
+ --primary:#E57DB1 ;
+ --secondary : #2D9CDB;
--text: #565656;
--bg: #ffffff;
--bg2: #f8f8f8;
--shadow: rgba(0, 0, 0, 0.15);
--gray : rgb(207, 210, 214);
- --linear : linear-gradient(118deg, #fcb04f, #f78c3f)
+ --linear : linear-gradient(118deg, #2D9CDB, #2D9CDB)
}
:root:has(.dark) {
diff --git a/src/Styles/Layout/Layout.scss b/src/Styles/Layout/Layout.scss
index 97f0bdd..f45372a 100644
--- a/src/Styles/Layout/Layout.scss
+++ b/src/Styles/Layout/Layout.scss
@@ -360,4 +360,30 @@ background: var(--bg);
@include Shadow;
background: var(--bg);
border-radius: 20px;
-}
\ No newline at end of file
+}
+.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;
+ }
+
+
+
\ No newline at end of file
diff --git a/src/Styles/Layout/SideBar.scss b/src/Styles/Layout/SideBar.scss
index 41b8807..5202996 100644
--- a/src/Styles/Layout/SideBar.scss
+++ b/src/Styles/Layout/SideBar.scss
@@ -84,7 +84,7 @@ overflow-x: hidden;
background: var(--primary);
color: var(--bg);
border-radius: 5px;
- box-shadow: 2px 2px 7px 0 var(--primary);
+ box-shadow: 2px 2px 7px 0 var(--shadow);
cursor: pointer;
transform: scale(1.01);
@include Shadow;
@@ -149,7 +149,7 @@ overflow-x: hidden;
background: var(--linear);
color: var(--bg);
border-radius: 5px;
- box-shadow: 2px 2px 7px 0 var(--primary);
+ box-shadow: 2px 2px 7px 0 var(--shadow);
svg {
background-color: transparent;
diff --git a/src/Styles/Layout/Table.scss b/src/Styles/Layout/Table.scss
index c27893f..689fd4f 100644
--- a/src/Styles/Layout/Table.scss
+++ b/src/Styles/Layout/Table.scss
@@ -53,4 +53,28 @@
z-index: 999999999 !important;
}
-
\ No newline at end of file
+
+ .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%;
+ }
+
\ No newline at end of file
diff --git a/src/api/Categories.ts b/src/api/Categories.ts
index 1485af0..63183a3 100644
--- a/src/api/Categories.ts
+++ b/src/api/Categories.ts
@@ -17,7 +17,7 @@ const KEY = "CATEGORIES"
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 useUpdateCategories = () => useUpdateMutation(KEY, API.UPDATE);
diff --git a/src/api/Slider.ts b/src/api/Slider.ts
new file mode 100644
index 0000000..c9026cc
--- /dev/null
+++ b/src/api/Slider.ts
@@ -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);
diff --git a/src/api/auth.ts b/src/api/auth.ts
index cde2c19..84804f7 100644
--- a/src/api/auth.ts
+++ b/src/api/auth.ts
@@ -5,7 +5,7 @@ import useAddMutation from "./helper/useAddMutation";
const KEY = "AUTH"
const API = {
- LOGIN: `/api/admin/login`,
+ LOGIN: `admin/login`,
LOGOUT: `/api/admin/logout`,
};
export const useLoginAdmin = ()=>useAddMutation(KEY , API.LOGIN)
\ No newline at end of file
diff --git a/src/api/helper/ueGetPagination.tsx b/src/api/helper/ueGetPagination.tsx
index 7533c1e..723dbf1 100644
--- a/src/api/helper/ueGetPagination.tsx
+++ b/src/api/helper/ueGetPagination.tsx
@@ -1,12 +1,16 @@
import { useQuery } from 'react-query';
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={}) {
const axios = useAxios();
const location = useLocation();
const pagination = location?.search || '';
// console.log(params);
+const {logout} = useAuthState()
+const language = localStorage.getItem("language") ?? "en"
+const navigate = useNavigate()
return useQuery(
[KEY, pagination], async () => {
@@ -14,14 +18,19 @@ export default function useGetQueryPagination(KEY:string , Api: string , params
return response.data;
},
{
+ 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,
- // }
);
}
diff --git a/src/api/helper/useAxios.ts b/src/api/helper/useAxios.ts
index 2b4822d..7cdd7db 100644
--- a/src/api/helper/useAxios.ts
+++ b/src/api/helper/useAxios.ts
@@ -14,9 +14,7 @@ function useAxios() {
if(isAuthenticated){
- buildAxios.withHeaders({ Authorization: 'Bearer '+
- "31|wDE4pbzJitVVrHhYlBnRIQjIJpkDfwOjqM8Yhbmdb0a4e257"
- })
+ buildAxios.withHeaders({ Authorization: 'Bearer '+ token })
}
return (
diff --git a/src/api/helper/useGetOneQuery.ts b/src/api/helper/useGetOneQuery.ts
index 0d290f5..3013249 100644
--- a/src/api/helper/useGetOneQuery.ts
+++ b/src/api/helper/useGetOneQuery.ts
@@ -1,16 +1,20 @@
import { useQuery } from 'react-query';
import useAxios from './useAxios';
import useAuthState from '../../lib/state mangment/AuthState';
+import { useNavigate, useParams } from 'react-router-dom';
function useGetOneQuery(key: string, url: string , params:any={},options:any={}) {
const axios = useAxios();
const {logout} = useAuthState()
const language = localStorage.getItem("language") ?? "en"
+ const navigate = useNavigate()
+ const {id} = useParams()
+
return useQuery(
- params ? [key, params] : key,
+ [id, key],
async () => {
- const response = await axios.get(url+"/"+ params?.id+`?lang=${language}`);
- return response.data.data;
+ const response = await axios.get(url+"/"+ id+`?lang=${language}`);
+ return response.data;
},
@@ -18,6 +22,7 @@ function useGetOneQuery(key: string, url: string , params:any={},options:any={})
onError: (error:any) => {
if(error.response.status == 401 || error.response.status == 403){
logout()
+ navigate("/auth")
}
diff --git a/src/api/helper/useGetQuery.ts b/src/api/helper/useGetQuery.ts
index 16307a8..31ab3a8 100644
--- a/src/api/helper/useGetQuery.ts
+++ b/src/api/helper/useGetQuery.ts
@@ -1,10 +1,12 @@
import { useQuery } from 'react-query';
import useAxios from './useAxios';
import useAuthState from '../../lib/state mangment/AuthState';
+import { useNavigate } from 'react-router-dom';
function useGetQuery(key: string, url: string , params:any={},options:any={}) {
const axios = useAxios();
const {logout} = useAuthState()
+ const navigate = useNavigate()
return useQuery(
params ? [key, params] : key,
async () => {
@@ -15,8 +17,13 @@ function useGetQuery(key: string, url: string , params:any={},options:any={}) {
{
onError: (error:any) => {
+ console.log('====================================');
+ console.log(error.response.status);
+ console.log('====================================');
if(error.response.status == 401 || error.response.status == 403){
logout()
+ navigate("/auth")
+
}
diff --git a/src/api/helper/useUpdateMutation.ts b/src/api/helper/useUpdateMutation.ts
index b1306fc..99ea8d7 100644
--- a/src/api/helper/useUpdateMutation.ts
+++ b/src/api/helper/useUpdateMutation.ts
@@ -2,6 +2,7 @@ import { useQueryClient, useMutation, UseMutationResult } from "react-query";
import { toast } from "react-toastify";
import useAxios from "./useAxios";
import { useTranslation } from "react-i18next";
+import { useParams } from "react-router-dom";
type AxiosResponse = {
message: string;
@@ -16,10 +17,11 @@ const useUpdateMutation = (
const axios = useAxios();
const queryClient = useQueryClient();
const [t] = useTranslation();
+ const {id}= useParams()
return useMutation(
async (dataToSend) => {
- const { data } = await axios.post(url, dataToSend);
+ const { data } = await axios.post(url+"/"+id, dataToSend);
return data;
},
{
diff --git a/src/api/order.ts b/src/api/order.ts
new file mode 100644
index 0000000..7d90415
--- /dev/null
+++ b/src/api/order.ts
@@ -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)
+
diff --git a/src/api/product.ts b/src/api/product.ts
new file mode 100644
index 0000000..f8cf512
--- /dev/null
+++ b/src/api/product.ts
@@ -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);
diff --git a/src/api/users.ts b/src/api/users.ts
new file mode 100644
index 0000000..f72957f
--- /dev/null
+++ b/src/api/users.ts
@@ -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);
diff --git a/src/lib/state mangment/AuthState.ts b/src/lib/state mangment/AuthState.ts
index 4171e44..310a3ee 100644
--- a/src/lib/state mangment/AuthState.ts
+++ b/src/lib/state mangment/AuthState.ts
@@ -1,15 +1,14 @@
import create from 'zustand';
import { TOKEN_KEY, TOKEN_KEY_SOCKET, USER_KEY } from '../../config/AppKey';
-import { IUser } from '../../types/User';
interface LoginResponse {
token:string ,
- "user": IUser,
+ "admin": any,
token_node:string
}
interface AuthStore {
- user: IUser | null |undefined;
+ user: any | null |undefined;
token:string |null | undefined;
isAuthenticated: boolean;
login: (userData: LoginResponse) => Promise;
@@ -25,16 +24,15 @@ const useAuthState = create((set) => {
return {
user: initialUser,
- isAuthenticated: true,
+ isAuthenticated: !!storedToken,
token:storedToken,
login: async (userData) => {
- // console.log(userData);
+ console.log(userData);
localStorage.setItem(TOKEN_KEY , userData.token)
- localStorage.setItem(TOKEN_KEY_SOCKET , userData.token_node)
- localStorage.setItem(USER_KEY , JSON.stringify(userData.user))
+ localStorage.setItem(USER_KEY , JSON.stringify(userData.admin))
- set((state)=>({user:userData.user , isAuthenticated:true , token:userData.token}))
+ set((state)=>({user:userData.admin , isAuthenticated:true , token:userData.token}))
},
logout: async () => {
diff --git a/src/utils/Date/ChangeFormat.ts b/src/utils/Date/ChangeFormat.ts
new file mode 100644
index 0000000..311775f
--- /dev/null
+++ b/src/utils/Date/ChangeFormat.ts
@@ -0,0 +1,5 @@
+export function ChangeformatDate(dateString:string) {
+ const dateObject = new Date(dateString);
+ const formattedDate = `${dateObject.toLocaleDateString()} ${dateObject.toLocaleTimeString()}`;
+ return formattedDate;
+}
\ No newline at end of file