add_setting
This commit is contained in:
parent
09022c9aef
commit
5f67441d9d
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"cSpell.words": [
|
||||
"aldeen",
|
||||
"antd",
|
||||
"Datepicker",
|
||||
"formik",
|
||||
"Karim",
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
<title>E-Menu - App</title>
|
||||
</head>
|
||||
<script type="module" src="/src/index.tsx"></script>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
89
package.json
89
package.json
|
|
@ -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
BIN
public/Layout/images.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
BIN
public/Logo.png
BIN
public/Logo.png
Binary file not shown.
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 124 KiB |
|
|
@ -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 });
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 });
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
position: relative;
|
||||
max-width: 350px;
|
||||
width: 350px;
|
||||
|
||||
}
|
||||
|
||||
.input {
|
||||
|
|
@ -21,17 +20,13 @@
|
|||
color: var(--text);
|
||||
border: none;
|
||||
box-shadow: 2px 2px 7px 0 var(--bg);
|
||||
|
||||
}
|
||||
|
||||
.input::placeholder {
|
||||
color: var(--subtext);
|
||||
opacity: .4;
|
||||
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.icon {
|
||||
position: absolute;
|
||||
left: 1rem;
|
||||
|
|
@ -39,10 +34,4 @@
|
|||
width: 1rem;
|
||||
height: 1rem;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
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 [searchQuery, setSearchQuery] = useState("");
|
||||
const [searchParams] = useSearchParams();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleChange = (event: any) => {
|
||||
|
|
@ -13,23 +13,33 @@ const SearchBar = () => {
|
|||
};
|
||||
|
||||
const updateUrlParams = (value: any) => {
|
||||
navigate(`?search=${value}`);
|
||||
|
||||
|
||||
navigate(`?search=${value}`, { replace: true });
|
||||
};
|
||||
|
||||
return (
|
||||
<div className='SearchBar'>
|
||||
<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"
|
||||
<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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
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>
|
||||
</Form.Item>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default CheckboxField
|
||||
export default CheckboxField;
|
||||
|
|
|
|||
|
|
@ -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'>
|
||||
<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,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;
|
||||
|
|
|
|||
|
|
@ -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'>
|
||||
<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;
|
||||
|
|
|
|||
|
|
@ -1,31 +1,58 @@
|
|||
import { Form, Input } from 'antd'
|
||||
import React from 'react'
|
||||
import useFormField from '../../../Hooks/useFormField';
|
||||
|
||||
const Default = ({ name, label, placeholder, isDisabled, onChange, props,type }: any) => {
|
||||
const { Field, formik, isError, errorMsg, t } = useFormField(name, props);
|
||||
|
||||
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,
|
||||
type,
|
||||
no_label,
|
||||
label_icon,
|
||||
...props
|
||||
}: any) => {
|
||||
const { errorMsg, isError, t } = useFormField(name, props);
|
||||
|
||||
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 : ''}
|
||||
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"
|
||||
|
||||
{...props}
|
||||
// onChange={onChange ? onChange : handleChange}
|
||||
{...(type === "number" && { min: 0 })}
|
||||
/>
|
||||
</Form.Item>
|
||||
</div>
|
||||
|
|
@ -33,4 +60,3 @@ const Default = ({ name, label, placeholder, isDisabled, onChange, props,type }:
|
|||
};
|
||||
|
||||
export default React.memo(Default);
|
||||
;
|
||||
|
|
|
|||
93
src/Components/ValidationField/View/DropFile.tsx.tsx
Normal file
93
src/Components/ValidationField/View/DropFile.tsx.tsx
Normal 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;
|
||||
|
|
@ -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[] = [
|
||||
|
||||
{
|
||||
uid: '-1',
|
||||
name: '',
|
||||
status: 'done',
|
||||
url: FormikName == ""? imageUrl : imageUrl?.replace("public", "/storage"),
|
||||
thumbUrl: FormikName == ""? imageUrl : imageUrl?.replace("public", "/storage")
|
||||
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);
|
||||
|
||||
const FilehandleChange = (value: any) => {
|
||||
|
||||
formik.setFieldValue(name, value.file.originFileObj)
|
||||
|
||||
// console.log(value,"filevalue");
|
||||
if (value.fileList.length === 0) {
|
||||
formik.setFieldValue(name, null);
|
||||
} else {
|
||||
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
|
||||
className={isError ? "isError w-100 " : " w-100"}
|
||||
icon={<UploadOutlined />}
|
||||
>
|
||||
{placholder ?? t("Click_to_upload_the_image")}
|
||||
</Button>
|
||||
<div className='Error_color'> {isError ? "required" : ""}</div>
|
||||
<div className="Error_color"> {isError ? "required" : ""}</div>
|
||||
</Upload>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default File
|
||||
export default File;
|
||||
|
|
|
|||
93
src/Components/ValidationField/View/LocalSearch.tsx
Normal file
93
src/Components/ValidationField/View/LocalSearch.tsx
Normal 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);
|
||||
|
|
@ -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) => ({
|
||||
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',
|
||||
url: file.url || '',
|
||||
thumbUrl: file.url || '',
|
||||
})) : [];
|
||||
|
||||
const FilehandleChange = ({ file, fileList }: any) => {
|
||||
formik.setFieldValue(name, fileList.map((file: any) => file.originFileObj));
|
||||
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 />}
|
||||
|
||||
>
|
||||
<Button className={isError ? "isError w-100" : " w-100"} icon={<UploadOutlined />}>
|
||||
{placholder ?? t("upload_image")}
|
||||
{t(placeholder ?? t("upload_image") )}
|
||||
</Button>
|
||||
<div className='Error_color'> {isError ? "required" : ""}</div>
|
||||
<div className="Error_color"> {isError ? "required" : ""}</div>
|
||||
</Upload>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
75
src/Components/ValidationField/View/NumberFormate.tsx
Normal file
75
src/Components/ValidationField/View/NumberFormate.tsx
Normal 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);
|
||||
|
|
@ -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);
|
||||
const searchParams = new URLSearchParams(window?.location?.search);
|
||||
setSearchQuery(searchParams?.get("search") || "");
|
||||
}, []);
|
||||
|
||||
}, [location]);
|
||||
|
||||
|
||||
|
||||
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()}`);
|
||||
}
|
||||
|
||||
navigate(`${window?.location?.pathname}?${searchBy}=${value}`, {
|
||||
replace: true,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className='ValidationField'>
|
||||
<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}
|
||||
onChange={onChange || SelectableChange}
|
||||
showSearch
|
||||
optionFilterProp="label"
|
||||
onSearch={SearchHandleChange}
|
||||
loading={loading}
|
||||
|
||||
/>
|
||||
</Form.Item>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
<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}
|
||||
options={translateOptions(option, t)}
|
||||
loading={option?.length < 1}
|
||||
size="large"
|
||||
className={`${className} w-100`}
|
||||
className={`${className} ${isError ? "Select_error" : ""} w-100`}
|
||||
value={formik.values[name]}
|
||||
allowClear
|
||||
{...(isMulti && { mode: "multiple" })}
|
||||
onChange={onChange || SelecthandleChange}
|
||||
|
||||
|
||||
|
||||
onChange={onChange || SelectableChange}
|
||||
/>
|
||||
</Form.Item>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(SelectField);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
;
|
||||
50
src/Components/ValidationField/View/TextAreaField.tsx
Normal file
50
src/Components/ValidationField/View/TextAreaField.tsx
Normal 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);
|
||||
65
src/Components/ValidationField/View/TextField.tsx
Normal file
65
src/Components/ValidationField/View/TextField.tsx
Normal 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);
|
||||
|
|
@ -1,21 +1,47 @@
|
|||
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'>
|
||||
const Formater = "H:mm";
|
||||
const FormikValue = formik.values[name];
|
||||
|
||||
return (
|
||||
<div className="ValidationField w-100 ">
|
||||
{no_label ? (
|
||||
<label htmlFor={name} className="text">
|
||||
{t(`${label}`)}
|
||||
<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" : ""}
|
||||
|
|
@ -25,17 +51,18 @@ const Time = ({ name, label,className,isDisabled,onChange,props }: any) => {
|
|||
allowClear
|
||||
className={`${className} w-100`}
|
||||
size="large"
|
||||
defaultValue={formik.values[name]}
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -5,9 +5,10 @@ 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,
|
||||
|
|
@ -17,6 +18,8 @@ export {
|
|||
CheckboxField,
|
||||
Default,
|
||||
File,
|
||||
TextAreaField
|
||||
|
||||
}
|
||||
MaltyFile,
|
||||
SearchField,
|
||||
TextField,
|
||||
DropFile,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
ErrorMessage,
|
||||
useField,
|
||||
Field,
|
||||
useFormikContext,
|
||||
useTranslation,
|
||||
FaExclamationCircle,
|
||||
Select,
|
||||
convert_data_to_select,
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
200
src/Components/ValidationField/utils/ValidationField.scss
Normal file
200
src/Components/ValidationField/utils/ValidationField.scss
Normal 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;
|
||||
// }
|
||||
11
src/Components/ValidationField/utils/ValidationState.ts
Normal file
11
src/Components/ValidationField/utils/ValidationState.ts
Normal 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 })),
|
||||
}));
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
export const translateOptions = (options: any, t: any) => {
|
||||
return options.map((opt: any) => ({
|
||||
...opt,
|
||||
label: t(`${opt.label}`),
|
||||
}));
|
||||
};
|
||||
171
src/Components/ValidationField/utils/types.ts
Normal file
171
src/Components/ValidationField/utils/types.ts
Normal 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;
|
||||
|
|
@ -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 };
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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.`);
|
||||
|
|
@ -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()
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -7,15 +7,19 @@ import { Rate, Spin } from 'antd';
|
|||
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
10
src/Pages/Home/Page.tsx
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import React from 'react'
|
||||
|
||||
const Page = () => {
|
||||
|
||||
return (
|
||||
<div>Page</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Page
|
||||
|
|
@ -7,15 +7,19 @@ import { Rate, Spin } from 'antd';
|
|||
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" ){
|
||||
|
|
|
|||
|
|
@ -7,15 +7,19 @@ import { Rate, Spin } from 'antd';
|
|||
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"]
|
||||
|
|
|
|||
96
src/Pages/Setting/Groups/FieldGroup.tsx
Normal file
96
src/Pages/Setting/Groups/FieldGroup.tsx
Normal 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;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
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/statemangment/AuthState";
|
||||
import ReactPlayer from 'react-player'
|
||||
|
|
@ -9,8 +9,6 @@ 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");
|
||||
const fakeIMage = [1,1,1,1,1,1]
|
||||
const handel_navigate = (id:number)=>{
|
||||
console.log(id);
|
||||
|
||||
console.log(video,"video");
|
||||
|
||||
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>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ 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)
|
||||
|
|
@ -15,12 +15,17 @@ function Form() {
|
|||
<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' />
|
||||
|
||||
|
|
|
|||
|
|
@ -7,25 +7,42 @@ import { Rate, Spin } from 'antd';
|
|||
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 {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(() => {
|
||||
|
|
@ -43,7 +60,6 @@ const EditPage = () => {
|
|||
}
|
||||
|
||||
|
||||
|
||||
const ViewProps = { getInitialValues, getValidationSchema, handleSubmit,IsloadingButton };
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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='/'>
|
||||
|
|
|
|||
|
|
@ -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: "/",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
:root {
|
||||
--primary:#E57DB1 ;
|
||||
--primary:black ;
|
||||
--secondary : #2D9CDB;
|
||||
--text: #565656;
|
||||
--bg: #ffffff;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -1,21 +1,19 @@
|
|||
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 baseURL: string = "";
|
||||
private headers: Record<any, any> = {};
|
||||
private timeout: number = 60000; // Request failed with 60 second
|
||||
private withCreds: boolean = false;
|
||||
private responseType: ResponseType = 'json';
|
||||
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 {
|
||||
withHeaders(headers: Record<any, any>): AxiosBuilder {
|
||||
this.headers = headers;
|
||||
return this;
|
||||
}
|
||||
|
|
@ -25,25 +23,21 @@ class AxiosBuilder {
|
|||
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
|
||||
responseType: this.responseType,
|
||||
};
|
||||
|
||||
return axios.create(config);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default AxiosBuilder
|
||||
|
||||
export default AxiosBuilder;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -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
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
@ -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, {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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 { isAuthenticated, token } = useAuthState();
|
||||
|
||||
const buildAxios = new AxiosBuilder().
|
||||
withBaseURL(BaseURL)
|
||||
.withResponseType('json')
|
||||
.withTimeout(120000)
|
||||
.withHeaders({"Content-Type" :"application/json"})
|
||||
const { setValidation } = useValidationState((state) => state);
|
||||
const [t] = useTranslation();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const { logout } = useAuthState();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const buildAxios = new AxiosBuilder()
|
||||
.withBaseURL(BaseURL)
|
||||
.withResponseType("json")
|
||||
.withTimeout(120000);
|
||||
|
||||
if (isAuthenticated) {
|
||||
|
||||
buildAxios.withHeaders({ Authorization: 'Bearer '+ token })
|
||||
buildAxios.withHeaders({
|
||||
Authorization: "Bearer " + token,
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
buildAxios.build()
|
||||
)
|
||||
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");
|
||||
}
|
||||
|
||||
export default useAxios
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
},
|
||||
{
|
||||
onSuccess: (data) => {
|
||||
queryClient.invalidateQueries(key);
|
||||
toast.success(t('deleted_successfully'));
|
||||
});
|
||||
return data;
|
||||
},
|
||||
onError: (error:any) => {
|
||||
const message = error?.response?.data?.message || t("failed_to_add_data");
|
||||
toast.error(message);
|
||||
}
|
||||
},
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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);
|
||||
},
|
||||
refetchOnWindowFocus: false,
|
||||
...options
|
||||
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 ?? [];
|
||||
},
|
||||
options,
|
||||
);
|
||||
}
|
||||
|
||||
export default useGetQuery;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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) => {
|
||||
|
||||
},
|
||||
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
},
|
||||
}
|
||||
);
|
||||
};
|
||||
|
|
@ -1,58 +1,36 @@
|
|||
import { useQueryClient, useMutation, UseMutationResult } from "react-query";
|
||||
import { toast } from "react-toastify";
|
||||
import { useMutation, UseMutationResult } from "react-query";
|
||||
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 { 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;
|
||||
return useMutation<AxiosResponse, any, any>(async (dataToSend) => {
|
||||
let request = null;
|
||||
let id = null;
|
||||
|
||||
if (dataToSend instanceof FormData) {
|
||||
dataToSend.append("_method", "PUT");
|
||||
request = dataToSend;
|
||||
id = dataToSend.get("id");
|
||||
} else {
|
||||
const { data } = await axios.post(url+"/"+id, dataToSend,{
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
},
|
||||
{
|
||||
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 useUpdateMutation;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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
22
src/api/setting.ts
Normal 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);
|
||||
7
src/api/utils/PaginationParams.ts
Normal file
7
src/api/utils/PaginationParams.ts
Normal 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") || "",
|
||||
};
|
||||
}
|
||||
5
src/api/utils/filterParams.ts
Normal file
5
src/api/utils/filterParams.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
export function filterParams(params: any) {
|
||||
return Object.fromEntries(
|
||||
Object.entries(params ?? {}).filter(([_, value]) => value !== ""),
|
||||
);
|
||||
}
|
||||
16
src/api/utils/useSearchQuery.ts
Normal file
16
src/api/utils/useSearchQuery.ts
Normal 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
10
src/enums/Axios.ts
Normal 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
5
src/enums/QueryStatus.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
export enum QueryStatusEnum {
|
||||
LOADING = "loading",
|
||||
ERROR = "error",
|
||||
SUCCESS = "success",
|
||||
}
|
||||
7
src/enums/Validation.ts
Normal file
7
src/enums/Validation.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
export enum Payments {
|
||||
MAX_VALUE = 900000,
|
||||
}
|
||||
|
||||
export enum Exam {
|
||||
MAX_VALUE = 10000,
|
||||
}
|
||||
8
src/enums/params.ts
Normal file
8
src/enums/params.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
export enum ParamsEnum {
|
||||
STUDENT_ID = "student_id",
|
||||
COURSE_ID = "course_id",
|
||||
EDUCATION_CLASS_ID = "edu_class_id",
|
||||
SUBJECT_ID = "subject_id",
|
||||
BRANCH_ID = "branch_id",
|
||||
CYCLE_ID = "cycle_id",
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
import App from './App';
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
import './Styles/AppStyle/Import.scss'
|
||||
import 'react-tabs/style/react-tabs.css';
|
||||
import { createRoot } from "react-dom/client";
|
||||
import ProviderContainer from './ProviderContainer';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,18 @@
|
|||
import React from 'react'
|
||||
import { QueryClient, QueryClientProvider } from 'react-query'
|
||||
import React from "react";
|
||||
import { QueryClient, QueryClientProvider } from "react-query";
|
||||
|
||||
function QueryProvider({ children }: any) {
|
||||
const queryClient = new QueryClient()
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
refetchOnWindowFocus: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
{children}
|
||||
</QueryClientProvider>
|
||||
|
||||
)
|
||||
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default QueryProvider
|
||||
|
||||
|
||||
export default QueryProvider;
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
|
||||
import { Socket, io } from 'socket.io-client';
|
||||
import { TOKEN_KEY_SOCKET } from '../config/AppKey';
|
||||
|
||||
|
||||
export const BASE_URL_SOCKET = 'http://192.168.1.14:8001/';
|
||||
var socket :Socket | null = null ;
|
||||
|
||||
|
||||
function InitSocket(){
|
||||
|
||||
|
||||
|
||||
if (!socket){
|
||||
socket = io(BASE_URL_SOCKET , {
|
||||
transports:['websocket'],
|
||||
autoConnect:true,
|
||||
query:{
|
||||
token:localStorage.getItem(TOKEN_KEY_SOCKET),
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const disconnectSocket = ()=>{
|
||||
|
||||
socket?.disconnect();
|
||||
socket = null;
|
||||
}
|
||||
export const getScoket = ()=>{
|
||||
|
||||
InitSocket();
|
||||
return socket;
|
||||
}
|
||||
|
||||
|
||||
3
src/types/Axios.ts
Normal file
3
src/types/Axios.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
export type AxiosResponse = {
|
||||
message?: string;
|
||||
};
|
||||
49
src/types/item.ts
Normal file
49
src/types/item.ts
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
export interface Restaurant {
|
||||
id: number;
|
||||
name: string;
|
||||
address: string;
|
||||
logo: string;
|
||||
slogan: {
|
||||
text: string;
|
||||
};
|
||||
contact_info: {
|
||||
phone_number: string;
|
||||
email: string;
|
||||
};
|
||||
attributes: {
|
||||
attribute: string;
|
||||
};
|
||||
video: string;
|
||||
design_system: {
|
||||
primary_color: string;
|
||||
secondry_color: string;
|
||||
};
|
||||
location: {
|
||||
location: string;
|
||||
};
|
||||
images: any[]; // Assuming the images array contains objects, replace 'any' with appropriate type if known
|
||||
categories: Category[];
|
||||
offers: Offer[];
|
||||
uuid: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
interface Category {
|
||||
id: number;
|
||||
name: string;
|
||||
image: string;
|
||||
restaurant_id: number;
|
||||
meals_count: number;
|
||||
uuid: string;
|
||||
}
|
||||
|
||||
interface Offer {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
image: string;
|
||||
price: number;
|
||||
restaurant_id: number;
|
||||
uuid: string;
|
||||
}
|
||||
13
src/utils/Array/convertArrayToJsonString.ts
Normal file
13
src/utils/Array/convertArrayToJsonString.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
interface KeyValue {
|
||||
key: string;
|
||||
value: any;
|
||||
}
|
||||
|
||||
export function convertArrayToJsonString(array: KeyValue[]): string {
|
||||
const jsonObject: { [key: string]: any } = {};
|
||||
array.forEach(item => {
|
||||
jsonObject[item.key] = item.value;
|
||||
});
|
||||
return JSON.stringify(jsonObject);
|
||||
}
|
||||
|
||||
8
src/utils/object/objectToArray.ts
Normal file
8
src/utils/object/objectToArray.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
export interface KeyAndValue {
|
||||
key: string;
|
||||
value: any;
|
||||
}
|
||||
|
||||
export function objectToArray(obj: Record<string, any>): KeyAndValue[] {
|
||||
return Object.keys(obj).map((key: string) => ({ key, value: obj[key] }));
|
||||
}
|
||||
11
vite.config.js
Normal file
11
vite.config.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
|
||||
export default defineConfig(() => {
|
||||
return {
|
||||
build: {
|
||||
outDir: 'build',
|
||||
},
|
||||
plugins: [react()],
|
||||
};
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user