add karim field v4

This commit is contained in:
karimaldeen 2024-09-10 10:19:33 +03:00
parent b2ea58b19e
commit 1a78474120
49 changed files with 905 additions and 744 deletions

View File

@ -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'>

View File

@ -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;

View File

@ -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;
// }
// }

View File

@ -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;

View File

@ -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} />;

View File

@ -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>
); );
}; };

View File

@ -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>
); );
}; };

View File

@ -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>
); );
}; };

View File

@ -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>
); );
}; };

View File

@ -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

View File

@ -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);

View 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>
); );
}; };

View File

@ -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,28 +15,28 @@ 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(() => {
? imageUrl.map((file: any, index: number) => { return imageUrl
// console.log(file,"file"); ? imageUrl.map((file: any, index: number) => {
return file instanceof File
return file instanceof File ? {
? { uid: index,
uid: index, name: file?.name,
name: file?.name, status: "done",
status: "done", originFileObj: file,
originFileObj: file, }
} : {
: { uid: index,
uid: index, id: file?.id,
id: file?.id, name: file?.name,
name: file?.name, status: "done",
status: "done", url: file?.url || "",
url: file?.url || "", thumbUrl: file?.url || "",
thumbUrl: file?.url || "", };
}; })
}) : [];
: []; }, [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,19 +64,20 @@ 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"}
icon={<UploadOutlined />} icon={<UploadOutlined />}
> >
{t(`input.` + placeholder) ?? t("input.upload_image")} {t(`input.` + placeholder) ?? t("input.upload_image")}
</Button> </Button>
<div className="Error_color"> {isError ? "required" : ""}</div> <div className="Error_color">{isError ? "required" : ""}</div>
</Upload> </Upload>
</div> </div>
); );

View File

@ -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);

View File

@ -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>
); );
}; };

View File

@ -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;
if (isCleared) {
if (PageName) {
setValidationParamState({
[PageName]: 1,
});
}
}
console.log(value, "value");
}; };
const SearchHandleChange = (value: any) => {
navigate(`${window?.location?.pathname}?${searchBy}=${value}`, { const handleChange = useDebounce((value: string) => {
replace: true, 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>
); );
}; };

View File

@ -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>
); );
}; };

View File

@ -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>
); );
}; };

View File

@ -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>
); );
}; };

View File

@ -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>

View File

@ -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>
);

View File

@ -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>
)}
</>
);

View File

@ -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,
}; };

View File

@ -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: {},
}),
}));

View File

@ -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 {

View File

@ -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
}

View File

@ -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}`),
})); }));
}; };

View File

@ -1,195 +1,80 @@
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"; option: any[];
placeholder?: string; isMulti?: boolean;
label?: string; isLoading?: boolean;
className?: string; searchBy?: string;
isDisabled?: boolean; canChangePage?: boolean;
onChange?: any; PageName?: string;
dir?: "ltr" | "rtl"; page?: number;
option: any[]; };
isMulti?: boolean;
}
export interface ValidationFieldPropsLocalSearch { export type SearchFieldProps = BaseFieldProps &
name: string; SelectProps & {
no_label?: boolean; type: "Search";
label_icon?: boolean; option: any[];
type: "LocalSearch"; isMulti?: boolean;
placeholder?: string; isLoading: boolean;
label?: string; searchBy: string;
className?: string; canChangePage: boolean;
isDisabled?: boolean; PageName: string;
onChange?: (value: any) => void; page: number;
dir?: "ltr" | "rtl"; };
option: any[];
isMulti?: boolean; type DateFieldProps = BaseFieldProps & {
} type: "DataRange" | "Date" | "Time";
export interface ValidationFieldPropsSearch {
name: string;
no_label?: boolean;
label_icon?: boolean;
type: "Search";
placeholder?: string;
label?: string;
className?: string;
isDisabled?: boolean;
onChange?: (value: any) => void;
dir?: "ltr" | "rtl";
option: any[];
isMulti?: boolean;
searchBy: string;
isLoading?: any;
}
export interface ValidationFieldPropsDataRange {
name: string;
no_label?: boolean;
label_icon?: boolean;
type: "DataRange";
placeholder?: string;
label?: string;
className?: string;
isDisabled?: boolean;
onChange?: (value: any) => void;
dir?: "ltr" | "rtl";
Format?: "YYYY/MM/DD" | "MM/DD" | "YYYY/MM" | "YYYY-MM-DD HH:mm:ss.SSS"; 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;
no_label?: boolean;
label_icon?: boolean;
type?:
| "text"
| "number"
| "password"
| "email"
| "TextArea"
| "NumberFormate";
label?: string;
label2?: string;
className?: string;
placeholder?: string;
isDisabled?: boolean;
onChange?: (value: any) => void;
dir?: "ltr" | "rtl";
Group?: boolean;
[key: string]: any; // Index signature to allow any additional props
}
///// new export type FieldProps = BaseFieldProps &
export interface BaseField { InputProps & {
name: string; type?:
label?: string; | "text"
placeholder?: string; | "number"
} | "password"
export type OmitBaseType = "placeholder" | "name" | "label" | "type"; | "email"
| "TextArea"
export type OmitPicker = OmitBaseType | "format"; | "NumberFormate";
label2?: string;
export interface ValidationFieldPropsInput Group?: boolean;
extends Omit<InputProps, OmitBaseType>, [key: string]: any;
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;

View File

@ -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

View 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;

View 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;

View 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

View 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;

View 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"),
});
};

View 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;

View 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;

View 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;
};

View File

@ -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);
} }
}; };

View File

@ -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%" }}
/> />

View File

@ -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%" }}
/> />

View File

@ -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 };
} }

View File

@ -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,
}, },

View File

@ -11,3 +11,10 @@
} }
} }
} }
.filter_header_top{
color: #202C4B;
}

View File

@ -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;
}

View File

@ -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) =>

View File

@ -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": "ب",

View File

@ -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;

View File

@ -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
View 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>>;