@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.
@@ -1,7 +1,8 @@
1
1
  "use client"
2
2
 
3
- import { Fragment, ReactNode, useEffect, useMemo } from "react";
4
- import { ApiType, cn, conversion, registry, shortcut, ShortcutHandler, UseResourceIdb, UseResourceProps, useResponsive, useTable } from "@utils";
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
- {!!selected && (typeof detailControl === "object" && typeof detailControl.content === "object" && detailControl?.content?.length ? detailControl?.content?.map((column, key) => {
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={() => setToggle(`MODAL_SHOW_${toggleKey}`, false)}
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={() => setToggle(`MODAL_FORM_${toggleKey}`, false)}
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}