fix: enhance error handling and loading state management in Form and Table components

This commit is contained in:
faisolavolut 2025-03-06 13:58:51 +07:00
parent dfabe899d6
commit 32a24c9df1
7 changed files with 429 additions and 304 deletions

View File

@ -55,7 +55,10 @@ export const Form: React.FC<any> = ({
)}
/>
{toastMessage ? `${toastMessage}...` : "Saving..."}
</>
</>,
{
duration: Infinity,
}
);
local.btn_ready = false;
local.render();
@ -166,6 +169,8 @@ export const Form: React.FC<any> = ({
} else {
await onSubmit(local);
}
setTimeout(() => {
toast.dismiss();
setTimeout(() => {
toast.success(
<div
@ -184,8 +189,12 @@ export const Form: React.FC<any> = ({
</div>
);
}, 100);
}, 100);
} catch (ex: any) {
const msg = get(ex, "response.data.meta.message") || ex.message;
setTimeout(() => {
toast.dismiss();
setTimeout(() => {
toast.error(
<div className="flex flex-col w-full">
<div className="flex text-red-600 items-center">
@ -203,6 +212,8 @@ export const Form: React.FC<any> = ({
`,
}
);
}, 100);
}, 100);
}
local.btn_ready = true;
local.render();
@ -229,13 +240,18 @@ export const Form: React.FC<any> = ({
)}
/>
{"Loading..."}
</>
</>,
{
duration: Infinity,
}
);
local.data = null;
local.render();
try {
const res = await onLoad();
local.ready = true;
local.data = res;
} catch (ex) {}
local.ready = true;
local.render();
if (typeof afterLoad === "function") {
afterLoad(local);
@ -243,22 +259,6 @@ export const Form: React.FC<any> = ({
setTimeout(() => {
toast.dismiss();
}, 100);
// if (res instanceof Promise) {
// res.then((data) => {
// local.ready = true;
// local.data = data;
// local.render(); // Panggil render setelah data diperbarui
// // toast.dismiss();
// // toast.success("Data Loaded Successfully!");
// });
// } else {
// local.ready = true;
// local.data = res;
// local.render(); // Panggil render untuk memicu re-render
// toast.dismiss();
// toast.success("Data Loaded Successfully!");
// }
},
fields: {} as any,
render: () => {},
@ -295,19 +295,46 @@ export const Form: React.FC<any> = ({
)}
/>
{"Loading..."}
</>
</>,
{
duration: Infinity,
}
);
const res = await onLoad();
local.ready = true;
let res = null as any;
try {
res = await onLoad();
local.data = res;
setTimeout(() => {
toast.dismiss();
}, 100);
} catch (ex: any) {
const msg = get(ex, "response.data.meta.message") || ex.message;
setTimeout(() => {
toast.dismiss();
setTimeout(() => {
toast.error(
<div className="flex flex-col w-full">
<div className="flex text-red-600 items-center">
<AlertTriangle className="h-4 w-4 mr-1" />
{`Failed ${msg}.`}
</div>
</div>,
{
dismissible: true,
className: css`
background: #ffecec;
border: 2px solid red;
`,
}
);
}, 100);
}, 100);
}
local.ready = true;
local.render();
if (typeof afterLoad === "function") {
await afterLoad(local);
}
setTimeout(() => {
toast.dismiss();
}, 100);
};
run();
}, []);

View File

@ -1,7 +1,9 @@
"use client";
import { notFound } from "next/navigation";
import { ScrollArea } from "../ui/scroll-area";
import { Form } from "./Form";
import { useEffect, useState } from "react";
import get from "lodash.get";
export const FormBetter: React.FC<any> = ({
children,
@ -19,6 +21,10 @@ export const FormBetter: React.FC<any> = ({
const [fm, setFM] = useState<any>({
data: null as any,
});
const [show, setShow] = useState(true as boolean);
if (!show) {
notFound();
}
useEffect(() => {}, [fm.data]);
return (
<div className="flex flex-col flex-grow gap-y-3 ">
@ -37,7 +43,17 @@ export const FormBetter: React.FC<any> = ({
children,
header,
onTitle,
onLoad,
onLoad: async () => {
try {
const res = await onLoad();
return res;
} catch (ex: any) {
setShow(false);
throw new Error(
get(ex, "response.data.meta.message") || ex.message
);
}
},
onSubmit,
onFooter,
showResize,

View File

@ -4,6 +4,7 @@ import { useLocal } from "@/lib/utils/use-local";
import { toast } from "sonner";
import { Loader2 } from "lucide-react";
import { ScrollArea } from "../ui/scroll-area";
import get from "lodash.get";
export const ListBetter: React.FC<any> = ({
autoPagination = true,
@ -82,10 +83,14 @@ export const ListBetter: React.FC<any> = ({
)}
/>
{"Loading..."}
</>
</>,
{
duration: Infinity,
}
);
local.ready = false;
local.render();
try {
if (typeof onCount === "function") {
const res = await onCount();
local.count = res;
@ -112,6 +117,12 @@ export const ListBetter: React.FC<any> = ({
toast.dismiss();
}, 100);
}
} catch (ex: any) {
console.error(get(ex, "response.data.meta.message") || ex.message);
}
setTimeout(() => {
toast.dismiss();
}, 100);
local.ready = true;
local.render();
},
@ -135,9 +146,13 @@ export const ListBetter: React.FC<any> = ({
)}
/>
{"Loading..."}
</>
</>,
{
duration: Infinity,
}
);
const listData = local.data || [];
try {
if (Array.isArray(onLoad)) {
let res = onLoad;
local.data = listData.concat(res);
@ -157,6 +172,12 @@ export const ListBetter: React.FC<any> = ({
toast.dismiss();
}, 100);
}
} catch (ex: any) {
console.error(get(ex, "response.data.meta.message") || ex.message);
}
setTimeout(() => {
toast.dismiss();
}, 100);
},
});
useEffect(() => {
@ -180,10 +201,14 @@ export const ListBetter: React.FC<any> = ({
)}
/>
{"Loading..."}
</>
</>,
{
duration: Infinity,
}
);
local.ready = false;
local.render();
try {
if (typeof onCount === "function") {
const res = await onCount();
setMaxPage(Math.ceil(res / take));
@ -217,6 +242,9 @@ export const ListBetter: React.FC<any> = ({
setData(local.data);
}
}
} catch (ex: any) {
console.error(get(ex, "response.data.meta.message") || ex.message);
}
if (typeof onInit === "function") {
onInit(local);
}

View File

@ -10,6 +10,7 @@ import { getNumber } from "@/lib/utils/getNumber";
import { formatMoney } from "@/lib/components/form/field/TypeInput";
import "react-resizable/css/styles.css";
import { Resizable } from "react-resizable";
import get from "lodash.get";
export const TableEditBetter: React.FC<any> = ({
name,
column,
@ -101,8 +102,12 @@ export const TableEditBetter: React.FC<any> = ({
)}
/>
{"Loading..."}
</>
</>,
{
duration: Infinity,
}
);
try {
if (Array.isArray(onLoad)) {
local.data = onLoad;
local.render();
@ -127,11 +132,14 @@ export const TableEditBetter: React.FC<any> = ({
local.data = res;
local.render();
setData(res);
}
}
} catch (ex: any) {
console.error(get(ex, "response.data.meta.message") || ex.message);
}
setTimeout(() => {
toast.dismiss();
}, 100);
}
}
},
});
// const cloneListFM = (data: any[]) => {

View File

@ -193,7 +193,10 @@ export const TableList = <T extends object>({
)}
/>
{"Loading..."}
</>
</>,
{
duration: Infinity,
}
);
if (typeof onCount === "function") {
const params = await events("onload-param", {
@ -255,7 +258,10 @@ export const TableList = <T extends object>({
)}
/>
{"Loading..."}
</>
</>,
{
duration: Infinity,
}
);
if (Array.isArray(onLoad)) {
let res = onLoad;
@ -285,6 +291,9 @@ export const TableList = <T extends object>({
toast.dismiss();
}, 100);
}
setTimeout(() => {
toast.dismiss();
}, 100);
},
});
const cloneListFM = (data: any[]) => {
@ -351,8 +360,12 @@ export const TableList = <T extends object>({
)}
/>
{"Loading..."}
</>
</>,
{
duration: Infinity,
}
);
try {
try {
if (typeof onCount === "function") {
const params = await events("onload-param", {
@ -406,6 +419,7 @@ export const TableList = <T extends object>({
setData(local.data);
}
}
} catch (ex) {}
setTimeout(() => {
toast.dismiss();
}, 100);

View File

@ -111,12 +111,19 @@ export const TableListBetter: React.FC<any> = ({
)}
/>
{"Loading..."}
</>
</>,
{
duration: Infinity,
}
);
try {
if (Array.isArray(onLoad)) {
local.data = onLoad;
local.render();
setData(onLoad);
setTimeout(() => {
toast.dismiss();
}, 100);
} else {
const res: any = onLoad({
search: local.search,
@ -132,7 +139,7 @@ export const TableListBetter: React.FC<any> = ({
setData(e);
setTimeout(() => {
toast.dismiss();
}, 2000);
}, 100);
});
} else {
local.data = res;
@ -141,9 +148,15 @@ export const TableListBetter: React.FC<any> = ({
setData(res);
setTimeout(() => {
toast.dismiss();
}, 2000);
}, 100);
}
}
} catch (ex: any) {
console.error(get(ex, "response.data.meta.message") || ex.message);
}
setTimeout(() => {
toast.dismiss();
}, 100);
},
});
const cloneListFM = (data: any[]) => {
@ -173,8 +186,12 @@ export const TableListBetter: React.FC<any> = ({
)}
/>
{"Loading..."}
</>
</>,
{
duration: Infinity,
}
);
try {
if (typeof onCount === "function") {
const res = await onCount();
local.count = res;
@ -187,6 +204,9 @@ export const TableListBetter: React.FC<any> = ({
cloneListFM(onLoad);
local.render();
setData(onLoad);
setTimeout(() => {
toast.dismiss();
}, 100);
} else {
const res: any = await onLoad({
search: local.search,
@ -200,8 +220,14 @@ export const TableListBetter: React.FC<any> = ({
setData(res);
setTimeout(() => {
toast.dismiss();
}, 2000);
}, 100);
}
} catch (ex: any) {
console.error(get(ex, "response.data.meta.message") || ex.message);
}
setTimeout(() => {
toast.dismiss();
}, 100);
};
if (typeof onInit === "function") {
onInit(local);

View File

@ -46,11 +46,15 @@ export const actionToast = async (data: {
)}
/>
{msg_load ? msg_load : " Load..."}
</>
</>,
{
duration: Infinity,
}
);
if (typeof task === "function") await task();
setTimeout(() => {
toast.dismiss();
setTimeout(() => {
toast.success(
<div
className={cx(
@ -66,7 +70,7 @@ export const actionToast = async (data: {
</div>
</div>
);
}, 100);
if (typeof after === "function") after();
if (typeof success === "function") success();
}, 100);
@ -74,6 +78,7 @@ export const actionToast = async (data: {
setTimeout(() => {
if (typeof failed === "function") failed();
toast.dismiss();
setTimeout(() => {
toast.error(
<div className="flex flex-col w-full">
<div className="flex text-red-600 items-center">
@ -95,5 +100,6 @@ export const actionToast = async (data: {
}
);
}, 100);
}, 100);
}
};