@rozaqi02/reusable-dashboard 1.1.3 → 1.1.4

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
@@ -16,13 +16,15 @@ CSS sudah terbundle — tidak perlu konfigurasi Tailwind.
16
16
  2. [Prasyarat Teknis](#2-prasyarat-teknis)
17
17
  3. [Preset yang Tersedia](#3-preset-yang-tersedia)
18
18
  4. [Quick Start — Toko Sepatu (Contoh Lengkap)](#4-quick-start--toko-sepatu)
19
+ - [4.5 Cara Cepat dengan 1 File Config](#45-cara-cepat-dengan-createdasboardconfig)
19
20
  5. [Quick Start — Cidika Travel](#5-quick-start--cidika-travel)
20
21
  6. [Setup Database Supabase](#6-setup-database-supabase)
21
22
  7. [Cara Membuat Adapter untuk Domain Bisnis Baru](#7-cara-membuat-adapter-untuk-domain-bisnis-baru)
22
23
  8. [Konfigurasi Widget](#8-konfigurasi-widget)
23
24
  9. [Label & Internasionalisasi](#9-label--internasionalisasi)
24
25
  10. [API Reference Lengkap](#10-api-reference-lengkap)
25
- 11. [Pengembangan & Kontribusi](#11-pengembangan--kontribusi)
26
+ 11. [Setup Wizard — Panduan Konfigurasi Interaktif](#11-setup-wizard--panduan-konfigurasi-interaktif)
27
+ 12. [Pengembangan & Kontribusi](#12-pengembangan--kontribusi)
26
28
 
27
29
  ---
28
30
 
@@ -313,6 +315,100 @@ Buka browser → dashboard tampil dengan data dari Supabase.
313
315
 
314
316
  ---
315
317
 
318
+ ## 4.5 Cara Cepat dengan `createDashboardConfig`
319
+
320
+ Mulai versi **1.1.3**, modul menyediakan factory function `createDashboardConfig` yang
321
+ mengemas semua konfigurasi (widgetConfig + dataSource + adapter + labels) menjadi
322
+ **1 objek tunggal**. Ini cara yang lebih ringkas dan direkomendasikan untuk domain baru.
323
+
324
+ ```
325
+ Sebelum (4 parameter terpisah ke hook): Sesudah (1 objek terpadu):
326
+
327
+ useReusableDashboard({ const cfg = createDashboardConfig({
328
+ config: tokoSepatuWidgetConfig, widgetConfig: tokoSepatuWidgetConfig,
329
+ dataSource: source, →→→ dataSource: source,
330
+ adapter: adaptTokoSepatuData, adapter: adaptTokoSepatuData,
331
+ createEmptyState: createEmpty, createEmptyState: createEmpty,
332
+ languageCode: "id", languageCode: "id",
333
+ dateLocale: "id-ID", dateLocale: "id-ID",
334
+ labels, });
335
+ }); useReusableDashboard({ ...cfg, labels });
336
+ ```
337
+
338
+ **Contoh penggunaan lengkap:**
339
+
340
+ ```jsx
341
+ import { supabase } from "../lib/supabaseClient";
342
+ import {
343
+ ReusableDashboardView,
344
+ useReusableDashboard,
345
+ createDashboardConfig, // ← factory baru
346
+ tokoSepatuWidgetConfig,
347
+ createTokoSepatuSupabaseSource,
348
+ adaptTokoSepatuData,
349
+ createEmptyTokoSepatuData,
350
+ } from "@rozaqi02/reusable-dashboard";
351
+
352
+ import { myWidgetConfig } from "./myWidgetConfig";
353
+ import { createMySource } from "./myDataSource";
354
+ import { adaptMyData, createEmptyMyData } from "./myAdapter";
355
+
356
+ // Buat di luar komponen — sekali saja
357
+ const dashboardConfig = createDashboardConfig({
358
+ widgetConfig: myWidgetConfig,
359
+ dataSource: createMySource(supabase),
360
+ adapter: adaptMyData,
361
+ createEmptyState: createEmptyMyData,
362
+ languageCode: "id",
363
+ dateLocale: "id-ID",
364
+ // labels bisa disertakan di sini atau di-override saat render
365
+ });
366
+
367
+ const labels = { title: "Dashboard Saya", /* ... */ };
368
+
369
+ export default function MyDashboard() {
370
+ const state = useReusableDashboard({ ...dashboardConfig, labels });
371
+
372
+ return (
373
+ <ReusableDashboardView
374
+ config={dashboardConfig.config}
375
+ labels={labels}
376
+ loading={state.loading}
377
+ error={state.error}
378
+ filters={state.filters}
379
+ onFilterChange={state.updateFilter}
380
+ onResetFilters={state.resetFilters}
381
+ onRefresh={state.refresh}
382
+ data={state.data}
383
+ dateLocale={dashboardConfig.dateLocale}
384
+ liveUpdateEnabled={state.liveUpdateEnabled}
385
+ supabase={supabase} // aktifkan fitur baca tabel di wizard
386
+ dashboardConfig={dashboardConfig} // aktifkan validasi otomatis
387
+ />
388
+ );
389
+ }
390
+ ```
391
+
392
+ **Apa yang terjadi jika config belum lengkap?**
393
+
394
+ `createDashboardConfig` menyimpan info validasi di `dashboardConfig._meta`:
395
+
396
+ ```javascript
397
+ dashboardConfig._meta = {
398
+ isValid: true, // false jika ada bagian yang kurang
399
+ missing: [], // ["adapter", "dataSource"] jika belum diisi
400
+ hasDataSource: true,
401
+ hasRealtimeSupport: true, // false jika subscribeLiveUpdate tidak ada
402
+ hasLabels: true,
403
+ widgetCount: { stats: 4, charts: 4, tableColumns: 6 },
404
+ }
405
+ ```
406
+
407
+ Jika ada bagian yang kurang, `ReusableDashboardView` secara otomatis menampilkan
408
+ **Setup Wizard** (lihat [Bab 11](#11-setup-wizard--panduan-konfigurasi-interaktif)).
409
+
410
+ ---
411
+
316
412
  ## 5. Quick Start — Cidika Travel
317
413
 
318
414
  Ganti hanya 4 baris dari contoh Toko Sepatu di atas:
@@ -1053,6 +1149,20 @@ function Dashboard() {
1053
1149
  | `cidikaWidgetConfig` | Object | Config dashboard Cidika Travel |
1054
1150
  | `tokoSepatuWidgetConfig` | Object | Config dashboard Toko Sepatu |
1055
1151
  | `dummyUmkmWidgetConfig` | Object | Config dashboard UMKM generik |
1152
+ | `createDashboardConfig(options)` | Function | Factory: kemas semua config jadi 1 objek (v1.1.3+) |
1153
+ | `validateDashboardConfig(cfg)` | Function | Validasi config, kembalikan `{ valid, issues }` (v1.1.3+) |
1154
+
1155
+ **`createDashboardConfig(options)` — parameter:**
1156
+
1157
+ | Parameter | Tipe | Wajib | Keterangan |
1158
+ |-----------|------|-------|------------|
1159
+ | `widgetConfig` | Object | ✅ | Konfigurasi widget deklaratif |
1160
+ | `dataSource` | Object | ✅ | Hasil `createXxxSupabaseSource(supabase)` |
1161
+ | `adapter` | Function | ✅ | Fungsi `adaptXxxData` |
1162
+ | `createEmptyState` | Function | ✅ | Fungsi `createEmptyXxxData` |
1163
+ | `labels` | Object | — | Objek label UI (bisa di-override saat render) |
1164
+ | `languageCode` | string | — | Default `"id"` |
1165
+ | `dateLocale` | string | — | Default `"id-ID"` |
1056
1166
 
1057
1167
  ### Data Source
1058
1168
 
@@ -1103,6 +1213,7 @@ state.range // { fromISO, toISO, daysWindow }
1103
1213
  | Komponen | Deskripsi |
1104
1214
  |----------|-----------|
1105
1215
  | `ReusableDashboardView` | Halaman dashboard lengkap — gunakan ini untuk integrasi cepat |
1216
+ | `SetupWizard` | Pop-up wizard panduan konfigurasi interaktif (v1.1.3+) |
1106
1217
  | `StatCard` | Kartu metrik dengan warna aksen |
1107
1218
  | `ChartCard` | Kartu grafik (area/pie/bar) |
1108
1219
  | `DataTable` | Tabel dengan search, sort, pagination |
@@ -1119,6 +1230,24 @@ state.range // { fromISO, toISO, daysWindow }
1119
1230
  | `SidebarNavigation` | Navigasi sidebar |
1120
1231
  | `TopbarHeader` | Header atas |
1121
1232
 
1233
+ **Props `ReusableDashboardView` (lengkap):**
1234
+
1235
+ | Prop | Tipe | Wajib | Keterangan |
1236
+ |------|------|-------|------------|
1237
+ | `config` | Object | ✅ | Widget configuration |
1238
+ | `labels` | Object | ✅ | Objek label UI |
1239
+ | `loading` | boolean | — | Status loading data |
1240
+ | `error` | string | — | Pesan error |
1241
+ | `filters` | Object | — | State filter aktif |
1242
+ | `onFilterChange` | Function | ✅ | `(field, value) => void` |
1243
+ | `onResetFilters` | Function | ✅ | `() => void` |
1244
+ | `onRefresh` | Function | ✅ | `() => void` |
1245
+ | `data` | Object | — | Data `{ stats, charts, table }` |
1246
+ | `dateLocale` | string | — | Default `"id-ID"` |
1247
+ | `liveUpdateEnabled` | boolean | — | Badge "Live" aktif |
1248
+ | `supabase` | Object | — | Supabase client — aktifkan fitur baca tabel di wizard (v1.1.3+) |
1249
+ | `dashboardConfig` | Object | — | Hasil `createDashboardConfig()` — aktifkan validasi otomatis (v1.1.3+) |
1250
+
1122
1251
  ### Utility
1123
1252
 
1124
1253
  | Function | Deskripsi |
@@ -1136,7 +1265,91 @@ state.range // { fromISO, toISO, daysWindow }
1136
1265
 
1137
1266
  ---
1138
1267
 
1139
- ## 11. Pengembangan & Kontribusi
1268
+ ## 11. Setup Wizard — Panduan Konfigurasi Interaktif
1269
+
1270
+ Mulai versi **1.1.3**, modul menyertakan **Setup Wizard**: pop-up panduan interaktif yang
1271
+ muncul **otomatis** saat `ReusableDashboardView` mendeteksi konfigurasi belum lengkap.
1272
+
1273
+ Ini menjawab kebutuhan: *"developer baru yang belum pernah pakai modul ini tahu harus
1274
+ mulai dari mana tanpa harus baca README dari awal."*
1275
+
1276
+ ### Cara kerja
1277
+
1278
+ Wizard aktif ketika salah satu kondisi terpenuhi:
1279
+ - Prop `dashboardConfig` (dari `createDashboardConfig`) punya `_meta.isValid === false`
1280
+ - Prop `config`, `labels`, atau `labels.formatStatusLabel` tidak ditemukan
1281
+
1282
+ Wizard **tidak** muncul jika semua konfigurasi sudah valid.
1283
+
1284
+ ### Fitur wizard
1285
+
1286
+ **Step 0 — Overview:**
1287
+ - Checklist masalah yang ditemukan (mis. `"adapter belum diisi"`)
1288
+ - Diagram alur konfigurasi: Data Source → Adapter → Widget Config
1289
+
1290
+ **Step 1 — Data Source:**
1291
+ - Contoh kode `fetchDashboardSnapshot` yang siap di-copy
1292
+ - Tombol **"Baca tabel Supabase langsung"** — membaca daftar tabel dari project
1293
+ Supabase kamu secara realtime via `information_schema.tables`
1294
+
1295
+ **Step 2 — Adapter:**
1296
+ - Contoh kode `adaptMyData` dengan `buildDayBuckets` + `toNumber`
1297
+ - Penjelasan bahwa key `stats` harus cocok dengan `valueKey` di widget config
1298
+
1299
+ **Step 3 — Widget Config & Rangkaian Akhir:**
1300
+ - Contoh kode lengkap dengan `createDashboardConfig` dari langkah 1–3
1301
+
1302
+ ### Cara mengaktifkan fitur baca tabel Supabase
1303
+
1304
+ Tambahkan prop `supabase` ke `ReusableDashboardView`:
1305
+
1306
+ ```jsx
1307
+ <ReusableDashboardView
1308
+ config={dashboardConfig.config}
1309
+ labels={labels}
1310
+ // ... props lain
1311
+ supabase={supabase} // ← aktifkan fitur baca tabel
1312
+ dashboardConfig={dashboardConfig} // ← aktifkan validasi otomatis
1313
+ />
1314
+ ```
1315
+
1316
+ Saat wizard terbuka di Step 1, pengguna bisa klik tombol untuk melihat
1317
+ daftar tabel yang tersedia di project Supabase mereka:
1318
+
1319
+ ```
1320
+ Tabel ditemukan (4):
1321
+ bookings packages package_locales page_sections
1322
+ ```
1323
+
1324
+ > Fitur ini membutuhkan RLS Supabase mengizinkan `SELECT` pada
1325
+ > `information_schema.tables` untuk role `anon`, atau fallback ke RPC `get_tables`.
1326
+ > Jika tidak bisa diakses, wizard tetap berfungsi — hanya tombol baca tabel yang
1327
+ > menampilkan pesan error.
1328
+
1329
+ ### Menggunakan wizard tanpa `createDashboardConfig`
1330
+
1331
+ Wizard juga bisa dipakai standalone (misalnya saat testing atau demo):
1332
+
1333
+ ```jsx
1334
+ import { SetupWizard } from "@rozaqi02/reusable-dashboard";
1335
+
1336
+ // Tampilkan wizard dengan isu kustom
1337
+ <SetupWizard
1338
+ issues={["Widget config belum diisi", "Data source tidak ditemukan"]}
1339
+ supabase={supabase}
1340
+ onDismiss={() => console.log("wizard ditutup")}
1341
+ />
1342
+ ```
1343
+
1344
+ ### Menutup wizard
1345
+
1346
+ Klik tombol **"Lanjutkan tanpa wizard"** atau **"Tutup & lanjutkan ✓"** di Step 3.
1347
+ Wizard tidak muncul lagi selama sesi berlangsung (state `wizardDismissed` disimpan
1348
+ di level komponen).
1349
+
1350
+ ---
1351
+
1352
+ ## 12. Pengembangan & Kontribusi
1140
1353
 
1141
1354
  ```bash
1142
1355
  # Clone repository