add karim field v4
This commit is contained in:
parent
b2ea58b19e
commit
1a78474120
|
|
@ -10,6 +10,8 @@ const SelectTag: React.FC = () => {
|
||||||
const [fieldValue, setFieldValue] = useState<string>('');
|
const [fieldValue, setFieldValue] = useState<string>('');
|
||||||
const formik = useFormikContext<any>()
|
const formik = useFormikContext<any>()
|
||||||
const handleChange = (value: string[]) => {
|
const handleChange = (value: string[]) => {
|
||||||
|
console.log(value);
|
||||||
|
|
||||||
formik.setFieldValue("tags",value)
|
formik.setFieldValue("tags",value)
|
||||||
setSearchValue('');
|
setSearchValue('');
|
||||||
setFieldValue('');
|
setFieldValue('');
|
||||||
|
|
@ -38,7 +40,7 @@ const SelectTag: React.FC = () => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
|
||||||
const options = data?.data ?? []
|
const options = data?.data ?? []
|
||||||
const additionalData = options?.length < 1 && searchValue.length > 1 && !isLoading ? [{id:`new_${searchValue}`,name:searchValue}] :[];
|
const additionalData = options?.length < 1 && searchValue.length > 1 && !isLoading ? [{id:`${searchValue}`,name:searchValue}] :[];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='SelectTag'>
|
<div className='SelectTag'>
|
||||||
|
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
import { Spin } from "antd";
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
loading: boolean;
|
|
||||||
children: React.ReactNode;
|
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const KarimSpinner: React.FC<Props> = ({ loading, className, children }) => {
|
|
||||||
return (
|
|
||||||
<div className={className ?? ""}>
|
|
||||||
{loading ? (
|
|
||||||
<div className="text-center">
|
|
||||||
<Spin />
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
children
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default KarimSpinner;
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
// .SearchBar {
|
|
||||||
// // margin-top: 20px;
|
|
||||||
// .group {
|
|
||||||
// display: flex;
|
|
||||||
// align-items: center;
|
|
||||||
// position: relative;
|
|
||||||
// max-width: 350px;
|
|
||||||
// width: 350px;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .input {
|
|
||||||
// width: 100%;
|
|
||||||
// height: 40px;
|
|
||||||
// padding: 0 1rem;
|
|
||||||
// padding-left: 2.5rem;
|
|
||||||
// border-radius: 8px;
|
|
||||||
// outline: none;
|
|
||||||
// font-weight: 500;
|
|
||||||
// background: var(--bg);
|
|
||||||
// color: var(--text);
|
|
||||||
// border: none;
|
|
||||||
// box-shadow: 2px 2px 7px 0 var(--bg);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .input::placeholder {
|
|
||||||
// color: var(--subtext);
|
|
||||||
// opacity: 0.4;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// .icon {
|
|
||||||
// position: absolute;
|
|
||||||
// left: 1rem;
|
|
||||||
// fill: var(--subtext);
|
|
||||||
// width: 1rem;
|
|
||||||
// height: 1rem;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
import React, { useState } from "react";
|
|
||||||
import "./SearchBar.scss";
|
|
||||||
import { useNavigate, useSearchParams } from "react-router-dom";
|
|
||||||
const SearchBar = () => {
|
|
||||||
const [searchQuery, setSearchQuery] = useState("");
|
|
||||||
const [searchParams] = useSearchParams();
|
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
const handleChange = (event: any) => {
|
|
||||||
const { value } = event.target;
|
|
||||||
setSearchQuery(value);
|
|
||||||
updateUrlParams(value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateUrlParams = (value: any) => {
|
|
||||||
navigate(`?search=${value}`, { replace: true });
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="SearchBar">
|
|
||||||
<div className="group">
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlnsXlink="http://www.w3.org/1999/xlink"
|
|
||||||
className="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-1b5stb0 icon"
|
|
||||||
focusable="false"
|
|
||||||
aria-hidden="true"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
data-testid="SearchIcon"
|
|
||||||
>
|
|
||||||
<path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path>
|
|
||||||
</svg>
|
|
||||||
<input
|
|
||||||
placeholder="Search Product...."
|
|
||||||
type="search"
|
|
||||||
className="input"
|
|
||||||
value={searchQuery}
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SearchBar;
|
|
||||||
|
|
@ -6,17 +6,16 @@ import {
|
||||||
File,
|
File,
|
||||||
DataRange,
|
DataRange,
|
||||||
SelectField,
|
SelectField,
|
||||||
Default,
|
|
||||||
CheckboxField,
|
CheckboxField,
|
||||||
MaltyFile,
|
MaltyFile,
|
||||||
SearchField,
|
SearchField,
|
||||||
TextField,
|
TextField,
|
||||||
DropFile,
|
DropFile,
|
||||||
|
Default,
|
||||||
} from "./View";
|
} from "./View";
|
||||||
import { ValidationFieldProps, ValidationFieldType } from "./utils/types";
|
import { ValidationFieldProps, ValidationFieldType } from "./utils/types";
|
||||||
import LocalSearchField from "./View/LocalSearch";
|
import LocalSearchField from "./View/LocalSearch";
|
||||||
import NumberFormate from "./View/NumberFormate";
|
import NumberFormate from "./View/NumberFormate";
|
||||||
import NumberField from "./View/NumberField";
|
|
||||||
|
|
||||||
const components: { [key: string]: React.FC<any> } = {
|
const components: { [key: string]: React.FC<any> } = {
|
||||||
Select: SelectField,
|
Select: SelectField,
|
||||||
|
|
@ -31,12 +30,11 @@ const components: { [key: string]: React.FC<any> } = {
|
||||||
MaltyFile: MaltyFile,
|
MaltyFile: MaltyFile,
|
||||||
Checkbox: CheckboxField,
|
Checkbox: CheckboxField,
|
||||||
NumberFormate: NumberFormate,
|
NumberFormate: NumberFormate,
|
||||||
Number: NumberField,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const ValidationField: React.FC<ValidationFieldProps> = React.memo(
|
const ValidationField: React.FC<ValidationFieldProps> = React.memo(
|
||||||
({ type, ...otherProps }: any) => {
|
({ type = "text", ...otherProps }) => {
|
||||||
const Component = components[type as ValidationFieldType];
|
const Component = components[type ?? ("text" as ValidationFieldType)];
|
||||||
|
|
||||||
if (!Component) {
|
if (!Component) {
|
||||||
return <Default {...otherProps} />;
|
return <Default {...otherProps} />;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import useFormField from "../../../Hooks/useFormField";
|
import useFormField from "../../../Hooks/useFormField";
|
||||||
import { Checkbox, Form } from "antd";
|
import { Checkbox } from "antd";
|
||||||
import { getNestedValue } from "../utils/getNestedValue";
|
import { ValidationFieldContainer } from "../components/ValidationFieldContainer";
|
||||||
const CheckboxField = ({
|
const CheckboxField = ({
|
||||||
name,
|
name,
|
||||||
label,
|
label,
|
||||||
|
|
@ -17,25 +17,17 @@ const CheckboxField = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ `ValidationField ValidationFieldCheckbox`}>
|
<div className={Group ? "d-inline mt-3 Checkbox" : ``}>
|
||||||
<Form.Item
|
<ValidationFieldContainer isError={isError} errorMsg={errorMsg}>
|
||||||
hasFeedback
|
|
||||||
validateStatus={isError ? "error" : ""}
|
|
||||||
help={isError ? errorMsg : ""}
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
{t(`input.${label ? label : name}`)}
|
|
||||||
</div>
|
|
||||||
<Checkbox
|
<Checkbox
|
||||||
onChange={onChange || CheckboxhandleChange}
|
onChange={onChange || CheckboxhandleChange}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
checked={formik.values?.[name] ?? false}
|
checked={formik.values?.[name] ?? false}
|
||||||
className={className}
|
className={className}
|
||||||
>
|
>
|
||||||
|
{t(`input.${label ? label : name}`)}
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
|
</ValidationFieldContainer>
|
||||||
</Form.Item>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ import { Form, DatePicker } from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import useFormField from "../../../Hooks/useFormField";
|
import useFormField from "../../../Hooks/useFormField";
|
||||||
import { MdOutlineEdit } from "react-icons/md";
|
import { MdOutlineEdit } from "react-icons/md";
|
||||||
|
import { ValidationFieldLabel } from "../components/ValidationFieldLabel";
|
||||||
|
import { ValidationFieldContainer } from "../components/ValidationFieldContainer";
|
||||||
|
|
||||||
const { RangePicker } = DatePicker;
|
const { RangePicker } = DatePicker;
|
||||||
|
|
||||||
|
|
@ -24,28 +26,16 @@ const DataRange = ({
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div className="ValidationField w-100 ">
|
<div className="ValidationField w-100 ">
|
||||||
{no_label ? (
|
<ValidationFieldLabel
|
||||||
<label htmlFor={name} className="text">
|
name={name}
|
||||||
<span>empty</span>
|
label={label}
|
||||||
</label>
|
label_icon={label_icon}
|
||||||
) : label_icon ? (
|
no_label={no_label}
|
||||||
<div className="LabelWithIcon">
|
placeholder={placeholder}
|
||||||
<label htmlFor={name} className="text">
|
t={t}
|
||||||
{t(`input.${label ? label : name}`)}
|
/>
|
||||||
</label>
|
|
||||||
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<label htmlFor={name} className="text">
|
|
||||||
{t(`input.${label ? label : name}`)}
|
|
||||||
</label>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Form.Item
|
<ValidationFieldContainer isError={isError} errorMsg={errorMsg}>
|
||||||
hasFeedback
|
|
||||||
validateStatus={isError ? "error" : ""}
|
|
||||||
help={isError ? errorMsg : ""}
|
|
||||||
>
|
|
||||||
<RangePicker
|
<RangePicker
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
size="large"
|
size="large"
|
||||||
|
|
@ -55,8 +45,9 @@ const DataRange = ({
|
||||||
onChange={onChange || onCalendarChange}
|
onChange={onChange || onCalendarChange}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
defaultValue={formik.values[name]}
|
defaultValue={formik.values[name]}
|
||||||
|
id={name}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</ValidationFieldContainer>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,9 @@ import React from "react";
|
||||||
import useFormField from "../../../Hooks/useFormField";
|
import useFormField from "../../../Hooks/useFormField";
|
||||||
import { MdOutlineEdit } from "react-icons/md";
|
import { MdOutlineEdit } from "react-icons/md";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
import { DateEnum } from "../../../enums/Date";
|
||||||
|
import { ValidationFieldLabel } from "../components/ValidationFieldLabel";
|
||||||
|
import { ValidationFieldContainer } from "../components/ValidationFieldContainer";
|
||||||
|
|
||||||
const Date = ({
|
const Date = ({
|
||||||
name,
|
name,
|
||||||
|
|
@ -21,34 +24,21 @@ const Date = ({
|
||||||
const FormikValue = formik.values[name];
|
const FormikValue = formik.values[name];
|
||||||
const onCalendarChange = (value: any) => {
|
const onCalendarChange = (value: any) => {
|
||||||
formik.setFieldValue(name, value);
|
formik.setFieldValue(name, value);
|
||||||
// console.log(value,"value ");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const Formater = "YYYY/MM/DD";
|
const Formatter = [DateEnum?.FORMATE];
|
||||||
return (
|
return (
|
||||||
<div className="ValidationField w-100 ">
|
<div className="ValidationField w-100 ">
|
||||||
{no_label ? (
|
<ValidationFieldLabel
|
||||||
<label htmlFor={name} className="text">
|
name={name}
|
||||||
<span>empty</span>
|
label={label}
|
||||||
</label>
|
label_icon={label_icon}
|
||||||
) : label_icon ? (
|
no_label={no_label}
|
||||||
<div className="LabelWithIcon">
|
placeholder={placeholder}
|
||||||
<label htmlFor={name} className="text">
|
t={t}
|
||||||
{t(`input.${label ? label : name}`)}
|
/>
|
||||||
</label>
|
|
||||||
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<label htmlFor={name} className="text">
|
|
||||||
{t(`input.${label ? label : name}`)}
|
|
||||||
</label>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Form.Item
|
<ValidationFieldContainer isError={isError} errorMsg={errorMsg}>
|
||||||
hasFeedback
|
|
||||||
validateStatus={isError ? "error" : ""}
|
|
||||||
help={isError ? errorMsg : ""}
|
|
||||||
>
|
|
||||||
<DatePicker
|
<DatePicker
|
||||||
picker={picker}
|
picker={picker}
|
||||||
placeholder={t(`input.${placeholder}`)}
|
placeholder={t(`input.${placeholder}`)}
|
||||||
|
|
@ -58,10 +48,11 @@ const Date = ({
|
||||||
size="large"
|
size="large"
|
||||||
onChange={onChange || onCalendarChange}
|
onChange={onChange || onCalendarChange}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
format={Formater}
|
format={Formatter}
|
||||||
|
id={name}
|
||||||
/>
|
/>
|
||||||
{/* <DatePicker onChange={onChange} /> */}
|
{/* <DatePicker onChange={onChange} /> */}
|
||||||
</Form.Item>
|
</ValidationFieldContainer>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
import { Form, Input } from "antd";
|
import { Input } from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import useFormField from "../../../Hooks/useFormField";
|
import useFormField from "../../../Hooks/useFormField";
|
||||||
import { MdOutlineEdit } from "react-icons/md";
|
|
||||||
import { Field } from "formik";
|
import { Field } from "formik";
|
||||||
import { ValidationFieldPropsInput } from "../utils/types";
|
import { ValidationFieldLabel } from "../components/ValidationFieldLabel";
|
||||||
|
import { ValidationFieldContainer } from "../components/ValidationFieldContainer";
|
||||||
|
import { FieldProps } from "../utils/types";
|
||||||
|
|
||||||
const Default = ({
|
const Default = ({
|
||||||
name,
|
name,
|
||||||
|
|
@ -14,52 +15,34 @@ const Default = ({
|
||||||
type,
|
type,
|
||||||
no_label,
|
no_label,
|
||||||
label_icon,
|
label_icon,
|
||||||
label2,
|
|
||||||
...props
|
...props
|
||||||
}: ValidationFieldPropsInput) => {
|
}: any) => {
|
||||||
const { errorMsg, isError, t } = useFormField(name, props);
|
const { errorMsg, isError, t } = useFormField(name, props);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ValidationField w-100">
|
<div className="ValidationField w-100">
|
||||||
{label2 ? (
|
<ValidationFieldLabel
|
||||||
<label htmlFor={name} className="text">
|
name={name}
|
||||||
{label2}
|
label={label}
|
||||||
</label>
|
label_icon={label_icon}
|
||||||
) : no_label ? (
|
no_label={no_label}
|
||||||
<label htmlFor={name} className="text">
|
placeholder={placeholder}
|
||||||
<span>empty</span>
|
t={t}
|
||||||
</label>
|
/>
|
||||||
) : label_icon ? (
|
|
||||||
<div className="LabelWithIcon">
|
|
||||||
<label htmlFor={name} className="text">
|
|
||||||
{t(`input.${label ? label : name}`)}
|
|
||||||
</label>
|
|
||||||
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<label htmlFor={name} className="text">
|
|
||||||
{t(`input.${label ? label : placeholder ? placeholder : name}`)}
|
|
||||||
</label>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Form.Item
|
<ValidationFieldContainer isError={isError} errorMsg={errorMsg}>
|
||||||
hasFeedback
|
|
||||||
validateStatus={isError ? "error" : ""}
|
|
||||||
help={isError ? errorMsg : ""}
|
|
||||||
>
|
|
||||||
<Field
|
<Field
|
||||||
as={Input}
|
as={Input}
|
||||||
type={type ?? "text"}
|
type={type ?? "text"}
|
||||||
placeholder={t(
|
placeholder={t(`input.${placeholder || label || name}`)}
|
||||||
`input.${placeholder ? placeholder : label ? label : name}`,
|
|
||||||
)}
|
|
||||||
name={name}
|
name={name}
|
||||||
|
id={name}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
size="large"
|
size="large"
|
||||||
{...(type === "number" && { min: 0 })}
|
{...(type === "number" && { min: 0 })}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</ValidationFieldContainer>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ import { LoadingOutlined, PlusOutlined } from "@ant-design/icons";
|
||||||
import { message, Upload } from "antd";
|
import { message, Upload } from "antd";
|
||||||
import type { GetProp, UploadProps } from "antd";
|
import type { GetProp, UploadProps } from "antd";
|
||||||
import useFormField from "../../../Hooks/useFormField";
|
import useFormField from "../../../Hooks/useFormField";
|
||||||
import { ImageBaseURL } from "../../../api/config";
|
|
||||||
|
|
||||||
type FileType = Parameters<GetProp<UploadProps, "beforeUpload">>[0];
|
type FileType = Parameters<GetProp<UploadProps, "beforeUpload">>[0];
|
||||||
|
|
||||||
|
|
@ -12,7 +11,7 @@ const DropFile = ({
|
||||||
label,
|
label,
|
||||||
onChange,
|
onChange,
|
||||||
isDisabled,
|
isDisabled,
|
||||||
placholder,
|
placeholder,
|
||||||
className,
|
className,
|
||||||
props,
|
props,
|
||||||
no_label,
|
no_label,
|
||||||
|
|
@ -23,7 +22,7 @@ const DropFile = ({
|
||||||
|
|
||||||
const FormikValue =
|
const FormikValue =
|
||||||
typeof FormikName === "string"
|
typeof FormikName === "string"
|
||||||
? ImageBaseURL + FormikName
|
? FormikName
|
||||||
: FormikName instanceof File
|
: FormikName instanceof File
|
||||||
? URL.createObjectURL(FormikName)
|
? URL.createObjectURL(FormikName)
|
||||||
: "";
|
: "";
|
||||||
|
|
@ -71,6 +70,7 @@ const DropFile = ({
|
||||||
showUploadList={false}
|
showUploadList={false}
|
||||||
customRequest={customRequest}
|
customRequest={customRequest}
|
||||||
onChange={onChange || handleChange}
|
onChange={onChange || handleChange}
|
||||||
|
id={name}
|
||||||
>
|
>
|
||||||
{imageUrl ? (
|
{imageUrl ? (
|
||||||
<img
|
<img
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { Button, Upload, UploadFile } from "antd";
|
import { Button, Upload, UploadFile } from "antd";
|
||||||
import useFormField from "../../../Hooks/useFormField";
|
import useFormField from "../../../Hooks/useFormField";
|
||||||
import { UploadOutlined } from "@ant-design/icons";
|
import { UploadOutlined } from "@ant-design/icons";
|
||||||
import { useMemo } from "react";
|
import React, { useMemo } from "react";
|
||||||
|
|
||||||
const File = ({
|
const File = ({
|
||||||
name,
|
name,
|
||||||
|
|
@ -11,36 +11,34 @@ const File = ({
|
||||||
placeholder,
|
placeholder,
|
||||||
className,
|
className,
|
||||||
props,
|
props,
|
||||||
icon,
|
|
||||||
}: any) => {
|
}: any) => {
|
||||||
const { formik, t, isError, errorMsg } = useFormField(name, props);
|
const { formik, t, isError, errorMsg } = useFormField(name, props);
|
||||||
let imageUrl = formik?.values?.[name] ?? null;
|
let imageUrl = formik?.values?.[name] ?? null;
|
||||||
|
|
||||||
|
|
||||||
const fileList: UploadFile[] = useMemo(() => {
|
const fileList: UploadFile[] = useMemo(() => {
|
||||||
if (!imageUrl) return [];
|
if (!imageUrl) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
typeof imageUrl === "string"
|
typeof imageUrl === "string"
|
||||||
? {
|
? {
|
||||||
uid: "-1",
|
uid: "-1",
|
||||||
name: "uploaded-image",
|
name: "",
|
||||||
status: "done",
|
status: "done",
|
||||||
url: imageUrl,
|
url: imageUrl,
|
||||||
thumbUrl: imageUrl,
|
thumbUrl: imageUrl,
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
uid: imageUrl.uid || "-1",
|
uid: imageUrl.uid || "-1",
|
||||||
name: imageUrl.name || "uploaded-image",
|
name: imageUrl.name || "",
|
||||||
status: "done",
|
status: "done",
|
||||||
originFileObj: imageUrl,
|
originFileObj: imageUrl,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}, [imageUrl]);
|
}, [imageUrl]);
|
||||||
// console.log(1);
|
|
||||||
|
|
||||||
const FilehandleChange = (value: any) => {
|
const FilehandleChange = (value: any) => {
|
||||||
// console.log(value,"filevalue");
|
|
||||||
if (value.fileList.length === 0) {
|
if (value.fileList.length === 0) {
|
||||||
formik.setFieldValue(name, null);
|
formik.setFieldValue(name, null);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -64,12 +62,15 @@ const File = ({
|
||||||
onChange={onChange || FilehandleChange}
|
onChange={onChange || FilehandleChange}
|
||||||
customRequest={customRequest}
|
customRequest={customRequest}
|
||||||
className={` w-100`}
|
className={` w-100`}
|
||||||
|
id={name}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
className={isError ? "isError w-100 " : " w-100"}
|
className={isError ? "isError w-100 " : " w-100"}
|
||||||
icon={icon ? icon : <UploadOutlined />}
|
icon={<UploadOutlined />}
|
||||||
>
|
>
|
||||||
{placeholder ?? t("input.Click_to_upload_the_image")}
|
{placeholder
|
||||||
|
? t(`input.${placeholder}`)
|
||||||
|
: t("input.Click_to_upload_the_image")}
|
||||||
</Button>
|
</Button>
|
||||||
<div className="Error_color"> {isError ? "required" : ""}</div>
|
<div className="Error_color"> {isError ? "required" : ""}</div>
|
||||||
{errorMsg}
|
{errorMsg}
|
||||||
|
|
@ -78,4 +79,4 @@ const File = ({
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default File;
|
export default React.memo(File);
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import { Form, Select } from "antd";
|
import { Select } from "antd";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import useFormField from "../../../Hooks/useFormField";
|
import useFormField from "../../../Hooks/useFormField";
|
||||||
import { MdOutlineEdit } from "react-icons/md";
|
|
||||||
import { translateOptions } from "../utils/translatedOptions";
|
import { translateOptions } from "../utils/translatedOptions";
|
||||||
|
import { ValidationFieldLabel } from "../components/ValidationFieldLabel";
|
||||||
|
import { ValidationFieldContainer } from "../components/ValidationFieldContainer";
|
||||||
|
|
||||||
const LocalSelectField = ({
|
const LocalSelectField = ({
|
||||||
name,
|
name,
|
||||||
|
|
@ -13,9 +14,9 @@ const LocalSelectField = ({
|
||||||
isMulti,
|
isMulti,
|
||||||
onChange,
|
onChange,
|
||||||
className,
|
className,
|
||||||
props,
|
|
||||||
no_label,
|
no_label,
|
||||||
label_icon,
|
label_icon,
|
||||||
|
...props
|
||||||
}: any) => {
|
}: any) => {
|
||||||
const { errorMsg, isError, t, formik } = useFormField(name, props);
|
const { errorMsg, isError, t, formik } = useFormField(name, props);
|
||||||
|
|
||||||
|
|
@ -29,13 +30,6 @@ const LocalSelectField = ({
|
||||||
option?.label?.toString().toLowerCase().includes(input.toLowerCase()) ||
|
option?.label?.toString().toLowerCase().includes(input.toLowerCase()) ||
|
||||||
option?.value?.toString().toLowerCase().includes(input.toLowerCase());
|
option?.value?.toString().toLowerCase().includes(input.toLowerCase());
|
||||||
|
|
||||||
const SelectableChange = (value: {
|
|
||||||
value: string;
|
|
||||||
label: React.ReactNode;
|
|
||||||
}) => {
|
|
||||||
formik.setFieldValue(name, value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSelectChange = (value: any) => {
|
const handleSelectChange = (value: any) => {
|
||||||
formik.setFieldValue(name, value);
|
formik.setFieldValue(name, value);
|
||||||
if (onChange) onChange(value);
|
if (onChange) onChange(value);
|
||||||
|
|
@ -47,35 +41,21 @@ const LocalSelectField = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ValidationField w-100">
|
<div className="ValidationField w-100">
|
||||||
{no_label ? (
|
<ValidationFieldLabel
|
||||||
<label htmlFor={name} className="text">
|
name={name}
|
||||||
<span>empty</span>
|
label={label}
|
||||||
</label>
|
label_icon={label_icon}
|
||||||
) : label_icon ? (
|
no_label={no_label}
|
||||||
<div className="LabelWithIcon">
|
placeholder={placeholder}
|
||||||
<label htmlFor={name} className="text">
|
t={t}
|
||||||
{t(`input.${label ? label : name}`)}
|
/>
|
||||||
</label>
|
<ValidationFieldContainer isError={isError} errorMsg={errorMsg}>
|
||||||
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<label htmlFor={name} className="text">
|
|
||||||
{t(`input.${label ? label : name}`)}
|
|
||||||
</label>
|
|
||||||
)}
|
|
||||||
<Form.Item
|
|
||||||
hasFeedback
|
|
||||||
validateStatus={isError ? "error" : ""}
|
|
||||||
help={isError ? errorMsg : ""}
|
|
||||||
>
|
|
||||||
<Select
|
<Select
|
||||||
placeholder={t(
|
placeholder={t(`input.${placeholder || label || name}`)}
|
||||||
`input.${placeholder ? placeholder : label ? label : name}`,
|
|
||||||
)}
|
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
options={translateOptions(option, t)}
|
options={translateOptions(option, t)}
|
||||||
size="large"
|
size="large"
|
||||||
className={`${className} ${isError ? "Select_error" : ""} w-100`}
|
className={`${className} ${isError ? "SelectError" : ""} w-100`}
|
||||||
value={formik.values[name]}
|
value={formik.values[name]}
|
||||||
allowClear
|
allowClear
|
||||||
{...(isMulti && { mode: "multiple" })}
|
{...(isMulti && { mode: "multiple" })}
|
||||||
|
|
@ -84,8 +64,11 @@ const LocalSelectField = ({
|
||||||
filterOption={handleSearch} // Custom filter function
|
filterOption={handleSearch} // Custom filter function
|
||||||
searchValue={searchValue} // Control the search input value
|
searchValue={searchValue} // Control the search input value
|
||||||
onSearch={handleSearchChange} // Update search input value on change
|
onSearch={handleSearchChange} // Update search input value on change
|
||||||
|
id={name}
|
||||||
|
fieldNames={{ label: "name", value: "id" }}
|
||||||
|
{...props}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</ValidationFieldContainer>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
|
import React, { useMemo } from "react";
|
||||||
import { Button, Upload } from "antd";
|
import { Button, Upload } from "antd";
|
||||||
import { UploadOutlined } from "@ant-design/icons";
|
import { UploadOutlined } from "@ant-design/icons";
|
||||||
|
|
||||||
import useFormField from "../../../Hooks/useFormField";
|
import useFormField from "../../../Hooks/useFormField";
|
||||||
|
|
||||||
const MaltyFile = ({
|
const MaltyFile = ({
|
||||||
|
|
@ -15,11 +15,10 @@ const MaltyFile = ({
|
||||||
const { formik, t, isError } = useFormField(name, props);
|
const { formik, t, isError } = useFormField(name, props);
|
||||||
let imageUrl = formik?.values?.[name] ?? null;
|
let imageUrl = formik?.values?.[name] ?? null;
|
||||||
|
|
||||||
// Mapping formik values to fileList format
|
// Memoizing the fileList to prevent unnecessary recalculations
|
||||||
const fileList = imageUrl
|
const fileList = useMemo(() => {
|
||||||
|
return imageUrl
|
||||||
? imageUrl.map((file: any, index: number) => {
|
? imageUrl.map((file: any, index: number) => {
|
||||||
// console.log(file,"file");
|
|
||||||
|
|
||||||
return file instanceof File
|
return file instanceof File
|
||||||
? {
|
? {
|
||||||
uid: index,
|
uid: index,
|
||||||
|
|
@ -37,6 +36,7 @@ const MaltyFile = ({
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
: [];
|
: [];
|
||||||
|
}, [imageUrl]); // Dependency array ensures it recalculates only when imageUrl changes
|
||||||
|
|
||||||
const FilehandleChange = ({ fileList }: any) => {
|
const FilehandleChange = ({ fileList }: any) => {
|
||||||
if (fileList.length === 0) {
|
if (fileList.length === 0) {
|
||||||
|
|
@ -48,6 +48,7 @@ const MaltyFile = ({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Custom request function
|
// Custom request function
|
||||||
const customRequest = async ({ onSuccess }: any) => {
|
const customRequest = async ({ onSuccess }: any) => {
|
||||||
// Perform any necessary actions before onSuccess is called
|
// Perform any necessary actions before onSuccess is called
|
||||||
|
|
@ -63,11 +64,12 @@ const MaltyFile = ({
|
||||||
<Upload
|
<Upload
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
listType="picture"
|
listType="picture"
|
||||||
fileList={fileList} // Using fileList instead of defaultFileList
|
fileList={fileList} // Using memoized fileList
|
||||||
onChange={onChange || FilehandleChange}
|
onChange={onChange || FilehandleChange}
|
||||||
customRequest={customRequest}
|
customRequest={customRequest}
|
||||||
className={`${className} w-100`}
|
className={`${className} w-100`}
|
||||||
multiple // Allow multiple files to be selected
|
multiple // Allow multiple files to be selected
|
||||||
|
id={name}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
className={isError ? "isError w-100" : "w-100"}
|
className={isError ? "isError w-100" : "w-100"}
|
||||||
|
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
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";
|
|
||||||
import { ValidationFieldPropsInput } from "../utils/types";
|
|
||||||
|
|
||||||
const NumberField = ({
|
|
||||||
name,
|
|
||||||
label,
|
|
||||||
placeholder,
|
|
||||||
isDisabled,
|
|
||||||
onChange,
|
|
||||||
type,
|
|
||||||
no_label,
|
|
||||||
label_icon,
|
|
||||||
...props
|
|
||||||
}: ValidationFieldPropsInput) => {
|
|
||||||
const { errorMsg, isError, t, formik } = useFormField(name, props);
|
|
||||||
|
|
||||||
const handleChange = (
|
|
||||||
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
|
|
||||||
) => {
|
|
||||||
console.log("Change:", e);
|
|
||||||
formik.setFieldValue(name, e);
|
|
||||||
};
|
|
||||||
|
|
||||||
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(`input.${label ? label : name}`)}
|
|
||||||
</label>
|
|
||||||
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<label htmlFor={name} className="text">
|
|
||||||
{t(`input.${label ? label : placeholder ? placeholder : name}`)}
|
|
||||||
</label>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Form.Item
|
|
||||||
hasFeedback
|
|
||||||
validateStatus={isError ? "error" : ""}
|
|
||||||
help={isError ? errorMsg : ""}
|
|
||||||
>
|
|
||||||
<Field
|
|
||||||
as={InputNumber}
|
|
||||||
type={type ?? "text"}
|
|
||||||
placeholder={t(
|
|
||||||
`input.${placeholder ? placeholder : label ? label : name}`,
|
|
||||||
)}
|
|
||||||
name={name}
|
|
||||||
disabled={isDisabled}
|
|
||||||
size="large"
|
|
||||||
onChange={handleChange}
|
|
||||||
{...(type === "number" && { min: 0 })}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default React.memo(NumberField);
|
|
||||||
|
|
@ -1,18 +1,19 @@
|
||||||
import { Form, Input, InputNumber } from "antd";
|
import { InputNumber } from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import useFormField from "../../../Hooks/useFormField";
|
import useFormField from "../../../Hooks/useFormField";
|
||||||
import { MdOutlineEdit } from "react-icons/md";
|
|
||||||
import { Field } from "formik";
|
import { Field } from "formik";
|
||||||
|
import { ValidationFieldLabel } from "../components/ValidationFieldLabel";
|
||||||
|
import { ValidationFieldContainer } from "../components/ValidationFieldContainer";
|
||||||
|
|
||||||
const NumberFormate = ({
|
const NumberFormate = ({
|
||||||
name,
|
name,
|
||||||
label,
|
label,
|
||||||
placeholder,
|
placeholder,
|
||||||
isDisabled,
|
isDisabled,
|
||||||
props,
|
|
||||||
type,
|
type,
|
||||||
no_label,
|
no_label,
|
||||||
label_icon,
|
label_icon,
|
||||||
|
...props
|
||||||
}: any) => {
|
}: any) => {
|
||||||
const { errorMsg, isError, t, formik } = useFormField(name, props);
|
const { errorMsg, isError, t, formik } = useFormField(name, props);
|
||||||
const SelectableChange = (value: {
|
const SelectableChange = (value: {
|
||||||
|
|
@ -23,28 +24,15 @@ const NumberFormate = ({
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div className="ValidationField w-100">
|
<div className="ValidationField w-100">
|
||||||
{no_label ? (
|
<ValidationFieldLabel
|
||||||
<label htmlFor={name} className="text">
|
name={name}
|
||||||
<span>empty</span>
|
label={label}
|
||||||
</label>
|
label_icon={label_icon}
|
||||||
) : label_icon ? (
|
no_label={no_label}
|
||||||
<div className="LabelWithIcon">
|
placeholder={placeholder}
|
||||||
<label htmlFor={name} className="text">
|
t={t}
|
||||||
{t(`input.${label ? label : name}`)}
|
/>
|
||||||
</label>
|
<ValidationFieldContainer isError={isError} errorMsg={errorMsg}>
|
||||||
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<label htmlFor={name} className="text">
|
|
||||||
{t(`input.${label ? label : placeholder ? placeholder : name}`)}
|
|
||||||
</label>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Form.Item
|
|
||||||
hasFeedback
|
|
||||||
validateStatus={isError ? "error" : ""}
|
|
||||||
help={isError ? errorMsg : ""}
|
|
||||||
>
|
|
||||||
<Field
|
<Field
|
||||||
as={InputNumber}
|
as={InputNumber}
|
||||||
formatter={(value: any) =>
|
formatter={(value: any) =>
|
||||||
|
|
@ -57,16 +45,16 @@ const NumberFormate = ({
|
||||||
type={type ?? "text"}
|
type={type ?? "text"}
|
||||||
value={formik.values[name]}
|
value={formik.values[name]}
|
||||||
onChange={SelectableChange}
|
onChange={SelectableChange}
|
||||||
placeholder={t(
|
placeholder={t(`input.${placeholder || label || name}`)}
|
||||||
`input.${placeholder ? placeholder : label ? label : name}`,
|
|
||||||
)}
|
|
||||||
name={name}
|
name={name}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
size="large"
|
size="large"
|
||||||
|
id={name}
|
||||||
|
{...props}
|
||||||
|
|
||||||
// onChange={onChange ? onChange : handleChange}
|
// onChange={onChange ? onChange : handleChange}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</ValidationFieldContainer>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,87 +1,143 @@
|
||||||
import { Form, Select, Spin } from "antd";
|
import { Select, Spin } from "antd";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import useFormField from "../../../Hooks/useFormField";
|
import useFormField from "../../../Hooks/useFormField";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { ValidationFieldLabel } from "../components/ValidationFieldLabel";
|
||||||
import { MdOutlineEdit } from "react-icons/md";
|
import { ValidationFieldContainer } from "../components/ValidationFieldContainer";
|
||||||
|
import { SearchFieldProps } from "../utils/types";
|
||||||
|
import { useValidationValidationParamState } from "../state/ValidationValidationParamState";
|
||||||
|
import { useDebounce } from "../../../utils/useDebounce";
|
||||||
|
|
||||||
const SearchField = ({
|
const SearchField = ({
|
||||||
name,
|
name,
|
||||||
label,
|
label,
|
||||||
placeholder,
|
placeholder,
|
||||||
isDisabled,
|
isDisabled,
|
||||||
searchBy,
|
searchBy = "search",
|
||||||
option,
|
option = [],
|
||||||
isMulti,
|
isMulti,
|
||||||
onChange,
|
onChange,
|
||||||
className,
|
className,
|
||||||
props,
|
|
||||||
no_label,
|
no_label,
|
||||||
label_icon,
|
label_icon,
|
||||||
isLoading,
|
isLoading,
|
||||||
}: any) => {
|
canChangePage,
|
||||||
|
PageName,
|
||||||
|
page,
|
||||||
|
...props
|
||||||
|
}: SearchFieldProps) => {
|
||||||
const { errorMsg, isError, t, formik } = useFormField(name, props);
|
const { errorMsg, isError, t, formik } = useFormField(name, props);
|
||||||
const [searchQuery, setSearchQuery] = useState<string>("");
|
const { pushValidationParamState, setValidationParamState } =
|
||||||
const navigate = useNavigate();
|
useValidationValidationParamState();
|
||||||
useEffect(() => {
|
|
||||||
const searchParams = new URLSearchParams(window?.location?.search);
|
|
||||||
setSearchQuery(searchParams?.get("search") || "");
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const SelectableChange = (value: {
|
const [AllPagesOption, setAllPagesOption] = useState<any>([]);
|
||||||
value: string;
|
|
||||||
label: React.ReactNode;
|
useEffect(() => {
|
||||||
}) => {
|
if (option?.length > 0) {
|
||||||
|
const NewOption = [...option, ...AllPagesOption];
|
||||||
|
const FilteredOption = NewOption.filter(
|
||||||
|
(value, index, self) =>
|
||||||
|
index === self.findIndex((t) => t.id === value.id),
|
||||||
|
);
|
||||||
|
const sortedNewOption = FilteredOption.sort((a, b) => a.id - b.id);
|
||||||
|
setAllPagesOption(sortedNewOption);
|
||||||
|
}
|
||||||
|
}, [option]);
|
||||||
|
useEffect(() => {
|
||||||
|
if (page === 1) {
|
||||||
|
setAllPagesOption(option);
|
||||||
|
}
|
||||||
|
}, [page]);
|
||||||
|
|
||||||
|
const SelectableChange = (value: any) => {
|
||||||
formik?.setFieldValue(name, value);
|
formik?.setFieldValue(name, value);
|
||||||
};
|
const isCleared = value?.length === 0 || !value;
|
||||||
const SearchHandleChange = (value: any) => {
|
|
||||||
navigate(`${window?.location?.pathname}?${searchBy}=${value}`, {
|
if (isCleared) {
|
||||||
replace: true,
|
if (PageName) {
|
||||||
|
setValidationParamState({
|
||||||
|
[PageName]: 1,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(value, "value");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleChange = useDebounce((value: string) => {
|
||||||
|
if (PageName) {
|
||||||
|
pushValidationParamState({
|
||||||
|
[PageName]: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
pushValidationParamState({
|
||||||
|
[searchBy]: value,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleBlur = () => {
|
||||||
|
if (PageName && page === 1) {
|
||||||
|
setValidationParamState({
|
||||||
|
[PageName]: null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (PageName && page !== 1) {
|
||||||
|
setValidationParamState({
|
||||||
|
[PageName]: 1,
|
||||||
|
});
|
||||||
|
// setAllPagesOption([]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleScroll = (event: any) => {
|
||||||
|
const target = event.target;
|
||||||
|
const isAtBottom =
|
||||||
|
target.scrollHeight === target.scrollTop + target.clientHeight;
|
||||||
|
|
||||||
|
if (isAtBottom && canChangePage && PageName && page) {
|
||||||
|
console.log("Scrolled to the last option!");
|
||||||
|
let newPage = page + 1;
|
||||||
|
pushValidationParamState({
|
||||||
|
[PageName]: newPage,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log(AllPagesOption);
|
||||||
|
console.log(option,"option");
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ValidationField w-100">
|
<div className="ValidationField w-100">
|
||||||
{no_label ? (
|
<ValidationFieldLabel
|
||||||
<label htmlFor={name} className="text">
|
name={name}
|
||||||
<span>empty</span>
|
label={label}
|
||||||
</label>
|
label_icon={label_icon}
|
||||||
) : label_icon ? (
|
no_label={no_label}
|
||||||
<div className="LabelWithIcon">
|
placeholder={placeholder}
|
||||||
<label htmlFor={name} className="text">
|
t={t}
|
||||||
{t(`input.${label ? label : name}`)}
|
/>
|
||||||
</label>
|
<ValidationFieldContainer isError={isError} errorMsg={errorMsg}>
|
||||||
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<label htmlFor={name} className="text">
|
|
||||||
{t(`input.${label ? label : name}`)}
|
|
||||||
</label>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Form.Item
|
|
||||||
hasFeedback
|
|
||||||
validateStatus={isError ? "error" : ""}
|
|
||||||
help={isError ? errorMsg : ""}
|
|
||||||
>
|
|
||||||
<Select
|
<Select
|
||||||
placeholder={t(
|
placeholder={t(`input.${placeholder || label || name}`)}
|
||||||
`input.${placeholder ? placeholder : label ? label : name}`,
|
|
||||||
)}
|
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
options={option}
|
options={AllPagesOption}
|
||||||
size="large"
|
size="large"
|
||||||
className={`${className} w-100`}
|
className={`${className} w-100`}
|
||||||
value={formik.values[name]}
|
value={formik.values[name]}
|
||||||
loading={isLoading}
|
// loading={isLoading}
|
||||||
allowClear
|
allowClear
|
||||||
{...(isMulti && { mode: "multiple" })}
|
{...(isMulti && { mode: "multiple" })}
|
||||||
onChange={onChange || SelectableChange}
|
onChange={onChange || SelectableChange}
|
||||||
showSearch
|
showSearch
|
||||||
optionFilterProp="label"
|
optionFilterProp="name"
|
||||||
notFoundContent={isLoading ? <Spin /> : "لا يوجد"}
|
notFoundContent={isLoading ? <Spin /> : t("validation.undefined")}
|
||||||
onSearch={SearchHandleChange}
|
onSearch={handleChange}
|
||||||
|
onBlur={handleBlur}
|
||||||
|
id={name}
|
||||||
|
onPopupScroll={handleScroll}
|
||||||
|
fieldNames={{ label: "name", value: "id" }}
|
||||||
|
{...props}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</ValidationFieldContainer>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
import { Form, Select, Spin } from "antd";
|
import { Select } from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import useFormField from "../../../Hooks/useFormField";
|
import useFormField from "../../../Hooks/useFormField";
|
||||||
import { MdOutlineEdit } from "react-icons/md";
|
|
||||||
import { translateOptions } from "../utils/translatedOptions";
|
import { translateOptions } from "../utils/translatedOptions";
|
||||||
|
import { ValidationFieldLabel } from "../components/ValidationFieldLabel";
|
||||||
|
import { ValidationFieldContainer } from "../components/ValidationFieldContainer";
|
||||||
|
import { SelectFieldProps } from "../utils/types";
|
||||||
|
|
||||||
const SelectField = ({
|
const SelectField = ({
|
||||||
name,
|
name,
|
||||||
|
|
@ -13,10 +15,11 @@ const SelectField = ({
|
||||||
isMulti,
|
isMulti,
|
||||||
onChange,
|
onChange,
|
||||||
className,
|
className,
|
||||||
props,
|
|
||||||
no_label,
|
no_label,
|
||||||
label_icon,
|
label_icon,
|
||||||
}: any) => {
|
isLoading,
|
||||||
|
...props
|
||||||
|
}: SelectFieldProps) => {
|
||||||
const { errorMsg, isError, t, formik } = useFormField(name, props);
|
const { errorMsg, isError, t, formik } = useFormField(name, props);
|
||||||
const SelectableChange = (value: {
|
const SelectableChange = (value: {
|
||||||
value: string;
|
value: string;
|
||||||
|
|
@ -24,47 +27,36 @@ const SelectField = ({
|
||||||
}) => {
|
}) => {
|
||||||
formik.setFieldValue(name, value);
|
formik.setFieldValue(name, value);
|
||||||
};
|
};
|
||||||
// console.log(name,"Select");
|
const options = translateOptions(option, t);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ValidationField w-100">
|
<div className="ValidationField w-100">
|
||||||
{no_label ? (
|
<ValidationFieldLabel
|
||||||
<label htmlFor={name} className="text">
|
name={name}
|
||||||
<span>empty</span>
|
label={label}
|
||||||
</label>
|
label_icon={label_icon}
|
||||||
) : label_icon ? (
|
no_label={no_label}
|
||||||
<div className="LabelWithIcon">
|
placeholder={placeholder}
|
||||||
<label htmlFor={name} className="text">
|
t={t}
|
||||||
{t(`input.${label ? label : name}`)}
|
/>
|
||||||
</label>
|
|
||||||
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<label htmlFor={name} className="text">
|
|
||||||
{t(`input.${label ? label : name}`)}
|
|
||||||
</label>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Form.Item
|
<ValidationFieldContainer isError={isError} errorMsg={errorMsg}>
|
||||||
hasFeedback
|
|
||||||
validateStatus={isError ? "error" : ""}
|
|
||||||
help={isError ? errorMsg : ""}
|
|
||||||
>
|
|
||||||
<Select
|
<Select
|
||||||
placeholder={t(
|
placeholder={t(`input.${placeholder || label || name}`)}
|
||||||
`input.${placeholder ? placeholder : label ? label : name}`,
|
|
||||||
)}
|
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
options={translateOptions(option, t)}
|
options={options}
|
||||||
loading={option?.length < 1}
|
{...(isLoading && { loading: isLoading })}
|
||||||
size="large"
|
size="large"
|
||||||
className={`${className} ${isError ? "Select_error" : ""} w-100`}
|
className={`${className} ${isError ? "SelectError" : ""} w-100`}
|
||||||
value={formik.values[name]}
|
value={formik.values[name]}
|
||||||
allowClear
|
allowClear
|
||||||
{...(isMulti && { mode: "multiple" })}
|
{...(isMulti && { mode: "multiple" })}
|
||||||
onChange={onChange || SelectableChange}
|
onChange={onChange || SelectableChange}
|
||||||
|
showSearch={false}
|
||||||
|
id={name}
|
||||||
|
fieldNames={{label:"name",value:"id"}}
|
||||||
|
{...props}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</ValidationFieldContainer>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import { Form, Input } from "antd";
|
import { Input } from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import useFormField from "../../../Hooks/useFormField";
|
import useFormField from "../../../Hooks/useFormField";
|
||||||
import { Field } from "formik";
|
import { Field } from "formik";
|
||||||
|
import { ValidationFieldContainer } from "../components/ValidationFieldContainer";
|
||||||
const { TextArea } = Input;
|
const { TextArea } = Input;
|
||||||
|
|
||||||
const TextAreaField = ({
|
const TextAreaField = ({
|
||||||
|
|
@ -11,27 +12,21 @@ const TextAreaField = ({
|
||||||
isDisabled,
|
isDisabled,
|
||||||
onChange,
|
onChange,
|
||||||
props,
|
props,
|
||||||
type,
|
|
||||||
}: any) => {
|
}: any) => {
|
||||||
const { formik, isError, errorMsg, t } = useFormField(name, props);
|
const { formik, isError, errorMsg, t } = useFormField(name, props);
|
||||||
|
|
||||||
const handleChange = (
|
const handleChange = (
|
||||||
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
|
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
|
||||||
) => {
|
) => {
|
||||||
// console.log('Change:', e.target.value);
|
|
||||||
formik.setFieldValue(name, e.target.value);
|
formik.setFieldValue(name, e.target.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ValidationField w-100 ValidationFieldTextArea">
|
<div className="ValidationField w-100">
|
||||||
<label htmlFor={name} className="text">
|
<label htmlFor={name} className="text">
|
||||||
{t(`input.${label ? label : name}`)}
|
{t(`input.${label ? label : name}`)}
|
||||||
</label>
|
</label>
|
||||||
<Form.Item
|
<ValidationFieldContainer isError={isError} errorMsg={errorMsg}>
|
||||||
hasFeedback
|
|
||||||
validateStatus={isError ? "error" : ""}
|
|
||||||
help={isError ? errorMsg : ""}
|
|
||||||
>
|
|
||||||
<Field
|
<Field
|
||||||
as={TextArea}
|
as={TextArea}
|
||||||
placeholder={t(`input.${placeholder ? placeholder : name}`)}
|
placeholder={t(`input.${placeholder ? placeholder : name}`)}
|
||||||
|
|
@ -39,10 +34,10 @@ const TextAreaField = ({
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
size="large"
|
size="large"
|
||||||
onChange={onChange || handleChange}
|
onChange={onChange || handleChange}
|
||||||
|
id={name}
|
||||||
// onChange={onChange ? onChange : handleChange}
|
// onChange={onChange ? onChange : handleChange}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</ValidationFieldContainer>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ import React from "react";
|
||||||
import useFormField from "../../../Hooks/useFormField";
|
import useFormField from "../../../Hooks/useFormField";
|
||||||
import { MdOutlineEdit } from "react-icons/md";
|
import { MdOutlineEdit } from "react-icons/md";
|
||||||
import { Field } from "formik";
|
import { Field } from "formik";
|
||||||
|
import { ValidationFieldLabel } from "../components/ValidationFieldLabel";
|
||||||
|
import { ValidationFieldContainer } from "../components/ValidationFieldContainer";
|
||||||
const { TextArea } = Input;
|
const { TextArea } = Input;
|
||||||
|
|
||||||
const TextField = ({
|
const TextField = ({
|
||||||
|
|
@ -21,33 +23,20 @@ const TextField = ({
|
||||||
const TextFilehandleChange = (
|
const TextFilehandleChange = (
|
||||||
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
|
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
|
||||||
) => {
|
) => {
|
||||||
// console.log('Change:', e.target.value);
|
|
||||||
formik.setFieldValue(name, e.target.value);
|
formik.setFieldValue(name, e.target.value);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div className={`ValidationField w-100 ${className ?? ""} ValidationFieldTextArea`}>
|
<div className={`ValidationField w-100 ${className ?? ""} `}>
|
||||||
{no_label ? (
|
<ValidationFieldLabel
|
||||||
<label htmlFor={name} className="text">
|
name={name}
|
||||||
<span>empty</span>
|
label={label}
|
||||||
</label>
|
label_icon={label_icon}
|
||||||
) : label_icon ? (
|
no_label={no_label}
|
||||||
<div className="LabelWithIcon">
|
placeholder={placeholder}
|
||||||
<label htmlFor={name} className="text">
|
t={t}
|
||||||
{label2 ? label2 : t(`input.${label ? label : name}`)}
|
/>
|
||||||
</label>
|
|
||||||
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<label htmlFor={name} className="text">
|
|
||||||
{label2 ? label2 : t(`input.${label ? label : name}`)}
|
|
||||||
</label>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Form.Item
|
<ValidationFieldContainer isError={isError} errorMsg={errorMsg}>
|
||||||
hasFeedback
|
|
||||||
validateStatus={isError ? "error" : ""}
|
|
||||||
help={isError ? errorMsg : ""}
|
|
||||||
>
|
|
||||||
<Field
|
<Field
|
||||||
as={TextArea}
|
as={TextArea}
|
||||||
placeholder={t(`input.${placeholder ? placeholder : name}`)}
|
placeholder={t(`input.${placeholder ? placeholder : name}`)}
|
||||||
|
|
@ -57,9 +46,10 @@ const TextField = ({
|
||||||
showCount
|
showCount
|
||||||
maxLength={1000}
|
maxLength={1000}
|
||||||
onChange={onChange || TextFilehandleChange}
|
onChange={onChange || TextFilehandleChange}
|
||||||
|
style={{ height: 120 }}
|
||||||
|
id={name}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</ValidationFieldContainer>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import React from "react";
|
||||||
import useFormField from "../../../Hooks/useFormField";
|
import useFormField from "../../../Hooks/useFormField";
|
||||||
import { MdOutlineEdit } from "react-icons/md";
|
import { MdOutlineEdit } from "react-icons/md";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
import { ValidationFieldLabel } from "../components/ValidationFieldLabel";
|
||||||
|
|
||||||
const Time = ({
|
const Time = ({
|
||||||
name,
|
name,
|
||||||
|
|
@ -20,27 +21,19 @@ const Time = ({
|
||||||
formik.setFieldValue(name, value);
|
formik.setFieldValue(name, value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const Formater = "H:mm";
|
const Formatter = "H:mm";
|
||||||
const FormikValue = formik.values[name];
|
const FormikValue = formik.values[name];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ValidationField w-100 ">
|
<div className="ValidationField w-100 ">
|
||||||
{no_label ? (
|
<ValidationFieldLabel
|
||||||
<label htmlFor={name} className="text">
|
name={name}
|
||||||
<span>empty</span>
|
label={label}
|
||||||
</label>
|
label_icon={label_icon}
|
||||||
) : label_icon ? (
|
no_label={no_label}
|
||||||
<div className="LabelWithIcon">
|
placeholder={placeholder}
|
||||||
<label htmlFor={name} className="text">
|
t={t}
|
||||||
{t(`input.${label ? label : name}`)}
|
/>
|
||||||
</label>
|
|
||||||
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<label htmlFor={name} className="text">
|
|
||||||
{t(`input.${label ? label : name}`)}
|
|
||||||
</label>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
hasFeedback
|
hasFeedback
|
||||||
|
|
@ -51,14 +44,13 @@ const Time = ({
|
||||||
allowClear
|
allowClear
|
||||||
className={`${className} w-100`}
|
className={`${className} w-100`}
|
||||||
size="large"
|
size="large"
|
||||||
value={FormikValue ? dayjs(FormikValue, Formater) : null}
|
value={FormikValue ? dayjs(FormikValue, Formatter) : null}
|
||||||
onChange={onChange || onCalendarChange}
|
onChange={onChange || onCalendarChange}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
placeholder={t(
|
placeholder={t(`input.${placeholder || label || name}`)}
|
||||||
`input.${placeholder ? placeholder : label ? label : name}`,
|
format={Formatter}
|
||||||
)}
|
|
||||||
format={Formater}
|
|
||||||
needConfirm={false}
|
needConfirm={false}
|
||||||
|
id={name}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
import React, { FC } from "react";
|
||||||
|
import { Form } from "antd";
|
||||||
|
|
||||||
|
interface ValidationFieldContainerProps {
|
||||||
|
children: React.ReactNode;
|
||||||
|
isError: boolean;
|
||||||
|
errorMsg: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ValidationFieldContainer: FC<ValidationFieldContainerProps> = ({
|
||||||
|
children,
|
||||||
|
isError,
|
||||||
|
errorMsg,
|
||||||
|
}) => (
|
||||||
|
<div className="ValidationFieldContainer">
|
||||||
|
<Form.Item
|
||||||
|
hasFeedback
|
||||||
|
validateStatus={isError ? "error" : ""}
|
||||||
|
help={isError ? errorMsg : ""}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Form.Item>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
import React from "react";
|
||||||
|
import { MdOutlineEdit } from "react-icons/md";
|
||||||
|
|
||||||
|
interface ValidationFieldLabelProps {
|
||||||
|
name: string;
|
||||||
|
label?: string;
|
||||||
|
no_label?: boolean;
|
||||||
|
label_icon?: boolean;
|
||||||
|
placeholder?: string;
|
||||||
|
t: (key: string) => string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ValidationFieldLabel: React.FC<ValidationFieldLabelProps> = ({
|
||||||
|
name,
|
||||||
|
label,
|
||||||
|
placeholder,
|
||||||
|
no_label,
|
||||||
|
label_icon,
|
||||||
|
t,
|
||||||
|
}) => (
|
||||||
|
<>
|
||||||
|
{no_label ? (
|
||||||
|
<label htmlFor={name} className="text">
|
||||||
|
<span>empty</span>
|
||||||
|
</label>
|
||||||
|
) : label_icon ? (
|
||||||
|
<div className="LabelWithIcon">
|
||||||
|
<label htmlFor={name} className="text">
|
||||||
|
{t(`input.${label ? label : name}`)}
|
||||||
|
</label>
|
||||||
|
<MdOutlineEdit size={22} style={{ color: "#A098AE" }} />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<label htmlFor={name} className="text">
|
||||||
|
{t(`input.${label ? label : name}`)}
|
||||||
|
</label>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
@ -2,7 +2,6 @@ import { useState } from "react";
|
||||||
import { ErrorMessage, useField, Field, useFormikContext } from "formik";
|
import { ErrorMessage, useField, Field, useFormikContext } from "formik";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { FaExclamationCircle } from "react-icons/fa";
|
import { FaExclamationCircle } from "react-icons/fa";
|
||||||
import { convert_data_to_select } from "../../Layout/app/Const";
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
useState,
|
useState,
|
||||||
|
|
@ -12,5 +11,4 @@ export {
|
||||||
useFormikContext,
|
useFormikContext,
|
||||||
useTranslation,
|
useTranslation,
|
||||||
FaExclamationCircle,
|
FaExclamationCircle,
|
||||||
convert_data_to_select,
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { create } from "zustand";
|
||||||
|
|
||||||
|
interface ValidationParamState {
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ModalState {
|
||||||
|
ValidationParamState: ValidationParamState;
|
||||||
|
setValidationParamState: (validationParamState: ValidationParamState) => void;
|
||||||
|
pushValidationParamState: (
|
||||||
|
validationParamState: ValidationParamState,
|
||||||
|
) => void;
|
||||||
|
clearValidationParamState: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useValidationValidationParamState = create<ModalState>((set) => ({
|
||||||
|
ValidationParamState: {},
|
||||||
|
|
||||||
|
setValidationParamState: (validationParamState) =>
|
||||||
|
set(() => ({
|
||||||
|
ValidationParamState: validationParamState,
|
||||||
|
})),
|
||||||
|
|
||||||
|
pushValidationParamState: (validationParamState) =>
|
||||||
|
set((state) => ({
|
||||||
|
ValidationParamState: {
|
||||||
|
...state.ValidationParamState,
|
||||||
|
...validationParamState,
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
|
||||||
|
clearValidationParamState: () =>
|
||||||
|
set({
|
||||||
|
ValidationParamState: {},
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
@ -7,9 +7,10 @@
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
position: relative;
|
position: relative;
|
||||||
min-height: 80px;
|
min-height: 80px;
|
||||||
|
padding-inline: 20px;
|
||||||
> * {
|
> * {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
min-width: 200px;
|
min-width: 150px;
|
||||||
}
|
}
|
||||||
.text,
|
.text,
|
||||||
.ant-form-item {
|
.ant-form-item {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
export function getNestedValue(obj: any, path: any) {
|
|
||||||
return path
|
|
||||||
.replace(/\?.\[|\]\[|\]\.?/g, ".") // Replace question mark and square brackets
|
|
||||||
.split(".") // Split by dots
|
|
||||||
.filter(Boolean) // Remove empty strings
|
|
||||||
.reduce((acc: any, key: any) => acc && acc[key], obj); // Access nested properties
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
export const translateOptions = (options: any, t: any) => {
|
export const translateOptions = (options: any, t: any) => {
|
||||||
return options.map((opt: any) => ({
|
return options?.map((opt: any) => ({
|
||||||
...opt,
|
...opt,
|
||||||
label: t(`${opt.label}`),
|
label: t(`${opt?.label}`),
|
||||||
|
name: t(`${opt?.name}`),
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,149 +1,60 @@
|
||||||
import { InputProps } from "antd";
|
import { InputProps, SelectProps } from "antd";
|
||||||
|
|
||||||
export type ValidationFieldType =
|
// Common properties for all field types
|
||||||
| "text"
|
interface BaseFieldProps {
|
||||||
| "Select"
|
|
||||||
| "LocalSearch"
|
|
||||||
| "Search"
|
|
||||||
| "DataRange"
|
|
||||||
| "Date"
|
|
||||||
| "Time"
|
|
||||||
| "File"
|
|
||||||
| "MaltyFile"
|
|
||||||
| "DropFile"
|
|
||||||
| "Checkbox"
|
|
||||||
| "number"
|
|
||||||
| "password"
|
|
||||||
| "email"
|
|
||||||
| "TextArea";
|
|
||||||
|
|
||||||
export interface ValidationFieldPropsText {
|
|
||||||
name: string;
|
name: string;
|
||||||
no_label?: boolean;
|
|
||||||
label_icon?: boolean;
|
|
||||||
type: "text";
|
|
||||||
placeholder?: string;
|
|
||||||
label?: string;
|
label?: string;
|
||||||
|
placeholder?: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
isDisabled?: boolean;
|
isDisabled?: boolean;
|
||||||
onChange?: (value: any) => void;
|
onChange?: (value: any) => void;
|
||||||
dir?: "ltr" | "rtl";
|
dir?: "ltr" | "rtl";
|
||||||
|
no_label?: boolean;
|
||||||
|
label_icon?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ValidationFieldPropsSelect {
|
// Specific field type properties
|
||||||
name: string;
|
export type SelectFieldProps = BaseFieldProps &
|
||||||
no_label?: boolean;
|
SelectProps & {
|
||||||
label_icon?: boolean;
|
type: "Select" | "LocalSearch";
|
||||||
type: "Select";
|
|
||||||
placeholder?: string;
|
|
||||||
label?: string;
|
|
||||||
className?: string;
|
|
||||||
isDisabled?: boolean;
|
|
||||||
onChange?: any;
|
|
||||||
dir?: "ltr" | "rtl";
|
|
||||||
option: any[];
|
option: any[];
|
||||||
isMulti?: boolean;
|
isMulti?: boolean;
|
||||||
}
|
isLoading?: boolean;
|
||||||
|
searchBy?: string;
|
||||||
|
canChangePage?: boolean;
|
||||||
|
PageName?: string;
|
||||||
|
page?: number;
|
||||||
|
};
|
||||||
|
|
||||||
export interface ValidationFieldPropsLocalSearch {
|
export type SearchFieldProps = BaseFieldProps &
|
||||||
name: string;
|
SelectProps & {
|
||||||
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";
|
type: "Search";
|
||||||
placeholder?: string;
|
|
||||||
label?: string;
|
|
||||||
className?: string;
|
|
||||||
isDisabled?: boolean;
|
|
||||||
onChange?: (value: any) => void;
|
|
||||||
dir?: "ltr" | "rtl";
|
|
||||||
option: any[];
|
option: any[];
|
||||||
isMulti?: boolean;
|
isMulti?: boolean;
|
||||||
|
isLoading: boolean;
|
||||||
searchBy: string;
|
searchBy: string;
|
||||||
isLoading?: any;
|
canChangePage: boolean;
|
||||||
}
|
PageName: string;
|
||||||
export interface ValidationFieldPropsDataRange {
|
page: number;
|
||||||
name: string;
|
};
|
||||||
no_label?: boolean;
|
|
||||||
label_icon?: boolean;
|
type DateFieldProps = BaseFieldProps & {
|
||||||
type: "DataRange";
|
type: "DataRange" | "Date" | "Time";
|
||||||
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";
|
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";
|
picker?: "data" | "week" | "month" | "quarter" | "year";
|
||||||
}
|
};
|
||||||
|
|
||||||
export interface ValidationFieldPropsTime {
|
type FileFieldProps = BaseFieldProps & {
|
||||||
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";
|
type: "File" | "MaltyFile" | "DropFile";
|
||||||
placeholder?: string;
|
};
|
||||||
label?: string;
|
|
||||||
className?: string;
|
type CheckboxFieldProps = BaseFieldProps & {
|
||||||
isDisabled?: boolean;
|
|
||||||
onChange?: (value: any) => void;
|
|
||||||
dir?: "ltr" | "rtl";
|
|
||||||
icon?:any
|
|
||||||
}
|
|
||||||
export interface ValidationFieldPropsCheckbox {
|
|
||||||
name: string;
|
|
||||||
no_label?: boolean;
|
|
||||||
label_icon?: boolean;
|
|
||||||
type: "Checkbox";
|
type: "Checkbox";
|
||||||
label?: string;
|
|
||||||
className?: string;
|
|
||||||
isDisabled?: boolean;
|
|
||||||
onChange?: (value: any) => void;
|
|
||||||
dir?: "ltr" | "rtl";
|
|
||||||
Group?: boolean;
|
Group?: boolean;
|
||||||
}
|
};
|
||||||
export interface ValidationFieldPropstext {
|
|
||||||
name: string;
|
export type FieldProps = BaseFieldProps &
|
||||||
no_label?: boolean;
|
InputProps & {
|
||||||
label_icon?: boolean;
|
|
||||||
type?:
|
type?:
|
||||||
| "text"
|
| "text"
|
||||||
| "number"
|
| "number"
|
||||||
|
|
@ -151,45 +62,19 @@ export interface ValidationFieldPropstext {
|
||||||
| "email"
|
| "email"
|
||||||
| "TextArea"
|
| "TextArea"
|
||||||
| "NumberFormate";
|
| "NumberFormate";
|
||||||
label?: string;
|
|
||||||
label2?: string;
|
label2?: string;
|
||||||
className?: string;
|
|
||||||
placeholder?: string;
|
|
||||||
isDisabled?: boolean;
|
|
||||||
onChange?: (value: any) => void;
|
|
||||||
dir?: "ltr" | "rtl";
|
|
||||||
Group?: boolean;
|
Group?: boolean;
|
||||||
[key: string]: any; // Index signature to allow any additional props
|
[key: string]: any;
|
||||||
}
|
};
|
||||||
|
|
||||||
///// new
|
|
||||||
export interface BaseField {
|
|
||||||
name: string;
|
|
||||||
label?: string;
|
|
||||||
placeholder?: string;
|
|
||||||
}
|
|
||||||
export type OmitBaseType = "placeholder" | "name" | "label" | "type";
|
|
||||||
|
|
||||||
export type OmitPicker = OmitBaseType | "format";
|
|
||||||
|
|
||||||
export interface ValidationFieldPropsInput
|
|
||||||
extends Omit<InputProps, OmitBaseType>,
|
|
||||||
BaseField {
|
|
||||||
type: "text" | "number" | "password" | "email" | "Number";
|
|
||||||
isDisabled?: boolean;
|
|
||||||
no_label?: string;
|
|
||||||
label_icon?: string;
|
|
||||||
label2?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Union type for all field types
|
||||||
export type ValidationFieldProps =
|
export type ValidationFieldProps =
|
||||||
| ValidationFieldPropsInput
|
| SelectFieldProps
|
||||||
| ValidationFieldPropsSelect
|
| DateFieldProps
|
||||||
| ValidationFieldPropsLocalSearch
|
| FileFieldProps
|
||||||
| ValidationFieldPropsDataRange
|
| CheckboxFieldProps
|
||||||
| ValidationFieldPropsDate
|
| SearchFieldProps
|
||||||
| ValidationFieldPropsTime
|
| FieldProps;
|
||||||
| ValidationFieldPropsFile
|
|
||||||
| ValidationFieldPropsCheckbox
|
// Validation field type
|
||||||
| ValidationFieldPropstext
|
export type ValidationFieldType = ValidationFieldProps["type"];
|
||||||
| ValidationFieldPropsSearch;
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ const FilterLayout = ({filterTitle, sub_children}:{filterTitle:string,sub_childr
|
||||||
return (
|
return (
|
||||||
<div className='filter_header'>
|
<div className='filter_header'>
|
||||||
<div className='filter_header_top'>
|
<div className='filter_header_top'>
|
||||||
<h1>{t(filterTitle)}</h1>
|
<h4>{t(filterTitle)}</h4>
|
||||||
<div className='filter_and_order_by'>
|
<div className='filter_and_order_by'>
|
||||||
<span>
|
<span>
|
||||||
<LayoutFilterModal
|
<LayoutFilterModal
|
||||||
|
|
|
||||||
33
src/Pages/Admin/Student/Model/AddModel.tsx
Normal file
33
src/Pages/Admin/Student/Model/AddModel.tsx
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
import React from "react";
|
||||||
|
import { getInitialValues, getValidationSchema } from "./formUtil";
|
||||||
|
import { ModalEnum } from "../../../../enums/Model";
|
||||||
|
import LayoutModel from "../../../../Layout/Dashboard/LayoutModel";
|
||||||
|
import { QueryStatusEnum } from "../../../../enums/QueryStatus";
|
||||||
|
import ModelForm from "./ModelForm";
|
||||||
|
import { useAddStudent } from "../../../../api/student";
|
||||||
|
|
||||||
|
const AddModel: React.FC = () => {
|
||||||
|
const { mutate, status } = useAddStudent();
|
||||||
|
|
||||||
|
const handleSubmit = (values: any) => {
|
||||||
|
mutate({
|
||||||
|
...values,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<LayoutModel
|
||||||
|
status={status as QueryStatusEnum}
|
||||||
|
ModelEnum={ModalEnum.STUDENT_ADD}
|
||||||
|
modelTitle="student"
|
||||||
|
handleSubmit={handleSubmit}
|
||||||
|
getInitialValues={getInitialValues({})}
|
||||||
|
getValidationSchema={getValidationSchema}
|
||||||
|
>
|
||||||
|
<ModelForm />
|
||||||
|
</LayoutModel>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddModel;
|
||||||
37
src/Pages/Admin/Student/Model/EditModel.tsx
Normal file
37
src/Pages/Admin/Student/Model/EditModel.tsx
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
import React from "react";
|
||||||
|
import { getInitialValues, getValidationSchema } from "./formUtil";
|
||||||
|
import { ModalEnum } from "../../../../enums/Model";
|
||||||
|
import LayoutModel from "../../../../Layout/Dashboard/LayoutModel";
|
||||||
|
import ModelForm from "./ModelForm";
|
||||||
|
import { QueryStatusEnum } from "../../../../enums/QueryStatus";
|
||||||
|
import { useObjectToEdit } from "../../../../zustand/ObjectToEditState";
|
||||||
|
import { useUpdateStudent } from "../../../../api/student";
|
||||||
|
import { handelImageState } from "../../../../utils/DataToSendImageState";
|
||||||
|
|
||||||
|
const EditModel: React.FC = () => {
|
||||||
|
const { mutate, status } = useUpdateStudent();
|
||||||
|
const { objectToEdit } = useObjectToEdit((state) => state);
|
||||||
|
|
||||||
|
const handleSubmit = (values: any) => {
|
||||||
|
const Data_to_send = { ...values };
|
||||||
|
mutate(Data_to_send);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<LayoutModel
|
||||||
|
status={status as QueryStatusEnum}
|
||||||
|
ModelEnum={ModalEnum.STUDENT_EDIT}
|
||||||
|
modelTitle="student"
|
||||||
|
handleSubmit={handleSubmit}
|
||||||
|
getInitialValues={getInitialValues(objectToEdit)}
|
||||||
|
getValidationSchema={getValidationSchema}
|
||||||
|
isAddModal={false}
|
||||||
|
>
|
||||||
|
<ModelForm />
|
||||||
|
</LayoutModel>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditModel;
|
||||||
25
src/Pages/Admin/Student/Model/FilterForm.tsx
Normal file
25
src/Pages/Admin/Student/Model/FilterForm.tsx
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
import React from 'react'
|
||||||
|
import ValidationField from '../../../../Components/ValidationField/ValidationField'
|
||||||
|
import { Col, Row } from "reactstrap";
|
||||||
|
|
||||||
|
const FilterForm = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<ValidationField placeholder="name" label="name" name="name" />
|
||||||
|
<ValidationField placeholder="name" label="name" name="name" />
|
||||||
|
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<ValidationField placeholder="name" label="name" name="name" />
|
||||||
|
<ValidationField placeholder="name" label="name" name="name" />
|
||||||
|
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FilterForm
|
||||||
58
src/Pages/Admin/Student/Model/ModelForm.tsx
Normal file
58
src/Pages/Admin/Student/Model/ModelForm.tsx
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
import { Col, Row } from "reactstrap";
|
||||||
|
import ValidationField from "../../../../Components/ValidationField/ValidationField";
|
||||||
|
import { useGetAllGrade } from "../../../../api/grade";
|
||||||
|
import { useValidationValidationParamState } from "../../../../Components/ValidationField/state/ValidationValidationParamState";
|
||||||
|
|
||||||
|
const Form = ({ isEdit = false }: { isEdit?: boolean }) => {
|
||||||
|
const { ValidationParamState } = useValidationValidationParamState();
|
||||||
|
const {
|
||||||
|
GradeName, GradeCurrentPage,
|
||||||
|
} = ValidationParamState;
|
||||||
|
|
||||||
|
|
||||||
|
const { data: Grade, isLoading: isLoadingGrade } = useGetAllGrade({
|
||||||
|
name: GradeName,
|
||||||
|
page: GradeCurrentPage
|
||||||
|
});
|
||||||
|
const GradeOption = Grade?.data ?? []
|
||||||
|
const canChangeGradePage = !!Grade?.links?.next;
|
||||||
|
const GradePage = Grade?.meta?.currentPage;
|
||||||
|
|
||||||
|
const sex = [
|
||||||
|
{name:"male" , id :"male"},
|
||||||
|
{name:"female" , id :"female"}
|
||||||
|
]
|
||||||
|
return (
|
||||||
|
<Row className="w-100">
|
||||||
|
<Col>
|
||||||
|
<ValidationField name="first_name" placeholder="first_name" label="first_name" />
|
||||||
|
<ValidationField name="last_name" placeholder="last_name" label="last_name" />
|
||||||
|
<ValidationField name="username" placeholder="username" label="username" />
|
||||||
|
{!isEdit &&
|
||||||
|
<ValidationField name="password" placeholder="password" label="password" />
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<ValidationField name="phone_number" placeholder="contact_number1" label="contact_number1" />
|
||||||
|
<ValidationField
|
||||||
|
searchBy="GradeName"
|
||||||
|
name="grade_id"
|
||||||
|
label="grade"
|
||||||
|
type="Search"
|
||||||
|
option={GradeOption}
|
||||||
|
isLoading={isLoadingGrade}
|
||||||
|
canChangePage={canChangeGradePage}
|
||||||
|
PageName={"GradeCurrentPage"}
|
||||||
|
page={GradePage}
|
||||||
|
|
||||||
|
/>
|
||||||
|
<ValidationField type="Select" name="sex" option={sex} />
|
||||||
|
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Form;
|
||||||
27
src/Pages/Admin/Student/Model/formUtil.ts
Normal file
27
src/Pages/Admin/Student/Model/formUtil.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
import * as Yup from "yup";
|
||||||
|
import { Student, StudentInitialValues } from "../../../../types/Student";
|
||||||
|
|
||||||
|
export const getInitialValues = (
|
||||||
|
objectToEdit: Partial<Student>,
|
||||||
|
): StudentInitialValues => {
|
||||||
|
return {
|
||||||
|
id: objectToEdit?.user_id,
|
||||||
|
first_name: objectToEdit?.first_name ?? "",
|
||||||
|
last_name: objectToEdit?.last_name ?? "",
|
||||||
|
// address: objectToEdit?.address ?? "",
|
||||||
|
// birthday: objectToEdit?.birthday ?? "",
|
||||||
|
// city: objectToEdit?.city ?? "",
|
||||||
|
grade_id: objectToEdit?.grade_id ,
|
||||||
|
// image: objectToEdit?.image ?? "",
|
||||||
|
sex: objectToEdit?.sex ,
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getValidationSchema = () => {
|
||||||
|
// validate input
|
||||||
|
return Yup.object().shape({
|
||||||
|
first_name: Yup.string().required("validation.required"),
|
||||||
|
last_name: Yup.string().required("validation.required"),
|
||||||
|
});
|
||||||
|
};
|
||||||
47
src/Pages/Admin/Student/Page.tsx
Normal file
47
src/Pages/Admin/Student/Page.tsx
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { lazy, Suspense } from "react";
|
||||||
|
import { Spin } from "antd";
|
||||||
|
import useSetPageTitle from "../../../Hooks/useSetPageTitle";
|
||||||
|
import { ModalEnum } from "../../../enums/Model";
|
||||||
|
import { useDeleteStudent } from "../../../api/student";
|
||||||
|
import PageHeader from "../../../Layout/Dashboard/PageHeader";
|
||||||
|
import { canAddStudent } from "../../../utils/hasAbilityFn";
|
||||||
|
import FilterLayout from "../../../Layout/Dashboard/FilterLayout";
|
||||||
|
import FilterForm from "./Model/FilterForm";
|
||||||
|
|
||||||
|
const Table = lazy(() => import("./Table"));
|
||||||
|
const AddModalForm = lazy(() => import("./Model/AddModel"));
|
||||||
|
const EditModalForm = lazy(() => import("./Model/EditModel"));
|
||||||
|
const DeleteModalForm = lazy(
|
||||||
|
() => import("../../../Layout/Dashboard/DeleteModels"),
|
||||||
|
);
|
||||||
|
|
||||||
|
const TableHeader = () => {
|
||||||
|
const [t] = useTranslation();
|
||||||
|
const deleteMutation = useDeleteStudent();
|
||||||
|
|
||||||
|
useSetPageTitle(t(`page_header.student`));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="TableWithHeader">
|
||||||
|
<Suspense fallback={<Spin />}>
|
||||||
|
<PageHeader
|
||||||
|
pageTitle="student"
|
||||||
|
ModelAbility={ModalEnum?.STUDENT_ADD}
|
||||||
|
canAdd={canAddStudent}/>
|
||||||
|
<FilterLayout
|
||||||
|
sub_children={<FilterForm/>}
|
||||||
|
filterTitle="table.student"/>
|
||||||
|
<Table />
|
||||||
|
<AddModalForm />
|
||||||
|
<EditModalForm />
|
||||||
|
<DeleteModalForm
|
||||||
|
deleteMutation={deleteMutation}
|
||||||
|
ModelEnum={ModalEnum?.STUDENT_DELETE}
|
||||||
|
/>
|
||||||
|
</Suspense>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TableHeader;
|
||||||
13
src/Pages/Admin/Student/Table.tsx
Normal file
13
src/Pages/Admin/Student/Table.tsx
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { useColumns } from "./useTableColumns";
|
||||||
|
import React from "react";
|
||||||
|
import DataTable from "../../../Layout/Dashboard/Table/DataTable";
|
||||||
|
import { useGetAllStudent } from "../../../api/student";
|
||||||
|
|
||||||
|
const App: React.FC = () => {
|
||||||
|
const response = useGetAllStudent({ pagination: true });
|
||||||
|
|
||||||
|
return <DataTable response={response} useColumns={useColumns} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default App;
|
||||||
|
|
||||||
91
src/Pages/Admin/Student/useTableColumns.tsx
Normal file
91
src/Pages/Admin/Student/useTableColumns.tsx
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
import { TableColumnsType } from "antd";
|
||||||
|
import { Student } from "../../../types/Student";
|
||||||
|
import { FaPlus } from "react-icons/fa";
|
||||||
|
import useModalHandler from "../../../utils/useModalHandler";
|
||||||
|
import { ModalEnum } from "../../../enums/Model";
|
||||||
|
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import {
|
||||||
|
canAddStudent,
|
||||||
|
canDeleteStudent,
|
||||||
|
canEditStudent,
|
||||||
|
canShowStudent,
|
||||||
|
} from "../../../utils/hasAbilityFn";
|
||||||
|
import ActionButtons from "../../../Components/Table/ActionButtons";
|
||||||
|
|
||||||
|
export const useColumns = () => {
|
||||||
|
const { handel_open_model } = useModalHandler();
|
||||||
|
|
||||||
|
const { setObjectToEdit } = useObjectToEdit((state) => state);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const handelShow = (record: Student) => {
|
||||||
|
navigate(`${record?.user_id}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handelDelete = (data: Student) => {
|
||||||
|
setObjectToEdit(data);
|
||||||
|
handel_open_model(ModalEnum?.STUDENT_DELETE);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEdit = (record: Student) => {
|
||||||
|
setObjectToEdit(record);
|
||||||
|
handel_open_model(ModalEnum?.STUDENT_EDIT);
|
||||||
|
};
|
||||||
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
const columns: TableColumnsType<Student> = [
|
||||||
|
{
|
||||||
|
title: t("columns.id"),
|
||||||
|
dataIndex: "id",
|
||||||
|
key: "id",
|
||||||
|
align: "center",
|
||||||
|
render: (_text, record) => record?.user_id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: `${t("columns.first_name")}`,
|
||||||
|
dataIndex: "first_name",
|
||||||
|
key: "first_name",
|
||||||
|
align: "center",
|
||||||
|
render: (_text, record) => record?.first_name,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: `${t("columns.last_name")}`,
|
||||||
|
dataIndex: "last_name",
|
||||||
|
key: "last_name",
|
||||||
|
align: "center",
|
||||||
|
render: (_text, record) => record?.last_name,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: `${t("columns.sex")}`,
|
||||||
|
dataIndex: "sex",
|
||||||
|
key: "sex",
|
||||||
|
align: "center",
|
||||||
|
render: (_text, record) => record?.sex,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
title: "",
|
||||||
|
|
||||||
|
key: "actions",
|
||||||
|
align: "center",
|
||||||
|
render: (_text, record, index) => {
|
||||||
|
return (
|
||||||
|
<ActionButtons
|
||||||
|
canDelete={canDeleteStudent}
|
||||||
|
canEdit={canEditStudent}
|
||||||
|
canShow={canShowStudent}
|
||||||
|
index={index}
|
||||||
|
onDelete={() => handelDelete(record)}
|
||||||
|
onEdit={() => handleEdit(record)}
|
||||||
|
onShow={() => handelShow(record)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return columns;
|
||||||
|
};
|
||||||
|
|
@ -98,6 +98,7 @@ const AddPage: React.FC = () => {
|
||||||
"/" +
|
"/" +
|
||||||
t("practical.add"),
|
t("practical.add"),
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleSubmit = (
|
const handleSubmit = (
|
||||||
values: any,
|
values: any,
|
||||||
{ resetForm }: { resetForm: () => void },
|
{ resetForm }: { resetForm: () => void },
|
||||||
|
|
@ -109,7 +110,7 @@ const AddPage: React.FC = () => {
|
||||||
const newBseQuestion = {
|
const newBseQuestion = {
|
||||||
subject_id: subject_id,
|
subject_id: subject_id,
|
||||||
content: DataToSend?.content,
|
content: DataToSend?.content,
|
||||||
image: DataToSend?.image ?? "",
|
content_image: DataToSend?.content_image ?? "",
|
||||||
isBase: 1,
|
isBase: 1,
|
||||||
lessons_ids: [lesson_id],
|
lessons_ids: [lesson_id],
|
||||||
canAnswersBeShuffled,
|
canAnswersBeShuffled,
|
||||||
|
|
@ -145,22 +146,25 @@ const AddPage: React.FC = () => {
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const tags = processTags(DataToSend);
|
const tags = processTags(DataToSend);
|
||||||
console.log(values,"values");
|
|
||||||
const answers = values?.answers?.map((item:any,index:number)=>{
|
const answers = values?.answers?.map((item:any,index:number)=>{
|
||||||
return {
|
return {
|
||||||
order:index,
|
order:index,
|
||||||
...item
|
...item
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
const NewQuestion = {
|
||||||
mutate({
|
|
||||||
...values,
|
...values,
|
||||||
subject_id: subject_id,
|
subject_id: subject_id,
|
||||||
tags,
|
tags,
|
||||||
lessons_ids: [lesson_id],
|
lessons_ids: [lesson_id],
|
||||||
canAnswersBeShuffled,
|
canAnswersBeShuffled,
|
||||||
answers
|
answers
|
||||||
});
|
}
|
||||||
|
console.clear()
|
||||||
|
console.log(NewQuestion,"NewQuestion");
|
||||||
|
|
||||||
|
mutate(NewQuestion);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ const ChoiceFields = ({ index, data }: { index: number; data: Choice }) => {
|
||||||
type="TextArea"
|
type="TextArea"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ImageBoxField name={`answers.${index}.answer_image`} />
|
<ImageBoxField name={`answers.${index}.content_image`} />
|
||||||
|
|
||||||
<div className="answer_status">
|
<div className="answer_status">
|
||||||
|
|
||||||
|
|
@ -60,7 +60,7 @@ const ChoiceFields = ({ index, data }: { index: number; data: Choice }) => {
|
||||||
className=" "
|
className=" "
|
||||||
placeholder="_"
|
placeholder="_"
|
||||||
name={`answers.${index}.hint`}
|
name={`answers.${index}.hint`}
|
||||||
label="hint_question"
|
label="hint"
|
||||||
type="text"
|
type="text"
|
||||||
style={{ width: "100%" }}
|
style={{ width: "100%" }}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ const Form = () => {
|
||||||
...((formik?.values as any)?.answers as Choice[]),
|
...((formik?.values as any)?.answers as Choice[]),
|
||||||
{
|
{
|
||||||
content: null,
|
content: null,
|
||||||
answer_image: null,
|
content_image: null,
|
||||||
isCorrect: 0,
|
isCorrect: 0,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
@ -48,7 +48,7 @@ const Form = () => {
|
||||||
<Row className="w-100 exercise_form_container">
|
<Row className="w-100 exercise_form_container">
|
||||||
<div className="exercise_form">
|
<div className="exercise_form">
|
||||||
<ValidationField className="textarea_exercise" name="content" label="answer_content" type="TextArea" />
|
<ValidationField className="textarea_exercise" name="content" label="answer_content" type="TextArea" />
|
||||||
<ImageBoxField name="image" />
|
<ImageBoxField name="content_image" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Choices />
|
<Choices />
|
||||||
|
|
@ -65,7 +65,7 @@ const Form = () => {
|
||||||
className=" "
|
className=" "
|
||||||
placeholder="_"
|
placeholder="_"
|
||||||
name="hint"
|
name="hint"
|
||||||
label="hint"
|
label="hint_question"
|
||||||
type="text"
|
type="text"
|
||||||
style={{ width: "100%" }}
|
style={{ width: "100%" }}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ export const getInitialValues = (objectToEdit: Question): any => {
|
||||||
return {
|
return {
|
||||||
id: objectToEdit?.id ?? null,
|
id: objectToEdit?.id ?? null,
|
||||||
content: objectToEdit?.content ?? "",
|
content: objectToEdit?.content ?? "",
|
||||||
image: objectToEdit?.image ?? "",
|
content_image: objectToEdit?.content_image ?? "",
|
||||||
subject_id: objectToEdit?.subject_id ?? "",
|
subject_id: objectToEdit?.subject_id ?? "",
|
||||||
canAnswersBeShuffled: objectToEdit?.canAnswersBeShuffled ? 1 : 0,
|
canAnswersBeShuffled: objectToEdit?.canAnswersBeShuffled ? 1 : 0,
|
||||||
hint: objectToEdit?.hint ?? "",
|
hint: objectToEdit?.hint ?? "",
|
||||||
|
|
@ -26,13 +26,13 @@ export const getInitialValues = (objectToEdit: Question): any => {
|
||||||
export const getValidationSchema = () => {
|
export const getValidationSchema = () => {
|
||||||
// validate input
|
// validate input
|
||||||
return Yup.object().shape({
|
return Yup.object().shape({
|
||||||
image: Yup.string().nullable(),
|
content_image: Yup.string().nullable(),
|
||||||
content: Yup.string().required("validation.required"),
|
content: Yup.string().required("validation.required"),
|
||||||
answers: Yup.array()
|
answers: Yup.array()
|
||||||
.of(
|
.of(
|
||||||
Yup.object().shape({
|
Yup.object().shape({
|
||||||
content: Yup.string().required("validation.required"),
|
content: Yup.string().required("validation.required"),
|
||||||
answer_image: Yup.string().nullable(),
|
content_image: Yup.string().nullable(),
|
||||||
isCorrect: Yup.boolean(),
|
isCorrect: Yup.boolean(),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
@ -61,7 +61,7 @@ export const getInitialValuesBase = (objectToEdit: Question): any => {
|
||||||
return {
|
return {
|
||||||
id: objectToEdit?.id ?? null,
|
id: objectToEdit?.id ?? null,
|
||||||
content: objectToEdit?.content ?? "",
|
content: objectToEdit?.content ?? "",
|
||||||
image: objectToEdit?.image ?? "",
|
content_image: objectToEdit?.content_image ?? "",
|
||||||
subject_id: objectToEdit?.subject_id ?? "",
|
subject_id: objectToEdit?.subject_id ?? "",
|
||||||
isBase: 1,
|
isBase: 1,
|
||||||
parent_id: objectToEdit?.parent_id ?? "",
|
parent_id: objectToEdit?.parent_id ?? "",
|
||||||
|
|
@ -74,7 +74,7 @@ export const getInitialValuesBase = (objectToEdit: Question): any => {
|
||||||
export const getValidationSchemaBase = () => {
|
export const getValidationSchemaBase = () => {
|
||||||
// validate input
|
// validate input
|
||||||
return Yup.object().shape({
|
return Yup.object().shape({
|
||||||
image: Yup.string().nullable(),
|
content_image: Yup.string().nullable(),
|
||||||
content: Yup.string().required("validation.required"),
|
content: Yup.string().required("validation.required"),
|
||||||
Questions: Yup.array().of(
|
Questions: Yup.array().of(
|
||||||
Yup.object().shape({
|
Yup.object().shape({
|
||||||
|
|
@ -95,21 +95,29 @@ export const getValidationSchemaBase = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export function processTags(DataToSend: any) {
|
export function processTags(DataToSend: any) {
|
||||||
|
console.log(DataToSend?.tags);
|
||||||
|
|
||||||
const oldTags = DataToSend?.tags
|
const oldTags = DataToSend?.tags
|
||||||
?.map((item: any, index: number) => {
|
?.map((item: any, index: number) => {
|
||||||
if (typeof item?.id === "number") {
|
if (typeof item === "number") {
|
||||||
return item?.id;
|
return item;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.filter((item: any) => item !== undefined);
|
.filter((item: any) => item !== undefined);
|
||||||
|
|
||||||
const newTags = DataToSend?.tags
|
const newTags = DataToSend?.tags
|
||||||
?.map((item: any, index: number) => {
|
?.map((item: any, index: number) => {
|
||||||
if (typeof item?.id === "string" && item?.name !== "") {
|
console.log(item);
|
||||||
return { name: item?.name };
|
|
||||||
|
if (typeof item === "string" && item !== "") {
|
||||||
|
console.log(item);
|
||||||
|
|
||||||
|
return { name: item };
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.filter((item: any) => item !== undefined);
|
.filter((item: any) => item !== undefined);
|
||||||
|
console.log(newTags);
|
||||||
|
console.log(oldTags);
|
||||||
|
|
||||||
return { new: newTags, old: oldTags };
|
return { new: newTags, old: oldTags };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ const AddQuestionPage = React.lazy(() => import("./Pages/Admin/question/AddPage"
|
||||||
const EditQuestionPage = React.lazy(() => import("./Pages/Admin/question/EditPage"));
|
const EditQuestionPage = React.lazy(() => import("./Pages/Admin/question/EditPage"));
|
||||||
|
|
||||||
const Report = React.lazy(() => import("./Pages/Admin/Report/Page"));
|
const Report = React.lazy(() => import("./Pages/Admin/Report/Page"));
|
||||||
const User = React.lazy(() => import("./Pages/Admin/User/Page"));
|
const Student = React.lazy(() => import("./Pages/Admin/Student/Page"));
|
||||||
|
|
||||||
import { hasAbility } from "./utils/hasAbility";
|
import { hasAbility } from "./utils/hasAbility";
|
||||||
import { ABILITIES_ENUM, ABILITIES_VALUES_ENUM } from "./enums/abilities";
|
import { ABILITIES_ENUM, ABILITIES_VALUES_ENUM } from "./enums/abilities";
|
||||||
|
|
@ -65,12 +65,12 @@ export const menuItems: TMenuItem[] = [
|
||||||
prevPath: 0,
|
prevPath: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: "page_header.user",
|
header: "page_header.student",
|
||||||
element: <User />,
|
element: <Student />,
|
||||||
icon: <FaMoneyBill />,
|
icon: <FaMoneyBill />,
|
||||||
text: "sidebar.user",
|
text: "sidebar.student",
|
||||||
path: `/${ABILITIES_ENUM?.User}`,
|
path: `/${ABILITIES_ENUM?.STUDENT}`,
|
||||||
abilities: ABILITIES_ENUM?.User,
|
abilities: ABILITIES_ENUM?.STUDENT,
|
||||||
abilities_value: ABILITIES_VALUES_ENUM.INDEX,
|
abilities_value: ABILITIES_VALUES_ENUM.INDEX,
|
||||||
prevPath: 0,
|
prevPath: 0,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -11,3 +11,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.filter_header_top{
|
||||||
|
color: #202C4B;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -191,9 +191,20 @@
|
||||||
>*{
|
>*{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.exercise_forms{
|
.exercise_forms{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.row>*{
|
||||||
|
padding-right: 0 !important;
|
||||||
|
padding-left: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.SelectTag{
|
||||||
|
padding-inline: 20px;
|
||||||
|
}
|
||||||
|
|
@ -15,7 +15,7 @@ const KEY2 = "questionBases";
|
||||||
|
|
||||||
export const useGetAllQuestion = (params?: any) =>
|
export const useGetAllQuestion = (params?: any) =>
|
||||||
useGetQuery(KEY, API.GET, params);
|
useGetQuery(KEY, API.GET, params);
|
||||||
export const useAddQuestion = () => useAddMutation(KEY, API.ADD, false);
|
export const useAddQuestion = () => useAddMutation(KEY, API.ADD, true);
|
||||||
export const useAddQuestionAsync = () => useAddMutation(KEY2, API.ADD);
|
export const useAddQuestionAsync = () => useAddMutation(KEY2, API.ADD);
|
||||||
|
|
||||||
export const useUpdateQuestion = (params?: any) =>
|
export const useUpdateQuestion = (params?: any) =>
|
||||||
|
|
|
||||||
|
|
@ -691,7 +691,8 @@
|
||||||
"lesson":"الدرس",
|
"lesson":"الدرس",
|
||||||
"question":"السؤال",
|
"question":"السؤال",
|
||||||
"report":"تقرير",
|
"report":"تقرير",
|
||||||
"user":"مستخدم"
|
"user":"مستخدم",
|
||||||
|
"student":"الطلاب"
|
||||||
},
|
},
|
||||||
"message": {
|
"message": {
|
||||||
"some_thing_went_wrong": "حدث خطأ ما",
|
"some_thing_went_wrong": "حدث خطأ ما",
|
||||||
|
|
@ -725,6 +726,7 @@
|
||||||
"payment": " لوحة القيادة / الدفعات",
|
"payment": " لوحة القيادة / الدفعات",
|
||||||
"branch": " لوحة القيادة / الفروع",
|
"branch": " لوحة القيادة / الفروع",
|
||||||
"role": " لوحة القيادة / الادوار",
|
"role": " لوحة القيادة / الادوار",
|
||||||
|
"student": " لوحة القيادة / قائمة الطلاب ",
|
||||||
"admin": " لوحة القيادة / المسؤولون",
|
"admin": " لوحة القيادة / المسؤولون",
|
||||||
"student_details": "تفاصيل الطالب",
|
"student_details": "تفاصيل الطالب",
|
||||||
"create_student": "إنشاء طالب",
|
"create_student": "إنشاء طالب",
|
||||||
|
|
@ -750,6 +752,9 @@
|
||||||
"report":"تقرير",
|
"report":"تقرير",
|
||||||
"user":"مستخدم"
|
"user":"مستخدم"
|
||||||
},
|
},
|
||||||
|
"table":{
|
||||||
|
"student":"قائمة الطلاب"
|
||||||
|
},
|
||||||
"alphabet":{
|
"alphabet":{
|
||||||
"A": "أ",
|
"A": "أ",
|
||||||
"B": "ب",
|
"B": "ب",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { ReactElement, LazyExoticComponent, ReactNode } from "react";
|
import { ReactElement, LazyExoticComponent, ReactNode } from "react";
|
||||||
import { Mark_State, Payment_type, term_type } from "./Item";
|
import { Mark_State, Payment_type, term_type } from "./Item";
|
||||||
import { ABILITIES_ENUM, ABILITIES_VALUES_ENUM } from "../enums/abilities";
|
import { ABILITIES_ENUM, ABILITIES_VALUES_ENUM } from "../enums/abilities";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
export type ChildrenType = {
|
export type ChildrenType = {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
|
|
@ -404,3 +405,6 @@ export interface showAdmin {
|
||||||
branches: BranchRole[];
|
branches: BranchRole[];
|
||||||
}
|
}
|
||||||
export type Nullable<T> = { [K in keyof T]: T[K] | null };
|
export type Nullable<T> = { [K in keyof T]: T[K] | null };
|
||||||
|
|
||||||
|
|
||||||
|
export type DateType = string | dayjs.Dayjs | null | undefined;
|
||||||
|
|
|
||||||
|
|
@ -310,7 +310,7 @@ export interface Question {
|
||||||
canAnswersBeShuffled: number;
|
canAnswersBeShuffled: number;
|
||||||
max_mark: number;
|
max_mark: number;
|
||||||
min_mark_to_pass: number;
|
min_mark_to_pass: number;
|
||||||
image: string | null;
|
content_image: string | null;
|
||||||
Questions?: any[];
|
Questions?: any[];
|
||||||
question_options_count?: any;
|
question_options_count?: any;
|
||||||
answers: QuestionOption[];
|
answers: QuestionOption[];
|
||||||
|
|
|
||||||
34
src/types/Student.ts
Normal file
34
src/types/Student.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { DateType, Nullable } from "./App";
|
||||||
|
|
||||||
|
// Define the Teacher interface
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export interface Student {
|
||||||
|
first_name: string; // The first name of the user
|
||||||
|
last_name: string; // The last name of the user
|
||||||
|
city: string | null; // The city of the user, can be null
|
||||||
|
sex: string; // The sex of the user, using a union type for possible values
|
||||||
|
image: string | null; // The URL of the user's image, can be null
|
||||||
|
address: string | null; // The address of the user, can be null
|
||||||
|
card: string | null; // The card information, can be null
|
||||||
|
birthday: DateType; // The birthday of the user, can be null
|
||||||
|
grade_id: number | string; // The ID of the user's grade
|
||||||
|
user_id: number; // The unique ID of the user
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface InitialValues {
|
||||||
|
id: number;
|
||||||
|
first_name: string; // The first name of the user
|
||||||
|
last_name: string; // The last name of the user
|
||||||
|
city: string | null; // The city of the user, can be null
|
||||||
|
sex: string; // The sex of the user, using a union type for possible values
|
||||||
|
image: string | null; // The URL of the user's image, can be null
|
||||||
|
address: string | null; // The address of the user, can be null
|
||||||
|
card: string | null; // The card information, can be null
|
||||||
|
birthday: DateType; // The birthday of the user, can be null
|
||||||
|
grade_id: number | string; // The ID of the user's grade
|
||||||
|
user_id: number; // The unique ID of the user
|
||||||
|
}
|
||||||
|
|
||||||
|
export type StudentInitialValues = Partial<Nullable<InitialValues>>;
|
||||||
Loading…
Reference in New Issue
Block a user