260320:1131 Refactor Overrall #01
Build and Deploy / deploy (push) Has been cancelled

This commit is contained in:
admin
2026-03-20 11:31:27 +07:00
parent f1b81a7d0d
commit 1d3479770b
147 changed files with 1745 additions and 1567 deletions
@@ -57,15 +57,19 @@ interface Field {
options?: { label: string; value: string | number }[];
}
interface ApiError extends Error {
response?: { data?: { message?: string } };
}
interface GenericCrudTableProps<T> {
title: string;
description?: string;
entityName: string;
queryKey: any[];
queryKey: string[];
fetchFn: () => Promise<T[] | { data: T[] }>;
createFn: (data: any) => Promise<any>;
updateFn: (id: number, data: any) => Promise<any>;
deleteFn: (id: number) => Promise<any>;
createFn: (data: Record<string, unknown>) => Promise<unknown>;
updateFn: (id: number, data: Record<string, unknown>) => Promise<unknown>;
deleteFn: (id: number) => Promise<unknown>;
columns: ColumnDef<T>[];
fields: Field[];
filters?: React.ReactNode;
@@ -95,7 +99,7 @@ export function GenericCrudTable<T extends { id?: number; uuid?: string }>({
});
// ADR-019: Support both direct array or wrapped data object
const data: T[] = Array.isArray(rawData) ? rawData : (rawData as any)?.data || [];
const data: T[] = Array.isArray(rawData) ? rawData : (rawData as { data?: T[] } | undefined)?.data || [];
const createMutation = useMutation({
mutationFn: createFn,
@@ -105,13 +109,13 @@ export function GenericCrudTable<T extends { id?: number; uuid?: string }>({
setIsDialogOpen(false);
reset();
},
onError: (error: any) => {
onError: (error: ApiError) => {
toast.error(error.response?.data?.message || `Failed to create ${entityName}`);
},
});
const updateMutation = useMutation({
mutationFn: ({ id, data }: { id: number; data: any }) => updateFn(id, data),
mutationFn: ({ id, data }: { id: number; data: Record<string, unknown> }) => updateFn(id, data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey });
toast.success(`${entityName} updated successfully`);
@@ -119,7 +123,7 @@ export function GenericCrudTable<T extends { id?: number; uuid?: string }>({
setEditingId(null);
reset();
},
onError: (error: any) => {
onError: (error: ApiError) => {
toast.error(error.response?.data?.message || `Failed to update ${entityName}`);
},
});
@@ -131,7 +135,7 @@ export function GenericCrudTable<T extends { id?: number; uuid?: string }>({
toast.success(`${entityName} deleted successfully`);
setItemToDelete(null);
},
onError: (error: any) => {
onError: (error: ApiError) => {
toast.error(error.response?.data?.message || `Failed to delete ${entityName}`);
},
});
@@ -184,19 +188,20 @@ export function GenericCrudTable<T extends { id?: number; uuid?: string }>({
setIsDialogOpen(true);
};
const handleEdit = (item: any) => {
setEditingId(item.id);
reset(item);
const handleEdit = (item: T) => {
setEditingId(item.id as number);
reset(item as Record<string, unknown>);
// Ensure select values are strings for Shadcn Select
fields.forEach(f => {
if (f.type === 'select' && item[f.name]) {
setValue(f.name, String(item[f.name]));
const record = item as Record<string, unknown>;
if (f.type === 'select' && record[f.name]) {
setValue(f.name, String(record[f.name]));
}
});
setIsDialogOpen(true);
};
const onSubmit = (formData: any) => {
const onSubmit = (formData: Record<string, unknown>) => {
if (editingItem) {
updateMutation.mutate({ id: editingItem, data: formData });
} else {