@skalfa/skalfa-component 1.0.53 → 1.0.55
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/input/InputDate.component.d.ts +1 -0
- package/dist/input/InputDate.component.js +47 -29
- package/dist/input/InputDatetime.component.js +2 -2
- package/dist/input/InputTime.component.d.ts +5 -3
- package/dist/input/InputTime.component.js +109 -28
- package/dist/input/Select.component.d.ts +7 -2
- package/dist/input/Select.component.js +91 -38
- package/dist/supervision/TableSupervision.component.js +90 -4
- package/package.json +1 -1
- package/src/input/InputDate.component.tsx +95 -55
- package/src/input/InputDatetime.component.tsx +2 -0
- package/src/input/InputTime.component.tsx +218 -58
- package/src/input/Select.component.tsx +111 -53
- package/src/supervision/TableSupervision.component.tsx +102 -10
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
|
-
import { Fragment, ReactNode, useEffect, useMemo } from "react";
|
|
4
|
-
import {
|
|
3
|
+
import { Fragment, ReactNode, useEffect, useMemo, useState } from "react";
|
|
4
|
+
import { useRouter, useSearchParams } from "next/navigation";
|
|
5
|
+
import { api, ApiType, cn, conversion, registry, shortcut, ShortcutHandler, UseResourceIdb, UseResourceProps, useResponsive, useTable } from "@utils";
|
|
5
6
|
import { useToggleContext } from "@contexts";
|
|
6
7
|
import { FloatingPageComponent, FloatingPageProps, ButtonComponent, TableColumnType, TableComponent, FormSupervisionComponent, FormType, ModalConfirmComponent, TypographyColumnComponent, ButtonProps, ModalConfirmProps, TableProps, ControlBarOptionType, SwipeActionType, BottomSheetProps } from "../";
|
|
7
8
|
import { useLang } from "@skalfa/skalfa-lang";
|
|
@@ -105,12 +106,61 @@ export function TableSupervisionComponent({
|
|
|
105
106
|
urlParam,
|
|
106
107
|
}: TableSupervisionProps) {
|
|
107
108
|
const l = useLang();
|
|
109
|
+
const router = useRouter();
|
|
110
|
+
const searchParams = useSearchParams();
|
|
108
111
|
|
|
109
112
|
const { tableKey, tableControl, data, selected, setSelected, checks, setChecks, reset, focus, setFocus } = useTable(fetchControl, id, title, (urlParam || true))
|
|
110
113
|
const { setToggle, toggle } = useToggleContext()
|
|
111
114
|
const { isSm } = useResponsive();
|
|
112
115
|
|
|
113
116
|
const toggleKey = useMemo(() => conversion.strSnake(tableKey).toUpperCase(), [tableKey])
|
|
117
|
+
const detailQueryId = searchParams.get("detail") || searchParams.get("openDetail");
|
|
118
|
+
const editQueryId = searchParams.get("edit");
|
|
119
|
+
const [directLoading, setDirectLoading] = useState(false);
|
|
120
|
+
|
|
121
|
+
// Auto-open floating detail or edit modal if query parameter is present in URL
|
|
122
|
+
useEffect(() => {
|
|
123
|
+
if (detailControl === false && !editQueryId) return;
|
|
124
|
+
|
|
125
|
+
const targetId = detailQueryId || editQueryId;
|
|
126
|
+
const isEdit = !!editQueryId && !detailQueryId;
|
|
127
|
+
if (!targetId) return;
|
|
128
|
+
|
|
129
|
+
if (!selected || String((selected as any)?.id) !== String(targetId)) {
|
|
130
|
+
setDirectLoading(true);
|
|
131
|
+
if (isEdit) {
|
|
132
|
+
setToggle(`MODAL_FORM_${toggleKey}`, true);
|
|
133
|
+
} else {
|
|
134
|
+
setToggle(`MODAL_SHOW_${toggleKey}`, true);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const basePath = (fetchControl as ApiType)?.path;
|
|
138
|
+
if (basePath) {
|
|
139
|
+
api({
|
|
140
|
+
path: `${basePath}/${targetId}`,
|
|
141
|
+
method: "GET",
|
|
142
|
+
params: (fetchControl as ApiType)?.params || {},
|
|
143
|
+
})
|
|
144
|
+
.then((res: any) => {
|
|
145
|
+
const item = res?.data?.data || res?.data || res;
|
|
146
|
+
if (item) {
|
|
147
|
+
setSelected(item);
|
|
148
|
+
} else {
|
|
149
|
+
setSelected({ id: Number(targetId) });
|
|
150
|
+
}
|
|
151
|
+
})
|
|
152
|
+
.catch(() => {
|
|
153
|
+
setSelected({ id: Number(targetId) });
|
|
154
|
+
})
|
|
155
|
+
.finally(() => {
|
|
156
|
+
setDirectLoading(false);
|
|
157
|
+
});
|
|
158
|
+
} else {
|
|
159
|
+
setSelected({ id: Number(targetId) });
|
|
160
|
+
setDirectLoading(false);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}, [detailQueryId, editQueryId, fetchControl, toggleKey]);
|
|
114
164
|
|
|
115
165
|
|
|
116
166
|
useEffect(() => {
|
|
@@ -297,23 +347,35 @@ export function TableSupervisionComponent({
|
|
|
297
347
|
// ============================
|
|
298
348
|
const detailPage = useMemo(() => {
|
|
299
349
|
if (!toggle[`MODAL_SHOW_${toggleKey}`]) return null;
|
|
350
|
+
|
|
351
|
+
if (directLoading && !selected) {
|
|
352
|
+
return (
|
|
353
|
+
<div className="p-12 text-center text-slate-400 space-y-2">
|
|
354
|
+
<div className="inline-block animate-spin w-6 h-6 border-2 border-primary border-t-transparent rounded-full" />
|
|
355
|
+
<p className="text-xs font-semibold">{l?.base?.loading ? l.base.loading() : "Memuat detail..."}</p>
|
|
356
|
+
</div>
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if (!selected) return null;
|
|
361
|
+
|
|
300
362
|
return (
|
|
301
363
|
<div className="p-4">
|
|
302
364
|
<div className={cn(
|
|
303
365
|
"flex flex-col gap-y-4",
|
|
304
366
|
)}>
|
|
305
|
-
{
|
|
367
|
+
{typeof detailControl === "object" && typeof detailControl.content === "object" && detailControl?.content?.length ? detailControl?.content?.map((column, key) => {
|
|
306
368
|
if (typeof column === "string") {
|
|
307
369
|
return (<TypographyColumnComponent
|
|
308
370
|
key={key}
|
|
309
371
|
title={columns?.find((c) => c.selector == column)?.label}
|
|
310
|
-
content={selected[column]}
|
|
372
|
+
content={(selected as any)[column]}
|
|
311
373
|
/>)
|
|
312
374
|
} else if (typeof column === "object") {
|
|
313
375
|
return (<TypographyColumnComponent
|
|
314
376
|
key={key}
|
|
315
377
|
title={column?.label}
|
|
316
|
-
content={typeof column?.item === "string" ? selected[column?.item] : column?.item(selected)}
|
|
378
|
+
content={typeof column?.item === "string" ? (selected as any)[column?.item] : column?.item(selected)}
|
|
317
379
|
/>)
|
|
318
380
|
} else {
|
|
319
381
|
return column?.(selected)
|
|
@@ -322,13 +384,13 @@ export function TableSupervisionComponent({
|
|
|
322
384
|
<TypographyColumnComponent
|
|
323
385
|
key={key}
|
|
324
386
|
title={column.label}
|
|
325
|
-
content={selected[column.selector]}
|
|
387
|
+
content={(selected as any)[column.selector]}
|
|
326
388
|
/>
|
|
327
|
-
))
|
|
389
|
+
))}
|
|
328
390
|
</div>
|
|
329
391
|
</div>
|
|
330
392
|
)
|
|
331
|
-
}, [selected, detailControl]);
|
|
393
|
+
}, [selected, detailControl, toggle[`MODAL_SHOW_${toggleKey}`], directLoading, columns]);
|
|
332
394
|
|
|
333
395
|
|
|
334
396
|
|
|
@@ -401,6 +463,14 @@ export function TableSupervisionComponent({
|
|
|
401
463
|
payload={formControl?.payload}
|
|
402
464
|
onSuccess={() => {
|
|
403
465
|
reset();
|
|
466
|
+
if (typeof window !== "undefined") {
|
|
467
|
+
const url = new URL(window.location.href);
|
|
468
|
+
if (url.searchParams.has("edit")) {
|
|
469
|
+
url.searchParams.delete("edit");
|
|
470
|
+
const nextSearch = url.searchParams.toString();
|
|
471
|
+
router.replace(url.pathname + (nextSearch ? `?${nextSearch}` : ""), { scroll: false });
|
|
472
|
+
}
|
|
473
|
+
}
|
|
404
474
|
setTimeout(() => { setToggle(`MODAL_FORM_${toggleKey}`, false) }, 900);
|
|
405
475
|
}}
|
|
406
476
|
/>
|
|
@@ -553,7 +623,19 @@ export function TableSupervisionComponent({
|
|
|
553
623
|
|
|
554
624
|
<FloatingPageComponent
|
|
555
625
|
show={!!toggle[`MODAL_SHOW_${toggleKey}`]}
|
|
556
|
-
onClose={() =>
|
|
626
|
+
onClose={() => {
|
|
627
|
+
setToggle(`MODAL_SHOW_${toggleKey}`, false);
|
|
628
|
+
setSelected(null);
|
|
629
|
+
if (typeof window !== "undefined") {
|
|
630
|
+
const url = new URL(window.location.href);
|
|
631
|
+
if (url.searchParams.has("detail") || url.searchParams.has("openDetail")) {
|
|
632
|
+
url.searchParams.delete("detail");
|
|
633
|
+
url.searchParams.delete("openDetail");
|
|
634
|
+
const nextSearch = url.searchParams.toString();
|
|
635
|
+
router.replace(url.pathname + (nextSearch ? `?${nextSearch}` : ""), { scroll: false });
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
}}
|
|
557
639
|
title={l.base.detailTitle ? l.base.detailTitle() : "Detail"}
|
|
558
640
|
className="bg-background"
|
|
559
641
|
footer={renderTableAction(actionControl, undefined, {className: isSm ? "justify-end p-2 bg-background" : "justify-end", size: isSm ? "sm" : "md"})}
|
|
@@ -565,7 +647,17 @@ export function TableSupervisionComponent({
|
|
|
565
647
|
|
|
566
648
|
<FloatingPageComponent
|
|
567
649
|
show={!!toggle[`MODAL_FORM_${toggleKey}`]}
|
|
568
|
-
onClose={() =>
|
|
650
|
+
onClose={() => {
|
|
651
|
+
setToggle(`MODAL_FORM_${toggleKey}`, false);
|
|
652
|
+
if (typeof window !== "undefined") {
|
|
653
|
+
const url = new URL(window.location.href);
|
|
654
|
+
if (url.searchParams.has("edit")) {
|
|
655
|
+
url.searchParams.delete("edit");
|
|
656
|
+
const nextSearch = url.searchParams.toString();
|
|
657
|
+
router.replace(url.pathname + (nextSearch ? `?${nextSearch}` : ""), { scroll: false });
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}}
|
|
569
661
|
title={!!selected ? (l.base.editTitle ? l.base.editTitle() : "Edit") : (l.base.addTitle ? l.base.addTitle() : "Add")}
|
|
570
662
|
className={cn("bg-white", formControl?.modalControl?.className)}
|
|
571
663
|
{...formControl?.modalControl}
|