add_setting

This commit is contained in:
karimaldeen 2024-06-03 17:29:06 +03:00
parent 09022c9aef
commit 5f67441d9d
113 changed files with 2005 additions and 2075 deletions

View File

@ -1,6 +1,7 @@
{
"cSpell.words": [
"aldeen",
"antd",
"Datepicker",
"formik",
"Karim",

View File

@ -10,6 +10,7 @@
<title>E-Menu - App</title>
</head>
<script type="module" src="/src/index.tsx"></script>
<body>
<div id="root"></div>

View File

@ -4,85 +4,48 @@
"private": true,
"dependencies": {
"@ant-design/icons": "^4.8.3",
"@emotion/styled": "^11.11.0",
"@mui/icons-material": "^5.14.19",
"@mui/x-charts": "^6.19.4",
"@react-google-maps/api": "^2.19.2",
"@szhsin/react-menu": "github:szhsin/react-menu",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"@tinymce/tinymce-react": "^4.3.2",
"@types/jest": "^27.5.2",
"@types/node": "^16.18.60",
"@types/react": "^18.2.33",
"@types/react-dom": "^18.2.14",
"@types/socket.io-client": "^3.0.0",
"@wojtekmaj/react-daterange-picker": "^5.4.4",
"antd": "^5.12.1",
"apexcharts": "^3.44.2",
"axios": "^1.6.0",
"bootstrap": "^5.3.2",
"chart.js": "^4.4.0",
"dayjs": "^1.11.10",
"formik": "^2.4.5",
"google-map-react": "^2.2.1",
"history": "^5.3.0",
"i18next": "^23.6.0",
"i18next-browser-languagedetector": "^7.1.0",
"json-server": "^0.17.4",
"@types/node": "^16.18.97",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"antd": "^5.17.4",
"apexcharts": "^3.49.1",
"axios": "^1.7.2",
"bootstrap": "^5.3.3",
"chart.js": "^4.4.3",
"dayjs": "^1.11.11",
"formik": "^2.4.6",
"i18next": "^23.11.5",
"leaflet": "^1.9.4",
"moment": "^2.30.1",
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react": "^18.3.1",
"react-apexcharts": "^1.4.1",
"react-bootstrap": "^2.9.1",
"react-bootstrap": "^2.10.2",
"react-bootstrap-sweetalert": "^5.2.0",
"react-chartjs-2": "^5.2.0",
"react-confirm-alert": "^3.0.6",
"react-data-table-component": "^7.5.4",
"react-dom": "^18.2.0",
"react-feather": "^2.0.10",
"react-i18next": "^13.3.1",
"react-icons": "^4.11.0",
"react-input-range": "^1.3.0",
"react-data-table-component": "^7.6.2",
"react-dom": "^18.3.1",
"react-i18next": "^13.5.0",
"react-icons": "^4.12.0",
"react-leaflet": "^4.2.1",
"react-number-format": "^5.3.4",
"react-number-format": "^5.4.0",
"react-player": "^2.16.0",
"react-query": "^3.39.3",
"react-redux": "^8.1.3",
"react-router-dom": "^6.18.0",
"react-scripts": "5.0.1",
"react-select": "^5.7.7",
"react-simple-star-rating": "^5.1.7",
"react-switch": "^7.0.0",
"react-router-dom": "^6.23.1",
"react-select": "^5.8.0",
"react-tabs": "^6.0.2",
"react-toastify": "^9.1.3",
"react-toggle": "^4.1.3",
"reactstrap": "^9.2.0",
"redux": "^4.2.1",
"sass": "^1.69.5",
"socket.io-client": "^4.7.2",
"styled-components": "5.3.3",
"ts-xlsx": "^0.0.11",
"reactstrap": "^9.2.2",
"sass": "^1.77.4",
"typescript": "^4.9.5",
"web-vitals": "^2.1.4",
"xlsx": "^0.18.5",
"yup": "^1.3.2",
"zustand": "^4.4.5"
"yup": "^1.4.0",
"zustand": "^4.5.2"
},
"scripts": {
"start": "react-scripts start",
"start": "vite",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"g:api": "node src/Extensions/FileGenerator/generateApi.js",
"g:column": "node src/Extensions/FileGenerator/generateColumn.js",
"g:formutil": "node src/Extensions/FileGenerator/generateformUtils.js",
"g:page": "node src/Extensions/FileGenerator/generatePage.js",
"g:dashboard": "node src/Extensions/FileGenerator/generateDashboard.js ",
"g:modal:add": "node src/Extensions/FileGenerator/generateEditModal.js ",
"g:model:edit": "node src/Extensions/FileGenerator/generateEditModal.js "
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [

BIN
public/Layout/images.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 124 KiB

View File

@ -1,7 +1,7 @@
import React , {ReactNode} from "react";
import { FaEdit, FaEye, FaTrash } from "react-icons/fa";
import CustomConfirmAlert from "../Alert";
import { usePageState } from "../../../lib/state mangment/LayoutPagestate";
import { usePageState } from "../../../lib/statemangment/LayoutPagestate";
type TableActionsProps = {
onDelete?: () => any;

View File

@ -3,7 +3,7 @@ import React, { useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { BsExclamationCircle } from 'react-icons/bs';
import { Button, Card, CardBody, Input, Label, Modal, ModalHeader } from 'reactstrap';
import { useCommonModelState } from '../../lib/state mangment/driver&customer/ModelState';
import { useCommonModelState } from '../../lib/statemangment/driver&customer/ModelState';
import { LoadingButton } from '../Ui/LoadingButton';
interface BlockModelProps {
@ -20,7 +20,7 @@ const BlockModel: React.FC<BlockModelProps> = ({Mutation ,type}) => {
const handleSubmit = () => {
const blockInput = document.getElementById('block_input') as HTMLInputElement;
if (blockInput) {
Mutation.mutate({ [key_to_api]: objectID, block_timer: blockInput.value });
Mutation.mutate({ [key_to_api]: objectID, block_timer: blockvalue });
}
};

View File

@ -2,7 +2,7 @@ import React, { useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { BsExclamationCircle } from 'react-icons/bs';
import { Button, Card, CardBody, Col, Input, Label, Modal, ModalHeader, Row } from 'reactstrap';
import { useCommonModelState } from '../../lib/state mangment/driver&customer/ModelState';
import { useCommonModelState } from '../../lib/statemangment/driver&customer/ModelState';
import { LoadingButton } from '../Ui/LoadingButton';
@ -24,8 +24,8 @@ const GiftModal: React.FC<GiftModalProps> = ({Mutation ,type }) => {
const handleGift = () => {
const enterCodesInput = document.getElementById('enter_codes') as HTMLInputElement;
if (enterCodesInput && enterCodesInput.value) {
Mutation.mutate({ type, id: objectID, value: enterCodesInput.value });
if (enterCodesInput && enterCodesvalue) {
Mutation.mutate({ type, id: objectID, value: enterCodesvalue });
}
};

View File

@ -1,6 +1,6 @@
import { Menu, MenuItem, MenuButton } from '@szhsin/react-menu';
import { useTranslation } from 'react-i18next';
import { usePageState } from '../../lib/state mangment/LayoutPagestate';
import { usePageState } from '../../lib/statemangment/LayoutPagestate';
import { BsFillMoonStarsFill, BsFillSunFill, BsSunglasses } from 'react-icons/bs';

View File

@ -4,7 +4,7 @@ import { BsExclamationCircle } from 'react-icons/bs';
import { Button, Card, CardBody, Input, Label, Modal, ModalHeader } from 'reactstrap';
import { useTranslation } from 'react-i18next';
import { LoadingButton } from '../Ui/LoadingButton';
import { useCommonModelState } from '../../lib/state mangment/driver&customer/ModelState';
import { useCommonModelState } from '../../lib/statemangment/driver&customer/ModelState';
import { CiLock } from "react-icons/ci";
interface UnBlockModalProps {

View File

@ -1,5 +1,5 @@
import React from 'react';
import { Spin } from 'antd';
import React from "react";
import { Spin } from "antd";
interface Props {
loading: boolean;
@ -10,7 +10,13 @@ interface Props {
const KarimSpinner: React.FC<Props> = ({ loading, className, children }) => {
return (
<div className={className ?? ""}>
{loading ? <div className='text-center'><Spin /></div> : children}
{loading ? (
<div className="text-center">
<Spin />
</div>
) : (
children
)}
</div>
);
};

View File

@ -1,48 +1,37 @@
.SearchBar{
// margin-top: 20px;
.group {
display: flex;
align-items: center;
position: relative;
max-width: 350px;
width: 350px;
}
.input {
width: 100%;
height: 40px;
padding: 0 1rem;
padding-left: 2.5rem;
border-radius: 8px;
outline: none;
font-weight: 500;
background: var(--bg);
color: var(--text);
border: none;
box-shadow: 2px 2px 7px 0 var(--bg);
.SearchBar {
// margin-top: 20px;
.group {
display: flex;
align-items: center;
position: relative;
max-width: 350px;
width: 350px;
}
}
.input::placeholder {
color: var(--subtext);
opacity: .4;
}
.input {
width: 100%;
height: 40px;
padding: 0 1rem;
padding-left: 2.5rem;
border-radius: 8px;
outline: none;
font-weight: 500;
background: var(--bg);
color: var(--text);
border: none;
box-shadow: 2px 2px 7px 0 var(--bg);
}
.icon {
position: absolute;
left: 1rem;
fill: var(--subtext);
width: 1rem;
height: 1rem;
}
}
.input::placeholder {
color: var(--subtext);
opacity: 0.4;
}
.icon {
position: absolute;
left: 1rem;
fill: var(--subtext);
width: 1rem;
height: 1rem;
}
}

View File

@ -1,35 +1,45 @@
import React, { useState } from 'react'
import './SearchBar.scss'
import { useNavigate, useSearchParams } from 'react-router-dom';
import React, { useState } from "react";
import "./SearchBar.scss";
import { useNavigate, useSearchParams } from "react-router-dom";
const SearchBar = () => {
const [searchQuery, setSearchQuery] = useState('');
const [searchParams] = useSearchParams()
const navigate = useNavigate();
const [searchQuery, setSearchQuery] = useState("");
const [searchParams] = useSearchParams();
const navigate = useNavigate();
const handleChange = (event:any) => {
const { value } = event.target;
setSearchQuery(value);
updateUrlParams(value);
};
const handleChange = (event: any) => {
const { value } = event.target;
setSearchQuery(value);
updateUrlParams(value);
};
const updateUrlParams = (value:any) => {
navigate(`?search=${value}`);
const updateUrlParams = (value: any) => {
navigate(`?search=${value}`, { replace: true });
};
};
return (
<div className="SearchBar">
<div className="group">
<svg
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
className="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-1b5stb0 icon"
focusable="false"
aria-hidden="true"
viewBox="0 0 24 24"
data-testid="SearchIcon"
>
<path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path>
</svg>
<input
placeholder="Search Product...."
type="search"
className="input"
value={searchQuery}
onChange={handleChange}
/>
</div>
</div>
);
};
return (
<div className='SearchBar'>
<div className="group">
<svg xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" className="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-1b5stb0 icon" focusable="false" aria-hidden="true" viewBox="0 0 24 24" data-testid="SearchIcon"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path></svg>
<input placeholder="Search Product...." type="search"
className="input"
value={searchQuery}
onChange={handleChange}
/>
</div>
</div>
)
}
export default SearchBar
export default SearchBar;

View File

@ -1,78 +0,0 @@
.ValidationField{
>*{
width: 100%;
}
.text,.ant-form-item{
margin-bottom:7px !important;
}
>span{
margin-bottom: 0px !important;
&:focus-within{
border-color: var(--primary) ;
box-shadow: 0 0 0 1px var(--primary);
cursor: pointer;
}
&:has(.is-invalid){
border-color: red !important;
}
input{
color: var(--text);
background: var(--bg);
}
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active{
-webkit-box-shadow: 0 0 0 30px white inset !important;
}
}
}
.ant-upload-select{
width: 100%;
}
.Checkboxs{
padding: 4%;
}
.SearchField{
button{
background: var(--primary);
}
}
.text{
color: var(--text);
}
input:disabled{
color: var(--text) !important;
}
.isError{
outline: red 1px solid;
color: red;
}
.Error_color{
color: red;
}
input:-webkit-autofill {
-webkit-box-shadow: 0 0 0 1000px white inset !important; /* Change the color to your desired background color */
}
input:-webkit-autofill:focus {
-webkit-box-shadow: 0 0 0 1000px white inset !important; /* Change the color to your desired background color */
}
/* Remove autofill background color on hover */
input:-webkit-autofill:hover {
-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

@ -1,34 +1,46 @@
import React from "react";
import "./ValidationField.scss";
import { Date, Time, File, DataRange, SelectField, Default, CheckboxField ,TextAreaField} from './View';
import { ValidationFieldProps } from "./types";
import MaltyFile from "./View/MaltyFile";
import SearchField from "./View/SearchField";
import "./utils/ValidationField.scss";
import {
Date,
Time,
File,
DataRange,
SelectField,
Default,
CheckboxField,
MaltyFile,
SearchField,
TextField,
DropFile,
} from "./View";
import { ValidationFieldProps, ValidationFieldType } from "./utils/types";
import LocalSearchField from "./View/LocalSearch";
import NumberFormate from "./View/NumberFormate";
const ValidationField: React.FC<ValidationFieldProps> = ({type , ...otherProps}) => {
switch (type) {
case 'Select':
return <SelectField {...otherProps} />;
case 'Search':
return <SearchField {...otherProps} />;
case "DataRange":
return <DataRange {...otherProps} />;
case "Date":
return <Date {...otherProps} />;
case "Time":
return <Time {...otherProps} />;
case "File":
return <File {...otherProps} />;
case "MaltyFile":
return <MaltyFile {...otherProps} />;
case "Checkbox":
return <CheckboxField {...otherProps} />;
case "TextArea":
return <TextAreaField {...otherProps} />;
default:
return <Default {...otherProps} type={type}/>;
}
const components: { [key: string]: React.FC<any> } = {
Select: SelectField,
Search: SearchField,
LocalSearch: LocalSearchField,
DataRange: DataRange,
TextArea: TextField,
Date: Date,
Time: Time,
File: File,
DropFile: DropFile,
MaltyFile: MaltyFile,
Checkbox: CheckboxField,
NumberFormate: NumberFormate,
};
export default React.memo(ValidationField);
const ValidationField: React.FC<ValidationFieldProps> = React.memo(
({ type, ...otherProps }) => {
const Component = components[type as ValidationFieldType];
if (!Component) {
return <Default {...otherProps} />;
}
return <Component {...otherProps} />;
},
);
export default ValidationField;

View File

@ -1,36 +1,40 @@
import React from 'react'
import useFormField from '../../../Hooks/useFormField';
import { Checkbox, Form } from 'antd';
import React from "react";
import useFormField from "../../../Hooks/useFormField";
import { Checkbox, Form } from "antd";
const CheckboxField = ({ name, label, isDisabled, onChange,Group,className, props }: any) => {
const { t, formik,isError,errorMsg} = useFormField(name, props)
const CheckboxField = ({
name,
label,
isDisabled,
onChange,
Group,
className,
props,
no_label,
label_icon,
}: any) => {
const { t, formik, isError, errorMsg } = useFormField(name, props);
const CheckboxhandleChange = (value: any) => {
formik.setFieldValue(name, value?.target?.checked)
formik.setFieldValue(name, value?.target?.checked);
};
return (
<div className={Group ? "d-inline mt-3 Checkboxs" :``}>
<Form.Item
<div className={Group ? "d-inline mt-3 Checkboxs" : ``}>
<Form.Item
hasFeedback
validateStatus={isError ? 'error' : ''}
help={isError ? errorMsg : ''}
validateStatus={isError ? "error" : ""}
help={isError ? errorMsg : ""}
>
<Checkbox
onChange={onChange || CheckboxhandleChange}
disabled={isDisabled}
checked={formik.values[name] ?? false}
className={className}
>
{t(`${label ? label : name}`)}
</Checkbox>
<Checkbox
onChange={onChange || CheckboxhandleChange}
disabled={isDisabled}
checked={formik.values[name] ?? false}
className={className}
>
{t(`${label ? label : name}`)}
</Checkbox>
</Form.Item>
</div>
)
}
);
};
export default CheckboxField
export default CheckboxField;

View File

@ -1,24 +1,46 @@
import { Form, DatePicker } from 'antd'
import { Form, DatePicker } from "antd";
import React from 'react'
import useFormField from '../../../Hooks/useFormField';
import React from "react";
import useFormField from "../../../Hooks/useFormField";
import { MdOutlineEdit } from "react-icons/md";
const { RangePicker } = DatePicker;
const DataRange = ({ name, label, Format, props, onChange, isDisabled, placeholder, className }: any) => {
const { errorMsg, isError, t, formik } = useFormField(name, props)
const DataRange = ({
name,
label,
Format,
props,
onChange,
isDisabled,
placeholder,
className,
no_label,
label_icon,
}: any) => {
const { errorMsg, isError, t, formik } = useFormField(name, props);
const onCalendarChange = (value: any) => {
formik.setFieldValue(name, value)
formik.setFieldValue(name, value);
};
return (
<div className="ValidationField w-100 ">
{no_label ? (
<label htmlFor={name} className="text">
<span>empty</span>
</label>
) : label_icon ? (
<div className="LabelWithIcon">
<label htmlFor={name} className="text">
{t(`${label ? label : name}`)}
</label>
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
</div>
) : (
<label htmlFor={name} className="text">
{t(`${label ? label : name}`)}
</label>
)}
<div className='ValidationField'>
<label htmlFor={name} className="text">
{t(`${label ? label : name}`)}
</label>
<Form.Item
hasFeedback
validateStatus={isError ? "error" : ""}
@ -34,11 +56,9 @@ const DataRange = ({ name, label, Format, props, onChange, isDisabled, placehold
disabled={isDisabled}
defaultValue={formik.values[name]}
/>
</Form.Item>
</div>
)
}
);
};
export default DataRange
export default DataRange;

View File

@ -1,32 +1,49 @@
import { Form, DatePicker } from 'antd';
import React from 'react';
import useFormField from '../../../Hooks/useFormField';
import dayjs from 'dayjs';
const DateField = ({ name, label, picker = "date", isDisabled, props, onChange, placeholder, className, Format }: any) => {
import { Form, DatePicker } from "antd";
import React from "react";
import useFormField from "../../../Hooks/useFormField";
import { MdOutlineEdit } from "react-icons/md";
import dayjs from "dayjs";
const Date = ({
name,
label,
picker = "date",
isDisabled,
props,
onChange,
placeholder,
className,
no_label,
label_icon,
}: any) => {
const { errorMsg, isError, t, formik } = useFormField(name, props);
const FormikValue = formik.values[name];
const onCalendarChange = (value: any) => {
formik.setFieldValue(name, value);
// console.log(value,"value ");
};
// Function to check if a date is valid
const isValidDate = (date: any) => {
return date && !isNaN(date.valueOf()) && dayjs(date).isValid();
};
// Set a default invalid date if the provided defaultValue is invalid
const getDefaultDate = () => {
const defaultValue = formik.values[name];
return isValidDate(defaultValue) ? defaultValue : null; // Set to null or any other default invalid date
};
const Formater = "YYYY/MM/DD";
return (
<div className='ValidationField'>
<label htmlFor={name} className="text">
{t(`${label ? label : name}`)}
</label>
<div className="ValidationField w-100 ">
{no_label ? (
<label htmlFor={name} className="text">
<span>empty</span>
</label>
) : label_icon ? (
<div className="LabelWithIcon">
<label htmlFor={name} className="text">
{t(`${label ? label : name}`)}
</label>
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
</div>
) : (
<label htmlFor={name} className="text">
{t(`${label ? label : name}`)}
</label>
)}
<Form.Item
hasFeedback
validateStatus={isError ? "error" : ""}
@ -34,18 +51,19 @@ const DateField = ({ name, label, picker = "date", isDisabled, props, onChange,
>
<DatePicker
picker={picker}
placeholder={placeholder ? t(placeholder) : t(name)}
placeholder={t(`${placeholder}`)}
allowClear
className={`${className} w-100`}
defaultValue={getDefaultDate()}
value={FormikValue ? FormikValue : null}
size="large"
onChange={onChange || onCalendarChange}
disabled={isDisabled}
format={Format}
format={Formater}
/>
{/* <DatePicker onChange={onChange} /> */}
</Form.Item>
</div>
);
}
};
export default DateField;
export default Date;

View File

@ -1,36 +1,62 @@
import { Form, Input } from 'antd'
import React from 'react'
import useFormField from '../../../Hooks/useFormField';
import { Form, Input } from "antd";
import React from "react";
import useFormField from "../../../Hooks/useFormField";
import { MdOutlineEdit } from "react-icons/md";
import { Field } from "formik";
const Default = ({ name, label, placeholder, isDisabled, onChange, props,type }: any) => {
const { Field, formik, isError, errorMsg, t } = useFormField(name, props);
const Default = ({
name,
label,
placeholder,
isDisabled,
onChange,
type,
no_label,
label_icon,
...props
}: any) => {
const { errorMsg, isError, t } = useFormField(name, props);
return (
<div className="ValidationField w-100" >
<label htmlFor={name} className="text">
{t(`${label ? label : name}`)}
<div className="ValidationField w-100">
{no_label ? (
<label htmlFor={name} className="text">
<span>empty</span>
</label>
) : label_icon ? (
<div className="LabelWithIcon">
<label htmlFor={name} className="text">
{t(`${label ? label : name}`)}
</label>
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
</div>
) : (
<label htmlFor={name} className="text">
{t(`${label ? label : placeholder ? placeholder : name}`)}
</label>
)}
<Form.Item
hasFeedback
validateStatus={isError ? 'error' : ''}
help={isError ? errorMsg : ''}
validateStatus={isError ? "error" : ""}
help={isError ? errorMsg : ""}
>
<Field
as={Input}
type={type ?? "text"}
placeholder={t(`${placeholder ?placeholder : name}`)}
placeholder={t(
`${placeholder ? placeholder : label ? label : name}`,
)}
name={name}
disabled={isDisabled}
size="large"
// onChange={onChange ? onChange : handleChange}
size="large"
{...props}
// onChange={onChange ? onChange : handleChange}
{...(type === "number" && { min: 0 })}
/>
</Form.Item>
</div>
);
};
export default React.memo(Default);
;
export default React.memo(Default);

View File

@ -0,0 +1,93 @@
import React, { useEffect, useState } from "react";
import { LoadingOutlined, PlusOutlined } from "@ant-design/icons";
import { message, Upload } from "antd";
import type { GetProp, UploadProps } from "antd";
import useFormField from "../../../Hooks/useFormField";
import { ImageBaseURL } from "../../../api/config";
type FileType = Parameters<GetProp<UploadProps, "beforeUpload">>[0];
const DropFile = ({
name,
label,
onChange,
isDisabled,
placholder,
className,
props,
no_label,
label_icon,
}: any) => {
const { formik, t, isError } = useFormField(name, props);
let FormikName = formik?.values[name];
const FormikValue =
typeof FormikName === "string"
? ImageBaseURL + FormikName
: FormikName instanceof File
? URL.createObjectURL(FormikName)
: "";
const [imageUrl, setImageUrl] = useState<any>(FormikValue ?? "");
useEffect(() => {
setImageUrl(FormikName);
}, [FormikName]);
const getBase64 = (img: FileType, callback: (url: string) => void) => {
const reader = new FileReader();
reader.addEventListener("load", () => callback(reader.result as string));
reader.readAsDataURL(img);
};
const handleChange: UploadProps["onChange"] = (info) => {
if (info.file.status === "done") {
getBase64(info.file.originFileObj as FileType, (url) => {
setImageUrl(url);
});
}
formik.setFieldValue(name, info.file.originFileObj);
};
const customRequest = async ({ onSuccess }: any) => {
onSuccess();
};
const uploadButton = (
<button style={{ border: 0, background: "none" }} type="button">
<div className={`CustomFile ${isError ? "uploader_error" : ""} `}>
{t("drag_and_drop_or_click_here_to_select_the_file")}
</div>
</button>
);
return (
<div className="ValidationField w-100">
<label htmlFor={name} className="text">
{t(`${label || name}`)}
</label>
<Upload
name="avatar"
listType="picture-card"
className={`avatar-uploader ${isError ? "uploader_error" : ""} ${className}`}
showUploadList={false}
customRequest={customRequest}
onChange={onChange || handleChange}
>
{imageUrl ? (
<img
src={
imageUrl instanceof File
? URL.createObjectURL(imageUrl)
: imageUrl
}
alt=""
style={{ width: "100%" }}
/>
) : (
uploadButton
)}
</Upload>
</div>
);
};
export default DropFile;

View File

@ -1,34 +1,53 @@
import { Button, Upload, UploadFile } from 'antd'
import useFormField from '../../../Hooks/useFormField';
import { UploadOutlined } from '@ant-design/icons';
import { ImageBaseURL } from '../../../api/config';
import { Button, Upload, UploadFile } from "antd";
import useFormField from "../../../Hooks/useFormField";
import { UploadOutlined } from "@ant-design/icons";
const File = ({
name,
label,
onChange,
isDisabled,
placholder,
className,
acceptedFileType,
props,
}: any) => {
const { formik, t, isError } = useFormField(name, props);
let imageUrl = formik?.values?.[name] ?? null;
const File = ({ name, label, onChange, isDisabled,placholder,className,acceptedFileType, props }: any) => {
const { formik, t ,isError} = useFormField(name, props)
let FormikName = formik.values[name];
const imageUrl = formik.values[name] ? ImageBaseURL + FormikName : '';
const fileList: UploadFile[] = [
const fileList: UploadFile[] = imageUrl
? [
typeof imageUrl === "string"
? {
uid: "-1",
name: "",
status: "done",
url: imageUrl,
thumbUrl: imageUrl,
}
: {
uid: imageUrl.uid || "-1",
name: imageUrl.name || "",
status: "done",
originFileObj: imageUrl,
},
]
: [];
// console.log(1);
{
uid: '-1',
name: '',
status: 'done',
url: FormikName == ""? imageUrl : imageUrl?.replace("public", "/storage"),
thumbUrl: FormikName == ""? imageUrl : imageUrl?.replace("public", "/storage")
const FilehandleChange = (value: any) => {
// console.log(value,"filevalue");
if (value.fileList.length === 0) {
formik.setFieldValue(name, null);
} else {
formik.setFieldValue(name, value?.file?.originFileObj);
}
];
const FilehandleChange = (value:any) => {
formik.setFieldValue(name, value.file.originFileObj)
};
const customRequest = async ({ onSuccess}: any) => {
const customRequest = async ({ onSuccess, no_label, label_icon }: any) => {
onSuccess();
};
return (
<div className="ValidationField">
<div className="ValidationField upload_image_button ">
<label htmlFor={name} className="text">
{t(`${label || name}`)}
</label>
@ -36,28 +55,24 @@ const File = ({ name, label, onChange, isDisabled,placholder,className,acceptedF
<Upload
disabled={isDisabled}
listType="picture"
maxCount={1}
defaultFileList={[...fileList]}
fileList={[...fileList]}
onChange={onChange || FilehandleChange}
customRequest={customRequest}
className={`${className} w-100`}
accept={acceptedFileType ? acceptedFileType : undefined}
>
<Button className={isError ? "isError w-100" : " w-100"} icon={<UploadOutlined />}>
{placholder ?? t("upload_image") }
</Button>
<div className='Error_color'> {isError ? "required" : ""}</div>
<Button
className={isError ? "isError w-100 " : " w-100"}
icon={<UploadOutlined />}
>
{placholder ?? t("Click_to_upload_the_image")}
</Button>
<div className="Error_color"> {isError ? "required" : ""}</div>
</Upload>
</div>
)
}
);
};
export default File
export default File;

View File

@ -0,0 +1,93 @@
import { Form, Select } from "antd";
import React, { useState } from "react";
import useFormField from "../../../Hooks/useFormField";
import { MdOutlineEdit } from "react-icons/md";
import { translateOptions } from "../utils/translatedOptions";
const LocalSelectField = ({
name,
label,
placeholder,
isDisabled,
option,
isMulti,
onChange,
className,
props,
no_label,
label_icon,
}: any) => {
const { errorMsg, isError, t, formik } = useFormField(name, props);
// State to manage the search input value
const [searchValue, setSearchValue] = useState("");
const handleSearch = (
input: string,
option: { value: string; label: React.ReactNode | undefined },
) =>
option?.label?.toString().toLowerCase().includes(toLowerCase()) ||
option?.value?.toString().toLowerCase().includes(toLowerCase());
const SelectableChange = (value: {
value: string;
label: React.ReactNode;
}) => {
formik.setFieldValue(name, value);
};
const handleSelectChange = (value: any) => {
formik.setFieldValue(name, value);
if (onChange) onChange(value);
};
const handleSearchChange = (input: string) => {
setSearchValue(input); // Update the search input value
};
return (
<div className="ValidationField w-100">
{no_label ? (
<label htmlFor={name} className="text">
<span>empty</span>
</label>
) : label_icon ? (
<div className="LabelWithIcon">
<label htmlFor={name} className="text">
{t(`${label ? label : name}`)}
</label>
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
</div>
) : (
<label htmlFor={name} className="text">
{t(`${label ? label : name}`)}
</label>
)}
<Form.Item
hasFeedback
validateStatus={isError ? "error" : ""}
help={isError ? errorMsg : ""}
>
<Select
placeholder={t(
`${placeholder ? placeholder : label ? label : name}`,
)}
disabled={isDisabled}
options={translateOptions(option, t)}
size="large"
className={`${className} ${isError ? "Select_error" : ""} w-100`}
value={formik.values[name]}
allowClear
{...(isMulti && { mode: "multiple" })}
onChange={handleSelectChange}
showSearch
filterOption={handleSearch} // Custom filter function
searchValue={searchValue} // Control the search input value
onSearch={handleSearchChange} // Update search input value on change
/>
</Form.Item>
</div>
);
};
export default React.memo(LocalSelectField);

View File

@ -1,31 +1,61 @@
import { Button, Upload } from 'antd';
import { UploadOutlined } from '@ant-design/icons';
import { ImageBaseURL } from '../../../api/config';
import { useTranslation } from 'react-i18next';
import useFormField from '../../../Hooks/useFormField';
import { Button, Upload } from "antd";
import { UploadOutlined } from "@ant-design/icons";
const MaltyFile = ({ name, label, onChange, isDisabled, placholder, className, props }: any) => {
import useFormField from "../../../Hooks/useFormField";
const MaltyFile = ({
name,
label,
onChange,
isDisabled,
placeholder,
className,
props,
}: any) => {
const { formik, t, isError } = useFormField(name, props);
const imageUrl = formik?.values[name] ? ImageBaseURL + formik.values[name] : '';
const fileList = formik?.values[name] ? formik?.values[name]?.map((file: any, index: number) => ({
uid: index,
name: file.name,
status: 'done',
url: file.url || '',
thumbUrl: file.url || '',
})) : [];
const FilehandleChange = ({ file, fileList }: any) => {
formik.setFieldValue(name, fileList.map((file: any) => file.originFileObj));
};
let imageUrl = formik?.values?.[name] ?? null;
// Mapping formik values to fileList format
const fileList = imageUrl
? imageUrl.map((file: any, index: number) => {
// console.log(file,"file");
return file instanceof File
? {
uid: index,
name: file?.name,
status: "done",
originFileObj: file,
}
: {
uid: index,
id: file?.id,
name: file?.name,
status: "done",
url: file?.url || "",
thumbUrl: file?.url || "",
};
})
: [];
const FilehandleChange = ({ fileList }: any) => {
if (fileList.length === 0) {
formik.setFieldValue(name, null);
} else {
formik.setFieldValue(
name,
fileList.map((file: any) => file?.originFileObj ?? file),
);
}
};
// Custom request function
const customRequest = async ({ onSuccess }: any) => {
// Perform any necessary actions before onSuccess is called
onSuccess();
};
return (
<div className="ValidationField">
<div className="ValidationField upload_image_button">
<label htmlFor={name} className="text">
{t(`${label || name}`)}
</label>
@ -33,17 +63,20 @@ const MaltyFile = ({ name, label, onChange, isDisabled, placholder, className, p
<Upload
disabled={isDisabled}
listType="picture"
defaultFileList={[...fileList]}
fileList={fileList} // Using fileList instead of defaultFileList
onChange={onChange || FilehandleChange}
customRequest={customRequest}
className={`${className} w-100`}
multiple // Allow multiple files to be selected
>
<Button className={isError ? "isError w-100" : " w-100"} icon={<UploadOutlined />}>
{placholder ?? t("upload_image")}
<Button
className={isError ? "isError w-100" : " w-100"}
icon={<UploadOutlined />}
>
{t(placeholder ?? t("upload_image") )}
</Button>
<div className='Error_color'> {isError ? "required" : ""}</div>
<div className="Error_color"> {isError ? "required" : ""}</div>
</Upload>
</div>
);

View File

@ -0,0 +1,75 @@
import { Form, Input, InputNumber } from "antd";
import React from "react";
import useFormField from "../../../Hooks/useFormField";
import { MdOutlineEdit } from "react-icons/md";
import { Field } from "formik";
const NumberFormate = ({
name,
label,
placeholder,
isDisabled,
props,
type,
no_label,
label_icon,
}: any) => {
const { errorMsg, isError, t, formik } = useFormField(name, props);
const SelectableChange = (value: {
value: string;
label: React.ReactNode;
}) => {
formik.setFieldValue(name, value);
};
return (
<div className="ValidationField w-100">
{no_label ? (
<label htmlFor={name} className="text">
<span>empty</span>
</label>
) : label_icon ? (
<div className="LabelWithIcon">
<label htmlFor={name} className="text">
{t(`${label ? label : name}`)}
</label>
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
</div>
) : (
<label htmlFor={name} className="text">
{t(`${label ? label : placeholder ? placeholder : name}`)}
</label>
)}
<Form.Item
hasFeedback
validateStatus={isError ? "error" : ""}
help={isError ? errorMsg : ""}
>
<Field
as={InputNumber}
formatter={(value: any) =>
`${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ",")
}
parser={(value: any) =>
value?.replace(/\$\s?|(,*)/g, "") as unknown as number
}
min="0"
type={type ?? "text"}
value={formik.values[name]}
onChange={SelectableChange}
placeholder={t(
`${placeholder ? placeholder : label ? label : name}`,
)}
name={name}
disabled={isDisabled}
size="large"
// onChange={onChange ? onChange : handleChange}
/>
</Form.Item>
</div>
);
};
export default React.memo(NumberFormate);

View File

@ -1,65 +1,83 @@
import { Form, Select } from 'antd';
import React, { useEffect, useState } from 'react';
import useFormField from '../../../Hooks/useFormField';
import { useLocation, useNavigate } from 'react-router-dom';
import { Form, Select } from "antd";
import React, { useEffect, useState } from "react";
import useFormField from "../../../Hooks/useFormField";
import { useNavigate } from "react-router-dom";
import { MdOutlineEdit } from "react-icons/md";
const SearchField = ({ name, label, placeholder, isDisabled, searchBy, option, isMulti, onChange, className, loading,props }: any) => {
const SearchField = ({
name,
label,
placeholder,
isDisabled,
searchBy,
option,
isMulti,
onChange,
className,
props,
no_label,
label_icon,
}: any) => {
const { errorMsg, isError, t, formik } = useFormField(name, props);
const [searchQuery, setSearchQuery] = useState<string>('');
const location = useLocation()
const navigate = useNavigate()
const [searchQuery, setSearchQuery] = useState<string>("");
const navigate = useNavigate();
useEffect(() => {
const searchParams = new URLSearchParams(location?.search);
setSearchQuery(searchParams?.get('search') || '');
console.log(searchParams);
}, [location]);
const searchParams = new URLSearchParams(window?.location?.search);
setSearchQuery(searchParams?.get("search") || "");
}, []);
const SelecthandleChange = (value: { value: string; label: React.ReactNode }) => {
const SelectableChange = (value: {
value: string;
label: React.ReactNode;
}) => {
formik?.setFieldValue(name, value);
console.log(value);
};
const SearchHandleChange = (value:any) => {
if (value || value !== "") {
navigate(`${window?.location?.pathname}?${searchBy}=${value}`);
} else {
const params = new URLSearchParams(location.search);
params.delete(searchBy ?? "search");
navigate(`${window?.location.pathname}?${params.toString()}`);
}
const SearchHandleChange = (value: any) => {
navigate(`${window?.location?.pathname}?${searchBy}=${value}`, {
replace: true,
});
};
return (
<div className='ValidationField'>
<label htmlFor={name} className="text">
{t(`${label ? label : name}`)}
</label>
<div className="ValidationField w-100 ">
{no_label ? (
<label htmlFor={name} className="text">
<span>empty</span>
</label>
) : label_icon ? (
<div className="LabelWithIcon">
<label htmlFor={name} className="text">
{t(`${label ? label : name}`)}
</label>
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
</div>
) : (
<label htmlFor={name} className="text">
{t(`${label ? label : name}`)}
</label>
)}
<Form.Item
hasFeedback
validateStatus={isError ? "error" : ""}
help={isError ? errorMsg : ""}
>
<Select
placeholder={t(`${placeholder ? placeholder : name}`)}
placeholder={t(
`${placeholder ? placeholder : label ? label : name}`,
)}
disabled={isDisabled}
options={option}
size="large"
className={`${className} w-100`}
value={formik.values[name]}
// defaultValue={formik.values[name]}
loading={option?.length < 1}
allowClear
{...(isMulti && { mode: "multiple" })}
onChange={onChange || SelecthandleChange}
showSearch
optionFilterProp="label"
onSearch={SearchHandleChange}
loading={loading}
onChange={onChange || SelectableChange}
showSearch
optionFilterProp="label"
onSearch={SearchHandleChange}
/>
</Form.Item>
</div>

View File

@ -1,41 +1,72 @@
import { Form, Select } from 'antd'
import React from 'react'
import useFormField from '../../../Hooks/useFormField';
const SelectField = ({ name, label, placeholder, isDisabled,option,isMulti,onChange,className, props}: any) => {
const { errorMsg, isError, t ,formik} = useFormField(name, props)
const SelecthandleChange = (value: { value: string; label: React.ReactNode }) => {
formik.setFieldValue(name, value)
import { Form, Select } from "antd";
import React from "react";
import useFormField from "../../../Hooks/useFormField";
import { MdOutlineEdit } from "react-icons/md";
import { translateOptions } from "../utils/translatedOptions";
const SelectField = ({
name,
label,
placeholder,
isDisabled,
option,
isMulti,
onChange,
className,
props,
no_label,
label_icon,
}: any) => {
const { errorMsg, isError, t, formik } = useFormField(name, props);
const SelectableChange = (value: {
value: string;
label: React.ReactNode;
}) => {
formik.setFieldValue(name, value);
};
// console.log(name,"Select");
return (
<div className='ValidationField'>
<div className="ValidationField w-100">
{no_label ? (
<label htmlFor={name} className="text">
{t(`${label ? label : name}`)}
<span>empty</span>
</label>
<Form.Item
hasFeedback
validateStatus={isError ? "error" : ""}
help={isError ? errorMsg : ""}
>
<Select
placeholder={t(`${placeholder ?placeholder : name}`)}
disabled={isDisabled}
options={option}
size="large"
className={`${className} w-100`}
value={formik.values[name]}
allowClear
{...(isMulti && { mode: "multiple" })}
onChange={onChange || SelecthandleChange}
) : label_icon ? (
<div className="LabelWithIcon">
<label htmlFor={name} className="text">
{t(`${label ? label : name}`)}
</label>
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
</div>
) : (
<label htmlFor={name} className="text">
{t(`${label ? label : name}`)}
</label>
)}
/>
</Form.Item>
</div>
)
}
<Form.Item
hasFeedback
validateStatus={isError ? "error" : ""}
help={isError ? errorMsg : ""}
>
<Select
placeholder={t(
`${placeholder ? placeholder : label ? label : name}`,
)}
disabled={isDisabled}
options={translateOptions(option, t)}
loading={option?.length < 1}
size="large"
className={`${className} ${isError ? "Select_error" : ""} w-100`}
value={formik.values[name]}
allowClear
{...(isMulti && { mode: "multiple" })}
onChange={onChange || SelectableChange}
/>
</Form.Item>
</div>
);
};
export default React.memo(SelectField);

View File

@ -1,45 +0,0 @@
import { Form, Input } from 'antd'
import React from 'react'
import useFormField from '../../../Hooks/useFormField';
const { TextArea } = Input;
const TextAreaField = ({ name, label, placeholder, isDisabled, onChange, props,type }: any) => {
const { Field, formik, isError, errorMsg, t } = useFormField(name, props);
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
console.log('Change:', e.target.value);
formik.setFieldValue(name, e.target.value)
};
return (
<div className="ValidationField w-100" >
<label htmlFor={name} className="text">
{t(`${label ? label : name}`)}
</label>
<Form.Item
hasFeedback
validateStatus={isError ? 'error' : ''}
help={isError ? errorMsg : ''}
>
<Field
as={TextArea}
placeholder={t(`${placeholder ?placeholder : name}`)}
name={name}
disabled={isDisabled}
size="large"
onChange={onChange || handleChange}
// onChange={onChange ? onChange : handleChange}
/>
</Form.Item>
</div>
);
};
export default React.memo(TextAreaField);
;

View File

@ -0,0 +1,50 @@
import { Form, Input } from "antd";
import React from "react";
import useFormField from "../../../Hooks/useFormField";
import { Field } from "formik";
const { TextArea } = Input;
const TextAreaField = ({
name,
label,
placeholder,
isDisabled,
onChange,
props,
type,
}: any) => {
const { formik, isError, errorMsg, t } = useFormField(name, props);
const handleChange = (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
) => {
// console.log('Change:', e.target.value);
formik.setFieldValue(name, e.target.value);
};
return (
<div className="ValidationField w-100">
<label htmlFor={name} className="text">
{t(`${label ? label : name}`)}
</label>
<Form.Item
hasFeedback
validateStatus={isError ? "error" : ""}
help={isError ? errorMsg : ""}
>
<Field
as={TextArea}
placeholder={t(`${placeholder ? placeholder : name}`)}
name={name}
disabled={isDisabled}
size="large"
onChange={onChange || handleChange}
// onChange={onChange ? onChange : handleChange}
/>
</Form.Item>
</div>
);
};
export default React.memo(TextAreaField);

View File

@ -0,0 +1,65 @@
import { Form, Input } from "antd";
import React from "react";
import useFormField from "../../../Hooks/useFormField";
import { MdOutlineEdit } from "react-icons/md";
import { Field } from "formik";
const { TextArea } = Input;
const TextField = ({
name,
label,
placeholder,
isDisabled,
onChange,
props,
no_label,
label_icon,
}: any) => {
const { formik, isError, errorMsg, t } = useFormField(name, props);
const TextFieldhandleChange = (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
) => {
// console.log('Change:', e.target.value);
formik.setFieldValue(name, e.target.value);
};
return (
<div className="ValidationField w-100">
{no_label ? (
<label htmlFor={name} className="text">
<span>empty</span>
</label>
) : label_icon ? (
<div className="LabelWithIcon">
<label htmlFor={name} className="text">
{t(`${label ? label : name}`)}
</label>
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
</div>
) : (
<label htmlFor={name} className="text">
{t(`${label ? label : name}`)}
</label>
)}
<Form.Item
hasFeedback
validateStatus={isError ? "error" : ""}
help={isError ? errorMsg : ""}
>
<Field
as={TextArea}
placeholder={t(`${placeholder ? placeholder : name}`)}
name={name}
disabled={isDisabled}
size="large"
// showCount
maxLength={1000}
onChange={onChange || TextFieldhandleChange}
style={{ height: 100, resize: "none" }}
/>
</Form.Item>
</div>
);
};
export default React.memo(TextField);

View File

@ -1,41 +1,68 @@
import { Form, TimePicker } from 'antd'
import React from 'react'
import useFormField from '../../../Hooks/useFormField';
import { Form, TimePicker } from "antd";
import React from "react";
import useFormField from "../../../Hooks/useFormField";
import { MdOutlineEdit } from "react-icons/md";
import dayjs from "dayjs";
const Time = ({ name, label,className,isDisabled,onChange,props }: any) => {
const { errorMsg, isError, t, formik } = useFormField(name, props)
const Time = ({
name,
label,
className,
isDisabled,
onChange,
props,
placeholder,
no_label,
label_icon,
}: any) => {
const { errorMsg, isError, t, formik } = useFormField(name, props);
const onCalendarChange = (value: any) => {
formik.setFieldValue(name, value)
formik.setFieldValue(name, value);
};
return (
<div className='ValidationField'>
<label htmlFor={name} className="text">
{t(`${label}`)}
</label>
const Formater = "H:mm";
const FormikValue = formik.values[name];
return (
<div className="ValidationField w-100 ">
{no_label ? (
<label htmlFor={name} className="text">
<span>empty</span>
</label>
) : label_icon ? (
<div className="LabelWithIcon">
<label htmlFor={name} className="text">
{t(`${label ? label : name}`)}
</label>
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
</div>
) : (
<label htmlFor={name} className="text">
{t(`${label ? label : name}`)}
</label>
)}
<Form.Item
hasFeedback
validateStatus={isError ? "error" : ""}
help={isError ? errorMsg : ""}
>
<TimePicker
allowClear
className={`${className} w-100`}
size="large"
defaultValue={formik.values[name]}
onChange={onChange || onCalendarChange}
disabled={isDisabled}
/>
<TimePicker
allowClear
className={`${className} w-100`}
size="large"
value={FormikValue ? dayjs(FormikValue, Formater) : null}
onChange={onChange || onCalendarChange}
disabled={isDisabled}
placeholder={t(
`${placeholder ? placeholder : label ? label : name}`,
)}
format={Formater}
needConfirm={false}
/>
</Form.Item>
</div>
)
}
);
};
export default Time
export default Time;

View File

@ -5,18 +5,21 @@ import DataRange from "./DataRange";
import CheckboxField from "./CheckboxField";
import Default from "./Default";
import File from "./File";
import TextAreaField from './TextArea'
import MaltyFile from "./MaltyFile";
import SearchField from "./SearchField";
import TextField from "./TextField";
import DropFile from "./DropFile.tsx";
export {
Time,
SelectField,
Date,
DataRange,
CheckboxField,
Default,
File,
TextAreaField
}
Time,
SelectField,
Date,
DataRange,
CheckboxField,
Default,
File,
MaltyFile,
SearchField,
TextField,
DropFile,
};

View File

@ -1,21 +1,16 @@
import { useState } from 'react';
import { ErrorMessage, useField, Field, useFormikContext } from 'formik';
import { useTranslation } from 'react-i18next';
import { FaExclamationCircle } from 'react-icons/fa';
import Select from 'react-select';
import { convert_data_to_select } from '../../Layout/app/Const';
import { useState } from "react";
import { ErrorMessage, useField, Field, useFormikContext } from "formik";
import { useTranslation } from "react-i18next";
import { FaExclamationCircle } from "react-icons/fa";
import { convert_data_to_select } from "../../Layout/app/Const";
export {
useState,
ErrorMessage, useField, Field, useFormikContext,
useTranslation,
FaExclamationCircle,
Select,
convert_data_to_select,
}
useState,
ErrorMessage,
useField,
Field,
useFormikContext,
useTranslation,
FaExclamationCircle,
convert_data_to_select,
};

View File

@ -1,133 +0,0 @@
// export interface ValidationFieldProps {
// name: string;
// type?: "text" | "Select" | "DataRange" | "Date" | "Time" | "File" | "number" | "Checkbox" | "password";
// placeholder?: string;
// label?: string;
// className?: string;
// option?: any[];
// isMulti?: boolean;
// isDisabled?: boolean;
// picker?: "data" | "week" | "month" | "quarter" | "year";
// Format?: "YYYY/MM/DD" | "MM/DD" | "YYYY/MM";
// onChange?: (value: any) => void;
// Group?: boolean
// dir?:'ltr' | "rtl"
// }
export interface ValidationFieldPropsText {
name: string;
type: "text";
placeholder?: string;
label?: string;
className?: string;
isDisabled?: boolean;
onChange?: (value: any) => void;
dir?:'ltr' | "rtl"
}
export interface ValidationFieldPropsSelect {
name: string;
type: "Select";
placeholder?: string;
label?: string;
className?: string;
isDisabled?: boolean;
onChange?:any;
dir?:'ltr' | "rtl";
option: any[];
isMulti?: boolean;
}
export interface ValidationFieldPropsSearch{
name: string;
type: "Search";
placeholder?: string;
label?: string;
className?: string;
isDisabled?: boolean;
onChange?: (value: any) => void;
dir?:'ltr' | "rtl";
option: any[];
isMulti?: boolean;
searchBy:string;
loading?:boolean;
}
export interface ValidationFieldPropsDataRange {
name: string;
type: "DataRange";
placeholder?: string;
label?: string;
className?: string;
isDisabled?: boolean;
onChange?: (value: any) => void;
dir?:'ltr' | "rtl"
Format?: "YYYY/MM/DD" | "MM/DD" | "YYYY/MM" | "YYYY-MM-DD HH:mm:ss.SSS";
}
export interface ValidationFieldPropsDate {
name: string;
type: "Date";
placeholder?: string;
label?: string;
className?: string;
isDisabled?: boolean;
onChange?: (value: any) => void;
dir?:'ltr' | "rtl"
picker?: "data" | "week" | "month" | "quarter" | "year";
Format?: "YYYY/MM/DD" | "MM/DD" | "YYYY/MM" | "YYYY-MM-DD HH:mm:ss.SSS" | "YYYY-MM-DD HH:MM:SS";
}
export interface ValidationFieldPropsTime {
name: string;
type: "Time";
label?: string;
placeholder?: string;
className?: string;
isDisabled?: boolean;
onChange?: (value: any) => void;
dir?:'ltr' | "rtl"
}
export interface ValidationFieldPropsFile {
name: string;
type: "File" | "MaltyFile";
acceptedFileType?:string;
placeholder?: string;
label?: string;
className?: string;
isDisabled?: boolean;
onChange?: (value: any) => void;
dir?:'ltr' | "rtl"
}
export interface ValidationFieldPropsCheckbox {
name: string;
type: "Checkbox";
label?: string;
className?: string;
isDisabled?: boolean;
onChange?: (value: any) => void;
dir?:'ltr' | "rtl"
Group?: boolean
}
export interface ValidationFieldPropstext {
name: string;
type?: "text" | "number" | "password" | "TextArea";
label?: string;
className?: string;
placeholder?: string;
isDisabled?: boolean;
onChange?: (value: any) => void;
dir?:'ltr' | "rtl"
Group?: boolean
}
export type ValidationFieldProps = ValidationFieldPropsText| ValidationFieldPropsSelect| ValidationFieldPropsDataRange| ValidationFieldPropsDate| ValidationFieldPropsTime| ValidationFieldPropsFile| ValidationFieldPropsCheckbox| ValidationFieldPropstext | ValidationFieldPropsSearch;

View File

@ -0,0 +1,200 @@
.LabelWithIcon {
display: flex;
width: 100%;
justify-content: space-between;
}
.ValidationField {
margin-bottom: 1.3vw;
position: relative;
> * {
width: 100%;
}
.text,
.ant-form-item {
margin-bottom: 7px !important;
> span {
color: transparent;
}
}
// .ant-select-outlined:not(.ant-select-customize-input) .ant-select-selector {
// border: 1px solid var(--border-color);
// }
.Select_error {
.ant-select-selector {
border: 1px solid red !important;
}
}
// .ValidationField{
// .ant-select-selector{
// border: 1px solid var(--border-color) ;
// }
// }
> span {
margin-bottom: 0px !important;
&:focus-within {
border-color: var(--primary);
box-shadow: 0 0 0 1px var(--primary);
cursor: pointer;
}
&:has(.is-invalid) {
border-color: red !important ;
}
input {
color: var(--text);
background: var(--bg);
}
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active {
-webkit-box-shadow: 0 0 0 30px white inset !important;
}
}
}
.ant-upload-select {
width: 100%;
}
.Checkboxs {
padding: 4%;
}
.SearchField {
button {
background: var(--primary);
}
}
.text {
color: var(--text);
margin-bottom: 15px;
font-weight: bold;
}
input:disabled {
color: var(--text) !important;
}
.isError {
outline: red 1px solid;
color: red;
}
.Error_color {
color: red;
}
// input:-webkit-autofill {
// -webkit-box-shadow: 0 0 0 1000px white inset !important; /* Change the color to your desired background color */
// }
// input:-webkit-autofill:focus {
// -webkit-box-shadow: 0 0 0 1000px white inset !important; /* Change the color to your desired background color */
// }
// /* Remove autofill background color on hover */
// input:-webkit-autofill:hover {
// -webkit-box-shadow: 0 0 0 1000px white inset !important; /* Change the color to your desired background color */
// }
// .upload_image_button {
// .ant-btn {
// min-height: 3vw !important;
// border: 0.1vw solid var(--border-color);
// display: flex;
// align-items: center;
// justify-content: center;
// }
// }
// .ant-select-outlined:not(.ant-select-customize-input) .ant-select-selector {
// min-height: 3vw !important;
// }
// .ant-select-multiple.ant-select-lg .ant-select-selection-overflow {
// min-height: 3vw !important;
// }
// .ant-upload-list .ant-upload-list-item {
// // height:3vw !important;
// border: 1px solid var(--border-color) !important;
// }
// .TowValidationItems {
// display: flex;
// gap: 3%;
// > label {
// display: none;
// }
// }
// .ant-select .ant-select-arrow {
// inset-inline-end: 1vw;
// }
// .ant-input-affix-wrapper-lg {
// padding: 0.5vw 1vw;
// font-size: 1vw;
// min-height: 3vw;
// border-radius: 0.6vw;
// }
// .ant-picker-outlined {
// padding: 0.5vw 1vw;
// font-size: 1vw;
// min-height: 3vw;
// border-radius: 0.6vw;
// border: 1px solid var(--border-color);
// }
// .ant-select-single.ant-select-lg .ant-select-selector {
// min-height: 3vw;
// border-radius: 0.6vw;
// }
// .ant-select-single .ant-select-selector .ant-select-selection-search-input {
// min-height: 3vw;
// }
// .ant-select-outlined .ant-select-selector {
// min-height: 3vw !important;
// border-radius: 0.6vw !important;
// }
// .ant-select-single.ant-select-lg {
// min-height: 3vw;
// }
// .ant-upload-wrapper .ant-upload-list .ant-upload-list-item {
// width: 21.5vw;
// }
// .ant-input-number-outlined {
// width: 100%;
// height: 3vw;
// }
// .ant-input-number-lg ant-input-number-input {
// width: 100%;
// height: 3vw;
// }
// .bigRow {
// width: 100%;
// display: flex;
// justify-content: space-between;
// flex-wrap: wrap;
// > *.w-100 {
// width: 48% !important;
// }
// }
// .ant-input-number-affix-wrapper-lg {
// width: 100%;
// height: 3vw;
// border-radius: 0.6vw;
// border: 1px solid var(--border-color);
// }
// .TwoSelectGroup {
// display: flex;
// gap: 10px;
// margin-bottom: 20px;
// }
// .TwoSelectGroupbutton {
// margin-bottom: 20px;
// }

View File

@ -0,0 +1,11 @@
import { create } from "zustand";
interface ValidationState {
Validation: any[];
setValidation: (value: any[]) => void;
}
export const useValidationState = create<ValidationState>((set) => ({
Validation: [],
setValidation: (value) => set((state) => ({ Validation: value })),
}));

View File

@ -0,0 +1,6 @@
export const translateOptions = (options: any, t: any) => {
return options.map((opt: any) => ({
...opt,
label: t(`${opt.label}`),
}));
};

View File

@ -0,0 +1,171 @@
export type ValidationFieldType =
| "text"
| "Select"
| "LocalSearch"
| "Search"
| "DataRange"
| "Date"
| "Time"
| "File"
| "MaltyFile"
| "DropFile"
| "Checkbox"
| "number"
| "password"
| "email"
| "TextArea";
export interface ValidationFieldPropsText {
name: string;
no_label?: boolean;
label_icon?: boolean;
type: "text";
placeholder?: string;
label?: string;
className?: string;
isDisabled?: boolean;
onChange?: (value: any) => void;
dir?: "ltr" | "rtl";
}
export interface ValidationFieldPropsSelect {
name: string;
no_label?: boolean;
label_icon?: boolean;
type: "Select";
placeholder?: string;
label?: string;
className?: string;
isDisabled?: boolean;
onChange?: any;
dir?: "ltr" | "rtl";
option: any[];
isMulti?: boolean;
}
export interface ValidationFieldPropsLocalSearch {
name: string;
no_label?: boolean;
label_icon?: boolean;
type: "LocalSearch";
placeholder?: string;
label?: string;
className?: string;
isDisabled?: boolean;
onChange?: (value: any) => void;
dir?: "ltr" | "rtl";
option: any[];
isMulti?: boolean;
}
export interface ValidationFieldPropsSearch {
name: string;
no_label?: boolean;
label_icon?: boolean;
type: "Search";
placeholder?: string;
label?: string;
className?: string;
isDisabled?: boolean;
onChange?: (value: any) => void;
dir?: "ltr" | "rtl";
option: any[];
isMulti?: boolean;
searchBy: string;
}
export interface ValidationFieldPropsDataRange {
name: string;
no_label?: boolean;
label_icon?: boolean;
type: "DataRange";
placeholder?: string;
label?: string;
className?: string;
isDisabled?: boolean;
onChange?: (value: any) => void;
dir?: "ltr" | "rtl";
Format?: "YYYY/MM/DD" | "MM/DD" | "YYYY/MM" | "YYYY-MM-DD HH:mm:ss.SSS";
}
export interface ValidationFieldPropsDate {
name: string;
no_label?: boolean;
label_icon?: boolean;
type: "Date";
placeholder?: string;
label?: string;
className?: string;
isDisabled?: boolean;
onChange?: (value: any) => void;
dir?: "ltr" | "rtl";
picker?: "data" | "week" | "month" | "quarter" | "year";
}
export interface ValidationFieldPropsTime {
name: string;
no_label?: boolean;
label_icon?: boolean;
type: "Time";
label?: string;
placeholder?: string;
className?: string;
isDisabled?: boolean;
onChange?: (value: any) => void;
dir?: "ltr" | "rtl";
}
export interface ValidationFieldPropsFile {
name: string;
no_label?: boolean;
label_icon?: boolean;
type: "File" | "MaltyFile" | "DropFile";
acceptedFileType?:string;
placeholder?: string;
label?: string;
className?: string;
isDisabled?: boolean;
onChange?: (value: any) => void;
dir?: "ltr" | "rtl";
}
export interface ValidationFieldPropsCheckbox {
name: string;
no_label?: boolean;
label_icon?: boolean;
type: "Checkbox";
label?: string;
className?: string;
isDisabled?: boolean;
onChange?: (value: any) => void;
dir?: "ltr" | "rtl";
Group?: boolean;
}
export interface ValidationFieldPropstext {
name: string;
no_label?: boolean;
label_icon?: boolean;
type?:
| "text"
| "number"
| "password"
| "email"
| "TextArea"
| "NumberFormate";
label?: string;
className?: string;
placeholder?: string;
isDisabled?: boolean;
onChange?: (value: any) => void;
dir?: "ltr" | "rtl";
Group?: boolean;
[key: string]: any; // Index signature to allow any additional props
}
export type ValidationFieldProps =
| ValidationFieldPropsText
| ValidationFieldPropsSelect
| ValidationFieldPropsLocalSearch
| ValidationFieldPropsDataRange
| ValidationFieldPropsDate
| ValidationFieldPropsTime
| ValidationFieldPropsFile
| ValidationFieldPropsCheckbox
| ValidationFieldPropstext
| ValidationFieldPropsSearch;

View File

@ -1,42 +0,0 @@
import React, { FC } from "react";
import { Editor } from '@tinymce/tinymce-react';
import { useFormikContext } from "formik";
interface HtmlEditorProps {
langCode: number;
name: string;
editorState: string;
}
const HtmlEditor: FC<HtmlEditorProps> = ({ langCode, name, editorState, ...props }) => {
const formik = useFormikContext();
const ar: boolean = langCode === 2;
return (
<Editor
apiKey='6xf0byrgd7m2j28p9dfjittsq884x9j0d3e6dsterqrvtvez'
value={editorState}
init={{
height: 500,
menubar: false,
directionality: ar ? "rtl" : "ltr",
plugins: [
'advlist autolink lists link image charmap print preview anchor',
'searchreplace visualblocks code fullscreen',
'insertdatetime media table paste code help wordcount'
],
toolbar: 'undo redo | formatselect | ' +
'bold italic backcolor | alignleft aligncenter ' +
'alignright alignjustify | bullist numlist outdent indent | ' +
'removeformat | help',
content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }'
}}
onEditorChange={(newValue, editor) => {
formik.setFieldValue(name, newValue)
}}
/>
);
}
export { HtmlEditor };

View File

@ -1,43 +0,0 @@
import React, { FC } from "react";
// import PropTypes from "";
import { HtmlEditor } from "./HtmlEditor";
import { useFormikContext } from "formik";
import { useTranslation } from "react-i18next";
interface SingleLangEditorProps {
langCode: number;
property: string;
}
const PROPERTY_TYPES: string[] = [
"privacy_description",
"conditions_description",
"about_us_description",
"product_description",
"auction_description"
];
const SingleLangEditor: FC<SingleLangEditorProps> = ({ langCode, property }) => {
const formik:any = useFormikContext();
const {t} = useTranslation();
const label = `${t(property)} (${t(`lang_${langCode}`)})`;
const fieldName = `translated_fields[${langCode}][${property}]`;
return (
<>
<h5 className="Information_title">{label}</h5>
<HtmlEditor
langCode={langCode}
name={fieldName}
editorState={formik.values.translated_fields[langCode][property]}
/>
</>
);
};
// SingleLangEditor.propTypes = {
// langCode: PropTypes.oneOf([1, 2]).isRequired,
// property: PropTypes.oneOf(PROPERTY_TYPES).isRequired,
// };
export default SingleLangEditor;

View File

@ -1,23 +0,0 @@
import React, { FC } from "react";
import { Card, CardBody, Spinner } from "reactstrap";
interface StatusCardProps {
isLoading: boolean;
isError: boolean;
}
const StatusCard= ({ isLoading, isError }:StatusCardProps) => {
return (
<Card>
<CardBody
className="d-flex align-items-center justify-content-center"
style={{ height: "15rem" }}
>
{isLoading && <Spinner size="lg" color="primary" />}
{isError && <h4>Failed !</h4>}
</CardBody>
</Card>
);
};
export default StatusCard;

View File

@ -1,65 +0,0 @@
const fs = require('fs');
// Get the file name from the command line arguments
const fileName = process.argv[2];
// Check if a file name is provided
if (!fileName) {
console.error('Please provide a file name.');
process.exit(1);
}
let FileContiner = `
import React from 'react'
import LayoutModal from '../../Layout/Dashboard/LayoutModal'
import Form${capitalizeFirstLetter(fileName)} from './Form${capitalizeFirstLetter(fileName)}'
import { useAdd${capitalizeFirstLetter(fileName)} } from '../../api/${(fileName)}'
import { getDataToSend, getInitialValues, getValidationSchema } from './formUtil'
import { QueryStatusEnum } from '../../config/QueryStatus'
import { useTranslation } from 'react-i18next'
function Add${capitalizeFirstLetter(fileName)}Modal() {
const [t] = useTranslation()
const {mutate , status} = useAdd${capitalizeFirstLetter(fileName)}()
const handelSubmit = (values:any )=>{
const dataToSend = getDataToSend(values)
mutate(dataToSend)
// Submit Value
}
return (
<LayoutModal
isAddModal={true}
getInitialValues={getInitialValues()}
handleSubmit={handelSubmit}
status={status as QueryStatusEnum}
headerText={t('Add') +t('${(fileName)}')}
getValidationSchema={getValidationSchema()}>
<Form${capitalizeFirstLetter(fileName)} />
</LayoutModal>
)
}
export default Add${capitalizeFirstLetter(fileName)}Modal
`
fs.writeFileSync('src/Pages/'+fileName+"/"+"Add"+ capitalizeFirstLetter(fileName)+"Modal.tsx",
FileContiner
);
console.log(`File "${fileName}" generated successfully.`);
function capitalizeFirstLetter(word) {
return (word).charAt(0).toUpperCase() + (word).slice(1);
}

View File

@ -1,40 +0,0 @@
const fs = require('fs');
const fileName = process.argv[2]
if (!fileName) {
console.error('Please provide a file name.');
process.exit(1);
}
let FileContiner = `
import useAddMutation from "./helper/useAddMutation"
import useDeleteMutation from "./helper/useDeleteMutation"
import useGetQuery from "./helper/useGetQuery"
import useUpdateMutation from "./helper/useUpdateMutation"
const API = {
GET: "/api/admin/${fileName}",
ADD: "/api/admin/${fileName}/create",
UPDATE: "/api/admin/${fileName}/update",
DELETE: "/api/admin/${fileName}/delete",
};
const KEY = "${fileName.toUpperCase()}";
export const useGet${capitalizeFirstLetter(fileName)} = (params?:any) => useGetQuery(KEY, API.GET, params);
export const useAdd${capitalizeFirstLetter(fileName)} = () => useAddMutation(KEY, API.ADD);
export const useUpdate${capitalizeFirstLetter(fileName)} = () => useUpdateMutation(KEY, API.UPDATE);
export const useDelete${capitalizeFirstLetter(fileName)} = () =>useDeleteMutation(KEY, API.DELETE);
`
fs.writeFileSync('src/api/'+fileName+".ts",
FileContiner
);
console.log(`File "${fileName}" generated successfully.`);
function capitalizeFirstLetter(word) {
return (word).charAt(0).toUpperCase() + (word).slice(1);
}

View File

@ -1,63 +0,0 @@
const fs = require('fs');
// Get the file name from the command line arguments
const fileName = process.argv[2];
// Check if a file name is provided
if (!fileName) {
console.error('Please provide a file name.');
process.exit(1);
}
let FileContiner = `
import React, { useMemo } from "react";
import { useTranslation } from "react-i18next";
import Actions from "../../Components/Ui/tables/Actions";
function fnDelete(props :any ){}
const useTableColumns :any = () => {
const [t] = useTranslation();
return useMemo(
() => [
{
name: t("email"),
sortable: false,
center: "true",
cell: (row:any) => row?.email
},
{
name: "#",
sortable: false,
center: "true",
cell: (row) => (
<Actions
// importnat to return the row in on Edit Function to store in objectToEdit That Upper in Edit Modal
onEdit={() => row}
onView={()=>{}}
objectToEdit={row}
showEdit={true}
// showDelete={false}
onDelete={() => fnDelete({ id: row.id })}
/>
),
},
],
[t]
);
};
export default useTableColumns;
`
fs.writeFileSync('src/Pages/'+fileName+"/useTableColumns"+".tsx",
FileContiner
);
console.log(`File "${fileName}" generated successfully.`);

View File

@ -1,30 +0,0 @@
const { exec } = require('child_process');
const fileName = process.argv[2]
const CreateApi = `node src/Extensions/FileGenerator/generateApi.js ${fileName}`
const CreatePage = `node src/Extensions/FileGenerator/generatePage.js ${fileName}`
const CreateColumn = `node src/Extensions/FileGenerator/generateColumn.js ${fileName}`
const CreateformUtil= `node src/Extensions/FileGenerator/generateformUtils.js ${fileName}`
const CreateAddModal= `node src/Extensions/FileGenerator/generateAddModal.js ${fileName}`
const CreateEditModal= `node src/Extensions/FileGenerator/generateEditModal.js ${fileName}`
const CreateForm= `node src/Extensions/FileGenerator/generateForm.js ${fileName}`
const RunCommand = async()=>{
exec(CreatePage)
exec(CreateApi)
setTimeout(()=>{},100)
exec(CreateColumn)
exec(CreateformUtil)
exec(CreateAddModal)
exec(CreateEditModal)
exec(CreateForm)
}
RunCommand()

View File

@ -1,47 +0,0 @@
const fs = require('fs');
// Get the file name from the command line arguments
const fileName = process.argv[2];
// Check if a file name is provided
if (!fileName) {
console.error('Please provide a file name.');
process.exit(1);
}
let FileContiner = `
import React from 'react'
import LayoutModal from '../../Layout/Dashboard/LayoutModal'
import Form${capitalizeFirstLetter(fileName)} from './Form${capitalizeFirstLetter(fileName)}'
import { getInitialValues, getValidationSchema } from './formUtil'
import { usePageState } from '../../lib/state mangment/LayoutPagestate'
function Edit${capitalizeFirstLetter(fileName)}Modal() {
const {objectToEdit} = usePageState()
return (
<LayoutModal
isAddModal={false}
getInitialValues={getInitialValues(objectToEdit)}
handleSubmit={() => { }}
headerText='Edit Modal'
getValidationSchema={getValidationSchema(objectToEdit)}>
<Form${capitalizeFirstLetter(fileName)} />
</LayoutModal>
)
}
export default Edit${capitalizeFirstLetter(fileName)}Modal
`
fs.writeFileSync('src/Pages/'+fileName+"/"+"Edit"+ capitalizeFirstLetter(fileName)+"Modal.tsx",
FileContiner
);
console.log(`File "${fileName}" generated successfully.`);
function capitalizeFirstLetter(word) {
return (word).charAt(0).toUpperCase() + (word).slice(1);
}

View File

@ -1,66 +0,0 @@
const fs = require('fs');
// Get the file name from the command line arguments
const fileName = process.argv[2];
// Check if a file name is provided
if (!fileName) {
console.error('Please provide a file name.');
process.exit(1);
}
let FileContiner = `
import React from 'react'
import { Col, Row } from 'reactstrap';
import ValidationField from '../../Components/ValidationField/ValidationField';
import { FakeSelectData } from '../../Layout/app/Const';
import { useFormikContext } from 'formik';
import { DatePicker } from 'antd';
function Form${capitalizeFirstLetter(fileName)}() {
const formik = useFormikContext<any>();
return (
<Row xs={1} sm={1} md={1} lg={2} xl={2}>
<Col>
// name from form utils
<ValidationField name="name" type="text"label='name' placeholder='placeholder' />
<ValidationField name="number" type="number" label='number' placeholder='placeholder' />
<ValidationField name="select" type="select"label='select' option={FakeSelectData} isMulti={true} placeholder='placeholder' />
<ValidationField name="Multiselect" type="select"label='Multiselect' option={FakeSelectData} Disabled={true} placeholder='placeholder'/>
</Col>
<Col>
<ValidationField name="date" type="date" label='date' placeholder='placeholder' />
<ValidationField name="time" type="text"label='time' placeholder='placeholder' />
<ValidationField name="CheckBox" name2='CheckBox2' type="checkbox" label='CheckBox' placeholder='placeholder' group={true} />
<ValidationField name="DateFrom" name2="DateTo" type="DataRange" />
</Col>
</Row>
)
}
export default Form${capitalizeFirstLetter(fileName)}
`
fs.writeFileSync('src/Pages/'+fileName+'/Form'+ capitalizeFirstLetter(fileName)+".tsx",
FileContiner
);
console.log(`File "${fileName}" generated successfully.`);
function capitalizeFirstLetter(word) {
return (word).charAt(0).toUpperCase() + (word).slice(1);
}

View File

@ -1,64 +0,0 @@
const fs = require('fs');
// Get the file name from the command line arguments
const fileName = process.argv[2];
// Check if a file name is provided
if (!fileName) {
console.error('Please provide a file name.');
process.exit(1);
}
let FileContiner = `
import React from 'react'
import LayoutModal from '../../Layout/Dashboard/LayoutModal'
import Form${capitalizeFirstLetter(fileName)} from './Form${capitalizeFirstLetter(fileName)}'
import { useAdd${capitalizeFirstLetter(fileName)} } from '../../api/${(fileName)}'
import { getDataToSend, getInitialValues, getValidationSchema } from './formUtil'
import { QueryStatusEnum } from '../../config/QueryStatus'
import { useTranslation } from 'react-i18next'
function Add${capitalizeFirstLetter(fileName)}Modal() {
const [t] = useTranslation()
const {mutate , status} = useAdd${capitalizeFirstLetter(fileName)}()
const handelSubmit = (values:any )=>{
const dataToSend = getDataToSend(values)
mutate(dataToSend)
// Submit Value
}
return (
<LayoutModal
isAddModal={true}
getInitialValues={getInitialValues()}
handleSubmit={handelSubmit}
status={status as QueryStatusEnum}
headerText={t('Add') +t('${(fileName)}')}
getValidationSchema={getValidationSchema()}>
<Form${capitalizeFirstLetter(fileName)} />
</LayoutModal>
)
}
export default Add${capitalizeFirstLetter(fileName)}Modal
`
fs.writeFileSync('src/Pages/'+fileName+"/"+"Add"+ capitalizeFirstLetter(fileName)+"Modal.tsx",
FileContiner
);
console.log(`File "${fileName}" generated successfully.`);
function capitalizeFirstLetter(word) {
return (word).charAt(0).toUpperCase() + (word).slice(1);
}

View File

@ -1,67 +0,0 @@
const fs = require('fs');
// Get the file name from the command line arguments
const fileName = process.argv[2];
// Check if a file name is provided
if (!fileName) {
console.error('Please provide a file name.');
process.exit(1);
}
const folderPath = 'src/Pages/'+fileName;
if (!fs.existsSync(folderPath)) {
fs.mkdirSync(folderPath, { recursive: true });
}
let FileContiner = `
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 { useGet${capitalizeFirstLetter(fileName)}} from '../../api/${fileName}'
import { QueryStatusEnum } from '../../config/QueryStatus'
import Edit${capitalizeFirstLetter(fileName)}Modal from './Edit${capitalizeFirstLetter(fileName)}Modal'
import Add${capitalizeFirstLetter(fileName)}Modal from './Add${capitalizeFirstLetter(fileName)}Modal'
function ${capitalizeFirstLetter(fileName)}Page() {
const column =useTableColumns()
const {data ,status } = useGet${capitalizeFirstLetter(fileName)}()
return (
// Pass Status to Layout
<DashBody status={status as QueryStatusEnum} >
<DashHeader title={'${capitalizeFirstLetter(fileName)}'}></DashHeader>
<LyTable
data={data}
isLoading={false}
columns={column}
/>
<Edit${capitalizeFirstLetter(fileName)}Modal />
<Add${capitalizeFirstLetter(fileName)}Modal />
</DashBody>
)
}
export default ${capitalizeFirstLetter(fileName)}Page
`
fs.writeFileSync('src/Pages/'+fileName+"/"+capitalizeFirstLetter(fileName)+"Page.tsx",
FileContiner
);
console.log(`File "${fileName}" generated successfully.`);
function capitalizeFirstLetter(word) {
return (word).charAt(0).toUpperCase() + (word).slice(1);
}

View File

@ -1,73 +0,0 @@
const fs = require('fs');
// Get the file name from the command line arguments
const fileName = process.argv[2];
// Check if a file name is provided
if (!fileName) {
console.error('Please provide a file name.');
process.exit(1);
}
let FileContiner = `
import * as Yup from "yup";
import { buildFormData } from "../../api/helper/buildFormData";
interface formUtilCommon {
name:string,
email:string
}
interface ObjectToEdit extends formUtilCommon {
id?:number,
}
interface InitialValues extends ObjectToEdit {
}
interface ValidateSchema extends formUtilCommon{
}
export const getInitialValues = (objectToEdit: ObjectToEdit | null = null): InitialValues => {
return {
id:objectToEdit?.id?? 0 ,
name:objectToEdit?.name ?? "",
email:objectToEdit?.email?? ""
}
};
export const getValidationSchema = (editMode: boolean = false): Yup.Schema<ValidateSchema> => {
// validate input
return Yup.object().shape({
name:Yup.string().required('required'),
email:Yup.string().required("required")
});
};
export const getDataToSend = (values: any): FormData => {
const data = { ...values };
const formData = new FormData();
buildFormData(formData, data);
return formData;
};
`
fs.writeFileSync('src/Pages/'+fileName+"/"+"formUtil.ts",
FileContiner
);
console.log(`File "${fileName}" generated successfully.`);
function capitalizeFirstLetter(word) {
return (word).charAt(0).toUpperCase() + (word).slice(1);
}

View File

@ -1,7 +1,7 @@
import React from 'react'
import './Add_Button.scss'
import { useTranslation } from 'react-i18next'
import { usePageState } from '../../../lib/state mangment/LayoutPagestate'
import { usePageState } from '../../../lib/statemangment/LayoutPagestate'

View File

@ -1,7 +1,7 @@
import React from 'react'
import './Add_Button.scss'
import { useTranslation } from 'react-i18next'
import { usePageState } from '../../../lib/state mangment/LayoutPagestate'
import { usePageState } from '../../../lib/statemangment/LayoutPagestate'

View File

@ -1,7 +1,7 @@
import { Form, Formik } from 'formik'
import React, { useEffect } from 'react'
import { Button, Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap'
import { usePageState } from '../../lib/state mangment/LayoutPagestate'
import { usePageState } from '../../lib/statemangment/LayoutPagestate'
import { useTranslation } from 'react-i18next';
import { LoadingButton } from '../../Components/Ui/LoadingButton';
import { QueryStatusEnum } from '../../config/QueryStatus';

View File

@ -4,7 +4,7 @@ import { Formik, Form } from "formik";
import { LoadingButton } from "../../Components/Ui/LoadingButton";
import ProgressBar from "../../Components/Ui/ProgressBar";
import { useLocation, useNavigate } from "react-router-dom";
import { usePageState } from "../../lib/state mangment/LayoutPagestate";
import { usePageState } from "../../lib/statemangment/LayoutPagestate";
import { useTranslation } from "react-i18next";
type TViewPage ={

View File

@ -1,5 +1,5 @@
import React, { useEffect } from 'react'
import { usePageState } from '../../lib/state mangment/LayoutPagestate'
import { usePageState } from '../../lib/statemangment/LayoutPagestate'
function useCloseModal(statusClose:any) {

View File

@ -3,7 +3,7 @@ import { UserImageURL } from './Const'
import Translate from '../../Components/Utils/Translate'
import { useTranslation } from 'react-i18next'
import { useNavigate } from 'react-router-dom';
import useAuthState from '../../lib/state mangment/AuthState';
import useAuthState from '../../lib/statemangment/AuthState';
import { GiHamburgerMenu } from 'react-icons/gi';
import WithDrawer from './WithDrawer';
import Sidebar from './SideBar';

View File

@ -2,7 +2,7 @@ import React, { useEffect } from 'react'
import SideBar from './SideBar'
import Header from './Header'
import { useNavigate } from 'react-router-dom'
import useAuthState from '../../lib/state mangment/AuthState'
import useAuthState from '../../lib/statemangment/AuthState'
const Layout = ({ children }: { children: React.ReactNode }) => {

View File

@ -7,7 +7,7 @@ import { useTranslation } from 'react-i18next';
import KarimLogo from './KarimLogo';
import { useWindowSize } from '../../Hooks/useWindowSize';
import Etaxi from './Etaxi';
import { usePageState } from '../../lib/state mangment/LayoutPagestate';
import { usePageState } from '../../lib/statemangment/LayoutPagestate';
interface SidebarProps {}

View File

@ -8,7 +8,7 @@ import * as Yup from "yup";
import { getInitialValues, getValidationSchema } from './formUtil';
import { LoadingButton } from '../../Components/Ui/LoadingButton';
import useNavigateOnSuccess from '../../Hooks/useNavigateOnSuccess';
import useAuthState from '../../lib/state mangment/AuthState';
import useAuthState from '../../lib/statemangment/AuthState';
import ValidationField from '../../Components/ValidationField/ValidationField';
const LoginForm = () => {

View File

@ -1,7 +1,7 @@
import React, { useEffect } from 'react'
import LoginForm from './LoginForm';
import { LoginBg } from '../../Layout/app/Const';
import useAuthState from '../../lib/state mangment/AuthState';
import useAuthState from '../../lib/statemangment/AuthState';
import { useNavigate } from 'react-router-dom';
const Auth = () => {

View File

@ -4,18 +4,22 @@ import { Tab, TabList, TabPanel as TabBody, Tabs } from 'react-tabs'
import { MdLanguage } from 'react-icons/md'
import ViewPage from '../../../Layout/Dashboard/ViewPage';
import { Rate, Spin } from 'antd';
import { usePageState } from '../../../lib/state mangment/LayoutPagestate';
import { usePageState } from '../../../lib/statemangment/LayoutPagestate';
import LoadingPage from '../../../Layout/app/LoadingPage';
import { useTranslation } from 'react-i18next';
import { useGetOneCategories, useUpdateCategories } from '../../../api/Categories';
import { useGetCategories, useUpdateCategories } from '../../../api/Categories';
import useNavigateOnSuccess from '../../../Hooks/useNavigateOnSuccess';
import Form from './EditForm';
import { useParams } from 'react-router-dom';
const EditPage = () => {
const { setObjectToEdit, objectToEdit } = usePageState()
const { t } = useTranslation();
const { data,isRefetching } = useGetOneCategories()
const { mutate, isSuccess,isLoading:IsloadingButton } = useUpdateCategories("put")
const {id} = useParams()
const { data,isRefetching } = useGetCategories({
show:id
})
const { mutate, isSuccess,isLoading:IsloadingButton } = useUpdateCategories()
const handleSubmit = (values: any) => {
if( typeof values?.image === "string" ){
delete values["image"]

10
src/Pages/Home/Page.tsx Normal file
View File

@ -0,0 +1,10 @@
import React from 'react'
const Page = () => {
return (
<div>Page</div>
)
}
export default Page

View File

@ -4,18 +4,22 @@ import { Tab, TabList, TabPanel as TabBody, Tabs } from 'react-tabs'
import { MdLanguage } from 'react-icons/md'
import ViewPage from '../../../Layout/Dashboard/ViewPage';
import { Rate, Spin } from 'antd';
import { usePageState } from '../../../lib/state mangment/LayoutPagestate';
import { usePageState } from '../../../lib/statemangment/LayoutPagestate';
import LoadingPage from '../../../Layout/app/LoadingPage';
import { useTranslation } from 'react-i18next';
import { useGetOneMeal, useUpdateMeal } from '../../../api/Meal';
import { useGetMeal, useUpdateMeal } from '../../../api/Meal';
import useNavigateOnSuccess from '../../../Hooks/useNavigateOnSuccess';
import Form from './EditForm';
import { useParams } from 'react-router-dom';
const EditPage = () => {
const { setObjectToEdit, objectToEdit } = usePageState()
const { t } = useTranslation();
const { data,isRefetching } = useGetOneMeal()
const { mutate, isSuccess,isLoading:IsloadingButton } = useUpdateMeal("put")
const {id} = useParams()
const { data,isRefetching } = useGetMeal({
show:id
})
const { mutate, isSuccess,isLoading:IsloadingButton } = useUpdateMeal()
const handleSubmit = (values: any) => {
if( typeof values?.image === "string" ){

View File

@ -4,18 +4,22 @@ import { Tab, TabList, TabPanel as TabBody, Tabs } from 'react-tabs'
import { MdLanguage } from 'react-icons/md'
import ViewPage from '../../../Layout/Dashboard/ViewPage';
import { Rate, Spin } from 'antd';
import { usePageState } from '../../../lib/state mangment/LayoutPagestate';
import { usePageState } from '../../../lib/statemangment/LayoutPagestate';
import LoadingPage from '../../../Layout/app/LoadingPage';
import { useTranslation } from 'react-i18next';
import { useGetOneOffer, useUpdateOffer } from '../../../api/Offer';
import { useGetOffer, useUpdateOffer } from '../../../api/Offer';
import useNavigateOnSuccess from '../../../Hooks/useNavigateOnSuccess';
import Form from './EditForm';
import { useParams } from 'react-router-dom';
const EditPage = () => {
const { setObjectToEdit, objectToEdit } = usePageState()
const { t } = useTranslation();
const { data,isRefetching } = useGetOneOffer()
const { mutate, isSuccess,isLoading:IsloadingButton } = useUpdateOffer("put")
const {id} = useParams()
const { data,isRefetching } = useGetOffer({
show:id
})
const { mutate, isSuccess,isLoading:IsloadingButton } = useUpdateOffer()
const handleSubmit = (values: any) => {
if( typeof values?.image === "string" ){
delete values["image"]

View File

@ -0,0 +1,96 @@
import React from "react";
import { Input, Button } from "antd";
import { useFormikContext } from "formik";
import { useTranslation } from "react-i18next";
interface FieldGroupProps {
array_name: string;
title:string;
static?: boolean;
only_value?: boolean;
}
const FieldGroup: React.FC<FieldGroupProps> = ({ array_name ,title,static:isStatic,only_value}) => {
const { values, setFieldValue } = useFormikContext<any>();
const addFieldGroup = () => {
setFieldValue(array_name, [
...(values?.[array_name] || []),
{ key: null, value: null },
]);
};
const deleteFieldGroup = () => {
const updatedArray = values?.[array_name]?.slice(0, -1) || [];
setFieldValue(array_name, updatedArray);
};
const handleChangeKey = (
e: React.ChangeEvent<HTMLInputElement>,
index: number
) => {
const Selects = values?.[array_name] ?? [];
Selects[index].key = e.target.value;
setFieldValue(array_name, Selects);
};
const handleChangeValue = (
e: React.ChangeEvent<HTMLInputElement>,
index: number
) => {
const Selects = values?.[array_name] ?? [];
Selects[index].value = e.target.value;
setFieldValue(array_name, Selects);
};
const selectsArray = values?.[array_name] ?? [];
const { t } = useTranslation();
return (
<>
<label htmlFor={array_name} className="text">
<h5 className="mb-2">{t(title)}</h5>
</label>
{selectsArray.map((group: { key: string; value: string }, index: number) => (
<div key={index} className="d-flex gap-2 mb-3">
<Input
placeholder={t("key")}
onChange={(e) => handleChangeKey(e, index)}
value={group.key}
size="large"
style={{ width: "100%" }}
allowClear
disabled={only_value}
/>
<Input
placeholder={t("value")}
onChange={(e) => handleChangeValue(e, index)}
value={group.value}
size="large"
style={{ width: "100%" }}
allowClear
/>
</div>
))}
{!isStatic &&
<div className="d-flex gap-2">
<Button
type="dashed"
onClick={addFieldGroup}
>
{t("add_new")}
</Button>
<Button
type="dashed"
onClick={deleteFieldGroup}
>
{t("delete_last")}
</Button>
</div>
}
</>
);
};
export default FieldGroup;

View File

@ -1,16 +1,14 @@
import { Image, Spin } from "antd";
import React from "react";
import SimpleMap from "./Map";
import { useGetOneSetting, useGetSetting } from "../../api/GuestApi";
import { useGetSetting } from "../../api/GuestApi";
import { TOKEN_KEY } from "../../api/config";
import useAuthState from "../../lib/state mangment/AuthState";
import useAuthState from "../../lib/statemangment/AuthState";
import ReactPlayer from 'react-player'
import { FaEdit } from "react-icons/fa";
import { useNavigate } from "react-router-dom";
const Page = () => {
const { token } = useAuthState();
console.log(token, "token");
const navigate= useNavigate()
const fake = "900310ff-610f-11ee-9fbc-00505649cf62";
const { data, isLoading } = useGetSetting({
@ -29,10 +27,13 @@ const Page = () => {
id
} = data?.data ?? [];
console.log(attributes, "attribute");
console.log(video,"video");
const fakeIMage = [1,1,1,1,1,1]
const handel_navigate = (id:number)=>{
console.log(id);
navigate(`/Setting/${id}`)
}
if(isLoading){
return <Spin/>
}
@ -43,6 +44,7 @@ const Page = () => {
width={200}
src={logo}
className="Personal_Image"
fallback="/Layout/images.png"
/>
<div>
<h1>{name}</h1>
@ -86,8 +88,8 @@ const Page = () => {
}
<div className="EditButton" onClick={()=> navigate(id)} >
<FaEdit size={30}/>
<div className="EditButton" >
<FaEdit onClick={()=> handel_navigate(id)} size={30}/>
</div>
</div>
);

View File

@ -4,23 +4,28 @@ import { Col, Row } from 'reactstrap';
import ValidationField from '../../../Components/ValidationField/ValidationField';
import { useGetCategories } from '../../../api/Categories';
import useFormatToSelect from '../../../Hooks/useFormatToSelect';
import FieldGroup from '../Groups/FieldGroup';
function Form() {
const {data:Categories} = useGetCategories()
const SelectCategoriesData = useFormatToSelect(Categories?.data)
return (
<Row xs={1} sm={1} md={1} lg={2} xl={2}>
<Col>
<ValidationField name="name" />
<ValidationField name="address" />
<ValidationField name="categories_id" type='Select' option={SelectCategoriesData} />
<ValidationField name="description" type='TextArea' />
<ValidationField name="categories" type='Select' option={SelectCategoriesData} isMulti />
{/* <ValidationField name="description" type='TextArea' /> */}
<ValidationField name="phone_number" />
<ValidationField name="email" />
<FieldGroup array_name='slogan' title='slogan' />
</Col>
<Col>
<ValidationField type='File' name='logo' />
<ValidationField type='MaltyFile' name='images' />
<ValidationField type='File' name='video' acceptedFileType='.mp4' />

View File

@ -4,28 +4,45 @@ import { Tab, TabList, TabPanel as TabBody, Tabs } from 'react-tabs'
import { MdLanguage } from 'react-icons/md'
import ViewPage from '../../../Layout/Dashboard/ViewPage';
import { Rate, Spin } from 'antd';
import { usePageState } from '../../../lib/state mangment/LayoutPagestate';
import { usePageState } from '../../../lib/statemangment/LayoutPagestate';
import LoadingPage from '../../../Layout/app/LoadingPage';
import { useTranslation } from 'react-i18next';
import { useGetOneMeal, useUpdateMeal } from '../../../api/Meal';
import { useGetSetting, useUpdateSetting } from '../../../api/setting';
import useNavigateOnSuccess from '../../../Hooks/useNavigateOnSuccess';
import Form from './EditForm';
import { useParams } from 'react-router-dom';
import { convertArrayToJsonString } from '../../../utils/Array/convertArrayToJsonString';
const EditPage = () => {
const { setObjectToEdit, objectToEdit } = usePageState()
const { t } = useTranslation();
const { data,isRefetching } = useGetOneMeal()
const { mutate, isSuccess,isLoading:IsloadingButton } = useUpdateMeal("put")
const handleSubmit = (values: any) => {
const {id} = useParams()
const { data,isRefetching } = useGetSetting({
show:id
})
const { mutate, isSuccess,isLoading:IsloadingButton } = useUpdateSetting()
const handleSubmit = (values:any) => {
const dataToSend = {...values};
const slogan = convertArrayToJsonString(values?.slogan);
const phone_number = values?.phone_number;
const email = values?.email;
const contact_info = convertArrayToJsonString([{key: 'phone_number', value:phone_number},{key: 'email', value:email}])
dataToSend["slogan"] = slogan;
dataToSend["contact_info"] = contact_info;
// mutate({...values, _method : "put"});
console.log(dataToSend,"dataToSend");
if( typeof values?.image === "string" ){
delete values["video"]
}
mutate({...values, _method : "put"});
}
useNavigateOnSuccess(isSuccess, '/Meal')
useNavigateOnSuccess(isSuccess, '/Setting')
useEffect(() => {
@ -42,11 +59,10 @@ const EditPage = () => {
return <Spin />
}
const ViewProps = { getInitialValues, getValidationSchema, handleSubmit,IsloadingButton };
return (
<div className='ViewPage'>
{objectToEdit && data ?

View File

@ -1,15 +1,29 @@
import * as Yup from "yup";
import { KeyAndValue, objectToArray } from "../../utils/object/objectToArray";
import { Restaurant } from "../../types/item";
export const getInitialValues = (objectToEdit: any | null = null): any => {
export const getInitialValues = (objectToEdit: Restaurant ): any => {
console.log(objectToEdit,"objectToEdit");
const slogan: KeyAndValue[] = objectToArray(objectToEdit?.slogan);
const contact_info: KeyAndValue[] = objectToArray(objectToEdit?.contact_info);
const categories = objectToEdit?.categories?.map((item:any)=>(item.id)) || null;
console.log(categories,"categories");
return {
id: objectToEdit?.id ?? null,
name: objectToEdit?.name ?? null,
images: objectToEdit?.images ?? null,
logo: objectToEdit?.logo ?? null,
address: objectToEdit?.address ?? null,
contact_info: objectToEdit?.contact_info ?? null,
slogan: objectToEdit?.slogan ?? null,
phone_number:contact_info?.[0]?.value ?? null,
email:contact_info?.[1]?.value ?? null,
categories:categories,
slogan: slogan ?? null,
video: objectToEdit?.video ?? null,
attributes: objectToEdit?.attributes ?? null,
};

View File

@ -2,13 +2,11 @@ import React, { ReactNode } from 'react'
import QueryProvider from './lib/ReactQueryProvider'
import { BrowserRouter } from 'react-router-dom'
import ToastProvider from './lib/ToastProvider'
import { createBrowserHistory } from 'history'
type ProviderContainerProps = {
children:ReactNode
}
export let history = createBrowserHistory()
function ProviderContainer({children}:ProviderContainerProps) {
return (
<BrowserRouter basename='/'>

View File

@ -29,7 +29,7 @@ import { SettingFilled } from "@ant-design/icons";
import { GiMeal } from "react-icons/gi";
import Home from './Pages/Home/Page'
@ -48,7 +48,7 @@ export const RoutesLinks: RoutesLinksType[] = [
{
name: "Home",
element: <>Home Page</>,
element: <Home/>,
icon: <FaHome />,
href: "/",
},

View File

@ -1,5 +1,5 @@
:root {
--primary:#E57DB1 ;
--primary:black ;
--secondary : #2D9CDB;
--text: #565656;
--bg: #ffffff;

View File

@ -1,9 +1,8 @@
import useGetQueryPagination from "./helper/ueGetPagination";
import useGetQuery from "./helper/useGetQuery";
import useAddMutation from "./helper/useAddMutation"
import useDeleteMutation from "./helper/useDeleteMutation"
import useGetOneQuery from "./helper/useGetOneQuery";
import useUpdateMutationPost from "./helper/useUpdateMutationPut";
import useUpdateMutation from "./helper/useUpdateMutation";
const API = {
ADD: `category`,
@ -15,10 +14,9 @@ const API = {
const KEY = "categories"
export const useGetCategories = (params?:any) => useGetQueryPagination(KEY, API.GET_ALL,params);
export const useGetOneCategories = () => useGetOneQuery(KEY, API.GET_ALL);
export const useGetCategories = (params?:any,option?:any) => useGetQuery(KEY, API.GET_ALL,params);
export const useAddCategories = () => useAddMutation(KEY, API.ADD);
export const useUpdateCategories = (method?:any) => useUpdateMutationPost(KEY, API.UPDATE,true,method);
export const useUpdateCategories = (method?:any) => useUpdateMutation(KEY, API.UPDATE);
export const useDeleteCategories = () =>useDeleteMutation(KEY, API.DELETE);

View File

@ -1,10 +1,8 @@
import useGetQuery from "./helper/useGetQuery";
import useGetQueryPagination from "./helper/ueGetPagination";
import useAddMutation from "./helper/useAddMutation"
import useDeleteMutation from "./helper/useDeleteMutation"
import useGetOneQuery from "./helper/useGetOneQuery";
import useUpdateMutationPost from "./helper/useUpdateMutationPut";
import useUpdateMutation from "./helper/useUpdateMutation";
const API = {
ADD: `guest/restaurant`,
@ -16,10 +14,9 @@ const API = {
const KEY = "setting"
export const useGetSetting = (params?:any) => useGetQuery(KEY, API.GET_ALL,params);
export const useGetOneSetting = () => useGetOneQuery(KEY, API.GET_ALL);
export const useGetSetting = (params?:any,option?:any) => useGetQuery(KEY, API.GET_ALL,params);
export const useAddSetting = () => useAddMutation(KEY, API.ADD);
export const useUpdateSetting = (method?:any) => useUpdateMutationPost(KEY, API.UPDATE,true,method);
export const useUpdateSetting = (method?:any) => useUpdateMutation(KEY, API.UPDATE);
export const useDeleteSetting = () =>useDeleteMutation(KEY, API.DELETE);

View File

@ -1,9 +1,8 @@
import useGetQueryPagination from "./helper/ueGetPagination";
import useAddMutation from "./helper/useAddMutation"
import useDeleteMutation from "./helper/useDeleteMutation"
import useGetOneQuery from "./helper/useGetOneQuery";
import useUpdateMutationPost from "./helper/useUpdateMutationPut";
import useGetQuery from "./helper/useGetQuery";
import useUpdateMutation from "./helper/useUpdateMutation";
const API = {
ADD: `meal`,
@ -15,10 +14,9 @@ const API = {
const KEY = "Meal"
export const useGetMeal = (params?:any) => useGetQueryPagination(KEY, API.GET_ALL,params);
export const useGetOneMeal = () => useGetOneQuery(KEY, API.GET_ALL);
export const useGetMeal = (params?:any,option?:any) => useGetQuery(KEY, API.GET_ALL,params,option);
export const useAddMeal = () => useAddMutation(KEY, API.ADD);
export const useUpdateMeal = (method?:any) => useUpdateMutationPost(KEY, API.UPDATE,true,method);
export const useUpdateMeal = () => useUpdateMutation(KEY, API.UPDATE);
export const useDeleteMeal = () =>useDeleteMutation(KEY, API.DELETE);

View File

@ -1,9 +1,8 @@
import useGetQueryPagination from "./helper/ueGetPagination";
import useGetQuery from "./helper/useGetQuery";
import useAddMutation from "./helper/useAddMutation"
import useDeleteMutation from "./helper/useDeleteMutation"
import useGetOneQuery from "./helper/useGetOneQuery";
import useUpdateMutationPost from "./helper/useUpdateMutationPut";
import useUpdateMutation from "./helper/useUpdateMutation";
const API = {
ADD: `offer`,
@ -15,10 +14,9 @@ const API = {
const KEY = "Offer"
export const useGetOffer = (params?:any) => useGetQueryPagination(KEY, API.GET_ALL,params);
export const useGetOneOffer = () => useGetOneQuery(KEY, API.GET_ALL);
export const useGetOffer = (params?:any,option?:any) => useGetQuery(KEY, API.GET_ALL,params);
export const useAddOffer = () => useAddMutation(KEY, API.ADD);
export const useUpdateOffer = (method?:any) => useUpdateMutationPost(KEY, API.UPDATE,true,method);
export const useUpdateOffer = (method?:any) => useUpdateMutation(KEY, API.UPDATE);
export const useDeleteOffer = () =>useDeleteMutation(KEY, API.DELETE);

View File

@ -1,9 +1,8 @@
import useGetQueryPagination from "./helper/ueGetPagination";
import useGetQuery from "./helper/useGetQuery";
import useAddMutation from "./helper/useAddMutation"
import useDeleteMutation from "./helper/useDeleteMutation"
import useGetOneQuery from "./helper/useGetOneQuery";
import useUpdateMutationPost from "./helper/useUpdateMutationPut";
import useUpdateMutation from "./helper/useUpdateMutation";
const API = {
ADD: `restaurant`,
@ -15,10 +14,9 @@ const API = {
const KEY = "Restaurant"
export const useGetRestaurant = (params?:any) => useGetQueryPagination(KEY, API.GET_ALL,params);
export const useGetOneRestaurant = () => useGetOneQuery(KEY, API.GET_ALL);
export const useGetRestaurant = (params?:any,option?:any) => useGetQuery(KEY, API.GET_ALL,params);
export const useAddRestaurant = () => useAddMutation(KEY, API.ADD);
export const useUpdateRestaurant = (method?:any) => useUpdateMutationPost(KEY, API.UPDATE,true,method);
export const useUpdateRestaurant = (method?:any) => useUpdateMutation(KEY, API.UPDATE);
export const useDeleteRestaurant = () =>useDeleteMutation(KEY, API.DELETE);

View File

@ -15,3 +15,5 @@ export const TOKEN_KEY = PROJECT_NAME + "_TOKEN"
export const USER_KEY = PROJECT_NAME + "_USER"
export const HEADER_KEY = "X-Custom-Query-Key";

View File

@ -1,49 +1,43 @@
import axios, { AxiosInstance, AxiosRequestConfig ,ResponseType } from 'axios';
import axios, { AxiosInstance, AxiosRequestConfig, ResponseType } from "axios";
class AxiosBuilder {
private baseURL: string = '';
private headers: Record<string, string> = {};
private timeout: number = 60000; // Request failed with 60 second
private withCreds: boolean = false;
private responseType: ResponseType = 'json';
// Custom Another Props with Your Position
private baseURL: string = "";
private headers: Record<any, any> = {};
private timeout: number = 60000; // Request failed with 60 second
private withCreds: boolean = false;
private responseType: ResponseType = "json";
// Custom Another Props with Your Position
withBaseURL(baseURL: string): AxiosBuilder {
this.baseURL = baseURL;
return this;
}
withHeaders(headers: Record<string, string>): AxiosBuilder {
this.headers = headers;
return this;
}
withTimeout(timeout: number): AxiosBuilder {
this.timeout = timeout;
return this;
}
withBaseURL(baseURL: string): AxiosBuilder {
this.baseURL = baseURL;
return this;
}
withHeaders(headers: Record<any, any>): AxiosBuilder {
this.headers = headers;
return this;
}
withTimeout(timeout: number): AxiosBuilder {
this.timeout = timeout;
return this;
}
withResponseType(responseType: ResponseType): AxiosBuilder {
this.responseType = responseType;
return this;
}
build(): AxiosInstance {
const config: AxiosRequestConfig = {
baseURL: this.baseURL,
headers: this.headers,
timeout: this.timeout,
responseType:this.responseType
};
return axios.create(config);
}
build(): AxiosInstance {
const config: AxiosRequestConfig = {
baseURL: this.baseURL,
headers: this.headers,
timeout: this.timeout,
responseType: this.responseType,
};
return axios.create(config);
}
}
export default AxiosBuilder
export default AxiosBuilder;

View File

@ -1,27 +0,0 @@
export const buildFormData = (
formData: FormData,
data: any,
parentKey?: string
): void => {
if (
data &&
typeof data === "object" &&
!(data instanceof Date) &&
!(data instanceof File)
) {
Object.keys(data).forEach((key) => {
buildFormData(
formData,
data[key],
parentKey ? `${parentKey}[${key}]` : key
);
});
} else {
const value = data == null ? "" : data;
formData.append(parentKey as string, value);
}
};

View File

@ -1,44 +0,0 @@
import { useQuery } from 'react-query';
import useAxios from './useAxios';
import { useLocation, useNavigate } from 'react-router-dom';
import useAuthState from '../../lib/state mangment/AuthState';
export default function useGetQueryPagination(KEY: string | string[], Api: string, params: any = {}, options: any = {}, dontSearchBy?: string) {
const axios = useAxios();
const location = useLocation();
let pagination = location?.search || '';
const language = localStorage.getItem("language") ?? "en"
const { logout } = useAuthState();
const navigate = useNavigate();
if (dontSearchBy && pagination.includes(dontSearchBy)) {
const searchParams = new URLSearchParams(pagination);
searchParams.delete(dontSearchBy);
pagination = searchParams.toString();
}
if (pagination && !pagination.startsWith('?')) {
pagination = '?' + pagination;
}
// Check if pagination exists and append it to the API endpoint
const paginationParams = pagination ? pagination + '&orderById=desc' : '?orderById=desc';
const apiUrl = Api + paginationParams;
return useQuery(
[Array.isArray(KEY) ? KEY.join(',') : KEY, pagination,language], async () => {
const response = await axios.get(apiUrl, { params });
return response.data;
},
{
onError: (error: any) => {
if (error?.response?.status === 401 || error?.response?.status === 403) {
logout();
navigate("/auth");
}
},
refetchOnWindowFocus: false,
...options
}
);
}

View File

@ -1,38 +1,28 @@
import { useMutation, useQueryClient, UseMutationResult } from 'react-query';
import { toast } from 'react-toastify';
import useAxios from './useAxios';
import { useTranslation } from 'react-i18next';
import { useMutation, UseMutationResult } from "react-query";
import useAxios from "./useAxios";
import { HEADER_KEY } from "../config";
import { AxiosResponse } from "../../types/Axios";
type AxiosResponse = {
message: string;
data:any ,
success:true
};
function useAddMutation(
key: string,
url: string,
message?: string,
function useAddMutation(key: string, url: string,message?:string): UseMutationResult<AxiosResponse, unknown, any, unknown> {
): UseMutationResult<AxiosResponse, unknown, any, unknown> {
const axios = useAxios();
const [t] = useTranslation();
const queryClient = useQueryClient();
return useMutation<AxiosResponse, unknown, any, unknown>(
async (dataToSend) => {
const { data } = await axios.post(url, dataToSend,{
const { data } = await axios.post(url, dataToSend, {
headers: {
'Content-Type': 'multipart/form-data'
}
} );
"Content-Type": "multipart/form-data",
[HEADER_KEY]: key,
},
});
return data;
},
{
onSuccess: (data) => {
queryClient.invalidateQueries([key]);
toast.success(data.message || t(message??"") || t("added_successful"));
},
onError: (error:any) => {
const message = error?.response?.data?.message || t("failed_to_add_data");
toast.error(message);
}
}
);
}

View File

@ -1,35 +0,0 @@
import { useMutation, useQueryClient, UseMutationResult } from 'react-query';
import { toast } from 'react-toastify';
import useAxios from './useAxios';
import { useTranslation } from 'react-i18next';
type AxiosResponse = {
message: string;
data:any ,
success:true
};
function useAddMutationJson(key: string, url: string): UseMutationResult<AxiosResponse, unknown, any, unknown> {
const axios = useAxios();
const [t] = useTranslation();
const queryClient = useQueryClient();
return useMutation<AxiosResponse, unknown, any, unknown>(
async (dataToSend) => {
const { data } = await axios.post(url, dataToSend);
return data;
},
{
onSuccess: (data) => {
queryClient.invalidateQueries([key]);
toast.success(data.message || t("added_successful"));
},
onError: (error:any) => {
const message = error?.response?.data?.message || t("failed_to_add_data");
toast.error(message);
}
}
);
}
export default useAddMutationJson;

View File

@ -1,25 +1,78 @@
import { BaseURL } from '../config'
import useAuthState from '../../lib/state mangment/AuthState'
import AxiosBuilder from './AxiosBuilder'
import { BaseURL, HEADER_KEY } from "../config";
import AxiosBuilder from "./AxiosBuilder";
import { useTranslation } from "react-i18next";
import { toast } from "react-toastify";
import { useQueryClient } from "react-query";
import { useNavigate } from "react-router-dom";
import useAuthState from "../../lib/statemangment/AuthState";
import { useValidationState } from "../../Components/ValidationField/utils/ValidationState";
import { AxiosQueryEnum, AxiosStatusEnum } from "../../enums/Axios";
function useAxios() {
const {isAuthenticated , token}= useAuthState()
const buildAxios = new AxiosBuilder().
withBaseURL(BaseURL)
.withResponseType('json')
.withTimeout(120000)
.withHeaders({"Content-Type" :"application/json"})
const { isAuthenticated, token } = useAuthState();
if(isAuthenticated){
const { setValidation } = useValidationState((state) => state);
const [t] = useTranslation();
const queryClient = useQueryClient();
buildAxios.withHeaders({ Authorization: 'Bearer '+ token })
}
return (
buildAxios.build()
)
const { logout } = useAuthState();
const navigate = useNavigate();
const buildAxios = new AxiosBuilder()
.withBaseURL(BaseURL)
.withResponseType("json")
.withTimeout(120000);
if (isAuthenticated) {
buildAxios.withHeaders({
Authorization: "Bearer " + token,
});
}
const build_Axios = buildAxios.build();
build_Axios.interceptors.response.use(
function (response: any) {
const responseMsg = response?.data?.message;
const method = response.config.method;
const key = response.config.headers[HEADER_KEY];
const ResponseMessage =
responseMsg || t("validation.the_possess_done_successful");
if (method !== AxiosQueryEnum?.GET) {
queryClient.invalidateQueries(key);
toast.success(ResponseMessage);
setValidation([{}]);
}
return response;
},
function (error) {
const status = error?.request?.status;
const errorMsg = error?.response?.data?.message;
const errorField = error?.response?.data;
const method = error.config.method;
if (status === AxiosStatusEnum.VALIDATION) {
setValidation(errorMsg ?? errorField);
const errorMessage = errorMsg || t("validation.some_thing_went_wrong");
toast.error(errorMessage);
}
if (status === AxiosStatusEnum.AUTHENTICATED) {
logout();
navigate("/auth");
}
if (method !== AxiosQueryEnum?.GET) {
const errorMessage = errorMsg || t("validation.some_thing_went_wrong");
toast.error(errorMessage);
return Promise.reject(error);
}
},
);
return build_Axios;
// return buildAxios.build();
}
export default useAxios
export default useAxios;

View File

@ -1,34 +1,27 @@
import { useMutation, useQueryClient, UseMutationResult } from 'react-query';
import { toast } from 'react-toastify';
import useAxios from './useAxios';
import { useTranslation } from 'react-i18next';
import { useMutation, UseMutationResult } from "react-query";
import useAxios from "./useAxios";
import { HEADER_KEY } from "../config";
import { AxiosResponse } from "../../types/Axios";
type AxiosResponse = {
message: string;
// Add other properties as needed
type DataToSend = {
id: number | string;
};
function useDeleteMutation(key:any , url: string): UseMutationResult<AxiosResponse, unknown, any, unknown> {
function useDeleteMutation(
key: any,
url: string,
message?: string,
): UseMutationResult<AxiosResponse, unknown, DataToSend, unknown> {
const axios = useAxios();
const queryClient = useQueryClient();
const {t} = useTranslation();
return useMutation<AxiosResponse, unknown, any, unknown>(
async ({dataToSend,id}:any) => {
const { data } = await axios.delete(url+"/"+id );
return {...data, id,dataToSend};
return useMutation<AxiosResponse, unknown, DataToSend, unknown>(
async (dataToSend) => {
const { data } = await axios.delete(url + `/` + dataToSend?.id, {
headers: {
[HEADER_KEY]: key,
},
});
return data;
},
{
onSuccess: (data) => {
queryClient.invalidateQueries(key);
toast.success(t('deleted_successfully'));
},
onError: (error:any) => {
const message = error?.response?.data?.message || t("failed_to_add_data");
toast.error(message);
}
},
);
}

View File

@ -1,39 +0,0 @@
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(
[id, key,language],
async () => {
const response = await axios.get(url+"/"+ id+`?lang=${language}`);
return response.data;
},
{
onError: (error:any) => {
if(error.response.status == 401 || error.response.status == 403){
logout()
navigate("/auth")
}
},
cacheTime: 0, // Set cacheTime to 0 to disable caching
refetchOnWindowFocus: false,
...options
}
);
}
export default useGetOneQuery;

View File

@ -1,24 +1,39 @@
import { useQuery } from 'react-query';
import useAxios from './useAxios';
import { useQuery } from "react-query";
import useAxios from "./useAxios";
import { useLocation } from "react-router-dom";
import { PaginationParams } from "../utils/PaginationParams";
import { filterParams } from "../utils/filterParams";
function useGetQuery(KEY: string | string[], url: string, params: any = {}, options: any = {}) {
function useGetQuery(
KEY: string | string[],
url: string,
params: any = {},
options: any = {},
) {
const axios = useAxios();
const show = params.show ? "/" + params.show : '';
const filteredParams = Object.fromEntries(
Object.entries(params).filter(([_, value]) => value !== '')
);
const { show, pagination, ...remainingParams } = params;
return useQuery([KEY, filteredParams], async () => {
const response = await axios.get(url + show, { params: filteredParams });
return response.data;
}, {
onError: (error) => {
console.error('An error occurred:', error);
const location = useLocation();
const { page, per_page } = PaginationParams(location);
const param_to_send = pagination
? { ...remainingParams, page: page, per_page: per_page }
: { ...remainingParams };
const filteredParams = filterParams(param_to_send);
return useQuery(
[KEY, filteredParams, show],
async () => {
const response = await axios.get(url + (show ? `/${show}` : ""), {
params: filteredParams,
});
return response?.data ?? [];
},
refetchOnWindowFocus: false,
...options
});
options,
);
}
export default useGetQuery;

View File

@ -1,38 +0,0 @@
import { useQuery } from 'react-query';
import useAxios from './useAxios';
import useAuthState from '../../lib/state mangment/AuthState';
import { useNavigate, useParams } from 'react-router-dom';
function useGetSingleQuery(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(
[id, key,params?.id],
async () => {
const response = await axios.get(url+"?"+params?.name+"="+params?.id+`?lang=${language}`);
return response.data;
},
{
onError: (error:any) => {
if(error.response.status == 401 || error.response.status == 403){
logout()
navigate("/auth")
}
},
refetchOnWindowFocus: false,
...options
}
);
}
export default useGetSingleQuery;

View File

@ -1,22 +0,0 @@
import { useQuery } from 'react-query';
import useAxios from './useAxios';
export default function useGetQueryPagination(KEY: string | string[], Api: string, options: any = {}) {
const axios = useAxios();
const pagination = options;
return useQuery(
[ KEY], async () => {
const response = await axios.get(Api + pagination );
return response.data;
},
{
onError: (error:any) => {
},
}
);
}

View File

@ -1,32 +0,0 @@
import { useQueryClient, useMutation } from "react-query";
import { toast } from "react-toastify";
import { useTranslation } from "react-i18next";
import useAxios from "./useAxios";
export const useToggleStatus = (key:any, url:any, object_id:any) => {
const axios = useAxios();
const queryClient = useQueryClient();
const [t] = useTranslation();
return useMutation(
async ({ id, new_status }:any) => {
const { data } = await axios.post(url, {
[object_id]: id,
new_status,
});
return { ...data, id, new_status };
},
{
onSuccess: ({ message, id, new_status }) => {
toast.success(message || t("toggle_success"));
queryClient.invalidateQueries([key]);
},
onError: (err:any) => {
const message = err?.response?.data?.message || t("toggle_failed");
toast.error(message);
// validateSession(err.response);
},
}
);
};

View File

@ -1,58 +1,36 @@
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;
// Add other properties as needed
};
import { useMutation, UseMutationResult } from "react-query";
import useAxios from "./useAxios";
import { HEADER_KEY } from "../config";
import { AxiosResponse } from "../../types/Axios";
const useUpdateMutation = (
key: string,
url: string,
toastMessage: boolean = false,
method?:string
): UseMutationResult<AxiosResponse, unknown, unknown> => {
message?: string,
): UseMutationResult<AxiosResponse, any, any, any> => {
const axios = useAxios();
const queryClient = useQueryClient();
const [t] = useTranslation();
const {id}= useParams()
return useMutation<AxiosResponse, unknown, unknown>(
async (dataToSend) => {
if(method === "put"){
const { data } = await axios.put(url+"/"+id, dataToSend );
return data;
}else{
const { data } = await axios.post(url+"/"+id, dataToSend,{
headers: {
'Content-Type': 'multipart/form-data'
}
});
return data;
}
return useMutation<AxiosResponse, any, any>(async (dataToSend) => {
let request = null;
let id = null;
},
{
onSuccess: (data) => {
if (toastMessage) {
toast.success(data.message || t("updated_successfully"));
}
queryClient.invalidateQueries([key]);
},
onError: (err:any) => {
const message = err?.response?.data?.message || t("failed_to_update_data");
toast.error(message);
// validateSession(err.response);
},
if (dataToSend instanceof FormData) {
dataToSend.append("_method", "PUT");
request = dataToSend;
id = dataToSend.get("id");
} else {
request = { ...dataToSend, _method: "PUT" };
id = dataToSend?.id;
}
);
const { data } = await axios.post(url + `/` + id, request, {
headers: {
"Content-Type": "multipart/form-data",
[HEADER_KEY]: key,
},
});
return data;
});
};
export default useUpdateMutation;

View File

@ -1,57 +0,0 @@
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;
// Add other properties as needed
};
const useUpdateMutationById = (
key: string,
url: string,
toastMessage: boolean = false,
method?:string
): UseMutationResult<AxiosResponse, unknown, unknown> => {
const axios = useAxios();
const queryClient = useQueryClient();
const [t] = useTranslation();
return useMutation<AxiosResponse, unknown, unknown>(
async (dataToSend:any) => {
if(method === "put"){
const { data } = await axios.put(url+"/"+dataToSend?.id, dataToSend );
return data;
}else{
const { data } = await axios.post(url+"/"+dataToSend?.id, dataToSend,{
headers: {
'Content-Type': 'multipart/form-data'
}
});
return data;
}
},
{
onSuccess: (data) => {
if (toastMessage) {
toast.success(data.message || t("updated_successfully"));
}
queryClient.invalidateQueries([key]);
},
onError: (err:any) => {
const message = err?.response?.data?.message || t("failed_to_update_data");
toast.error(message);
// validateSession(err.response);
},
}
);
};
export default useUpdateMutationById;

View File

@ -1,52 +0,0 @@
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;
// Add other properties as needed
};
const useUpdateMutationPost = (
key: string,
url: string,
toastMessage: boolean = true,
method?:string
): UseMutationResult<AxiosResponse, unknown, unknown> => {
const axios = useAxios();
const queryClient = useQueryClient();
const [t] = useTranslation();
const {id}= useParams()
return useMutation<AxiosResponse, unknown, unknown>(
async (dataToSend) => {
const { data } = await axios.post(url+"/"+id, dataToSend,{
headers: {
'Content-Type': 'multipart/form-data'
}
});
return data;
},
{
onSuccess: (data) => {
if (toastMessage) {
toast.success(data.message || t("updated_successfully"));
}
queryClient.invalidateQueries([key]);
},
onError: (err:any) => {
const message = err?.response?.data?.message || t("failed_to_update_data");
toast.error(message);
// validateSession(err.response);
},
}
);
};
export default useUpdateMutationPost;

View File

@ -1,75 +0,0 @@
import { useState } from "react";
import { useQueryClient, useMutation, MutationFunction } from "react-query";
import { toast } from "react-toastify";
import useAxios from "./useAxios";
import { AxiosResponse } from "axios";
import { useTranslation } from "react-i18next";
import { QueryStatusEnum } from "../../config/QueryStatus";
// import { validateSession } from "./validateSession";
interface UploadWithProgressReturnType {
percentCompleted: number;
mutate: MutationFunction;
isLoading: boolean;
isError: boolean;
error: unknown;
isSuccess:boolean,
value:any,
status : QueryStatusEnum
}
export const useUploadWithProgress = (
key: string,
url: string
): UploadWithProgressReturnType => {
const axios = useAxios();
const queryClient = useQueryClient();
const [percentCompleted, setPercentCompleted] = useState<number>(0.0);
const {t} = useTranslation();
const mutation = useMutation<
AxiosResponse<any>,
unknown,
any,
{
onSuccess: (data: AxiosResponse<any>) => void;
onError: (error: unknown) => void;
}
>(
async (dataToSend) => {
setPercentCompleted(0.0);
const { data } = await axios.post(url, dataToSend, {
onUploadProgress: (event:any) => {
console.log();
if (event?.event?.lengthComputable) {
setPercentCompleted(Math.round((event.loaded * 100) / event.total));
}
},
});
return data;
},
{
onSuccess: ({ data }) => {
toast.success(data.message || t("_messages.success.upload"));
queryClient.invalidateQueries([key]);
},
onError: (err:any) => {
const message =
err?.response?.data?.message || t("_messages.error.upload");
toast.error(message);
// validateSession(err.response);
},
}
);
return {
percentCompleted,
value:percentCompleted,
mutate: mutation.mutate as MutationFunction,
isLoading: mutation.isLoading,
isError: mutation.isError,
error: mutation.error,
isSuccess :mutation.isSuccess,
status : mutation.status as QueryStatusEnum
};
};

22
src/api/setting.ts Normal file
View File

@ -0,0 +1,22 @@
import useGetQuery from "./helper/useGetQuery";
import useAddMutation from "./helper/useAddMutation"
import useDeleteMutation from "./helper/useDeleteMutation"
import useUpdateMutation from "./helper/useUpdateMutation";
const API = {
ADD: `restaurant`,
GET_ALL: `restaurant`,
DELETE: `restaurant`,
UPDATE: `restaurant`,
};
const KEY = "restaurant"
export const useGetSetting = (params?:any,option?:any) => useGetQuery(KEY, API.GET_ALL,params);
export const useAddSetting = () => useAddMutation(KEY, API.ADD);
export const useUpdateSetting = (method?:any) => useUpdateMutation(KEY, API.UPDATE);
export const useDeleteSetting = () =>useDeleteMutation(KEY, API.DELETE);

View File

@ -0,0 +1,7 @@
export function PaginationParams(location: any) {
const searchParams = new URLSearchParams(location?.search);
return {
page: searchParams.get("page") || "",
per_page: searchParams.get("per_page") || "",
};
}

View File

@ -0,0 +1,5 @@
export function filterParams(params: any) {
return Object.fromEntries(
Object.entries(params ?? {}).filter(([_, value]) => value !== ""),
);
}

View File

@ -0,0 +1,16 @@
import { useState, useEffect } from "react";
import { useLocation } from "react-router-dom";
function useSearchQuery(paramName: string): [string, (value: string) => void] {
const location = useLocation();
const [queryValue, setQueryValue] = useState<string>("");
useEffect(() => {
const searchParams = new URLSearchParams(location.search);
setQueryValue(searchParams.get(paramName) || "");
}, [location, paramName]);
return [queryValue, setQueryValue];
}
export default useSearchQuery;

10
src/enums/Axios.ts Normal file
View File

@ -0,0 +1,10 @@
export enum AxiosQueryEnum {
GET = "get",
POST = "post",
DELETE = "delete",
}
export enum AxiosStatusEnum {
VALIDATION = 422,
AUTHENTICATED = 401,
}

5
src/enums/QueryStatus.ts Normal file
View File

@ -0,0 +1,5 @@
export enum QueryStatusEnum {
LOADING = "loading",
ERROR = "error",
SUCCESS = "success",
}

7
src/enums/Validation.ts Normal file
View File

@ -0,0 +1,7 @@
export enum Payments {
MAX_VALUE = 900000,
}
export enum Exam {
MAX_VALUE = 10000,
}

Some files were not shown because too many files have changed in this diff Show More