feat: enhance form validation logic to include table field checks and improve error handling
This commit is contained in:
parent
6b122bafd8
commit
6c311f4b2e
|
|
@ -57,58 +57,107 @@ export const Form: React.FC<any> = ({
|
||||||
);
|
);
|
||||||
try {
|
try {
|
||||||
const fieldDate: any = local?.fields;
|
const fieldDate: any = local?.fields;
|
||||||
|
let isError = false;
|
||||||
|
let error: Record<string, string> = {};
|
||||||
try {
|
try {
|
||||||
const dateFields = Object.values(fieldDate).filter(
|
const dateFields = Object.values(fieldDate).filter(
|
||||||
(field: any) => get(field, "type") === "date"
|
(field: any) => get(field, "type") === "date"
|
||||||
);
|
);
|
||||||
if (Array.isArray(dateFields) && dateFields?.length) {
|
if (dateFields.length) {
|
||||||
dateFields.map((e: any) => {
|
dateFields.forEach((e: any) => {
|
||||||
if (e?.name)
|
if (e?.name) {
|
||||||
local.data[e?.name] = normalDate(local.data[e?.name]);
|
local.data[e.name] = normalDate(local.data[e.name]);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
local.render();
|
local.render();
|
||||||
}
|
}
|
||||||
} catch (ex) {}
|
} catch (ex) {
|
||||||
|
console.error("Error processing date fields:", ex);
|
||||||
|
}
|
||||||
|
|
||||||
const fieldRequired = Object.values(fieldDate).filter(
|
const fieldRequired = Object.values(fieldDate).filter(
|
||||||
(field: any) => field?.required
|
(field: any) => field?.required || field?.type === "table"
|
||||||
);
|
);
|
||||||
let error = {} as any;
|
|
||||||
if (Array.isArray(fieldRequired) && fieldRequired?.length) {
|
if (fieldRequired.length) {
|
||||||
fieldRequired.map((e: any) => {
|
fieldRequired.forEach((e: any) => {
|
||||||
const type = e?.type;
|
|
||||||
let keys = e?.name;
|
let keys = e?.name;
|
||||||
if (["dropdown-async", "multi-async"].includes(type)) {
|
const type = e?.type;
|
||||||
keys = e?.target || e?.name;
|
|
||||||
}
|
if (type === "table" && e?.fields?.length) {
|
||||||
if (
|
e.fields.forEach((item: any, index: number) => {
|
||||||
[
|
let errorChilds: Record<string, string> = {};
|
||||||
"multi-dropdown",
|
const fieldRequired = Object.values(item?.fields).filter(
|
||||||
"checkbox",
|
(field: any) => field?.required
|
||||||
"multi-upload",
|
);
|
||||||
"multi-async",
|
console.log({ fieldRequired });
|
||||||
].includes(type)
|
fieldRequired.forEach((subField: any) => {
|
||||||
) {
|
let keySub = subField?.name;
|
||||||
if (
|
const typeSub = subField?.type;
|
||||||
!Array.isArray(get(local.data, keys)) ||
|
const val = get(local.data, `${keys}[${index}].${keySub}`);
|
||||||
!get(local.data, `${keys}.length`)
|
if (["dropdown-async", "multi-async"].includes(typeSub)) {
|
||||||
) {
|
keySub = subField?.target || subField?.name;
|
||||||
error[e?.name] = `This field requires at least one item.`;
|
}
|
||||||
}
|
if (
|
||||||
|
[
|
||||||
|
"multi-dropdown",
|
||||||
|
"checkbox",
|
||||||
|
"multi-upload",
|
||||||
|
"multi-async",
|
||||||
|
].includes(typeSub)
|
||||||
|
) {
|
||||||
|
if (!Array.isArray(get(local.data, keys)) || !val?.length) {
|
||||||
|
errorChilds[subField.name] =
|
||||||
|
"This field requires at least one item.";
|
||||||
|
isError = true;
|
||||||
|
}
|
||||||
|
} else if (!val) {
|
||||||
|
errorChilds[subField.name] = "Please fill out this field.";
|
||||||
|
isError = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log({
|
||||||
|
keySub,
|
||||||
|
data: get(local.data, `${keys}[${index}]`),
|
||||||
|
val,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
item.error = errorChilds;
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
if (!get(local.data, keys)) {
|
if (["dropdown-async", "multi-async"].includes(type)) {
|
||||||
error[e?.name] = `Please fill out this field.`;
|
keys = e?.target || e?.name;
|
||||||
|
}
|
||||||
|
const val = get(local.data, keys);
|
||||||
|
if (
|
||||||
|
[
|
||||||
|
"multi-dropdown",
|
||||||
|
"checkbox",
|
||||||
|
"multi-upload",
|
||||||
|
"multi-async",
|
||||||
|
].includes(type)
|
||||||
|
) {
|
||||||
|
if (!Array.isArray(val) || !val?.length) {
|
||||||
|
error[e.name] = "This field requires at least one item.";
|
||||||
|
isError = true;
|
||||||
|
}
|
||||||
|
} else if (!val) {
|
||||||
|
error[e.name] = "Please fill out this field.";
|
||||||
|
isError = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
local.error = error;
|
local.error = error;
|
||||||
local.render();
|
local.render();
|
||||||
console.log({ error });
|
console.log(isError);
|
||||||
if (Object.keys(error).length) {
|
// if (isError) {
|
||||||
throw new Error("please check your input field.");
|
// throw new Error("please check your input field.");
|
||||||
} else {
|
// } else {
|
||||||
await onSubmit(local);
|
// await onSubmit(local);
|
||||||
}
|
// }
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
toast.success(
|
toast.success(
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
|
|
@ -285,7 +285,7 @@ export const TypeAsyncDropdown: React.FC<any> = ({
|
||||||
placeholder={disabled ? "" : placeholderField}
|
placeholder={disabled ? "" : placeholderField}
|
||||||
isDisabled={disabled}
|
isDisabled={disabled}
|
||||||
className={cx(
|
className={cx(
|
||||||
"rounded-md border-none text-sm",
|
"rounded-md border-none text-sm w-full",
|
||||||
css`
|
css`
|
||||||
[role="listbox"] {
|
[role="listbox"] {
|
||||||
padding: 0px !important;
|
padding: 0px !important;
|
||||||
|
|
|
||||||
|
|
@ -230,6 +230,7 @@ export const TypeInput: React.FC<any> = ({
|
||||||
asSingle={true}
|
asSingle={true}
|
||||||
useRange={false}
|
useRange={false}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
|
console.log(value);
|
||||||
fm.data[name] = value?.startDate
|
fm.data[name] = value?.startDate
|
||||||
? new Date(value?.startDate)
|
? new Date(value?.startDate)
|
||||||
: null;
|
: null;
|
||||||
|
|
|
||||||
|
|
@ -154,6 +154,12 @@ export const TableEditBetter: React.FC<any> = ({
|
||||||
local.data = fm?.data[name] || [];
|
local.data = fm?.data[name] || [];
|
||||||
local.render();
|
local.render();
|
||||||
console.log(columns);
|
console.log(columns);
|
||||||
|
fm.fields[name] = {
|
||||||
|
name: name,
|
||||||
|
type: "table",
|
||||||
|
fields: [],
|
||||||
|
};
|
||||||
|
fm.render();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleResize = (index: any, width: any) => {
|
const handleResize = (index: any, width: any) => {
|
||||||
|
|
@ -168,9 +174,11 @@ export const TableEditBetter: React.FC<any> = ({
|
||||||
<div className="tbl-wrapper flex flex-grow flex-col">
|
<div className="tbl-wrapper flex flex-grow flex-col">
|
||||||
{!disabledHeader ? (
|
{!disabledHeader ? (
|
||||||
<div className="head-tbl-list block items-start justify-between bg-white px-0 py-4 sm:flex">
|
<div className="head-tbl-list block items-start justify-between bg-white px-0 py-4 sm:flex">
|
||||||
<div className="flex flex-row items-end">
|
<div className="flex flex-row h-full">
|
||||||
<div className="sm:flex flex flex-col space-y-2">
|
<div className="sm:flex flex flex-col space-y-2 flex-grow">
|
||||||
<div className="flex">{sideLeft ? sideLeft(local) : <></>}</div>
|
<div className="flex flex-grow flex-row">
|
||||||
|
{sideLeft ? sideLeft(local) : <></>}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-auto flex items-center flex-row">
|
<div className="ml-auto flex items-center flex-row">
|
||||||
|
|
@ -265,10 +273,21 @@ export const TableEditBetter: React.FC<any> = ({
|
||||||
)}
|
)}
|
||||||
<tbody>
|
<tbody>
|
||||||
{local.data.map((row: any, index: any) => {
|
{local.data.map((row: any, index: any) => {
|
||||||
|
if (
|
||||||
|
typeof fm.fields?.[name]?.fields?.[index]?.fields !==
|
||||||
|
"object"
|
||||||
|
) {
|
||||||
|
fm.fields[name].fields[index] = {
|
||||||
|
fields: {},
|
||||||
|
};
|
||||||
|
}
|
||||||
const fm_row = {
|
const fm_row = {
|
||||||
...fm,
|
...fm,
|
||||||
|
name: name,
|
||||||
|
type: "table",
|
||||||
data: row,
|
data: row,
|
||||||
|
error: fm.fields?.[name]?.fields?.[index]?.error,
|
||||||
|
fields: fm.fields?.[name]?.fields?.[index]?.fields,
|
||||||
render: () => {
|
render: () => {
|
||||||
local.render();
|
local.render();
|
||||||
fm.data[name] = local.data;
|
fm.data[name] = local.data;
|
||||||
|
|
@ -302,7 +321,9 @@ export const TableEditBetter: React.FC<any> = ({
|
||||||
return (
|
return (
|
||||||
<td
|
<td
|
||||||
key={`row_${name}_${index}_${col?.accessorKey}_${idx}`}
|
key={`row_${name}_${index}_${col?.accessorKey}_${idx}`}
|
||||||
className={"table-header-tbl capitalize"}
|
className={
|
||||||
|
"table-header-tbl align-top capitalize"
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<div className="p-1">{renderData}</div>
|
<div className="p-1">{renderData}</div>
|
||||||
</td>
|
</td>
|
||||||
|
|
|
||||||
|
|
@ -74,9 +74,7 @@ const Input: React.FC<Props> = (e: Props) => {
|
||||||
const handleInputChange = useCallback(
|
const handleInputChange = useCallback(
|
||||||
(e: React.ChangeEvent<HTMLInputElement>) => {
|
(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const inputValue = e.target.value;
|
const inputValue = e.target.value;
|
||||||
|
|
||||||
const dates = [];
|
const dates = [];
|
||||||
|
|
||||||
if (asSingle) {
|
if (asSingle) {
|
||||||
const date = parseFormattedDate(inputValue, displayFormat);
|
const date = parseFormattedDate(inputValue, displayFormat);
|
||||||
if (dateIsValid(date.toDate())) {
|
if (dateIsValid(date.toDate())) {
|
||||||
|
|
@ -121,6 +119,8 @@ const Input: React.FC<Props> = (e: Props) => {
|
||||||
if (dates[1])
|
if (dates[1])
|
||||||
changeDayHover(dayjs(dates[1]).add(-1, "day").format(DATE_FORMAT));
|
changeDayHover(dayjs(dates[1]).add(-1, "day").format(DATE_FORMAT));
|
||||||
else changeDayHover(dates[0]);
|
else changeDayHover(dates[0]);
|
||||||
|
} else {
|
||||||
|
changeDatepickerValue(null, e.target);
|
||||||
}
|
}
|
||||||
|
|
||||||
changeInputText(e.target.value);
|
changeInputText(e.target.value);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue