@gemafajarramadhan/dynamic-ui 1.1.27 → 1.1.29

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/README.md CHANGED
@@ -19,6 +19,13 @@ Library **Vue 3** component yang bisa digunakan di berbagai framework (Vue, Reac
19
19
  - [Penggunaan di Vue 3 (Import Per Komponen)](#penggunaan-di-vue-3-import-per-komponen)
20
20
  - [Penggunaan di Vue 3 (Global Plugin)](#penggunaan-di-vue-3-global-plugin)
21
21
  - [Penggunaan di Nuxt 3](#penggunaan-di-nuxt-3-vue-components)
22
+ - [DCodeDataTable – Tabel Dinamis](#dcodedatatable--tabel-dinamis)
23
+ - [Props Utama](#props-utama)
24
+ - [Pola 1 — fetchHandler (MFE)](#pola-1--fetchhandler--disarankan-untuk-mfe)
25
+ - [Pola 2 — Static Data](#pola-2--static-data-consumer-fetch-di-luar)
26
+ - [Pola 3 — Realtime Socket](#pola-3--realtime-socket-consumer-kelola-socket)
27
+ - [Format Response](#format-response-yang-didukung)
28
+ - [Expose Methods](#expose-methods-via-ref)
22
29
  - [DCodeAutoComplete – Komponen dengan API](#dcodeautocomplete--komponen-dengan-api)
23
30
  - [Web Components (Framework Agnostic)](#web-components-framework-agnostic)
24
31
  - [API Referensi Web Components](#api-referensi-web-components)
@@ -379,6 +386,269 @@ Kemudian gunakan di page atau component manapun:
379
386
 
380
387
  ---
381
388
 
389
+ ## DCodeDataTable – Tabel Dinamis
390
+
391
+ `DCodeDataTable` adalah komponen tabel dinamis yang mendukung **pagination server-side**, **sorting**, **filtering**, **action buttons**, dan **badge kondisional** — seluruhnya dikonfigurasi via JSON schema.
392
+
393
+ Komponen ini dirancang sebagai **micro-frontend**: consumer bertanggung jawab penuh atas HTTP client, auth token, dan sistem permission.
394
+
395
+ ---
396
+
397
+ ### Props Utama
398
+
399
+ | Prop | Tipe | Default | Deskripsi |
400
+ |------|------|---------|-----------|
401
+ | `table-config` | `Object` | — | Config JSON (kolom, filter, action, pagination) |
402
+ | `fetch-handler` | `(params) => Promise<any>` | — | **[MFE]** Consumer kontrol penuh fetch. Component tidak hit endpoint sama sekali. |
403
+ | `http-client` | `({ url, method, data }) => Promise<any>` | — | **[MFE]** Axios instance consumer untuk action tombol row/header (DELETE, PATCH, dll.) |
404
+ | `action-access-checker` | `(path, action) => boolean` | `() => true` | **[MFE]** Fungsi RBAC dari consumer. Default: semua action allow. |
405
+ | `ignore-permissions` | `boolean` | `false` | Matikan filter permission sepenuhnya |
406
+ | `data` | `any[]` | `[]` | Data statis (tanpa API); pakai jika consumer sudah fetch di luar |
407
+ | `loading` | `boolean` | `false` | Loading state untuk mode data statis |
408
+ | `columns` | `TableColumn[]` | `[]` | Kolom manual (tanpa table-config) |
409
+ | `per-page` | `number` | `10` | Jumlah baris per halaman awal |
410
+ | `show-pagination` | `boolean` | `true` | Tampilkan pagination |
411
+ | `has-actions` | `boolean` | `false` | Tampilkan kolom aksi (untuk mode kolom manual) |
412
+ | `api-url` | `string` | — | URL endpoint langsung (tanpa table-config) |
413
+ | `api-method` | `string` | `'POST'` | HTTP method untuk apiUrl |
414
+ | `api-params` | `object` | `{}` | Parameter tetap yang selalu disertakan di setiap request |
415
+
416
+ ### Events
417
+
418
+ | Event | Payload | Deskripsi |
419
+ |-------|---------|-----------|
420
+ | `@action` | `{ action, row, selection? }` | Dipanggil saat tombol action diklik |
421
+ | `@update:selection` | `any[]` | Dipanggil saat checkbox selection berubah |
422
+ | `@update:page` | `number` | Dipanggil saat halaman berganti |
423
+
424
+ ---
425
+
426
+ ### Pola 1 — `fetchHandler` ⭐ Disarankan untuk MFE
427
+
428
+ Consumer kontrol penuh HTTP. Component tidak hit endpoint sama sekali — cocok untuk menghindari error 401.
429
+
430
+ ```vue
431
+ <template>
432
+ <DCodeDataTable
433
+ :table-config="tableConfig"
434
+ :fetch-handler="fetchUsers"
435
+ :http-client="httpClient"
436
+ :action-access-checker="checkPermission"
437
+ @action="handleAction"
438
+ />
439
+ </template>
440
+
441
+ <script setup lang="ts">
442
+ import { DCodeDataTable } from '@gemafajarramadhan/dynamic-ui'
443
+ import axios from '@/lib/axios' // axios instance consumer — interceptor token sudah terpasang
444
+
445
+ // 1. fetchHandler: dipanggil tiap page/filter/sort/search change
446
+ // params: { page, perPage, keyword?, ...filters }
447
+ const fetchUsers = async (params: Record<string, any>) => {
448
+ const { data } = await axios.post('/api/users/list', params)
449
+ return data
450
+ }
451
+
452
+ // 2. httpClient: untuk call dari tombol action row (delete, toggle, dll.)
453
+ const httpClient = async ({ url, method, data }: any) => {
454
+ const res = await axios({ url, method, data })
455
+ return res.data
456
+ }
457
+
458
+ // 3. Permission checker dari sistem RBAC consumer
459
+ const checkPermission = (path: string, action: string): boolean => {
460
+ return useAuthStore().can(`${path}:${action}`)
461
+ }
462
+
463
+ // 4. Handle action event dari tabel
464
+ const handleAction = ({ action, row, selection }: any) => {
465
+ if (action === 'edit') router.push(`/users/${row.id}/edit`)
466
+ if (action === 'delete') deleteUser(row.id)
467
+ if (action === 'export') exportSelected(selection)
468
+ }
469
+
470
+ // 5. Konfigurasi tabel via JSON schema
471
+ const tableConfig = {
472
+ headers: [
473
+ { key: 'no', labelID: 'No', labelEN: 'No', align: 'CENTER' },
474
+ { key: 'name', labelID: 'Nama', labelEN: 'Name', align: 'LEFT' },
475
+ { key: 'email', labelID: 'Email', labelEN: 'Email', align: 'LEFT' },
476
+ {
477
+ key: 'status',
478
+ labelID: 'Status', labelEN: 'Status',
479
+ custom: {
480
+ type: 'BADGE',
481
+ conditionBadge: [
482
+ { value: 'active', labelID: 'Aktif', labelEN: 'Active', color: 'success' },
483
+ { value: 'inactive', labelID: 'Nonaktif', labelEN: 'Inactive', color: 'danger' },
484
+ ],
485
+ },
486
+ },
487
+ {
488
+ key: 'action',
489
+ labelID: 'Aksi', labelEN: 'Actions',
490
+ custom: {
491
+ type: 'ACTION',
492
+ actionCustom: [
493
+ {
494
+ permission: 'EDIT',
495
+ propsActionCustom: {
496
+ labelID: 'Edit', labelEN: 'Edit',
497
+ icon: 'SquarePen', actionType: 'edit', bgColor: 'primary',
498
+ },
499
+ },
500
+ {
501
+ permission: 'DELETE',
502
+ requireConfirm: true,
503
+ propCustomMessage: {
504
+ titleID: 'Hapus Data', titleEN: 'Delete',
505
+ messageID: 'Yakin ingin menghapus?', messageEN: 'Are you sure?',
506
+ },
507
+ propsActionCustom: {
508
+ labelID: 'Hapus', labelEN: 'Delete',
509
+ icon: 'Trash2', actionType: 'delete', bgColor: 'red',
510
+ },
511
+ },
512
+ ],
513
+ },
514
+ },
515
+ ],
516
+ filters: [
517
+ {
518
+ seq: 1, model: 'name', labelID: 'Nama', labelEN: 'Name', type: 'TEXT',
519
+ },
520
+ {
521
+ seq: 2, model: 'status', labelID: 'Status', labelEN: 'Status', type: 'SELECT',
522
+ propsFilters: {
523
+ items: [
524
+ { value: 'active', label: 'Active' },
525
+ { value: 'inactive', label: 'Inactive' },
526
+ ],
527
+ },
528
+ },
529
+ ],
530
+ actionGlobal: [
531
+ {
532
+ permission: 'CREATE',
533
+ propsActionGlobal: {
534
+ labelID: 'Tambah', labelEN: 'Add New',
535
+ icon: 'Plus', variant: 'default',
536
+ route: '/users/create',
537
+ },
538
+ },
539
+ ],
540
+ pagination: true,
541
+ }
542
+ </script>
543
+ ```
544
+
545
+ ---
546
+
547
+ ### Pola 2 — Static Data (consumer fetch di luar)
548
+
549
+ Pakai ketika consumer sudah fetch data sendiri dan ingin sekadar menampilkan tabel.
550
+
551
+ ```vue
552
+ <template>
553
+ <DCodeDataTable
554
+ :columns="columns"
555
+ :data="users"
556
+ :loading="isLoading"
557
+ has-actions
558
+ ignore-permissions
559
+ @action="handleAction"
560
+ />
561
+ </template>
562
+
563
+ <script setup lang="ts">
564
+ import { ref, onMounted } from 'vue'
565
+ import axios from '@/lib/axios'
566
+
567
+ const users = ref([])
568
+ const isLoading = ref(false)
569
+
570
+ onMounted(async () => {
571
+ isLoading.value = true
572
+ const { data } = await axios.get('/api/users')
573
+ users.value = data.data
574
+ isLoading.value = false
575
+ })
576
+
577
+ const columns = [
578
+ { key: 'no', label: 'No', align: 'center' },
579
+ { key: 'name', label: 'Nama', align: 'left' },
580
+ { key: 'email', label: 'Email', align: 'left' },
581
+ ]
582
+ </script>
583
+ ```
584
+
585
+ ---
586
+
587
+ ### Pola 3 — Realtime Socket (consumer kelola socket)
588
+
589
+ Consumer connect ke WebSocket sendiri, push data ke tabel melalui `:data`.
590
+
591
+ ```vue
592
+ <template>
593
+ <DCodeDataTable :columns="columns" :data="realtimeData" ignore-permissions />
594
+ </template>
595
+
596
+ <script setup lang="ts">
597
+ import { ref, onMounted, onUnmounted } from 'vue'
598
+ import { io } from 'socket.io-client'
599
+
600
+ const realtimeData = ref([])
601
+ let socket: any = null
602
+
603
+ onMounted(() => {
604
+ socket = io('wss://your-server.com', {
605
+ auth: { token: localStorage.getItem('token') }
606
+ })
607
+ socket.emit('dashboard:list', { page: 1, perPage: 10 })
608
+ socket.on('dashboard:result', (res: any) => {
609
+ realtimeData.value = res.data ?? res
610
+ })
611
+ })
612
+
613
+ onUnmounted(() => socket?.disconnect())
614
+ </script>
615
+ ```
616
+
617
+ ---
618
+
619
+ ### Format Response yang Didukung
620
+
621
+ Component secara otomatis mendeteksi berbagai format response API:
622
+
623
+ ```json
624
+ { "data": [], "totalData": 100 } ✅ (disarankan)
625
+ { "data": [], "maxPage": 10 } ✅
626
+ { "items": [], "total": 100 } ✅
627
+ { "list": [], "total": 100 } ✅
628
+ { "rows": [], "count": 100 } ✅
629
+ { "result": [], "total": 100 } ✅
630
+ [] ✅ (array langsung)
631
+ ```
632
+
633
+ ---
634
+
635
+ ### Expose Methods (via `ref`)
636
+
637
+ ```typescript
638
+ const tableRef = ref()
639
+
640
+ tableRef.value.fetchData() // Refresh data (panggil ulang fetchHandler)
641
+ tableRef.value.handleRefresh() // Reset filter & refresh
642
+ tableRef.value.resetFilters() // Reset nilai filter saja (tanpa fetch)
643
+ console.log(tableRef.value.filters) // Reactive nilai filter saat ini
644
+ ```
645
+
646
+ ```vue
647
+ <DCodeDataTable ref="tableRef" :fetch-handler="fetchUsers" ... />
648
+ ```
649
+
650
+ ---
651
+
382
652
  ## DCodeAutoComplete – Komponen dengan API
383
653
 
384
654
  `DCodeAutoComplete` adalah komponen autocomplete yang bisa **langsung fetch data dari API** menggunakan konfigurasi yang sudah di-set di host project.