@skalfa/skalfa-component 1.0.8 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/accordion/Accordion.component.js +2 -3
- package/dist/breadcrumb/Breadcrumb.component.js +2 -3
- package/dist/button/Button.component.d.ts +2 -1
- package/dist/button/Button.component.js +2 -2
- package/dist/carousel/Carousel.component.js +2 -3
- package/dist/chip/Chip.component.js +2 -3
- package/dist/contexts-mock.d.ts +2 -0
- package/dist/contexts-mock.js +10 -0
- package/dist/input/Checkbox.component.js +2 -3
- package/dist/input/Input.component.d.ts +3 -2
- package/dist/input/Input.component.js +3 -3
- package/dist/input/InputCheckbox.component.js +1 -1
- package/dist/input/InputCurrency.component.d.ts +3 -2
- package/dist/input/InputCurrency.component.js +3 -3
- package/dist/input/InputDate.component.js +4 -5
- package/dist/input/InputDatetime.component.d.ts +3 -2
- package/dist/input/InputDatetime.component.js +3 -3
- package/dist/input/InputDocument.component.js +7 -8
- package/dist/input/InputImage.component.js +3 -4
- package/dist/input/InputNumber.component.js +3 -4
- package/dist/input/InputPassword.component.js +3 -3
- package/dist/input/InputRadio.component.js +1 -1
- package/dist/input/InputTime.component.js +3 -3
- package/dist/input/InputValues.component.js +3 -4
- package/dist/input/Select.component.js +6 -7
- package/dist/modal/FloatingPage.component.d.ts +3 -1
- package/dist/modal/FloatingPage.component.js +7 -3
- package/dist/modal/Modal.component.js +1 -2
- package/dist/modal/ModalConfirm.component.d.ts +2 -2
- package/dist/modal/ModalConfirm.component.js +14 -12
- package/dist/modal/Toast.component.js +1 -2
- package/dist/nav/Bottombar.component.d.ts +2 -2
- package/dist/nav/Bottombar.component.js +7 -8
- package/dist/nav/Footer.component.d.ts +2 -2
- package/dist/nav/Footer.component.js +6 -7
- package/dist/nav/Headbar.component.js +2 -3
- package/dist/nav/Navbar.component.d.ts +2 -2
- package/dist/nav/Navbar.component.js +3 -4
- package/dist/nav/Sidebar.component.d.ts +3 -7
- package/dist/nav/Sidebar.component.js +14 -17
- package/dist/supervision/FormSupervision.component.d.ts +4 -29
- package/dist/supervision/FormSupervision.component.js +84 -136
- package/dist/supervision/TableSupervision.component.d.ts +17 -26
- package/dist/supervision/TableSupervision.component.js +207 -193
- package/dist/table/ControlBar.component.js +15 -16
- package/dist/table/FilterComponent.js +4 -6
- package/dist/table/Pagination.component.js +2 -3
- package/dist/table/Table.component.js +3 -4
- package/dist/wrap/Swipe.component.js +2 -2
- package/package.json +18 -10
- package/src/accordion/Accordion.component.tsx +3 -3
- package/src/breadcrumb/Breadcrumb.component.tsx +4 -4
- package/src/button/Button.component.tsx +3 -3
- package/src/carousel/Carousel.component.tsx +4 -4
- package/src/chip/Chip.component.tsx +3 -4
- package/src/contexts-mock.ts +6 -0
- package/src/input/Checkbox.component.tsx +3 -3
- package/src/input/Input.component.tsx +6 -6
- package/src/input/InputCheckbox.component.tsx +1 -1
- package/src/input/InputCurrency.component.tsx +6 -6
- package/src/input/InputDate.component.tsx +6 -7
- package/src/input/InputDatetime.component.tsx +6 -6
- package/src/input/InputDocument.component.tsx +9 -9
- package/src/input/InputImage.component.tsx +4 -5
- package/src/input/InputNumber.component.tsx +7 -8
- package/src/input/InputPassword.component.tsx +4 -4
- package/src/input/InputRadio.component.tsx +1 -1
- package/src/input/InputTime.component.tsx +4 -4
- package/src/input/InputValues.component.tsx +5 -6
- package/src/input/Select.component.tsx +10 -10
- package/src/modal/FloatingPage.component.tsx +33 -3
- package/src/modal/Modal.component.tsx +1 -2
- package/src/modal/ModalConfirm.component.tsx +34 -49
- package/src/modal/Toast.component.tsx +1 -2
- package/src/nav/Bottombar.component.tsx +9 -10
- package/src/nav/Footer.component.tsx +8 -9
- package/src/nav/Headbar.component.tsx +3 -3
- package/src/nav/Navbar.component.tsx +9 -10
- package/src/nav/Sidebar.component.tsx +55 -46
- package/src/supervision/FormSupervision.component.tsx +203 -224
- package/src/supervision/TableSupervision.component.tsx +420 -455
- package/src/table/ControlBar.component.tsx +16 -16
- package/src/table/FilterComponent.tsx +9 -11
- package/src/table/Pagination.component.tsx +6 -6
- package/src/table/Table.component.tsx +5 -5
- package/src/wrap/Swipe.component.tsx +3 -3
- package/src/types.d.ts +0 -7
|
@@ -1,24 +1,15 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
|
-
import { ReactNode,
|
|
4
|
-
import {
|
|
5
|
-
import { faEdit, faFileExcel, faFilePdf, faPlus, faTrash } from "@fortawesome/free-solid-svg-icons";
|
|
6
|
-
import { ApiType, cn, conversion, FetchControlType, registry, shortcut, ShortcutHandler, UseResourceIdb, UseResourceProps, useResponsive, useTable } from "@utils";
|
|
3
|
+
import { ReactNode, useEffect, useMemo } from "react";
|
|
4
|
+
import { ApiType, cn, conversion, registry, shortcut, ShortcutHandler, UseResourceIdb, UseResourceProps, useResponsive, useTable } from "@utils";
|
|
7
5
|
import { useToggleContext } from "@contexts";
|
|
8
|
-
import { FloatingPageComponent, FloatingPageProps } from "../
|
|
9
|
-
import {
|
|
10
|
-
import { TableColumnType, TableComponent, TableProps } from "../table/Table.component";
|
|
11
|
-
import { FormSupervisionComponent, FormType } from "./FormSupervision.component";
|
|
12
|
-
import { ModalConfirmComponent, ModalConfirmProps } from "../modal/ModalConfirm.component";
|
|
13
|
-
import { TypographyColumnComponent } from "../typography/TypographyColumn.component";
|
|
14
|
-
import { ControlBarOptionType } from "../table/ControlBar.component";
|
|
15
|
-
import { BottomSheetComponent } from "../modal/BottomSheet.component";
|
|
6
|
+
import { FloatingPageComponent, FloatingPageProps, ButtonComponent, TableColumnType, TableComponent, FormSupervisionComponent, FormType, ModalConfirmComponent, TypographyColumnComponent, ButtonProps, ModalConfirmProps, TableProps, ControlBarOptionType, SwipeActionType, BottomSheetProps } from "../";
|
|
7
|
+
import { useLang } from "@skalfa/skalfa-lang";
|
|
16
8
|
|
|
17
9
|
const ExportExcel = registry.get("ExportExcel");
|
|
18
10
|
const ImportExcel = registry.get("ImportExcel");
|
|
19
11
|
|
|
20
12
|
|
|
21
|
-
|
|
22
13
|
export interface TableSupervisionColumnProps {
|
|
23
14
|
selector : string;
|
|
24
15
|
label ?: string;
|
|
@@ -34,58 +25,46 @@ export interface TableSupervisionColumnProps {
|
|
|
34
25
|
accessCode ?: string;
|
|
35
26
|
item ?: (data: any) => string | ReactNode;
|
|
36
27
|
tip ?: string | ((data: any) => string);
|
|
37
|
-
|
|
38
|
-
importable ?: boolean;
|
|
39
|
-
}
|
|
28
|
+
};
|
|
40
29
|
|
|
41
30
|
export interface TableSupervisionFormProps {
|
|
42
31
|
fields : string[] | (FormType & { visibility?: "*" | "create" | "update" })[];
|
|
43
32
|
defaultValue ?: (item: Record<string, any> | null) => Promise<Record<string, any>> | Record<string, any>;
|
|
44
33
|
payload ?: (values: any) => Promise<Record<string, any>> | object;
|
|
45
|
-
modalControl ?: Omit<FloatingPageProps, "show" | "onClose" | "children">;
|
|
34
|
+
modalControl ?: Omit<FloatingPageProps, "show" | "onClose" | "children"> | Omit<BottomSheetProps, "show" | "onClose" | "children">;
|
|
46
35
|
contentType ?: "application/json" | "multipart/form-data";
|
|
47
|
-
}
|
|
48
|
-
|
|
36
|
+
};
|
|
49
37
|
|
|
50
38
|
export type TableSupervisionDetailProps = boolean
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
| {
|
|
58
|
-
modal?: Omit<FloatingPageProps, "show" | "onClose" | "children">;
|
|
59
|
-
content?: boolean
|
|
60
|
-
| (
|
|
61
|
-
| string
|
|
62
|
-
| { label: string, item: string | ((data: Record<string, any>) => ReactNode), conversion?: keyof typeof conversion }
|
|
63
|
-
| ((data: Record<string, any>) => ReactNode)
|
|
64
|
-
)[]
|
|
65
|
-
| ((data: Record<string, any>) => ReactNode);
|
|
66
|
-
action?: (data: Record<string, any>) => void;
|
|
67
|
-
};
|
|
39
|
+
| (
|
|
40
|
+
| string
|
|
41
|
+
| { label: string, item: string | ((data: Record<string, any>) => ReactNode), conversion?: keyof typeof conversion }
|
|
42
|
+
| ((data: Record<string, any>) => ReactNode)
|
|
43
|
+
)[]
|
|
44
|
+
| ((data: Record<string, any>) => ReactNode);
|
|
68
45
|
|
|
69
46
|
export type TableSupervisionProps = {
|
|
70
47
|
fetchControl : UseResourceProps;
|
|
71
48
|
title ?: string;
|
|
72
49
|
id ?: string;
|
|
73
50
|
accessCode ?: number;
|
|
74
|
-
urlParam ?: boolean | { compressed ?: boolean }
|
|
51
|
+
urlParam ?: boolean | { compressed ?: boolean }
|
|
52
|
+
onRowClick ?: (data: Record<string, any>) => void;
|
|
75
53
|
columnControl ?: string[] | TableSupervisionColumnProps[];
|
|
76
54
|
formControl ?: TableSupervisionFormProps;
|
|
77
55
|
detailControl ?: TableSupervisionDetailProps;
|
|
78
56
|
actionControl ?: boolean | (
|
|
79
57
|
| 'EDIT' | 'DELETE' | {
|
|
80
58
|
label : string,
|
|
81
|
-
modal ?:
|
|
59
|
+
modal ?: ModalConfirmProps,
|
|
82
60
|
button ?: ButtonProps,
|
|
83
61
|
shortcut ?: { key: string, description: string },
|
|
84
62
|
} | ((
|
|
85
|
-
row :
|
|
86
|
-
setModal
|
|
63
|
+
row : object,
|
|
64
|
+
setModal ?: (type: "EDIT" | "DELETE") => void,
|
|
87
65
|
setDataSelected ?: () => void,
|
|
88
|
-
setShortcut ?: (key: string, handler: ShortcutHandler, description?: string) => void
|
|
66
|
+
setShortcut ?: (key: string, handler: ShortcutHandler, description?: string) => void,
|
|
67
|
+
size ?: string,
|
|
89
68
|
) => ReactNode)
|
|
90
69
|
)[];
|
|
91
70
|
block ?: boolean,
|
|
@@ -93,9 +72,12 @@ export type TableSupervisionProps = {
|
|
|
93
72
|
actionBulkingControl ?: TableProps["actionBulking"],
|
|
94
73
|
controlBar ?: (ControlBarOptionType | "CREATE" | "IMPORT" | "EXPORT" | "PRINT")[];
|
|
95
74
|
responsiveControl ?: {
|
|
96
|
-
mobile
|
|
97
|
-
|
|
98
|
-
|
|
75
|
+
mobile ?: boolean | {
|
|
76
|
+
item ?: (item: Record<string, any>, key: number) => ReactNode,
|
|
77
|
+
leftActionControl ?: Omit<SwipeActionType, "onAction"> & { onAction?: (item: Record<string, any>, key?: number) => void },
|
|
78
|
+
rightActionControl ?: Omit<SwipeActionType, "onAction"> & { onAction?: (item: Record<string, any>, key?: number) => void },
|
|
79
|
+
}
|
|
80
|
+
}
|
|
99
81
|
};
|
|
100
82
|
|
|
101
83
|
|
|
@@ -106,6 +88,7 @@ export function TableSupervisionComponent({
|
|
|
106
88
|
fetchControl,
|
|
107
89
|
columnControl,
|
|
108
90
|
formControl,
|
|
91
|
+
onRowClick,
|
|
109
92
|
detailControl,
|
|
110
93
|
actionControl,
|
|
111
94
|
actionBulkingControl,
|
|
@@ -114,87 +97,66 @@ export function TableSupervisionComponent({
|
|
|
114
97
|
noIndex,
|
|
115
98
|
responsiveControl,
|
|
116
99
|
urlParam,
|
|
117
|
-
importControl,
|
|
118
100
|
}: TableSupervisionProps) {
|
|
119
|
-
const
|
|
101
|
+
const l = useLang();
|
|
102
|
+
|
|
103
|
+
const { tableKey, tableControl, data, selected, setSelected, checks, setChecks, reset, focus, setFocus } = useTable(fetchControl, id, title, (urlParam || true))
|
|
120
104
|
const { setToggle, toggle } = useToggleContext()
|
|
121
105
|
const { isSm } = useResponsive();
|
|
122
106
|
|
|
123
|
-
const isDetailControlObject = detailControl && typeof detailControl === "object" && !Array.isArray(detailControl);
|
|
124
|
-
const detailAction = isDetailControlObject
|
|
125
|
-
? (detailControl as any)?.action
|
|
126
|
-
: (typeof detailControl === "function" ? detailControl : undefined);
|
|
127
|
-
const detailContent = isDetailControlObject
|
|
128
|
-
? (detailControl as any)?.content
|
|
129
|
-
: (typeof detailControl === "function" ? undefined : detailControl);
|
|
130
|
-
const detailModalProps = isDetailControlObject
|
|
131
|
-
? (detailControl as any)?.modal
|
|
132
|
-
: undefined;
|
|
133
|
-
|
|
134
107
|
const toggleKey = useMemo(() => conversion.strSnake(tableKey).toUpperCase(), [tableKey])
|
|
135
108
|
|
|
136
|
-
|
|
137
|
-
// ## Shortcut register
|
|
138
|
-
// ============================
|
|
109
|
+
|
|
139
110
|
useEffect(() => {
|
|
140
|
-
if(!
|
|
141
|
-
|
|
142
|
-
|
|
111
|
+
if(data?.data?.length && !toggle[`MODAL_DELETE_${toggleKey}`] && !toggle[`MODAL_DELETE_${toggleKey}`] && !toggle[`MODAL_SHOW_${toggleKey}`]) {
|
|
112
|
+
shortcut.register("arrowdown", () => {
|
|
113
|
+
const max = data?.data?.length - 1;
|
|
114
|
+
setFocus(focus == null ? 0 : focus >= max ? max : (focus + 1))
|
|
115
|
+
}, "Pilih data kebawah")
|
|
116
|
+
|
|
117
|
+
shortcut.register("arrowup", () => {
|
|
118
|
+
setFocus(focus == null ? 0 : focus <= 0 ? 0 : (focus - 1))
|
|
119
|
+
}, "Pilih data keatas")
|
|
120
|
+
|
|
121
|
+
if(focus != null) {
|
|
122
|
+
shortcut.register("delete", () => {
|
|
123
|
+
setSelected(data?.data?.at(focus))
|
|
124
|
+
setToggle(`MODAL_DELETE_${toggleKey}`)
|
|
125
|
+
}, "Delete data yang dipilih")
|
|
126
|
+
|
|
127
|
+
shortcut.register(" ", () => {
|
|
128
|
+
setSelected(data?.data?.at(focus))
|
|
143
129
|
setToggle(`MODAL_FORM_${toggleKey}`)
|
|
144
|
-
|
|
145
|
-
}, "Tambah Data Baru")
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (controlBar?.includes("IMPORT")) {
|
|
149
|
-
shortcut.register("alt+i", () => {
|
|
150
|
-
setToggle(`MODAL_IMPORT_${toggleKey}`)
|
|
151
|
-
}, "Import Data Dari Excel")
|
|
152
|
-
}
|
|
130
|
+
}, "Edit data yang dipilih")
|
|
153
131
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
setToggle(`
|
|
157
|
-
}, "
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
if(!isSm) {
|
|
163
|
-
shortcut.unregister("alt+n")
|
|
164
|
-
shortcut.unregister("alt+i")
|
|
165
|
-
shortcut.unregister("alt+e")
|
|
132
|
+
shortcut.register("enter", () => {
|
|
133
|
+
setSelected(data?.data?.at(focus))
|
|
134
|
+
setToggle(`MODAL_SHOW_${toggleKey}`)
|
|
135
|
+
}, "Detail data yang dipilih")
|
|
136
|
+
|
|
137
|
+
shortcut.register("escape", () => {
|
|
138
|
+
setFocus(null)
|
|
139
|
+
}, "Kembali")
|
|
166
140
|
}
|
|
167
141
|
}
|
|
168
|
-
}, [controlBar, isSm])
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
useEffect(() => {
|
|
172
|
-
if(actionControl && Array.isArray(actionControl) && selected) {
|
|
173
|
-
actionControl.filter((ac) => typeof ac == "object")?.forEach((ac) => {
|
|
174
|
-
if(typeof ac == "object" && ac?.shortcut) {
|
|
175
|
-
shortcut.register(ac.shortcut.key, () => {
|
|
176
|
-
setToggle(`MODAL_${conversion.strSnake(ac.label).toUpperCase()}_${toggleKey}`)
|
|
177
|
-
}, ac.shortcut.description)
|
|
178
|
-
}
|
|
179
|
-
})
|
|
180
|
-
}
|
|
181
142
|
|
|
182
143
|
return () => {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
144
|
+
shortcut.unregister("arrowdown")
|
|
145
|
+
shortcut.unregister("arrowup")
|
|
146
|
+
shortcut.unregister("delete")
|
|
147
|
+
shortcut.unregister(" ")
|
|
148
|
+
shortcut.unregister("enter")
|
|
149
|
+
shortcut.unregister("escape")
|
|
190
150
|
}
|
|
191
|
-
}, [actionControl,
|
|
192
|
-
|
|
193
|
-
|
|
151
|
+
}, [data?.data, actionControl, focus, toggle[`MODAL_DELETE_${toggleKey}`], toggle[`MODAL_DELETE_${toggleKey}`], toggle[`MODAL_SHOW_${toggleKey}`]])
|
|
152
|
+
|
|
194
153
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
154
|
+
// ============================
|
|
155
|
+
// ## Column preparation
|
|
156
|
+
// ============================
|
|
157
|
+
const columns = useMemo(() => {
|
|
158
|
+
return columnControl?.length ? columnControl.map((col) => {
|
|
159
|
+
if (typeof col === "string") {
|
|
198
160
|
return {
|
|
199
161
|
selector : col,
|
|
200
162
|
label : col,
|
|
@@ -221,14 +183,14 @@ export function TableSupervisionComponent({
|
|
|
221
183
|
) => {
|
|
222
184
|
return (
|
|
223
185
|
<>
|
|
224
|
-
<div className={cn("
|
|
186
|
+
<div className={cn("flex items-center gap-2", options?.className)}>
|
|
225
187
|
{(Array.isArray(actions) ? actions : (actions || actions == undefined) ? ['EDIT', "DELETE"] : [])?.map((action, key) => {
|
|
226
188
|
if(action == "EDIT") {
|
|
227
189
|
return (
|
|
228
190
|
<ButtonComponent
|
|
229
191
|
key={key}
|
|
230
|
-
icon={
|
|
231
|
-
label={"
|
|
192
|
+
icon={"solid/edit"}
|
|
193
|
+
label={l.base.edit ? l.base.edit() : "Edit"}
|
|
232
194
|
variant="outline"
|
|
233
195
|
paint="warning"
|
|
234
196
|
size={options?.size || "xs"}
|
|
@@ -245,8 +207,8 @@ export function TableSupervisionComponent({
|
|
|
245
207
|
return (
|
|
246
208
|
<ButtonComponent
|
|
247
209
|
key={key}
|
|
248
|
-
icon={
|
|
249
|
-
label={"
|
|
210
|
+
icon={"solid/trash"}
|
|
211
|
+
label={l.base.delete ? l.base.delete() : "Delete"}
|
|
250
212
|
variant="outline"
|
|
251
213
|
paint="danger"
|
|
252
214
|
size={options?.size || "xs"}
|
|
@@ -259,38 +221,45 @@ export function TableSupervisionComponent({
|
|
|
259
221
|
)
|
|
260
222
|
}
|
|
261
223
|
|
|
262
|
-
if
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
onClick
|
|
272
|
-
|
|
224
|
+
if(typeof action == "object") {
|
|
225
|
+
<ButtonComponent
|
|
226
|
+
key={`action-object-${key}`}
|
|
227
|
+
label={action?.button?.label || action?.label}
|
|
228
|
+
variant={action?.button?.variant || "outline"}
|
|
229
|
+
paint={action?.button?.paint || "primary"}
|
|
230
|
+
size={action?.button?.size || options?.size || "xs"}
|
|
231
|
+
rounded={action?.button?.rounded || true}
|
|
232
|
+
onClick={() => {
|
|
233
|
+
if (action?.button?.onClick) {
|
|
234
|
+
action?.button?.onClick(item)
|
|
235
|
+
} else {
|
|
236
|
+
setToggle(`MODAL_${conversion.strSnake(action?.label).toUpperCase()}_${toggleKey}`);
|
|
273
237
|
item && setSelected?.(item);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
238
|
+
}
|
|
239
|
+
}}
|
|
240
|
+
{...action.button}
|
|
241
|
+
/>
|
|
278
242
|
}
|
|
279
243
|
|
|
280
|
-
if
|
|
244
|
+
if(typeof action == "function") {
|
|
281
245
|
return (
|
|
282
|
-
<
|
|
283
|
-
{action(
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
(
|
|
290
|
-
|
|
291
|
-
|
|
246
|
+
<span key={`action-fn-${key}`}>
|
|
247
|
+
{action(item || {}, (type: "EDIT" | "DELETE") => {
|
|
248
|
+
if(type == "EDIT") {
|
|
249
|
+
setToggle(`MODAL_FORM_${toggleKey}`);
|
|
250
|
+
item && setSelected?.(item);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (type == "DELETE") {
|
|
254
|
+
setToggle(`MODAL_DELETE_${toggleKey}`);
|
|
255
|
+
item && setSelected?.(item);
|
|
256
|
+
}
|
|
257
|
+
}, () => item && setSelected?.(item), () => {}, options?.size)}
|
|
258
|
+
</span>
|
|
292
259
|
)
|
|
293
260
|
}
|
|
261
|
+
|
|
262
|
+
return <span key={`action-default-${key}`}></span>;
|
|
294
263
|
})}
|
|
295
264
|
</div>
|
|
296
265
|
</>
|
|
@@ -298,37 +267,46 @@ export function TableSupervisionComponent({
|
|
|
298
267
|
}
|
|
299
268
|
|
|
300
269
|
|
|
270
|
+
// ============================
|
|
271
|
+
// ## Data table preparation
|
|
272
|
+
// ============================
|
|
273
|
+
const dataTables = useMemo(() => {
|
|
274
|
+
return data?.data?.map((row: object) => {
|
|
275
|
+
return {
|
|
276
|
+
...row,
|
|
277
|
+
action: renderTableAction(actionControl, row),
|
|
278
|
+
};
|
|
279
|
+
});
|
|
280
|
+
}, [actionControl, data]);
|
|
301
281
|
|
|
302
282
|
|
|
303
283
|
// ============================
|
|
304
284
|
// ## Render detail page
|
|
305
285
|
// ============================
|
|
306
286
|
const detailPage = useMemo(() => {
|
|
307
|
-
if (
|
|
287
|
+
if (!toggle[`MODAL_SHOW_${toggleKey}`]) return null;
|
|
308
288
|
return (
|
|
309
|
-
<div className="
|
|
310
|
-
<div className=
|
|
311
|
-
|
|
289
|
+
<div className="p-4">
|
|
290
|
+
<div className={cn(
|
|
291
|
+
"flex flex-col gap-y-4",
|
|
292
|
+
)}>
|
|
293
|
+
{!!selected && (typeof detailControl === "object" && detailControl?.length ? detailControl?.map((column, key) => {
|
|
312
294
|
if (typeof column === "string") {
|
|
313
295
|
return (<TypographyColumnComponent
|
|
314
296
|
key={key}
|
|
315
297
|
title={columns?.find((c) => c.selector == column)?.label}
|
|
316
298
|
content={selected[column]}
|
|
317
299
|
/>)
|
|
318
|
-
} else if (typeof column === "object"
|
|
319
|
-
const colObj = column as { label: string, item: string | ((data: Record<string, any>) => ReactNode), conversion?: keyof typeof conversion };
|
|
320
|
-
const rawContent = typeof colObj.item === "string" ? selected[colObj.item] : colObj.item(selected);
|
|
321
|
-
const conversionKey = colObj.conversion;
|
|
322
|
-
const content = conversionKey && conversion[conversionKey] ? (conversion[conversionKey] as any)(rawContent) : rawContent;
|
|
300
|
+
} else if (typeof column === "object") {
|
|
323
301
|
return (<TypographyColumnComponent
|
|
324
302
|
key={key}
|
|
325
|
-
title={
|
|
326
|
-
content={
|
|
303
|
+
title={column?.label}
|
|
304
|
+
content={typeof column?.item === "string" ? selected[column?.item] : column?.item(selected)}
|
|
327
305
|
/>)
|
|
328
306
|
} else {
|
|
329
307
|
return column?.(selected)
|
|
330
308
|
}
|
|
331
|
-
}) : typeof
|
|
309
|
+
}) : typeof detailControl == "function" ? detailControl(selected) : columns?.map((column, key) => (
|
|
332
310
|
<TypographyColumnComponent
|
|
333
311
|
key={key}
|
|
334
312
|
title={column.label}
|
|
@@ -338,7 +316,7 @@ export function TableSupervisionComponent({
|
|
|
338
316
|
</div>
|
|
339
317
|
</div>
|
|
340
318
|
)
|
|
341
|
-
}, [selected,
|
|
319
|
+
}, [selected, detailControl]);
|
|
342
320
|
|
|
343
321
|
|
|
344
322
|
|
|
@@ -349,43 +327,64 @@ export function TableSupervisionComponent({
|
|
|
349
327
|
const fields = useMemo(() => {
|
|
350
328
|
return formControl?.fields?.length ? formControl?.fields.map((form) => {
|
|
351
329
|
return typeof form === "string" ? {
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
330
|
+
col : 12,
|
|
331
|
+
type : "text",
|
|
332
|
+
construction : {
|
|
333
|
+
name : form,
|
|
334
|
+
label : form,
|
|
335
|
+
},
|
|
336
|
+
} : { ...form };
|
|
337
|
+
}) : data?.forms || data?.columns || columnControl?.map((col) => {
|
|
338
|
+
return {
|
|
339
|
+
col : 12,
|
|
340
|
+
type : "text",
|
|
341
|
+
construction : {
|
|
342
|
+
name : typeof col == "string" ? col : col?.selector,
|
|
343
|
+
label : typeof col == "string" ? col : col?.label,
|
|
344
|
+
placeholder : `Masukkan ${ typeof col == "string" ? col : col?.label}...`,
|
|
345
|
+
},
|
|
346
|
+
};
|
|
347
|
+
}) || (data?.data?.at(0) ? Object.keys(data.data[0]).map((col) => {
|
|
348
|
+
return {
|
|
349
|
+
col : 12,
|
|
350
|
+
type : "text",
|
|
351
|
+
construction : {
|
|
352
|
+
name : col,
|
|
353
|
+
label : col,
|
|
354
|
+
placeholder : `Masukkan ${col}...`,
|
|
355
|
+
},
|
|
356
|
+
};
|
|
357
|
+
})
|
|
358
|
+
: []);
|
|
359
|
+
}, [formControl, data]);
|
|
362
360
|
|
|
363
361
|
|
|
364
362
|
|
|
365
|
-
|
|
363
|
+
// ============================
|
|
364
|
+
// ## Render form page
|
|
365
|
+
// ============================
|
|
366
|
+
const formPage = useMemo(async () => {
|
|
366
367
|
return (
|
|
367
|
-
<FormSupervisionComponent
|
|
368
|
-
|
|
369
|
-
|
|
368
|
+
<FormSupervisionComponent
|
|
369
|
+
submitControl={(fetchControl as ApiType).path ? {
|
|
370
|
+
path: `${(fetchControl as ApiType).path}/${(selected as { id: number })?.id || "" }`,
|
|
371
|
+
method: !(selected as { id: number })?.id ? "POST" : "PUT",
|
|
372
|
+
} : (fetchControl as ApiType).url ? {
|
|
373
|
+
url: `${(fetchControl as ApiType).url}/${(selected as { id: number })?.id || ""}`,
|
|
374
|
+
method: !(selected as { id: number })?.id ? "POST" : "PUT",
|
|
375
|
+
} : { idb: (fetchControl as ({ idb: UseResourceIdb }))?.idb }
|
|
376
|
+
}
|
|
377
|
+
fields={fields?.filter((f: any) => f.visibility ? !(selected as { id: number })?.id ? ["*", "create"]?.includes(f.visibility) : ["*", "update"]?.includes(f.visibility) : true) as FormType[]}
|
|
378
|
+
defaultValue={formControl?.defaultValue ? await formControl?.defaultValue(selected || null) : selected}
|
|
370
379
|
payload={formControl?.payload}
|
|
371
|
-
submitControl={fetchControl}
|
|
372
380
|
onSuccess={() => {
|
|
373
|
-
|
|
374
|
-
|
|
381
|
+
reset();
|
|
382
|
+
setTimeout(() => { setToggle(`MODAL_FORM_${toggleKey}`, false) }, 900);
|
|
375
383
|
}}
|
|
376
384
|
/>
|
|
377
385
|
)
|
|
378
|
-
}, [selected,
|
|
379
|
-
|
|
386
|
+
}, [selected, fetchControl, formControl]);
|
|
380
387
|
|
|
381
|
-
const dataTables = useMemo(() => {
|
|
382
|
-
return data?.data?.map((item: Record<string, any>) => {
|
|
383
|
-
return {
|
|
384
|
-
...item,
|
|
385
|
-
action: renderTableAction(actionControl, item)
|
|
386
|
-
};
|
|
387
|
-
}) || [];
|
|
388
|
-
}, [actionControl, data]);
|
|
389
388
|
|
|
390
389
|
|
|
391
390
|
useEffect(() => {
|
|
@@ -395,131 +394,131 @@ export function TableSupervisionComponent({
|
|
|
395
394
|
|
|
396
395
|
return (
|
|
397
396
|
<>
|
|
398
|
-
<
|
|
399
|
-
{title && <h1 className="table-supervision-title">{title}</h1>}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
<TableComponent
|
|
403
|
-
id={tableKey}
|
|
404
|
-
controlBar={controlBar?.map((cb) => {
|
|
405
|
-
if (cb == "CREATE") {
|
|
406
|
-
if (isSm) return
|
|
407
|
-
return (
|
|
408
|
-
<div className="control-bar-create-wrapper" key="button-add">
|
|
409
|
-
<ButtonComponent
|
|
410
|
-
icon={faPlus}
|
|
411
|
-
label="Tambah Data"
|
|
412
|
-
size="sm"
|
|
413
|
-
onClick={() => {
|
|
414
|
-
setToggle(`MODAL_FORM_${toggleKey}`)
|
|
415
|
-
setSelected(null)
|
|
416
|
-
}}
|
|
417
|
-
/>
|
|
418
|
-
</div>
|
|
419
|
-
)
|
|
420
|
-
}
|
|
397
|
+
{title && <h1 className="text-lg lg:text-xl font-bold mb-2 lg:mb-4">{title}</h1>}
|
|
421
398
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
399
|
+
<TableComponent
|
|
400
|
+
id={tableKey}
|
|
401
|
+
controlBar={controlBar?.map((cb) => {
|
|
402
|
+
if (cb == "CREATE") {
|
|
403
|
+
if (isSm) return
|
|
404
|
+
return (
|
|
405
|
+
<div className="pl-1.5 pr-3 mr-2 border-r" key="button-add">
|
|
406
|
+
<ButtonComponent
|
|
407
|
+
icon={"solid/plus"}
|
|
408
|
+
label="Tambah Data"
|
|
409
|
+
size="sm"
|
|
410
|
+
onClick={() => {
|
|
411
|
+
setToggle(`MODAL_FORM_${toggleKey}`)
|
|
412
|
+
setSelected(null)
|
|
413
|
+
}}
|
|
414
|
+
/>
|
|
415
|
+
</div>
|
|
416
|
+
)
|
|
417
|
+
}
|
|
436
418
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
419
|
+
if (cb == "IMPORT") {
|
|
420
|
+
return (
|
|
421
|
+
<div className="px-1.5 rounded-md relative" key={"import"}>
|
|
422
|
+
<ButtonComponent
|
|
423
|
+
icon={"solid/file-excel"}
|
|
424
|
+
label="Import"
|
|
425
|
+
variant="outline"
|
|
426
|
+
className="!text-foreground"
|
|
427
|
+
onClick={() => setToggle(`MODAL_IMPORT_${toggleKey}`)}
|
|
428
|
+
size="sm"
|
|
429
|
+
/>
|
|
430
|
+
</div>
|
|
431
|
+
)
|
|
432
|
+
}
|
|
451
433
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
434
|
+
if (cb == "EXPORT") {
|
|
435
|
+
return (
|
|
436
|
+
<div className="px-1.5 rounded-md relative" key={"export-excel"}>
|
|
437
|
+
<ButtonComponent
|
|
438
|
+
icon={"solid/file-excel"}
|
|
439
|
+
label="Export"
|
|
440
|
+
variant="outline"
|
|
441
|
+
className="!text-foreground"
|
|
442
|
+
onClick={() => setToggle(`MODAL_EXPORT_${toggleKey}`)}
|
|
443
|
+
size="sm"
|
|
444
|
+
/>
|
|
445
|
+
</div>
|
|
446
|
+
)
|
|
447
|
+
}
|
|
466
448
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
"
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
449
|
+
if (cb == "PRINT") {
|
|
450
|
+
return (
|
|
451
|
+
<div className="px-1.5 rounded-md relative" key={"export-pdf"}>
|
|
452
|
+
<ButtonComponent
|
|
453
|
+
icon={"solid/file-pdf"}
|
|
454
|
+
label="Cetak"
|
|
455
|
+
variant="outline"
|
|
456
|
+
className="!text-foreground"
|
|
457
|
+
onClick={() => setToggle(`MODAL_PRINT_${toggleKey}`)}
|
|
458
|
+
size="sm"
|
|
459
|
+
/>
|
|
460
|
+
</div>
|
|
461
|
+
)
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
return cb
|
|
465
|
+
}) || [
|
|
466
|
+
...(!isSm ? [
|
|
467
|
+
<div className="pl-1.5 pr-3 mr-2 border-r" key="button-add">
|
|
468
|
+
<ButtonComponent
|
|
469
|
+
icon={"solid/plus"}
|
|
470
|
+
label="Tambah Data"
|
|
471
|
+
size="sm"
|
|
472
|
+
onClick={() => {
|
|
473
|
+
setToggle(`MODAL_FORM_${toggleKey}`)
|
|
474
|
+
setSelected(null)
|
|
475
|
+
}}
|
|
476
|
+
/>
|
|
477
|
+
</div>
|
|
478
|
+
] : []),
|
|
479
|
+
"SEARCH",
|
|
480
|
+
...(columns?.filter((c) => !!(c as { filterable?: any }).filterable)?.length ? ["FILTER"] : []),
|
|
481
|
+
...(columns?.filter((c) => !!(c as { sortable?: any }).sortable)?.length ? ["SORT"] : []),
|
|
482
|
+
"SELECTABLE", "REFRESH",
|
|
483
|
+
]}
|
|
484
|
+
columns={columns as TableColumnType[]}
|
|
485
|
+
data={dataTables}
|
|
486
|
+
onRowClick={onRowClick ? onRowClick : detailControl != false ? (e) => {
|
|
487
|
+
setToggle(`MODAL_SHOW_${toggleKey}`)
|
|
488
|
+
setSelected(e)
|
|
489
|
+
} : undefined}
|
|
490
|
+
actionBulking={actionBulkingControl}
|
|
491
|
+
checks={checks || []}
|
|
492
|
+
onChangeChecks={(e) => setChecks(e)}
|
|
493
|
+
block={block}
|
|
494
|
+
focus={focus}
|
|
495
|
+
noIndex={noIndex}
|
|
496
|
+
responsiveControl={responsiveControl ? {
|
|
497
|
+
mobile: responsiveControl?.mobile ? {
|
|
498
|
+
...(typeof responsiveControl.mobile === 'object' ? responsiveControl.mobile : {}),
|
|
499
|
+
leftActionControl: (typeof responsiveControl.mobile === 'object' && responsiveControl.mobile.leftActionControl !== undefined) ? responsiveControl.mobile.leftActionControl : (Array.isArray(actionControl) ? actionControl : (actionControl || actionControl == undefined) ? ['EDIT', "DELETE"] : []).includes('EDIT') ? {
|
|
500
|
+
icon: "solid/edit",
|
|
501
|
+
onAction: (item) => {
|
|
502
|
+
setToggle(`MODAL_FORM_${toggleKey}`);
|
|
503
|
+
item && setSelected?.(item);
|
|
504
|
+
}
|
|
505
|
+
} : undefined,
|
|
506
|
+
rightActionControl: (typeof responsiveControl.mobile === 'object' && responsiveControl.mobile.rightActionControl !== undefined) ? responsiveControl.mobile.rightActionControl : (Array.isArray(actionControl) ? actionControl : (actionControl || actionControl == undefined) ? ['EDIT', "DELETE"] : []).includes('DELETE') ? {
|
|
507
|
+
icon: "solid/trash",
|
|
508
|
+
onAction: (item) => {
|
|
509
|
+
setToggle(`MODAL_DELETE_${toggleKey}`);
|
|
510
|
+
item && setSelected?.(item);
|
|
511
|
+
}
|
|
512
|
+
} : undefined
|
|
513
|
+
} : undefined,
|
|
514
|
+
} : undefined}
|
|
515
|
+
{...tableControl}
|
|
516
|
+
/>
|
|
519
517
|
|
|
518
|
+
{controlBar?.find((cb) => cb == "CREATE") && (
|
|
520
519
|
<ButtonComponent
|
|
521
|
-
icon={
|
|
522
|
-
className="
|
|
520
|
+
icon={"solid/plus"}
|
|
521
|
+
className="fixed bottom-24 right-4 w-14 h-14 z-20 md:hidden"
|
|
523
522
|
size="lg"
|
|
524
523
|
rounded
|
|
525
524
|
onClick={() => {
|
|
@@ -527,162 +526,128 @@ export function TableSupervisionComponent({
|
|
|
527
526
|
setSelected(null)
|
|
528
527
|
}}
|
|
529
528
|
/>
|
|
529
|
+
)}
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
<FloatingPageComponent
|
|
533
|
+
show={!!toggle[`MODAL_SHOW_${toggleKey}`]}
|
|
534
|
+
onClose={() => setToggle(`MODAL_SHOW_${toggleKey}`, false)}
|
|
535
|
+
title="Detail"
|
|
536
|
+
className="bg-background"
|
|
537
|
+
footer={renderTableAction(actionControl, undefined, {className: isSm ? "justify-end p-2 bg-background" : "justify-end", size: isSm ? "sm" : "md"})}
|
|
538
|
+
>
|
|
539
|
+
{detailPage}
|
|
540
|
+
</FloatingPageComponent>
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
<FloatingPageComponent
|
|
544
|
+
show={!!toggle[`MODAL_FORM_${toggleKey}`]}
|
|
545
|
+
onClose={() => setToggle(`MODAL_FORM_${toggleKey}`, false)}
|
|
546
|
+
title={!!selected ? "Ubah Data" : "Tambah Data"}
|
|
547
|
+
className={cn("bg-white", formControl?.modalControl?.className)}
|
|
548
|
+
>
|
|
549
|
+
<div className="p-4">
|
|
550
|
+
{formPage}
|
|
551
|
+
</div>
|
|
552
|
+
</FloatingPageComponent>
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
<FloatingPageComponent
|
|
556
|
+
show={!!toggle[`MODAL_EXPORT_${toggleKey}`]}
|
|
557
|
+
onClose={() => setToggle(`MODAL_EXPORT_${toggleKey}`, false)}
|
|
558
|
+
title="Export Ke Excel"
|
|
559
|
+
className="bg-white md:w-[1200px] max-w-[1200px]"
|
|
560
|
+
>
|
|
561
|
+
<ExportExcel
|
|
562
|
+
fetchControl={fetchControl}
|
|
563
|
+
filename={"Export - " + title}
|
|
564
|
+
columnControl={columns?.map((cc) => ({
|
|
565
|
+
label: cc.label || "",
|
|
566
|
+
selector: cc.selector || "",
|
|
567
|
+
}))}
|
|
568
|
+
/>
|
|
569
|
+
</FloatingPageComponent>
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
<FloatingPageComponent
|
|
573
|
+
show={!!toggle[`MODAL_IMPORT_${toggleKey}`]}
|
|
574
|
+
onClose={() => setToggle(`MODAL_IMPORT_${toggleKey}`, false)}
|
|
575
|
+
title="Import Dari Excel"
|
|
576
|
+
className="bg-white md:w-[1200px] max-w-[1200px]"
|
|
577
|
+
>
|
|
578
|
+
<ImportExcel
|
|
579
|
+
submitControl={{ path: (fetchControl as ApiType)?.path + "/import" }}
|
|
580
|
+
columnControl={columns?.map((cc) => ({
|
|
581
|
+
label: cc.label || "",
|
|
582
|
+
selector: cc.selector || "",
|
|
583
|
+
}))}
|
|
584
|
+
/>
|
|
585
|
+
</FloatingPageComponent>
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
{/* <FloatingPageComponent
|
|
589
|
+
show={!!toggle[`MODAL_PRINT_${toggleKey}`]}
|
|
590
|
+
onClose={() => setToggle(`MODAL_PRINT_${toggleKey}`, false)}
|
|
591
|
+
title="Print PDF"
|
|
592
|
+
className="bg-white md:w-[1200px] max-w-[1200px]"
|
|
593
|
+
>
|
|
594
|
+
<PrintTable
|
|
595
|
+
fetchControl={fetchControl}
|
|
596
|
+
columnControl={columns?.map((cc) => ({
|
|
597
|
+
label: cc.label || "",
|
|
598
|
+
selector: cc.selector || "",
|
|
599
|
+
}))}
|
|
600
|
+
title={"Print - " + title}
|
|
601
|
+
/>
|
|
602
|
+
</FloatingPageComponent> */}
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
<ModalConfirmComponent
|
|
606
|
+
show={!!toggle[`MODAL_DELETE_${toggleKey}`]}
|
|
607
|
+
onClose={() => setToggle(`MODAL_DELETE_${toggleKey}`, false)}
|
|
608
|
+
title={<>Menghapus Data <span className="font-semibold">"{selected?.[columns?.at(0)?.selector || ""]}"</span> ?</>}
|
|
609
|
+
submitControl={{
|
|
610
|
+
onSubmit: {
|
|
611
|
+
...((fetchControl as ApiType).path
|
|
612
|
+
? {path: `${(fetchControl as ApiType).path}/${(selected as { id: number })?.id || ""}`}
|
|
613
|
+
: (fetchControl as ApiType).url ? {url: `${(fetchControl as ApiType).url}/${(selected as { id: number })?.id || ""}`}
|
|
614
|
+
: { idb: { ...(fetchControl as ({ idb: UseResourceIdb }))?.idb, id: (selected as { id: number })?.id || "" }}
|
|
615
|
+
),
|
|
616
|
+
method: "DELETE",
|
|
617
|
+
},
|
|
618
|
+
onSuccess: () => {
|
|
619
|
+
reset();
|
|
620
|
+
setTimeout(() => { setToggle(`MODAL_DELETE_${toggleKey}`, false) }, 900);
|
|
621
|
+
},
|
|
622
|
+
}}
|
|
623
|
+
/>
|
|
530
624
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
{
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
{isSm ? (
|
|
558
|
-
<BottomSheetComponent
|
|
559
|
-
show={!!toggle[`MODAL_FORM_${toggleKey}`]}
|
|
560
|
-
onClose={() => setToggle(`MODAL_FORM_${toggleKey}`, false)}
|
|
561
|
-
className={cn("table-supervision-modal", formControl?.modalControl?.className)}
|
|
562
|
-
size="98vh"
|
|
563
|
-
>
|
|
564
|
-
<div className="table-supervision-form-mobile-container">
|
|
565
|
-
{formPage}
|
|
566
|
-
</div>
|
|
567
|
-
</BottomSheetComponent>
|
|
568
|
-
) : (
|
|
569
|
-
<FloatingPageComponent
|
|
570
|
-
show={!!toggle[`MODAL_FORM_${toggleKey}`]}
|
|
571
|
-
onClose={() => setToggle(`MODAL_FORM_${toggleKey}`, false)}
|
|
572
|
-
title={!!selected ? "Ubah Data" : "Tambah Data"}
|
|
573
|
-
className={cn("table-supervision-modal", formControl?.modalControl?.className)}
|
|
574
|
-
>
|
|
575
|
-
<div className="table-supervision-form-container">
|
|
576
|
-
{formPage}
|
|
577
|
-
</div>
|
|
578
|
-
</FloatingPageComponent>
|
|
579
|
-
)}
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
{ExportExcel && (
|
|
583
|
-
<FloatingPageComponent
|
|
584
|
-
show={!!toggle[`MODAL_EXPORT_${toggleKey}`]}
|
|
585
|
-
onClose={() => setToggle(`MODAL_EXPORT_${toggleKey}`, false)}
|
|
586
|
-
title="Export Ke Excel"
|
|
587
|
-
className="table-supervision-large-modal"
|
|
588
|
-
>
|
|
589
|
-
<ExportExcel
|
|
590
|
-
fetchControl={fetchControl as FetchControlType}
|
|
591
|
-
filename={"Export - " + title}
|
|
592
|
-
columnControl={columns?.map((cc: TableSupervisionColumnProps) => ({
|
|
593
|
-
label: cc.label || "",
|
|
594
|
-
selector: cc.selector || "",
|
|
595
|
-
status: cc.exportable === false ? "hidden" : cc.exportable === true ? "default" : typeof cc.exportable === "string" ? cc.exportable : undefined,
|
|
596
|
-
}))}
|
|
597
|
-
/>
|
|
598
|
-
</FloatingPageComponent>
|
|
599
|
-
)}
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
{ImportExcel && (
|
|
603
|
-
<FloatingPageComponent
|
|
604
|
-
show={!!toggle[`MODAL_IMPORT_${toggleKey}`]}
|
|
605
|
-
onClose={() => setToggle(`MODAL_IMPORT_${toggleKey}`, false)}
|
|
606
|
-
title="Import Dari Excel"
|
|
607
|
-
className="table-supervision-large-modal"
|
|
608
|
-
>
|
|
609
|
-
<ImportExcel
|
|
610
|
-
submitControl={importControl}
|
|
611
|
-
fetchControl={
|
|
612
|
-
(fetchControl as ApiType).path ? {
|
|
613
|
-
path: (fetchControl as ApiType).path,
|
|
614
|
-
} : undefined
|
|
615
|
-
}
|
|
616
|
-
columnControl={columns?.filter((cc: TableSupervisionColumnProps) => cc.importable !== false).map((cc: TableSupervisionColumnProps) => ({
|
|
617
|
-
label: cc.label || "",
|
|
618
|
-
selector: cc.selector || "",
|
|
619
|
-
}))}
|
|
620
|
-
/>
|
|
621
|
-
</FloatingPageComponent>
|
|
622
|
-
)}
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
<ModalConfirmComponent
|
|
626
|
-
show={!!toggle[`MODAL_DELETE_${toggleKey}`]}
|
|
627
|
-
onClose={() => setToggle(`MODAL_DELETE_${toggleKey}`, false)}
|
|
628
|
-
icon={faQuestionCircle}
|
|
629
|
-
title={`Menghapus Data?`}
|
|
630
|
-
submitControl={{
|
|
631
|
-
onSubmit: {
|
|
632
|
-
...((fetchControl as ApiType).path
|
|
633
|
-
? {path: `${(fetchControl as ApiType).path}/${(selected as { id: number })?.id || ""}`}
|
|
634
|
-
: (fetchControl as ApiType).url ? {url: `${(fetchControl as ApiType).url}/${(selected as { id: number })?.id || ""}`}
|
|
635
|
-
: { idb: { ...(fetchControl as ({ idb: UseResourceIdb }))?.idb, id: (selected as { id: number })?.id || "" }}
|
|
636
|
-
),
|
|
637
|
-
method: "DELETE",
|
|
638
|
-
},
|
|
639
|
-
onSuccess: () => {
|
|
640
|
-
reset();
|
|
641
|
-
setToggle(`MODAL_DELETE_${toggleKey}`, false);
|
|
642
|
-
},
|
|
643
|
-
}}
|
|
644
|
-
>
|
|
645
|
-
{columns?.at(0)?.selector && selected ? (
|
|
646
|
-
<p className="table-supervision-confirm-text">Yakin menghapus <span className="table-supervision-confirm-item-name">"{selected[columns?.at(0)?.selector || ""]}"</span>?</p>
|
|
647
|
-
) : (
|
|
648
|
-
<p className="table-supervision-confirm-text">Yakin yang dihapus sudah benar?</p>
|
|
649
|
-
)}
|
|
650
|
-
</ModalConfirmComponent>
|
|
651
|
-
|
|
652
|
-
{actionControl && Array.isArray(actionControl) && actionControl.filter((ac) => typeof ac == "object")?.map((ac, acKey) => {
|
|
653
|
-
const submitControl = ac.modal?.submitControl?.onSubmit as ApiType;
|
|
654
|
-
return (
|
|
655
|
-
<ModalConfirmComponent
|
|
656
|
-
key={acKey}
|
|
657
|
-
show={!!toggle[`MODAL_${conversion.strSnake(ac.label).toUpperCase()}_${toggleKey}`]}
|
|
658
|
-
onClose={() => setToggle(`MODAL_${conversion.strSnake(ac.label).toUpperCase()}_${toggleKey}`, false)}
|
|
659
|
-
icon={faQuestionCircle}
|
|
660
|
-
title={`${ac.label} Data?`}
|
|
661
|
-
submitControl={{
|
|
662
|
-
onSubmit: {
|
|
663
|
-
...((submitControl as ApiType)?.path
|
|
664
|
-
? {path: `${(submitControl as ApiType).path}/${(selected as { id: number })?.id || ""}`}
|
|
665
|
-
: (submitControl as ApiType)?.url ? {url: `${(submitControl as ApiType).url}/${(selected as { id: number })?.id || ""}`}
|
|
666
|
-
: { idb: { ...(submitControl as ({ idb: UseResourceIdb }))?.idb, id: (selected as { id: number })?.id || "" }}
|
|
667
|
-
),
|
|
668
|
-
...ac.modal?.submitControl?.onSubmit,
|
|
669
|
-
},
|
|
670
|
-
onSuccess: () => {
|
|
671
|
-
reset();
|
|
672
|
-
setToggle(`MODAL_${conversion.strSnake(ac.label).toUpperCase()}_${toggleKey}`, false);
|
|
673
|
-
},
|
|
674
|
-
}}
|
|
675
|
-
{...ac.modal}
|
|
676
|
-
>
|
|
677
|
-
{columns?.at(0)?.selector && selected ? (
|
|
678
|
-
<p className="table-supervision-confirm-text">Yakin melakukan aksi untuk data <span className="table-supervision-confirm-item-name">"{selected[columns?.at(0)?.selector || ""]}"</span>?</p>
|
|
679
|
-
) : (
|
|
680
|
-
<p className="table-supervision-confirm-text">Yakin aksi yang dilakukan sudah benar?</p>
|
|
681
|
-
)}
|
|
682
|
-
</ModalConfirmComponent>
|
|
683
|
-
)
|
|
684
|
-
})}
|
|
685
|
-
</Suspense>
|
|
625
|
+
{actionControl && Array.isArray(actionControl) && actionControl.filter((ac) => typeof ac == "object")?.map((ac, acKey) => {
|
|
626
|
+
const submitControl = ac.modal?.submitControl?.onSubmit as ApiType;
|
|
627
|
+
return (
|
|
628
|
+
<ModalConfirmComponent
|
|
629
|
+
key={acKey}
|
|
630
|
+
show={!!toggle[`MODAL_${conversion.strSnake(ac.label).toUpperCase()}_${toggleKey}`]}
|
|
631
|
+
onClose={() => setToggle(`MODAL_${conversion.strSnake(ac.label).toUpperCase()}_${toggleKey}`, false)}
|
|
632
|
+
title={ac?.modal?.title || ac.label}
|
|
633
|
+
submitControl={{
|
|
634
|
+
onSubmit: {
|
|
635
|
+
...(submitControl?.path
|
|
636
|
+
? {path: `${submitControl?.path}/${(selected as { id: number })?.id || ""}`}
|
|
637
|
+
: {url: `${submitControl?.url}/${(selected as { id: number })?.id || ""}`}
|
|
638
|
+
),
|
|
639
|
+
method: submitControl?.method || "POST",
|
|
640
|
+
},
|
|
641
|
+
onSuccess: () => {
|
|
642
|
+
reset();
|
|
643
|
+
setToggle(`MODAL_${conversion.strSnake(ac.label).toUpperCase()}_${conversion.strSnake(tableKey).toUpperCase()}`, false);
|
|
644
|
+
setSelected(null)
|
|
645
|
+
ac.modal?.submitControl?.onSuccess?.()
|
|
646
|
+
},
|
|
647
|
+
}}
|
|
648
|
+
>{ac.modal?.children}</ModalConfirmComponent>
|
|
649
|
+
)
|
|
650
|
+
})}
|
|
686
651
|
</>
|
|
687
652
|
);
|
|
688
653
|
}
|