This commit is contained in:
KarimAldeen 2024-02-20 15:58:15 +03:00
parent 848e0b8005
commit 55216f6d88
21 changed files with 439 additions and 54 deletions

View File

@ -7,5 +7,5 @@
```bash ```bash
git clone https://repos.point-dev.net/Karimaldeen/hijabi-dashboard.git git clone https://repos.point-dev.net/Karimaldeen/hijabi-dashboard.git
cd hijabi-dashboard cd hijabi-dashboard
npm install npm install
npm start npm start

View File

@ -69,4 +69,10 @@ input:-webkit-autofill:focus {
/* Remove autofill background color on hover */ /* Remove autofill background color on hover */
input:-webkit-autofill:hover { input:-webkit-autofill:hover {
-webkit-box-shadow: 0 0 0 1000px white inset !important; /* Change the color to your desired background color */ -webkit-box-shadow: 0 0 0 1000px white inset !important; /* Change the color to your desired background color */
} }
.ant-upload-list .ant-upload-list-item{
height:78px !important;
}

View File

@ -41,6 +41,7 @@ const File = ({ name, label, onChange, isDisabled,placholder,className, props }:
customRequest={customRequest} customRequest={customRequest}
className={`${className} w-100`} className={`${className} w-100`}
> >

View File

@ -15,7 +15,7 @@ interface FormPageProps {
children: ReactNode; children: ReactNode;
} }
const FormPage: React.FC<FormPageProps> = ({ children, handleSubmit, initialValues, validationSchema, title = "Add New Item" }) => { const FormPage: React.FC<FormPageProps> = ({ children, handleSubmit, initialValues, validationSchema, title = "Edit Item" }) => {
return ( return (
<> <>
<h4 className='text-bold'>{title}</h4> <h4 className='text-bold'>{title}</h4>

View File

@ -0,0 +1,43 @@
import React from 'react'
import LayoutModal from '../../Layout/Dashboard/LayoutModal'
import AddForm from './AddForm'
import { useAddCoupon } from '../../api/Coupon'
import { getDataToSend, getInitialValues, getValidationSchema } from './formUtil'
import { QueryStatusEnum } from '../../config/QueryStatus'
import { useTranslation } from 'react-i18next'
function AddCouponModal() {
const [t] = useTranslation()
const {mutate , status} = useAddCoupon()
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('Coupon')}
getValidationSchema={getValidationSchema()}>
<AddForm />
</LayoutModal>
)
}
export default AddCouponModal

View File

@ -6,19 +6,25 @@ 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';
function FormCoupon() { function AddForm() {
const formik = useFormikContext<any>(); const formik = useFormikContext<any>();
const {data } = useGetCoupon()
return ( return (
<Row xs={1} sm={1} md={1} lg={2} xl={2}> <Row xs={1} sm={1} md={1} lg={2} xl={2}>
<Col> <Col>
<KarimField name="number" type="number"label='number' placeholder='placeholder' /> <KarimField name="name_ar" />
<KarimField name="name_en" />
<KarimField name="name_de" />
</Col> </Col>
<Col> <Col>
<KarimField name="value" type="number" label='value' placeholder='placeholder' /> <KarimField name="parent_id" type="Select" option={[]} />
<KarimField name="photo" type="File" />
</Col> </Col>
@ -26,6 +32,6 @@ function FormCoupon() {
) )
} }
export default FormCoupon export default AddForm

View 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 { useGetCoupon} from '../../api/Coupon'
import { useTranslation } from 'react-i18next'
import AddCouponModal from './AddCouponModal'
import { QueryStatusEnum } from '../../config/QueryStatus'
// import * as XLSX from 'ts-xlsx';
function CouponPage() {
const column =useTableColumns()
const {data ,status } = useGetCoupon()
const {t} = useTranslation();
return (
<DashBody status={status as QueryStatusEnum} >
<DashHeader title={'Coupon'}>
</DashHeader>
<LyTable
data={data?.Coupon}
isLoading={false}
columns={column}
// is_pagination={true}
// total={data?.meta?.total}
/>
<AddCouponModal />
</DashBody>
)
}
export default CouponPage

View File

@ -0,0 +1,23 @@
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

View File

@ -0,0 +1,41 @@
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 { useAddCoupon, useGetOneCoupon } from '../../../api/Coupon';
const EditPage = () => {
const { id } = useParams()
const { data,isLoading } = useGetOneCoupon({id})
const {mutate} = useAddCoupon()
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 Coupon'
>
<EditForm />
</FormPage>
</KarimSpinner>
);
};
export default EditPage;

View File

@ -0,0 +1,65 @@
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: "",
name_ar: objectToEdit?.name?.ar ?? '',
name_en: objectToEdit?.name?.en ?? '',
name_de: objectToEdit?.name?.de ?? '',
parent_id: objectToEdit?.parent_id ?? 1,
photo: objectToEdit?.photo ?? '',
};
};
export const getValidationSchema = (editMode: boolean = false): Yup.Schema<any> => {
// 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'),
});
};
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
}

View File

@ -0,0 +1,86 @@
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";
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("image"),
sortable: false,
center: "true",
cell: (row:any) => <ColumnsImage src={row?.photo} />
},
{
name: t("parent_id"),
sortable: false,
center: "true",
cell: (row:any) => row?.parent_id
},
{
name: t("product_count"),
sortable: false,
center: "true",
cell: (row:any) => row?.product_count
},
{
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;

View File

@ -2,7 +2,7 @@
import React from 'react' import React from 'react'
import LayoutModal from '../../Layout/Dashboard/LayoutModal' import LayoutModal from '../../Layout/Dashboard/LayoutModal'
import FormCategories from './FormCoupon' import AddForm from './AddForm'
import { useAddCategories } from '../../api/Categories' import { useAddCategories } from '../../api/Categories'
import { getDataToSend, getInitialValues, getValidationSchema } from './formUtil' import { getDataToSend, getInitialValues, getValidationSchema } from './formUtil'
import { QueryStatusEnum } from '../../config/QueryStatus' import { QueryStatusEnum } from '../../config/QueryStatus'
@ -14,11 +14,14 @@ function AddCategoriesModal() {
const [t] = useTranslation() const [t] = useTranslation()
const {mutate , status} = useAddCategories() const {mutate , status} = useAddCategories()
const handelSubmit = (values:any )=>{ const handelSubmit = (values:any )=>{
values['name'] = {
"en" : values.name_en,
"ar" : values.name_ar,
"de" : values.name_de,
}
console.log(values);
mutate(values)
const dataToSend = getDataToSend(values)
mutate(dataToSend)
// Submit Value
} }
return ( return (
<LayoutModal <LayoutModal
@ -31,7 +34,7 @@ function AddCategoriesModal() {
getValidationSchema={getValidationSchema()}> getValidationSchema={getValidationSchema()}>
<FormCategories /> <AddForm />
</LayoutModal> </LayoutModal>
) )
} }

View File

@ -0,0 +1,37 @@
import React from 'react'
import { Col, Row } from 'reactstrap';
import KarimField from '../../Components/Karimalden/KarimField';
import { FakeSelectData } from '../../Layout/app/Const';
import { useFormikContext } from 'formik';
import { DatePicker } from 'antd';
import { useGetCategories } from '../../api/Categories';
function AddForm() {
const formik = useFormikContext<any>();
const {data } = useGetCategories()
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="parent_id" type="Select" option={[]} />
<KarimField name="photo" type="File" />
</Col>
</Row>
)
}
export default AddForm

View File

@ -9,13 +9,12 @@ const CreateForm = () => {
<Row> <Row>
<Col> <Col>
<KarimField name="name" label='name' placeholder='full_name' /> <KarimField name="name" />
<KarimField name="description" type='text' label='description' placeholder='full_description' /> <KarimField name="parent_id" type="Select" option={[]} />
<KarimField name="price" label='price' type='number' placeholder='price' />
</Col> </Col>
<Col> <Col>
<KarimField name="image" type='File' label='image' placeholder='image' /> <KarimField name="photo" type="File" />
<KarimField name="is_published" type='Checkbox' label='is_published' />
</Col> </Col>
</Row> </Row>
) )

View File

@ -1,5 +1,4 @@
import React from 'react'; import React from 'react';
import FormPage from '../../../Layout/Dashboard/FormPage'; import FormPage from '../../../Layout/Dashboard/FormPage';
import EditForm from './EditForm'; import EditForm from './EditForm';
import { getInitialValues, getValidationSchema } from '../formUtil'; import { getInitialValues, getValidationSchema } from '../formUtil';
@ -12,7 +11,6 @@ const EditPage = () => {
const { id } = useParams() const { id } = useParams()
const { data,isLoading } = useGetOneCategories({id}) const { data,isLoading } = useGetOneCategories({id})
const {mutate} = useAddCategories() const {mutate} = useAddCategories()
const handleSubmit = (values: any) => { const handleSubmit = (values: any) => {
const newdata = {} as any; const newdata = {} as any;
@ -31,6 +29,7 @@ const EditPage = () => {
handleSubmit={(values: any) => handleSubmit(values)} handleSubmit={(values: any) => handleSubmit(values)}
initialValues={getInitialValues(data)} initialValues={getInitialValues(data)}
validationSchema={getValidationSchema} validationSchema={getValidationSchema}
title='Edit Categories'
> >
<EditForm /> <EditForm />

View File

@ -19,27 +19,32 @@ interface InitialValues extends ObjectToEdit {
interface ValidateSchema extends formUtilCommon{ interface ValidateSchema extends formUtilCommon{
} }
export const getInitialValues = (objectToEdit: any | null = null): any => {
export const getInitialValues = (objectToEdit: ObjectToEdit | null = null): InitialValues => {
return { return {
id:objectToEdit?.id?? 0 , id: objectToEdit?.id ?? 0,
number:objectToEdit?.number ?? 0, name: "",
value:objectToEdit?.value?? 0 name_ar: objectToEdit?.name?.ar ?? '',
} name_en: objectToEdit?.name?.en ?? '',
name_de: objectToEdit?.name?.de ?? '',
parent_id: objectToEdit?.parent_id ?? 1,
photo: objectToEdit?.photo ?? '',
};
}; };
export const getValidationSchema = (editMode: boolean = false): Yup.Schema<ValidateSchema> => {
// validate input export const getValidationSchema = (editMode: boolean = false): Yup.Schema<any> => {
// Validate input
return Yup.object().shape({ return Yup.object().shape({
number:Yup.number().required('required'), name : Yup.string().required('Required'),
value:Yup.number().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'),
}); });
}; };
export const getDataToSend = (values: any): FormData => { export const getDataToSend = (values: any): FormData => {
const data = { ...values }; const data = { ...values };

View File

@ -2,28 +2,17 @@ import { ReactNode, lazy } from "react";
// Icons Import // Icons Import
import { Home } from "react-feather"; import { FaUser, FaHome, FaSadCry } from "react-icons/fa"
import { AiFillQuestionCircle, AiFillStar} from "react-icons/ai"
import {FaUserFriends , FaUser, FaHome, FaSadCry } from "react-icons/fa"
import { MdPrivacyTip } from "react-icons/md";
import {DiDatabase} from "react-icons/di"
import { FiMail } from "react-icons/fi";
import {CgUnavailable} from "react-icons/cg"
import {BsCode, BsInfoCircle} from "react-icons/bs"
import {AiOutlineTransaction ,AiFillSetting ,AiFillGift} from "react-icons/ai"
import { IoIosNotificationsOutline, IoIosPaper, } from "react-icons/io";
import { BiCategory, BiLockAlt } from "react-icons/bi";
import { RiCouponFill } from "react-icons/ri";
import { IoPersonAddSharp } from "react-icons/io5";
import { MdOutlineManageAccounts } from "react-icons/md";
import { TbBrandSocketIo } from "react-icons/tb";
import { BsPersonFillAdd } from "react-icons/bs";
// Pages Import // Pages Import
import HomePage from "./Pages/Home/HomePage"; import HomePage from "./Pages/Home/HomePage";
import CategoriesPage from "./Pages/Categories/CategoriesPage"; import CategoriesPage from "./Pages/Categories/CategoriesPage";
import Page from "./Pages/Categories/EditCategories/Page"; import Page from "./Pages/Categories/EditCategories/Page";
import Page from "./Pages/";
import CouponPage from "./Pages/Categories copy/CouponPage";
interface RoutesLinksType { interface RoutesLinksType {
@ -53,6 +42,12 @@ export const RoutesLinks: RoutesLinksType[] = [
href: "/categories", href: "/categories",
}, },
{
name: "Coupon",
element: <CouponPage />,
icon: <FaUser />,
href: "/Coupon",
},
/////////////// hidden route /////////////// hidden route
@ -60,5 +55,10 @@ export const RoutesLinks: RoutesLinksType[] = [
href: "/categories/:id", href: "/categories/:id",
element: <Page />, element: <Page />,
hidden:true hidden:true
},
{
href: "/coupon/:id",
element: <Page />,
hidden:true
} }
] ]

View File

@ -15,6 +15,7 @@ const API = {
}; };
const KEY = "CATEGORIES" 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 = (params?:any) => useGetOneQuery(KEY, API.GET_ALL,params);

25
src/api/Coupon.ts Normal file
View 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: `coupon`,
GET_ALL: `coupon`,
DELETE: `coupon`,
UPDATE: `coupon`,
};
const KEY = "COUPON"
export const useGetCoupon = (params?:any) => useGetQueryPagination(KEY, API.GET_ALL,params);
export const useGetOneCoupon = (params?:any) => useGetOneQuery(KEY, API.GET_ALL,params);
export const useAddCoupon = () => useAddMutation(KEY, API.ADD);
export const useUpdateCoupon = () => useUpdateMutation(KEY, API.UPDATE);
export const useDeleteCoupon = () =>useDeleteMutation(KEY, API.DELETE);

View File

@ -16,7 +16,11 @@ function useAddMutation(key: string, url: string): UseMutationResult<AxiosRespon
return useMutation<AxiosResponse, unknown, any, unknown>( return useMutation<AxiosResponse, unknown, any, unknown>(
async (dataToSend) => { async (dataToSend) => {
const { data } = await axios.post(url, dataToSend); const { data } = await axios.post(url, dataToSend,{
headers: {
'Content-Type': 'multipart/form-data'
}
} );
return data; return data;
}, },
{ {

View File

@ -5,10 +5,11 @@ import useAuthState from '../../lib/state mangment/AuthState';
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"
return useQuery( return useQuery(
params ? [key, params] : key, params ? [key, params] : key,
async () => { async () => {
const response = await axios.get(url+"/"+ params?.id); const response = await axios.get(url+"/"+ params?.id+`?lang=${language}`);
return response.data.data; return response.data.data;
}, },