@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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.js","../src/config/cidikaWidgetConfig.js","../src/config/dummyUmkmWidgetConfig.js","../src/config/tokoSepatuWidgetConfig.js","../src/config/createDashboardConfig.js","../src/utils/formatters.js","../src/utils/adapterHelpers.js","../src/data-adapter/cidikaDashboardAdapter.js","../src/data-adapter/dummyUmkmDashboardAdapter.js","../src/data-adapter/tokoSepatuDashboardAdapter.js","../src/data-source/cidikaSupabaseSource.js","../src/data-source/tokoSepatuSupabaseSource.js","../src/hooks/useReusableDashboard.js","../src/utils/dateRange.js","../src/hooks/useRealtimeUpdate.js","../src/presentation/atoms/Button.jsx","../src/presentation/atoms/Input.jsx","../src/presentation/atoms/Icon.jsx","../src/presentation/atoms/Typography.jsx","../src/presentation/atoms/Badge.jsx","../src/presentation/atoms/SkeletonLoader.jsx","../src/presentation/molecules/StatCard.jsx","../src/presentation/molecules/SearchBar.jsx","../src/presentation/molecules/DateRangeFilter.jsx","../src/presentation/molecules/ChartHeader.jsx","../src/presentation/organisms/DataTable.jsx","../src/presentation/organisms/ChartCard.jsx","../src/presentation/organisms/FilterPanel.jsx","../src/presentation/organisms/SidebarNavigation.jsx","../src/presentation/organisms/TopbarHeader.jsx","../src/presentation/templates/DashboardLayout.jsx","../src/presentation/ReusableDashboardView.jsx","../src/presentation/SetupWizard.jsx","../src/utils/labels.js"],"sourcesContent":["// ──────────────────────────────────────────────────────────────────────────────\n// Config\n// ──────────────────────────────────────────────────────────────────────────────\nexport { cidikaWidgetConfig } from \"./config/cidikaWidgetConfig.js\";\nexport { dummyUmkmWidgetConfig } from \"./config/dummyUmkmWidgetConfig.js\";\nexport { tokoSepatuWidgetConfig } from \"./config/tokoSepatuWidgetConfig.js\";\n\n// Factory — mengemas semua konfigurasi menjadi 1 objek tunggal (revisi dosen)\nexport {\n createDashboardConfig,\n validateDashboardConfig,\n} from \"./config/createDashboardConfig.js\";\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Data Adapter\n// ──────────────────────────────────────────────────────────────────────────────\nexport {\n adaptCidikaDashboardData,\n createEmptyDashboardData,\n} from \"./data-adapter/cidikaDashboardAdapter.js\";\nexport {\n adaptDummyUmkmData,\n createEmptyDummyUmkmData,\n} from \"./data-adapter/dummyUmkmDashboardAdapter.js\";\nexport {\n adaptTokoSepatuData,\n createEmptyTokoSepatuData,\n} from \"./data-adapter/tokoSepatuDashboardAdapter.js\";\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Data Source\n// ──────────────────────────────────────────────────────────────────────────────\nexport { createCidikaSupabaseSource } from \"./data-source/cidikaSupabaseSource.js\";\nexport { createTokoSepatuSupabaseSource } from \"./data-source/tokoSepatuSupabaseSource.js\";\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Hook\n// ──────────────────────────────────────────────────────────────────────────────\nexport { useReusableDashboard } from \"./hooks/useReusableDashboard.js\";\nexport { useRealtimeUpdate } from \"./hooks/useRealtimeUpdate.js\";\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Presentation — Atoms\n// ──────────────────────────────────────────────────────────────────────────────\nexport { default as Button } from \"./presentation/atoms/Button.jsx\";\nexport { default as Input } from \"./presentation/atoms/Input.jsx\";\nexport { default as Icon, resolveIcon } from \"./presentation/atoms/Icon.jsx\";\nexport { default as Typography } from \"./presentation/atoms/Typography.jsx\";\nexport { default as Badge } from \"./presentation/atoms/Badge.jsx\";\nexport { default as SkeletonLoader } from \"./presentation/atoms/SkeletonLoader.jsx\";\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Presentation — Molecules\n// ──────────────────────────────────────────────────────────────────────────────\nexport { default as StatCard } from \"./presentation/molecules/StatCard.jsx\";\nexport { default as SearchBar } from \"./presentation/molecules/SearchBar.jsx\";\nexport { default as DateRangeFilter } from \"./presentation/molecules/DateRangeFilter.jsx\";\nexport { default as ChartHeader } from \"./presentation/molecules/ChartHeader.jsx\";\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Presentation — Organisms\n// ──────────────────────────────────────────────────────────────────────────────\nexport { default as DataTable } from \"./presentation/organisms/DataTable.jsx\";\nexport { default as ChartCard } from \"./presentation/organisms/ChartCard.jsx\";\nexport { default as FilterPanel } from \"./presentation/organisms/FilterPanel.jsx\";\nexport { default as SidebarNavigation } from \"./presentation/organisms/SidebarNavigation.jsx\";\nexport { default as TopbarHeader } from \"./presentation/organisms/TopbarHeader.jsx\";\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Presentation — Templates\n// ──────────────────────────────────────────────────────────────────────────────\nexport { default as DashboardLayout } from \"./presentation/templates/DashboardLayout.jsx\";\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Presentation — Page-Level View\n// ──────────────────────────────────────────────────────────────────────────────\nexport { ReusableDashboardView } from \"./presentation/ReusableDashboardView.jsx\";\n\n// Setup Wizard — pop-up panduan konfigurasi (revisi dosen Opsi B)\nexport { SetupWizard } from \"./presentation/SetupWizard.jsx\";\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Utils\n// ──────────────────────────────────────────────────────────────────────────────\nexport { createDashboardLabels } from \"./utils/labels.js\";\nexport {\n createDefaultFilters,\n formatYYYYMMDD,\n resolveDateRange,\n} from \"./utils/dateRange.js\";\nexport { formatDate, formatIDR, shortId } from \"./utils/formatters.js\";\nexport {\n toNumber,\n buildDayBuckets,\n sortMapEntries,\n} from \"./utils/adapterHelpers.js\";\n\n","export const cidikaWidgetConfig = {\n id: \"cidika.travel.dashboard\",\n defaultFilters: {\n statusScope: \"confirmed\",\n includePendingOverlay: false,\n audience: \"\",\n daysPreset: 30,\n sortPkgBy: \"bookings\",\n sortPkgDir: \"desc\",\n },\n widgets: {\n stats: [\n {\n id: \"bookingsConfirm\",\n label: \"confirmedBookings\",\n icon: \"TrendingUp\",\n valueKey: \"bookingsConfirm\",\n format: \"number\",\n accentColor: \"blue\",\n },\n {\n id: \"revenueConfirm\",\n label: \"confirmedRevenue\",\n icon: \"DollarSign\",\n valueKey: \"revenueConfirm\",\n format: \"currency\",\n accentColor: \"green\",\n },\n {\n id: \"avgRevenue\",\n label: \"avgRevenue\",\n icon: \"Users\",\n valueKey: \"avgRevenue\",\n format: \"currency\",\n accentColor: \"violet\",\n },\n {\n id: \"conversionRate\",\n label: \"conversionRate\",\n icon: \"PieChart\",\n valueKey: \"conversionRate\",\n format: \"percent\",\n accentColor: \"orange\",\n },\n ],\n charts: [\n {\n id: \"dailyTrends\",\n type: \"dailyArea\",\n label: \"dailyTrends\",\n icon: \"BarChart3\",\n },\n {\n id: \"statusDistribution\",\n type: \"statusPie\",\n label: \"statusDistribution\",\n icon: \"PieChart\",\n },\n {\n id: \"audienceDistribution\",\n type: \"audiencePie\",\n label: \"audienceDistribution\",\n icon: \"Users\",\n },\n {\n id: \"topPackages\",\n type: \"topPackagesBar\",\n label: \"topPackages\",\n icon: \"TrendingUp\",\n },\n ],\n table: {\n id: \"recentBookings\",\n label: \"recentBookings\",\n icon: \"Calendar\",\n emptyLabel: \"noRecentBookings\",\n columns: [\n { id: \"date\", label: \"date\", accessor: \"createdAt\", type: \"date\" },\n { id: \"customer\", label: \"customer\", accessor: \"customerName\" },\n { id: \"package\", label: \"package\", accessor: \"packageName\" },\n { id: \"audience\", label: \"audience\", accessor: \"audienceLabel\" },\n { id: \"total\", label: \"total\", accessor: \"totalIDR\", type: \"currency\" },\n {\n id: \"status\",\n label: \"status\",\n accessor: \"statusLabel\",\n type: \"statusBadge\",\n statusAccessor: \"status\",\n },\n ],\n },\n },\n};\n","export const dummyUmkmWidgetConfig = {\n id: \"dummy.umkm.dashboard\",\n defaultFilters: {\n statusScope: \"all\",\n includePendingOverlay: false,\n audience: \"\",\n daysPreset: 30,\n sortPkgBy: \"revenue\",\n sortPkgDir: \"desc\",\n },\n widgets: {\n stats: [\n {\n id: \"orders\",\n label: \"confirmedBookings\",\n icon: \"TrendingUp\",\n valueKey: \"bookingsConfirm\",\n format: \"number\",\n },\n {\n id: \"revenue\",\n label: \"confirmedRevenue\",\n icon: \"DollarSign\",\n valueKey: \"revenueConfirm\",\n format: \"currency\",\n },\n ],\n charts: [\n {\n id: \"revenueTrend\",\n type: \"dailyArea\",\n label: \"dailyTrends\",\n icon: \"BarChart3\",\n },\n {\n id: \"recentOrderStatus\",\n type: \"statusPie\",\n label: \"statusDistribution\",\n icon: \"PieChart\",\n },\n ],\n table: {\n id: \"recentOrders\",\n label: \"recentBookings\",\n icon: \"Calendar\",\n emptyLabel: \"noRecentBookings\",\n columns: [\n { id: \"date\", label: \"date\", accessor: \"createdAt\", type: \"date\" },\n { id: \"customer\", label: \"customer\", accessor: \"customerName\" },\n { id: \"total\", label: \"total\", accessor: \"totalIDR\", type: \"currency\" },\n ],\n },\n },\n};\n","/**\r\n * Widget Configuration — Toko Sepatu Online (Studi Kasus Dummy UMKM Non-Travel)\r\n *\r\n * Konfigurasi ini membuktikan bahwa modul reusable dashboard dapat digunakan\r\n * pada domain bisnis yang berbeda (retail sepatu) hanya dengan mendefinisikan\r\n * konfigurasi baru tanpa mengubah komponen inti.\r\n *\r\n * Perbedaan dengan cidikaWidgetConfig:\r\n * - 4 stat cards (orders, revenue, avg order, products)\r\n * - 2 charts (daily trends, status distribution)\r\n * - 1 tabel (recent orders) dengan 5 kolom\r\n * - Filter lebih sederhana (tanpa audience, tanpa pending overlay)\r\n */\r\nexport const tokoSepatuWidgetConfig = {\r\n id: \"toko.sepatu.dashboard\",\r\n defaultFilters: {\r\n statusScope: \"all\",\r\n includePendingOverlay: false,\r\n audience: \"\",\r\n daysPreset: 30,\r\n sortPkgBy: \"revenue\",\r\n sortPkgDir: \"desc\",\r\n },\r\n widgets: {\r\n stats: [\r\n {\r\n id: \"totalOrders\",\r\n label: \"confirmedBookings\",\r\n icon: \"TrendingUp\",\r\n valueKey: \"bookingsConfirm\",\r\n format: \"number\",\r\n accentColor: \"sky\",\r\n },\r\n {\r\n id: \"totalRevenue\",\r\n label: \"confirmedRevenue\",\r\n icon: \"DollarSign\",\r\n valueKey: \"revenueConfirm\",\r\n format: \"currency\",\r\n accentColor: \"green\",\r\n },\r\n {\r\n id: \"avgOrderValue\",\r\n label: \"avgRevenue\",\r\n icon: \"BarChart3\",\r\n valueKey: \"avgRevenue\",\r\n format: \"currency\",\r\n accentColor: \"violet\",\r\n },\r\n {\r\n id: \"totalProducts\",\r\n label: \"totalProducts\",\r\n icon: \"PieChart\",\r\n valueKey: \"packages\",\r\n format: \"number\",\r\n accentColor: \"orange\",\r\n },\r\n ],\r\n charts: [\r\n {\r\n id: \"dailyOrderTrends\",\r\n type: \"dailyArea\",\r\n label: \"dailyTrends\",\r\n icon: \"BarChart3\",\r\n },\r\n {\r\n id: \"orderStatusDistribution\",\r\n type: \"statusPie\",\r\n label: \"statusDistribution\",\r\n icon: \"PieChart\",\r\n },\r\n {\r\n id: \"topProducts\",\r\n type: \"topPackagesBar\",\r\n label: \"topPackages\",\r\n icon: \"TrendingUp\",\r\n },\r\n ],\r\n table: {\r\n id: \"recentOrders\",\r\n label: \"recentBookings\",\r\n icon: \"Calendar\",\r\n emptyLabel: \"noRecentBookings\",\r\n columns: [\r\n { id: \"date\", label: \"date\", accessor: \"createdAt\", type: \"date\" },\r\n { id: \"customer\", label: \"customer\", accessor: \"customerName\" },\r\n { id: \"product\", label: \"package\", accessor: \"packageName\" },\r\n { id: \"total\", label: \"total\", accessor: \"totalIDR\", type: \"currency\" },\r\n {\r\n id: \"status\",\r\n label: \"status\",\r\n accessor: \"statusLabel\",\r\n type: \"statusBadge\",\r\n statusAccessor: \"status\",\r\n },\r\n ],\r\n },\r\n },\r\n};\r\n","/**\r\n * createDashboardConfig — Factory function untuk mengemas semua konfigurasi\r\n * dashboard dalam satu objek tunggal.\r\n *\r\n * Sebelum adanya factory ini, developer harus menyiapkan 3 file terpisah\r\n * (widgetConfig, adapter, dataSource) dan mengimpornya satu per satu ke hook.\r\n * Dengan factory ini cukup 1 objek yang diserahkan ke useReusableDashboard.\r\n *\r\n * @param {object} options\r\n * @param {object} options.widgetConfig - Konfigurasi widget deklaratif.\r\n * @param {object} options.dataSource - Objek data source (fetchDashboardSnapshot, subscribeLiveUpdate).\r\n * @param {Function} options.adapter - Fungsi adapter pure function.\r\n * @param {Function} options.createEmptyState - Fungsi pembuat state kosong.\r\n * @param {object} [options.labels] - Objek label UI (opsional, bisa di-override di komponen).\r\n * @param {string} [options.languageCode=\"id\"] - Kode bahasa (id / en).\r\n * @param {string} [options.dateLocale=\"id-ID\"] - Locale format tanggal.\r\n *\r\n * @returns {object} Objek config terpadu yang siap dipakai useReusableDashboard.\r\n *\r\n * @example\r\n * // Sebelum (3 import terpisah):\r\n * const source = createCidikaSupabaseSource(supabase);\r\n * useReusableDashboard({ config: cidikaWidgetConfig, dataSource: source,\r\n * adapter: adaptCidikaDashboardData, createEmptyState: createEmptyDashboardData, ... })\r\n *\r\n * // Sesudah (1 file config):\r\n * const dashboardConfig = createDashboardConfig({\r\n * widgetConfig: cidikaWidgetConfig,\r\n * dataSource: createCidikaSupabaseSource(supabase),\r\n * adapter: adaptCidikaDashboardData,\r\n * createEmptyState: createEmptyDashboardData,\r\n * });\r\n * useReusableDashboard(dashboardConfig)\r\n */\r\nexport function createDashboardConfig({\r\n widgetConfig,\r\n dataSource,\r\n adapter,\r\n createEmptyState,\r\n labels,\r\n languageCode = \"id\",\r\n dateLocale = \"id-ID\",\r\n}) {\r\n // Validasi minimal — membantu developer yang lupa mengisi bagian penting\r\n const missing = [];\r\n if (!widgetConfig) missing.push(\"widgetConfig\");\r\n if (!dataSource) missing.push(\"dataSource\");\r\n if (!adapter) missing.push(\"adapter\");\r\n if (!createEmptyState) missing.push(\"createEmptyState\");\r\n\r\n return {\r\n // Properti yang langsung dibaca useReusableDashboard\r\n config: widgetConfig,\r\n dataSource,\r\n adapter,\r\n createEmptyState,\r\n languageCode,\r\n dateLocale,\r\n labels,\r\n\r\n // Metadata untuk setup wizard & validasi\r\n _meta: {\r\n isValid: missing.length === 0,\r\n missing,\r\n hasDataSource: Boolean(dataSource?.fetchDashboardSnapshot),\r\n hasRealtimeSupport: Boolean(dataSource?.subscribeLiveUpdate),\r\n hasLabels: Boolean(labels),\r\n widgetCount: {\r\n stats: widgetConfig?.widgets?.stats?.length ?? 0,\r\n charts: widgetConfig?.widgets?.charts?.length ?? 0,\r\n tableColumns: widgetConfig?.widgets?.table?.columns?.length ?? 0,\r\n },\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Memvalidasi apakah sebuah dashboardConfig sudah lengkap dan siap dipakai.\r\n * Digunakan oleh SetupWizard untuk menentukan apakah perlu menampilkan panduan.\r\n *\r\n * @param {object} dashboardConfig - Hasil dari createDashboardConfig.\r\n * @returns {{ valid: boolean, issues: string[] }}\r\n */\r\nexport function validateDashboardConfig(dashboardConfig) {\r\n const issues = [];\r\n\r\n if (!dashboardConfig) {\r\n return { valid: false, issues: [\"dashboardConfig tidak ditemukan. Pastikan sudah memanggil createDashboardConfig().\"] };\r\n }\r\n\r\n const meta = dashboardConfig?._meta;\r\n\r\n if (!meta) {\r\n issues.push(\"Config tidak dibuat melalui createDashboardConfig(). Gunakan factory function ini untuk validasi otomatis.\");\r\n } else {\r\n if (meta.missing.length > 0) {\r\n meta.missing.forEach(m => issues.push(`Properti wajib belum diisi: \"${m}\"`));\r\n }\r\n if (!meta.hasDataSource) {\r\n issues.push(\"dataSource.fetchDashboardSnapshot() tidak ditemukan. Pastikan sudah membuat data source yang benar.\");\r\n }\r\n }\r\n\r\n if (!dashboardConfig.config?.widgets?.stats?.length) {\r\n issues.push(\"widgetConfig.widgets.stats kosong. Tambahkan minimal 1 stat card.\");\r\n }\r\n if (!dashboardConfig.config?.widgets?.charts?.length) {\r\n issues.push(\"widgetConfig.widgets.charts kosong. Tambahkan minimal 1 chart.\");\r\n }\r\n if (!dashboardConfig.config?.widgets?.table?.columns?.length) {\r\n issues.push(\"widgetConfig.widgets.table.columns kosong. Tambahkan minimal 1 kolom tabel.\");\r\n }\r\n if (!dashboardConfig.labels) {\r\n issues.push(\"labels belum diisi. Sediakan objek labels agar teks UI tampil dengan benar.\");\r\n }\r\n\r\n return { valid: issues.length === 0, issues };\r\n}\r\n","export function formatIDR(value) {\n try {\n return (Number(value) || 0).toLocaleString(\"id-ID\");\n } catch (_error) {\n return String(value ?? 0);\n }\n}\n\nexport function shortId(value, length = 8) {\n if (!value) return \"-\";\n return String(value).slice(0, length);\n}\n\nexport function formatDate(value, locale) {\n if (!value) return \"-\";\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return \"-\";\n return date.toLocaleDateString(locale);\n}\n","/**\n * adapterHelpers — Fungsi utilitas bersama yang digunakan oleh semua data-adapter.\n * Diekstrak dari adapter individu untuk menghindari duplikasi kode (prinsip DRY).\n */\n\n/**\n * Mengkonversi nilai apapun ke angka yang valid.\n * Mengembalikan 0 jika nilai tidak valid atau bukan angka finite.\n *\n * @param {*} value - Nilai yang akan dikonversi.\n * @returns {number} Angka finite, atau 0 jika tidak valid.\n */\nexport function toNumber(value) {\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : 0;\n}\n\n/**\n * Membangun array bucket harian untuk chart tren.\n * Setiap bucket berisi dateKey, label terformat, dan counter awal (0).\n *\n * @param {number} daysWindow - Jumlah hari dalam rentang.\n * @param {string} fromISO - Tanggal awal dalam format ISO.\n * @param {string} dateLocale - Locale untuk format tanggal (misal: \"id-ID\").\n * @returns {Array<{dateKey: string, label: string, count: number, revenue: number, pendingCount: number}>}\n */\nexport function buildDayBuckets(daysWindow, fromISO, dateLocale) {\n const start = new Date(fromISO);\n return Array.from({ length: daysWindow }).map((_, index) => {\n const day = new Date(start);\n day.setDate(start.getDate() + index);\n return {\n dateKey: day.toISOString().slice(0, 10),\n label: day.toLocaleDateString(dateLocale, {\n day: \"2-digit\",\n month: \"short\",\n }),\n count: 0,\n revenue: 0,\n pendingCount: 0,\n };\n });\n}\n\n/**\n * Mengurutkan entri Map berdasarkan nilai numerik.\n *\n * @param {Map} map - Map yang akan diurutkan.\n * @param {\"asc\"|\"desc\"} direction - Arah pengurutan.\n * @returns {Array<[string, number]>} Array entri terurut.\n */\nexport function sortMapEntries(map, direction) {\n return Array.from(map.entries()).sort((a, b) =>\n direction === \"asc\" ? a[1] - b[1] : b[1] - a[1]\n );\n}\n","import { shortId } from \"../utils/formatters.js\";\nimport { toNumber, buildDayBuckets, sortMapEntries } from \"../utils/adapterHelpers.js\";\n\nfunction createPackageTitleResolver(packageLocales, languageCode) {\n const byPackage = new Map();\n\n packageLocales.forEach((row) => {\n if (!row.package_id) return;\n const current = byPackage.get(row.package_id) || {};\n byPackage.set(row.package_id, {\n ...current,\n [row.lang]: row.title,\n });\n });\n\n return (packageId) => {\n if (!packageId) return \"-\";\n const labels = byPackage.get(packageId);\n if (!labels) return shortId(packageId, 6);\n return (\n labels[languageCode] ||\n labels.en ||\n labels.id ||\n Object.values(labels).find(Boolean) ||\n shortId(packageId, 6)\n );\n };\n}\n\nexport function createEmptyDashboardData() {\n return {\n stats: {\n bookingsConfirm: 0,\n bookingsPending: 0,\n revenueConfirm: 0,\n packages: 0,\n sections: 0,\n avgRevenue: 0,\n conversionRate: 0,\n },\n charts: {\n dailyTrends: [],\n statusDistribution: [],\n audienceDistribution: [],\n topPackages: [],\n },\n table: {\n recentBookings: [],\n },\n };\n}\n\nexport function adaptCidikaDashboardData({\n raw,\n filters,\n range,\n dateLocale,\n languageCode,\n labels,\n}) {\n if (!raw) return createEmptyDashboardData();\n\n const dailyBuckets = buildDayBuckets(range.daysWindow, range.fromISO, dateLocale);\n const dayLookup = new Map(\n dailyBuckets.map((bucket) => [bucket.dateKey, bucket])\n );\n\n const statusMap = new Map();\n const audienceMap = new Map();\n const packageCountMap = new Map();\n const packageRevenueMap = new Map();\n const getPackageTitle = createPackageTitleResolver(\n raw.packageLocales || [],\n languageCode\n );\n\n let bookingsConfirm = 0;\n let bookingsPending = 0;\n let revenueConfirm = 0;\n\n (raw.bookings || []).forEach((row) => {\n const dayKey = String(row.created_at || \"\").slice(0, 10);\n const status = String(row.status || \"pending\").toLowerCase();\n const total = toNumber(row.total_idr);\n const audience = row.audience || \"unknown\";\n\n statusMap.set(status, (statusMap.get(status) || 0) + 1);\n audienceMap.set(audience, (audienceMap.get(audience) || 0) + 1);\n\n const bucket = dayLookup.get(dayKey);\n if (bucket) {\n if (status === \"confirmed\") {\n bucket.count += 1;\n bucket.revenue += total;\n }\n if (status === \"pending\") {\n bucket.pendingCount += 1;\n }\n }\n\n if (status === \"confirmed\") {\n bookingsConfirm += 1;\n revenueConfirm += total;\n packageCountMap.set(\n row.package_id,\n (packageCountMap.get(row.package_id) || 0) + 1\n );\n packageRevenueMap.set(\n row.package_id,\n (packageRevenueMap.get(row.package_id) || 0) + total\n );\n } else if (status === \"pending\") {\n bookingsPending += 1;\n }\n });\n\n const statusDistribution = sortMapEntries(statusMap, \"desc\").map(\n ([status, count]) => ({\n status,\n label: labels.formatStatusLabel(status),\n count,\n })\n );\n\n const audienceDistribution = sortMapEntries(audienceMap, \"desc\").map(\n ([audience, count]) => ({\n audience,\n label: labels.formatAudienceLabel(audience),\n count,\n })\n );\n\n const metricMap =\n filters.sortPkgBy === \"revenue\" ? packageRevenueMap : packageCountMap;\n\n const topPackages = sortMapEntries(metricMap, filters.sortPkgDir)\n .slice(0, 5)\n .map(([packageId, value]) => ({\n packageId,\n name: getPackageTitle(packageId),\n value: toNumber(value),\n }));\n\n const recentBookings = (raw.recent || []).map((row) => {\n const status = String(row.status || \"pending\").toLowerCase();\n return {\n id: row.id,\n createdAt: row.created_at,\n customerName: row.customer_name || \"-\",\n packageName: getPackageTitle(row.package_id),\n audienceLabel: labels.formatAudienceLabel(row.audience),\n totalIDR: toNumber(row.total_idr),\n status,\n statusLabel: labels.formatStatusLabel(status),\n };\n });\n\n const avgRevenue =\n bookingsConfirm > 0 ? Math.round(revenueConfirm / bookingsConfirm) : 0;\n const conversionRate =\n bookingsConfirm + bookingsPending > 0\n ? Math.round((bookingsConfirm / (bookingsConfirm + bookingsPending)) * 100)\n : 0;\n\n return {\n stats: {\n bookingsConfirm,\n bookingsPending,\n revenueConfirm,\n packages: toNumber(raw.staticCounts?.packages),\n sections: toNumber(raw.staticCounts?.sections),\n avgRevenue,\n conversionRate,\n },\n charts: {\n dailyTrends: dailyBuckets,\n statusDistribution,\n audienceDistribution,\n topPackages,\n },\n table: {\n recentBookings,\n },\n };\n}\n","/**\n * dummyUmkmDashboardAdapter — Data-adapter layer untuk studi kasus\n * aplikasi dummy UMKM non-travel (penjualan produk).\n *\n * Adapter ini membuktikan bahwa modul reusable dashboard dapat digunakan\n * pada domain bisnis yang berbeda dari Cidika Travel hanya dengan\n * mengganti adapter, tanpa mengubah komponen inti.\n *\n * Struktur data Supabase dummy UMKM yang diharapkan:\n * - Tabel `orders` : id, created_at, total_amount, status, customer_name, product_id\n * - Tabel `products` : id, name\n * - Tabel `customers`: id, name\n */\n\nimport { toNumber, buildDayBuckets } from \"../utils/adapterHelpers.js\";\n\n/**\n * Membuat state kosong yang sesuai dengan kontrak data dummy UMKM.\n * Dipanggil oleh useReusableDashboard sebagai initial state dan saat error.\n *\n * @returns {object} Empty dashboard data object.\n */\nexport function createEmptyDummyUmkmData() {\n return {\n stats: {\n bookingsConfirm: 0,\n revenueConfirm: 0,\n totalProducts: 0,\n totalCustomers: 0,\n },\n charts: {\n dailyTrends: [],\n statusDistribution: [],\n audienceDistribution: [],\n topPackages: [],\n },\n table: {\n recentBookings: [],\n },\n };\n}\n\n/**\n * Memetakan data mentah dari Supabase dummy UMKM ke format standar widget.\n *\n * Format `raw` yang diharapkan dari dataSource:\n * ```\n * {\n * bookings: Array<{ id, created_at, total_amount, status, customer_name, product_id }>,\n * recent: Array<{ id, created_at, customer_name, total_amount, status, product_id }>,\n * staticCounts: { packages: number, sections: number } // opsional\n * }\n * ```\n *\n * @param {object} params\n * @param {object} params.raw - Data mentah dari dataSource.\n * @param {object} params.filters - State filter aktif.\n * @param {object} params.range - Rentang tanggal { fromISO, toISO, daysWindow }.\n * @param {string} params.dateLocale - Locale untuk format tanggal (misal: \"id-ID\").\n * @param {object} [params.labels] - Label i18n (opsional, untuk format status).\n * @returns {object} Objek data standar { stats, charts, table }.\n */\nexport function adaptDummyUmkmData({ raw, filters, range, dateLocale, labels }) {\n if (!raw) return createEmptyDummyUmkmData();\n\n const orders = raw.bookings || [];\n const recent = raw.recent || [];\n\n // Bangun bucket harian untuk chart tren\n const dailyBuckets = buildDayBuckets(range.daysWindow, range.fromISO, dateLocale);\n const dayLookup = new Map(dailyBuckets.map((b) => [b.dateKey, b]));\n\n const statusMap = new Map();\n let totalOrders = 0;\n let totalRevenue = 0;\n\n orders.forEach((row) => {\n const dayKey = String(row.created_at || \"\").slice(0, 10);\n const status = String(row.status || \"pending\").toLowerCase();\n const amount = toNumber(row.total_amount);\n\n statusMap.set(status, (statusMap.get(status) || 0) + 1);\n\n const bucket = dayLookup.get(dayKey);\n if (bucket) {\n if (status === \"confirmed\") {\n bucket.count += 1;\n bucket.revenue += amount;\n }\n if (status === \"pending\") {\n bucket.pendingCount += 1;\n }\n }\n\n if (status === \"confirmed\") {\n totalOrders += 1;\n totalRevenue += amount;\n }\n });\n\n // Distribusi status untuk pie chart\n const statusDistribution = Array.from(statusMap.entries())\n .sort((a, b) => b[1] - a[1])\n .map(([status, count]) => ({\n status,\n label: labels?.formatStatusLabel ? labels.formatStatusLabel(status) : status,\n count,\n }));\n\n // Tabel recent orders — field mapping ke kontrak standar\n const recentBookings = recent.map((row) => {\n const status = String(row.status || \"pending\").toLowerCase();\n return {\n id: row.id,\n createdAt: row.created_at,\n customerName: row.customer_name || \"-\",\n packageName: row.product_name || row.product_id || \"-\",\n totalIDR: toNumber(row.total_amount),\n status,\n statusLabel: labels?.formatStatusLabel ? labels.formatStatusLabel(status) : status,\n };\n });\n\n return {\n stats: {\n bookingsConfirm: totalOrders,\n revenueConfirm: totalRevenue,\n totalProducts: toNumber(raw.staticCounts?.packages),\n totalCustomers: toNumber(raw.staticCounts?.sections),\n },\n charts: {\n dailyTrends: dailyBuckets,\n statusDistribution,\n audienceDistribution: [],\n topPackages: [],\n },\n table: {\n recentBookings,\n },\n };\n}\n","/**\r\n * tokoSepatuDashboardAdapter — Data-adapter layer untuk studi kasus\r\n * Toko Sepatu Online (domain retail/e-commerce).\r\n *\r\n * Adapter ini membuktikan bahwa modul reusable dashboard dapat digunakan\r\n * pada domain bisnis yang berbeda dari Cidika Travel hanya dengan\r\n * mengganti adapter, tanpa mengubah komponen inti.\r\n *\r\n * Struktur data Supabase Toko Sepatu yang diharapkan:\r\n * - Tabel `orders` : id, created_at, total_amount, status, customer_id\r\n * - Tabel `products` : id, name, brand, category, price_idr, stock\r\n * - Tabel `customers` : id, name, email, phone, city\r\n * - Tabel `order_items` : id, order_id, product_id, qty, price_idr, subtotal\r\n */\r\n\r\nimport { shortId } from \"../utils/formatters.js\";\r\nimport { toNumber, buildDayBuckets, sortMapEntries } from \"../utils/adapterHelpers.js\";\r\n\r\n/**\r\n * Membuat state kosong yang sesuai dengan kontrak data toko sepatu.\r\n * @returns {object} Empty dashboard data object.\r\n */\r\nexport function createEmptyTokoSepatuData() {\r\n return {\r\n stats: {\r\n bookingsConfirm: 0,\r\n bookingsPending: 0,\r\n revenueConfirm: 0,\r\n packages: 0,\r\n sections: 0,\r\n avgRevenue: 0,\r\n conversionRate: 0,\r\n },\r\n charts: {\r\n dailyTrends: [],\r\n statusDistribution: [],\r\n audienceDistribution: [],\r\n topPackages: [],\r\n },\r\n table: {\r\n recentBookings: [],\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Memetakan data mentah dari Supabase Toko Sepatu ke format standar widget.\r\n *\r\n * @param {object} params\r\n * @param {object} params.raw - Data mentah dari dataSource.\r\n * @param {object} params.filters - State filter aktif.\r\n * @param {object} params.range - Rentang tanggal { fromISO, toISO, daysWindow }.\r\n * @param {string} params.dateLocale - Locale untuk format tanggal.\r\n * @param {object} [params.labels] - Label i18n.\r\n * @returns {object} Objek data standar { stats, charts, table }.\r\n */\r\nexport function adaptTokoSepatuData({ raw, filters, range, dateLocale, labels }) {\r\n if (!raw) return createEmptyTokoSepatuData();\r\n\r\n const orders = raw.bookings || [];\r\n const recent = raw.recent || [];\r\n\r\n // Bangun bucket harian untuk chart tren\r\n const dailyBuckets = buildDayBuckets(range.daysWindow, range.fromISO, dateLocale);\r\n const dayLookup = new Map(dailyBuckets.map((b) => [b.dateKey, b]));\r\n\r\n const statusMap = new Map();\r\n const productCountMap = new Map();\r\n const productRevenueMap = new Map();\r\n\r\n let ordersConfirm = 0;\r\n let ordersPending = 0;\r\n let revenueConfirm = 0;\r\n\r\n // Buat lookup nama produk\r\n const productNameMap = new Map();\r\n (raw.products || []).forEach((p) => {\r\n productNameMap.set(p.id, p.name);\r\n });\r\n\r\n orders.forEach((row) => {\r\n const dayKey = String(row.created_at || \"\").slice(0, 10);\r\n const status = String(row.status || \"pending\").toLowerCase();\r\n const total = toNumber(row.total_amount);\r\n\r\n statusMap.set(status, (statusMap.get(status) || 0) + 1);\r\n\r\n const bucket = dayLookup.get(dayKey);\r\n if (bucket) {\r\n if (status === \"confirmed\") {\r\n bucket.count += 1;\r\n bucket.revenue += total;\r\n }\r\n if (status === \"pending\") {\r\n bucket.pendingCount += 1;\r\n }\r\n }\r\n\r\n if (status === \"confirmed\") {\r\n ordersConfirm += 1;\r\n revenueConfirm += total;\r\n\r\n // Hitung produk terlaris dari order_items\r\n const items = row.order_items || [];\r\n items.forEach((item) => {\r\n const pid = item.product_id;\r\n productCountMap.set(pid, (productCountMap.get(pid) || 0) + toNumber(item.qty));\r\n productRevenueMap.set(pid, (productRevenueMap.get(pid) || 0) + toNumber(item.subtotal));\r\n });\r\n } else if (status === \"pending\") {\r\n ordersPending += 1;\r\n }\r\n });\r\n\r\n // Distribusi status\r\n const statusDistribution = sortMapEntries(statusMap, \"desc\").map(\r\n ([status, count]) => ({\r\n status,\r\n label: labels?.formatStatusLabel ? labels.formatStatusLabel(status) : status,\r\n count,\r\n })\r\n );\r\n\r\n // Top products\r\n const metricMap =\r\n filters.sortPkgBy === \"revenue\" ? productRevenueMap : productCountMap;\r\n\r\n const topPackages = sortMapEntries(metricMap, filters.sortPkgDir || \"desc\")\r\n .slice(0, 5)\r\n .map(([productId, value]) => ({\r\n packageId: productId,\r\n name: productNameMap.get(productId) || shortId(productId, 6),\r\n value: toNumber(value),\r\n }));\r\n\r\n // Tabel recent orders\r\n const recentBookings = recent.map((row) => {\r\n const status = String(row.status || \"pending\").toLowerCase();\r\n // Ambil nama produk dari item pertama atau dari join\r\n const productName =\r\n row.product_name ||\r\n (row.order_items && row.order_items[0]\r\n ? productNameMap.get(row.order_items[0].product_id)\r\n : null) ||\r\n \"-\";\r\n\r\n return {\r\n id: row.id,\r\n createdAt: row.created_at,\r\n customerName: row.customer_name || \"-\",\r\n packageName: productName,\r\n totalIDR: toNumber(row.total_amount),\r\n status,\r\n statusLabel: labels?.formatStatusLabel ? labels.formatStatusLabel(status) : status,\r\n };\r\n });\r\n\r\n const avgRevenue =\r\n ordersConfirm > 0 ? Math.round(revenueConfirm / ordersConfirm) : 0;\r\n const conversionRate =\r\n ordersConfirm + ordersPending > 0\r\n ? Math.round((ordersConfirm / (ordersConfirm + ordersPending)) * 100)\r\n : 0;\r\n\r\n return {\r\n stats: {\r\n bookingsConfirm: ordersConfirm,\r\n bookingsPending: ordersPending,\r\n revenueConfirm,\r\n packages: toNumber(raw.staticCounts?.products),\r\n sections: toNumber(raw.staticCounts?.customers),\r\n avgRevenue,\r\n conversionRate,\r\n },\r\n charts: {\r\n dailyTrends: dailyBuckets,\r\n statusDistribution,\r\n audienceDistribution: [],\r\n topPackages,\r\n },\r\n table: {\r\n recentBookings,\r\n },\r\n };\r\n}\r\n","function ensureNoError(response, message) {\n if (response?.error) {\n const err = new Error(message);\n err.cause = response.error;\n throw err;\n }\n}\n\nexport function createCidikaSupabaseSource(supabase) {\n return {\n async fetchDashboardSnapshot({\n fromISO,\n toISO,\n audience,\n statusScope,\n languageCode,\n }) {\n const bookingsQuery = supabase\n .from(\"bookings\")\n .select(\n \"id, created_at, total_idr, status, package_id, audience, customer_name\"\n )\n .gte(\"created_at\", fromISO)\n .lte(\"created_at\", toISO)\n .order(\"created_at\", { ascending: true });\n\n if (audience) bookingsQuery.eq(\"audience\", audience);\n\n const recentQuery = supabase\n .from(\"bookings\")\n .select(\n \"id, created_at, customer_name, total_idr, status, package_id, audience\"\n )\n .gte(\"created_at\", fromISO)\n .lte(\"created_at\", toISO)\n .order(\"created_at\", { ascending: false })\n .limit(10);\n\n if (audience) recentQuery.eq(\"audience\", audience);\n if (statusScope && statusScope !== \"all\") {\n recentQuery.eq(\"status\", statusScope);\n }\n\n const [bookingsRes, recentRes, packagesRes, sectionsRes] = await Promise.all(\n [\n bookingsQuery,\n recentQuery,\n supabase.from(\"packages\").select(\"*\", { count: \"exact\", head: true }),\n supabase\n .from(\"page_sections\")\n .select(\"*\", { count: \"exact\", head: true }),\n ]\n );\n\n ensureNoError(bookingsRes, \"Failed to load booking rows.\");\n ensureNoError(recentRes, \"Failed to load recent rows.\");\n\n const bookings = bookingsRes.data || [];\n const recent = recentRes.data || [];\n\n const packageIds = Array.from(\n new Set(\n [...bookings, ...recent]\n .map((row) => row.package_id)\n .filter((value) => Boolean(value))\n )\n );\n\n let packageLocales = [];\n if (packageIds.length > 0) {\n const localeRes = await supabase\n .from(\"package_locales\")\n .select(\"package_id,title,lang\")\n .in(\"package_id\", packageIds)\n .in(\"lang\", [languageCode, \"en\", \"id\"]);\n\n if (!localeRes.error) {\n packageLocales = localeRes.data || [];\n }\n }\n\n return {\n bookings,\n recent,\n packageLocales,\n staticCounts: {\n packages: packagesRes.error ? 0 : packagesRes.count || 0,\n sections: sectionsRes.error ? 0 : sectionsRes.count || 0,\n },\n };\n },\n\n subscribeLiveUpdate(onEvent) {\n const channel = supabase\n .channel(\"reusable-dashboard-live\")\n .on(\n \"postgres_changes\",\n { event: \"*\", schema: \"public\", table: \"bookings\" },\n onEvent\n )\n .on(\n \"postgres_changes\",\n { event: \"*\", schema: \"public\", table: \"packages\" },\n onEvent\n )\n .on(\n \"postgres_changes\",\n { event: \"*\", schema: \"public\", table: \"page_sections\" },\n onEvent\n )\n .on(\n \"postgres_changes\",\n { event: \"*\", schema: \"public\", table: \"package_locales\" },\n onEvent\n )\n .subscribe();\n\n return () => {\n supabase.removeChannel(channel);\n };\n },\n };\n}\n","/**\r\n * tokoSepatuSupabaseSource — Data-source layer untuk studi kasus\r\n * Toko Sepatu Online.\r\n *\r\n * Mengimplementasikan kontrak yang sama dengan cidikaSupabaseSource:\r\n * - fetchDashboardSnapshot({ fromISO, toISO, statusScope })\r\n * - subscribeLiveUpdate(onEvent)\r\n *\r\n * Tabel yang diquery: orders, order_items, products, customers\r\n */\r\n\r\nfunction ensureNoError(response, message) {\r\n if (response?.error) {\r\n const err = new Error(message);\r\n err.cause = response.error;\r\n throw err;\r\n }\r\n}\r\n\r\n/**\r\n * Membuat data source untuk Toko Sepatu Online.\r\n *\r\n * @param {object} supabase - Instance Supabase client.\r\n * @returns {object} Objek data source { fetchDashboardSnapshot, subscribeLiveUpdate }.\r\n */\r\nexport function createTokoSepatuSupabaseSource(supabase) {\r\n return {\r\n /**\r\n * Mengambil snapshot data dashboard dari Supabase.\r\n */\r\n async fetchDashboardSnapshot({\r\n fromISO,\r\n toISO,\r\n audience,\r\n statusScope,\r\n }) {\r\n // Query semua orders dalam rentang waktu (dengan order_items untuk top products)\r\n const ordersQuery = supabase\r\n .from(\"orders\")\r\n .select(\r\n \"id, created_at, total_amount, status, customer_id, order_items(product_id, qty, price_idr, subtotal)\"\r\n )\r\n .gte(\"created_at\", fromISO)\r\n .lte(\"created_at\", toISO)\r\n .order(\"created_at\", { ascending: true });\r\n\r\n // Query recent orders (10 terbaru) dengan nama customer\r\n const recentQuery = supabase\r\n .from(\"orders\")\r\n .select(\r\n \"id, created_at, total_amount, status, customers(name), order_items(product_id, qty, products(name))\"\r\n )\r\n .gte(\"created_at\", fromISO)\r\n .lte(\"created_at\", toISO)\r\n .order(\"created_at\", { ascending: false })\r\n .limit(10);\r\n\r\n if (statusScope && statusScope !== \"all\") {\r\n recentQuery.eq(\"status\", statusScope);\r\n }\r\n\r\n const [ordersRes, recentRes, productsRes, customersRes] =\r\n await Promise.all([\r\n ordersQuery,\r\n recentQuery,\r\n supabase\r\n .from(\"products\")\r\n .select(\"id, name, brand, category, price_idr\"),\r\n supabase\r\n .from(\"customers\")\r\n .select(\"*\", { count: \"exact\", head: true }),\r\n ]);\r\n\r\n ensureNoError(ordersRes, \"Failed to load orders.\");\r\n ensureNoError(recentRes, \"Failed to load recent orders.\");\r\n\r\n const orders = ordersRes.data || [];\r\n const recentRaw = recentRes.data || [];\r\n const products = productsRes.data || [];\r\n\r\n // Map recent orders ke format yang adapter harapkan\r\n const recent = recentRaw.map((row) => ({\r\n id: row.id,\r\n created_at: row.created_at,\r\n total_amount: row.total_amount,\r\n status: row.status,\r\n customer_name: row.customers?.name || \"-\",\r\n product_name:\r\n row.order_items?.[0]?.products?.name || \"-\",\r\n order_items: row.order_items,\r\n }));\r\n\r\n return {\r\n bookings: orders,\r\n recent,\r\n products,\r\n packageLocales: [],\r\n staticCounts: {\r\n products: products.length,\r\n customers: customersRes.error ? 0 : customersRes.count || 0,\r\n },\r\n };\r\n },\r\n\r\n /**\r\n * Subscribe ke perubahan realtime pada tabel orders dan products.\r\n */\r\n subscribeLiveUpdate(onEvent) {\r\n const channel = supabase\r\n .channel(\"toko-sepatu-dashboard-live\")\r\n .on(\r\n \"postgres_changes\",\r\n { event: \"*\", schema: \"public\", table: \"orders\" },\r\n onEvent\r\n )\r\n .on(\r\n \"postgres_changes\",\r\n { event: \"*\", schema: \"public\", table: \"products\" },\r\n onEvent\r\n )\r\n .on(\r\n \"postgres_changes\",\r\n { event: \"*\", schema: \"public\", table: \"order_items\" },\r\n onEvent\r\n )\r\n .subscribe();\r\n\r\n return () => {\r\n supabase.removeChannel(channel);\r\n };\r\n },\r\n };\r\n}\r\n","import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { createDefaultFilters, resolveDateRange } from \"../utils/dateRange.js\";\nimport { useRealtimeUpdate } from \"./useRealtimeUpdate.js\";\n\nexport function useReusableDashboard({\n config,\n dataSource,\n adapter,\n createEmptyState,\n languageCode,\n dateLocale,\n labels,\n}) {\n const [filters, setFilters] = useState(() =>\n createDefaultFilters(config?.defaultFilters)\n );\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState(\"\");\n const [lastUpdatedAt, setLastUpdatedAt] = useState(null);\n const [data, setData] = useState(() => createEmptyState());\n\n\n const range = useMemo(\n () =>\n resolveDateRange({\n daysPreset: filters.daysPreset,\n dateFrom: filters.dateFrom,\n dateTo: filters.dateTo,\n }),\n [filters.daysPreset, filters.dateFrom, filters.dateTo]\n );\n\n const refresh = useCallback(\n async ({ silent = false } = {}) => {\n if (!dataSource?.fetchDashboardSnapshot) return;\n\n if (!silent) {\n setLoading(true);\n setError(\"\");\n }\n\n try {\n const raw = await dataSource.fetchDashboardSnapshot({\n fromISO: range.fromISO,\n toISO: range.toISO,\n audience: filters.audience,\n statusScope: filters.statusScope,\n languageCode,\n });\n\n const adapted = adapter({\n raw,\n filters,\n range,\n dateLocale,\n languageCode,\n labels,\n });\n\n setData(adapted);\n setLastUpdatedAt(new Date());\n if (!silent) setError(\"\");\n } catch (loadError) {\n console.error(loadError);\n if (!silent) {\n setError(labels.loadFailed);\n setData(createEmptyState());\n }\n } finally {\n if (!silent) setLoading(false);\n }\n },\n [\n dataSource,\n range,\n filters,\n languageCode,\n adapter,\n dateLocale,\n labels,\n createEmptyState,\n ]\n );\n\n useEffect(() => {\n refresh();\n }, [refresh]);\n\n const { liveUpdateEnabled } = useRealtimeUpdate({\n dataSource,\n onUpdate: () => refresh({ silent: true }),\n });\n\n const updateFilter = useCallback((field, value) => {\n setFilters((current) => ({\n ...current,\n [field]: value,\n }));\n }, []);\n\n const resetFilters = useCallback(() => {\n setFilters(createDefaultFilters(config?.defaultFilters));\n }, [config?.defaultFilters]);\n\n return {\n filters,\n updateFilter,\n resetFilters,\n loading,\n error,\n data,\n refresh,\n range,\n liveUpdateEnabled,\n lastUpdatedAt,\n };\n}\n","function startOfDayISO(date) {\n const value = new Date(date);\n value.setHours(0, 0, 0, 0);\n return value.toISOString();\n}\n\nfunction endOfDayISO(date) {\n const value = new Date(date);\n value.setHours(23, 59, 59, 999);\n return value.toISOString();\n}\n\nexport function formatYYYYMMDD(date) {\n const value = new Date(date);\n const year = value.getFullYear();\n const month = String(value.getMonth() + 1).padStart(2, \"0\");\n const day = String(value.getDate()).padStart(2, \"0\");\n return `${year}-${month}-${day}`;\n}\n\nexport function createDefaultFilters(base = {}) {\n const fromDate = new Date();\n fromDate.setDate(fromDate.getDate() - 29);\n\n return {\n statusScope: \"confirmed\",\n includePendingOverlay: false,\n audience: \"\",\n daysPreset: 30,\n dateFrom: formatYYYYMMDD(fromDate),\n dateTo: formatYYYYMMDD(new Date()),\n sortPkgBy: \"bookings\",\n sortPkgDir: \"desc\",\n ...base,\n };\n}\n\n/** Tahun minimum yang diizinkan untuk input tanggal kustom. */\nconst MIN_YEAR = 2000;\n/** Batas maksimum rentang hari untuk mencegah loop tak terhingga (5 tahun). */\nconst MAX_DAYS_WINDOW = 365 * 5;\n\n/**\n * Memvalidasi apakah tanggal masuk akal (tahun >= MIN_YEAR dan <= tahun sekarang + 1).\n * @param {Date} date\n * @returns {boolean}\n */\nfunction isReasonableDate(date) {\n if (!date || Number.isNaN(date.getTime())) return false;\n const year = date.getFullYear();\n return year >= MIN_YEAR && year <= new Date().getFullYear() + 1;\n}\n\nexport function resolveDateRange({ daysPreset, dateFrom, dateTo }) {\n if (Number(daysPreset) > 0) {\n const fromDate = new Date();\n fromDate.setDate(fromDate.getDate() - (Number(daysPreset) - 1));\n const toDate = new Date();\n return {\n fromISO: startOfDayISO(fromDate),\n toISO: endOfDayISO(toDate),\n daysWindow: Number(daysPreset),\n };\n }\n\n const fallbackFrom = new Date(Date.now() - 29 * 24 * 60 * 60 * 1000);\n const fallbackTo = new Date();\n\n let from = dateFrom ? new Date(dateFrom) : fallbackFrom;\n let to = dateTo ? new Date(dateTo) : fallbackTo;\n\n // Jika tanggal tidak masuk akal (misal tahun 0202), gunakan fallback\n if (!isReasonableDate(from)) from = fallbackFrom;\n if (!isReasonableDate(to)) to = fallbackTo;\n\n if (from.getTime() > to.getTime()) {\n const swap = from;\n from = to;\n to = swap;\n }\n\n const fromISO = startOfDayISO(from);\n const toISO = endOfDayISO(to);\n const diffMs = new Date(toISO).getTime() - new Date(fromISO).getTime();\n // Cap daysWindow agar tidak pernah melebihi MAX_DAYS_WINDOW\n const daysWindow = Math.min(\n MAX_DAYS_WINDOW,\n Math.max(1, Math.round(diffMs / 86400000) + 1)\n );\n\n return { fromISO, toISO, daysWindow };\n}\n","import { useEffect, useState } from \"react\";\n\n/**\n * useRealtimeUpdate — Custom hook untuk mengelola subscription live update\n * melalui mekanisme Supabase Realtime (Postgres Changes).\n *\n * Hook ini mengabstraksikan logika subscription dan debounce sehingga dapat\n * digunakan secara independen oleh consumer yang membutuhkan live update\n * tanpa menggunakan useReusableDashboard secara penuh.\n *\n * @param {object} params\n * @param {object} params.dataSource - Objek data source yang mengimplementasikan\n * `subscribeLiveUpdate(callback): unsubscribeFn`.\n * @param {Function} params.onUpdate - Callback yang dipanggil saat ada perubahan data.\n * Dipanggil setelah debounce selesai.\n * @param {number} [params.debounceMs=350] - Durasi debounce dalam milidetik.\n *\n * @returns {{ liveUpdateEnabled: boolean }} State apakah live update aktif.\n *\n * @example\n * const { liveUpdateEnabled } = useRealtimeUpdate({\n * dataSource,\n * onUpdate: () => refresh({ silent: true }),\n * });\n */\nexport function useRealtimeUpdate({ dataSource, onUpdate, debounceMs = 350 }) {\n const [liveUpdateEnabled, setLiveUpdateEnabled] = useState(false);\n\n useEffect(() => {\n if (!dataSource?.subscribeLiveUpdate) return undefined;\n\n let debounceId;\n setLiveUpdateEnabled(true);\n\n const unsubscribe = dataSource.subscribeLiveUpdate(() => {\n clearTimeout(debounceId);\n debounceId = setTimeout(() => {\n onUpdate?.();\n }, debounceMs);\n });\n\n return () => {\n clearTimeout(debounceId);\n setLiveUpdateEnabled(false);\n unsubscribe?.();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [dataSource, debounceMs]);\n // Note: onUpdate sengaja tidak dimasukkan dependency array untuk menghindari\n // re-subscribe yang tidak perlu saat parent re-render. Consumer harus\n // memoize callback-nya dengan useCallback jika ingin reaktivitas penuh.\n\n return { liveUpdateEnabled };\n}\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\n\nexport default function Button({\n variant = \"primary\",\n size = \"md\",\n disabled = false,\n className = \"\",\n onClick,\n children,\n ...rest\n}) {\n const classes = [\n \"rdb-btn\",\n `rdb-btn-${variant}`,\n `rdb-btn-${size}`,\n className,\n ].filter(Boolean).join(\" \");\n\n return (\n <button type=\"button\" className={classes} disabled={disabled} onClick={onClick} {...rest}>\n {children}\n </button>\n );\n}\n\nButton.propTypes = {\n variant: PropTypes.oneOf([\"primary\", \"secondary\", \"ghost\"]),\n size: PropTypes.oneOf([\"sm\", \"md\", \"lg\"]),\n disabled: PropTypes.bool,\n className: PropTypes.string,\n onClick: PropTypes.func,\n children: PropTypes.node.isRequired,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\n\nexport default function Input({\n type = \"text\",\n value,\n onChange,\n placeholder,\n label,\n disabled = false,\n className = \"\",\n ...rest\n}) {\n return (\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 4 }}>\n {label ? <label className=\"rdb-label\">{label}</label> : null}\n <input\n type={type}\n value={value}\n onChange={onChange}\n placeholder={placeholder}\n disabled={disabled}\n className={[\"rdb-input\", className].filter(Boolean).join(\" \")}\n {...rest}\n />\n </div>\n );\n}\n\nInput.propTypes = {\n type: PropTypes.string,\n value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n onChange: PropTypes.func,\n placeholder: PropTypes.string,\n label: PropTypes.string,\n disabled: PropTypes.bool,\n className: PropTypes.string,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport {\n BarChart3,\n Calendar,\n DollarSign,\n PieChart,\n RotateCcw,\n TrendingUp,\n TrendingDown,\n Users,\n Search,\n ChevronLeft,\n ChevronRight,\n ArrowUp,\n ArrowDown,\n AlertCircle,\n} from \"lucide-react\";\n\n/**\n * Registry ikon yang tersedia di modul dashboard.\n * @type {Object.<string, React.ComponentType>}\n */\nconst ICON_REGISTRY = {\n BarChart3,\n Calendar,\n DollarSign,\n PieChart,\n RotateCcw,\n TrendingUp,\n TrendingDown,\n Users,\n Search,\n ChevronLeft,\n ChevronRight,\n ArrowUp,\n ArrowDown,\n AlertCircle,\n};\n\n/**\n * Icon — Atom komponen ikon berbasis SVG menggunakan Lucide React.\n *\n * @param {object} props\n * @param {string} props.name - Nama ikon dari registry (misal: \"TrendingUp\").\n * @param {number} [props.size=20] - Ukuran ikon dalam piksel.\n * @param {string} [props.className=\"\"] - ClassName tambahan.\n */\nexport default function Icon({ name, size = 20, className = \"\", ...rest }) {\n const IconComponent = ICON_REGISTRY[name] || BarChart3;\n\n return <IconComponent size={size} className={className} {...rest} />;\n}\n\n/**\n * Resolves an icon name to its Lucide React component.\n * Backward-compatible utility used internally.\n *\n * @param {string} name - Nama ikon.\n * @returns {React.ComponentType} Komponen ikon.\n */\nexport function resolveIcon(name) {\n return ICON_REGISTRY[name] || BarChart3;\n}\n\nIcon.propTypes = {\n /** Nama ikon dari registry Lucide React. */\n name: PropTypes.string.isRequired,\n /** Ukuran ikon dalam piksel. */\n size: PropTypes.number,\n /** ClassName tambahan. */\n className: PropTypes.string,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\n\nconst VARIANT_CLASS = {\n h1: \"rdb-h1\",\n h2: \"rdb-h2\",\n h3: \"rdb-h3\",\n subheading: \"rdb-subheading\",\n body: \"rdb-body\",\n caption: \"rdb-caption\",\n metric: \"rdb-metric\",\n};\n\nconst VARIANT_TAG = {\n h1: \"h1\", h2: \"h2\", h3: \"h3\",\n subheading: \"p\", body: \"p\", caption: \"span\", metric: \"span\",\n};\n\nexport default function Typography({ variant = \"body\", className = \"\", children, ...rest }) {\n const Tag = VARIANT_TAG[variant] || \"p\";\n const cls = [VARIANT_CLASS[variant] || \"rdb-body\", className].filter(Boolean).join(\" \");\n return <Tag className={cls} {...rest}>{children}</Tag>;\n}\n\nTypography.propTypes = {\n variant: PropTypes.oneOf([\"h1\",\"h2\",\"h3\",\"subheading\",\"body\",\"caption\",\"metric\"]),\n className: PropTypes.string,\n children: PropTypes.node.isRequired,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\n\nconst STATUS_CLASS = {\n confirmed: \"rdb-badge-confirmed\",\n pending: \"rdb-badge-pending\",\n cancelled: \"rdb-badge-cancelled\",\n success: \"rdb-badge-success\",\n info: \"rdb-badge-info\",\n default: \"rdb-badge-default\",\n};\n\nexport default function Badge({ status = \"default\", className = \"\", children, ...rest }) {\n const statusClass = STATUS_CLASS[status] || STATUS_CLASS.default;\n return (\n <span className={[\"rdb-badge\", statusClass, className].filter(Boolean).join(\" \")} {...rest}>\n {children}\n </span>\n );\n}\n\nBadge.propTypes = {\n status: PropTypes.string,\n className: PropTypes.string,\n children: PropTypes.node.isRequired,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\n\nexport default function SkeletonLoader({ className = \"\", style = {} }) {\n return (\n <div\n className={[\"rdb-skeleton\", className].filter(Boolean).join(\" \")}\n style={{ minHeight: 20, ...style }}\n role=\"status\"\n aria-label=\"Loading...\"\n />\n );\n}\n\nSkeletonLoader.propTypes = {\n className: PropTypes.string,\n style: PropTypes.object,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport Icon from \"../atoms/Icon.jsx\";\nimport { formatIDR } from \"../../utils/formatters.js\";\n\nfunction renderValue(format, value) {\n if (format === \"currency\") return `Rp ${formatIDR(value)}`;\n if (format === \"percent\") return `${Number(value) || 0}%`;\n return String(Number(value) || 0);\n}\n\nexport default function StatCard({\n label,\n value,\n icon = \"TrendingUp\",\n format = \"number\",\n trend = null,\n accentColor = \"blue\",\n className = \"\",\n}) {\n return (\n <div className={[\"rdb-card rdb-statcard\", `rdb-accent-${accentColor}`, className].filter(Boolean).join(\" \")}>\n <div className=\"rdb-statcard-header\">\n <div className=\"rdb-statcard-label-group\">\n <div className=\"rdb-statcard-icon\">\n <Icon name={icon} size={16} />\n </div>\n <span className=\"rdb-statcard-label\">{label}</span>\n </div>\n {trend ? (\n <Icon\n name={trend === \"up\" ? \"TrendingUp\" : \"TrendingDown\"}\n size={16}\n style={{ color: trend === \"up\" ? \"#10b981\" : \"#ef4444\" }}\n />\n ) : null}\n </div>\n <div className=\"rdb-statcard-value\">{renderValue(format, value)}</div>\n </div>\n );\n}\n\nStatCard.propTypes = {\n label: PropTypes.string.isRequired,\n value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),\n icon: PropTypes.string,\n format: PropTypes.oneOf([\"number\", \"currency\", \"percent\"]),\n trend: PropTypes.oneOf([\"up\", \"down\", null]),\n accentColor: PropTypes.string,\n className: PropTypes.string,\n};\n","import React, { useState, useCallback } from \"react\";\nimport PropTypes from \"prop-types\";\nimport Icon from \"../atoms/Icon.jsx\";\n\nexport default function SearchBar({\n value: controlledValue,\n onChange,\n onSearch,\n placeholder = \"Search...\",\n className = \"\",\n}) {\n const [internalValue, setInternalValue] = useState(\"\");\n const isControlled = controlledValue !== undefined;\n const currentValue = isControlled ? controlledValue : internalValue;\n\n const handleChange = useCallback((event) => {\n const v = event.target.value;\n if (!isControlled) setInternalValue(v);\n if (onChange) onChange(v);\n if (onSearch) onSearch(v);\n }, [isControlled, onChange, onSearch]);\n\n const handleKeyDown = useCallback((event) => {\n if (event.key === \"Enter\" && onSearch) onSearch(currentValue);\n }, [currentValue, onSearch]);\n\n return (\n <div className={[\"rdb-searchbar\", className].filter(Boolean).join(\" \")}>\n <div className=\"rdb-searchbar-icon\">\n <Icon name=\"Search\" size={16} />\n </div>\n <input\n type=\"search\"\n value={currentValue}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n className=\"rdb-input rdb-searchbar-input\"\n style={{ width: \"100%\" }}\n />\n </div>\n );\n}\n\nSearchBar.propTypes = {\n value: PropTypes.string,\n onChange: PropTypes.func,\n onSearch: PropTypes.func,\n placeholder: PropTypes.string,\n className: PropTypes.string,\n};\n","import React, { useState, useCallback } from \"react\";\nimport PropTypes from \"prop-types\";\n\nconst CURRENT_YEAR = new Date().getFullYear();\nconst MIN_YEAR = 2020;\nconst MAX_YEAR = CURRENT_YEAR + 1;\nconst MONTHS = [\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"];\n\nfunction getYears() {\n const y = [];\n for (let i = MAX_YEAR; i >= MIN_YEAR; i--) y.push(i);\n return y;\n}\n\nfunction getDaysInMonth(year, month) {\n return new Date(year, month, 0).getDate();\n}\n\nfunction parseDate(value) {\n if (value && /^\\d{4}-\\d{2}-\\d{2}$/.test(value)) {\n const [y, m, d] = value.split(\"-\").map(Number);\n if (y >= MIN_YEAR && y <= MAX_YEAR && m >= 1 && m <= 12)\n return { year: y, month: m, day: d };\n }\n const now = new Date();\n return { year: now.getFullYear(), month: now.getMonth() + 1, day: now.getDate() };\n}\n\nfunction fmt({ year, month, day }) {\n return `${year}-${String(month).padStart(2,\"0\")}-${String(day).padStart(2,\"0\")}`;\n}\n\nfunction DatePicker({ value, onChange, disabled = false, label = \"\" }) {\n const p = parseDate(value);\n const years = getYears();\n const maxDay = getDaysInMonth(p.year, p.month);\n\n const handleChange = useCallback((field, val) => {\n const u = { ...p, [field]: Number(val) };\n const max = getDaysInMonth(u.year, u.month);\n if (u.day > max) u.day = max;\n onChange(fmt(u));\n }, [p, onChange]);\n\n return (\n <div style={{ display:\"flex\", flexDirection:\"column\", gap:2 }}>\n {label ? <span className=\"rdb-caption rdb-label\">{label}</span> : null}\n <div style={{ display:\"flex\", gap:4, alignItems:\"center\" }}>\n <select className=\"rdb-select\" style={{ width:52 }} value={p.day}\n onChange={e => handleChange(\"day\", e.target.value)} disabled={disabled}>\n {Array.from({ length: maxDay }, (_,i) => i+1).map(d => (\n <option key={d} value={d}>{String(d).padStart(2,\"0\")}</option>\n ))}\n </select>\n <select className=\"rdb-select\" style={{ width:62 }} value={p.month}\n onChange={e => handleChange(\"month\", e.target.value)} disabled={disabled}>\n {MONTHS.map((name, idx) => (\n <option key={idx+1} value={idx+1}>{name}</option>\n ))}\n </select>\n <select className=\"rdb-select\" style={{ width:72 }} value={p.year}\n onChange={e => handleChange(\"year\", e.target.value)} disabled={disabled}>\n {years.map(y => <option key={y} value={y}>{y}</option>)}\n </select>\n </div>\n </div>\n );\n}\n\nexport default function DateRangeFilter({\n dateFrom, dateTo, onRangeChange,\n disabled = false, labelFrom = \"From\", labelTo = \"To\", className = \"\",\n}) {\n const handleFrom = useCallback(v => onRangeChange?.({ dateFrom: v, dateTo }), [dateTo, onRangeChange]);\n const handleTo = useCallback(v => onRangeChange?.({ dateFrom, dateTo: v }), [dateFrom, onRangeChange]);\n\n return (\n <div className={[\"rdb-daterange\", className].filter(Boolean).join(\" \")}>\n <DatePicker value={dateFrom} onChange={handleFrom} disabled={disabled} label={labelFrom} />\n <DatePicker value={dateTo} onChange={handleTo} disabled={disabled} label={labelTo} />\n </div>\n );\n}\n\nDateRangeFilter.propTypes = {\n dateFrom: PropTypes.string.isRequired,\n dateTo: PropTypes.string.isRequired,\n onRangeChange: PropTypes.func.isRequired,\n disabled: PropTypes.bool,\n labelFrom: PropTypes.string,\n labelTo: PropTypes.string,\n className: PropTypes.string,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport Icon from \"../atoms/Icon.jsx\";\n\nexport default function ChartHeader({ title, icon = \"BarChart3\", actions = null, className = \"\" }) {\n return (\n <div className={[\"rdb-chart-title-wrap\", className].filter(Boolean).join(\" \")}>\n <div className=\"rdb-chart-title\">\n <Icon name={icon} size={18} />\n {title}\n </div>\n {actions}\n </div>\n );\n}\n\nChartHeader.propTypes = {\n title: PropTypes.string.isRequired,\n icon: PropTypes.string,\n actions: PropTypes.node,\n className: PropTypes.string,\n};\n","import React, { useMemo, useState, useCallback } from \"react\";\nimport PropTypes from \"prop-types\";\nimport SearchBar from \"../molecules/SearchBar.jsx\";\nimport Badge from \"../atoms/Badge.jsx\";\nimport Icon from \"../atoms/Icon.jsx\";\nimport { formatDate, formatIDR } from \"../../utils/formatters.js\";\n\nexport default function DataTable({\n columns, data = [], labels = {}, dateLocale = \"id-ID\",\n searchable = true, sortable = true, pageSize = 10,\n emptyLabel = \"No data\", searchPlaceholder = \"Search...\", className = \"\",\n}) {\n const [searchQuery, setSearchQuery] = useState(\"\");\n const [sortField, setSortField] = useState(null);\n const [sortDirection, setSortDirection] = useState(\"asc\");\n const [currentPage, setCurrentPage] = useState(1);\n\n const filteredData = useMemo(() => {\n if (!searchQuery.trim()) return data;\n const q = searchQuery.toLowerCase();\n return data.filter(row =>\n columns.some(col => {\n const v = row[col.accessor];\n return v != null && String(v).toLowerCase().includes(q);\n })\n );\n }, [data, searchQuery, columns]);\n\n const sortedData = useMemo(() => {\n if (!sortField) return filteredData;\n return [...filteredData].sort((a, b) => {\n const aV = a[sortField] ?? \"\";\n const bV = b[sortField] ?? \"\";\n if (typeof aV === \"number\" && typeof bV === \"number\")\n return sortDirection === \"asc\" ? aV - bV : bV - aV;\n const cmp = String(aV).localeCompare(String(bV), undefined, { numeric: true });\n return sortDirection === \"asc\" ? cmp : -cmp;\n });\n }, [filteredData, sortField, sortDirection]);\n\n const totalPages = Math.max(1, Math.ceil(sortedData.length / pageSize));\n const safePage = Math.min(currentPage, totalPages);\n const paginatedData = useMemo(() => {\n const start = (safePage - 1) * pageSize;\n return sortedData.slice(start, start + pageSize);\n }, [sortedData, safePage, pageSize]);\n\n const handleSearch = useCallback(v => { setSearchQuery(v); setCurrentPage(1); }, []);\n const handleSort = useCallback(acc => {\n if (!sortable) return;\n if (sortField === acc) setSortDirection(p => p === \"asc\" ? \"desc\" : \"asc\");\n else { setSortField(acc); setSortDirection(\"asc\"); }\n setCurrentPage(1);\n }, [sortable, sortField]);\n const handlePrev = useCallback(() => setCurrentPage(p => Math.max(1, p-1)), []);\n const handleNext = useCallback(() => setCurrentPage(p => Math.min(totalPages, p+1)), [totalPages]);\n\n return (\n <div style={{ display:\"flex\", flexDirection:\"column\", gap:12 }} className={className}>\n {searchable ? (\n <SearchBar value={searchQuery} onSearch={handleSearch} placeholder={searchPlaceholder} />\n ) : null}\n\n <div className=\"rdb-table-wrapper\">\n <table className=\"rdb-table\">\n <thead>\n <tr>\n {columns.map(col => (\n <th key={col.id} onClick={() => handleSort(col.accessor)}>\n <div style={{ display:\"flex\", alignItems:\"center\", gap:4 }}>\n <span>{labels[col.label] || col.label}</span>\n {sortable && sortField === col.accessor ? (\n <Icon name={sortDirection === \"asc\" ? \"ArrowUp\" : \"ArrowDown\"} size={13}\n style={{ color: \"var(--rdb-blue-500)\" }} />\n ) : null}\n </div>\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {paginatedData.map(row => (\n <tr key={row.id}>\n {columns.map(col => (\n <td key={`${row.id}-${col.id}`}>{renderCell(col, row, dateLocale)}</td>\n ))}\n </tr>\n ))}\n {paginatedData.length === 0 ? (\n <tr>\n <td className=\"rdb-table-empty\" colSpan={columns.length}>{emptyLabel}</td>\n </tr>\n ) : null}\n </tbody>\n </table>\n </div>\n\n {sortedData.length > pageSize ? (\n <div className=\"rdb-pagination\">\n <span className=\"rdb-pagination-info\">\n {(safePage-1)*pageSize+1}–{Math.min(safePage*pageSize, sortedData.length)} of {sortedData.length}\n </span>\n <div className=\"rdb-pagination-controls\">\n <button type=\"button\" className=\"rdb-page-btn\" onClick={handlePrev} disabled={safePage <= 1} aria-label=\"Previous\">\n <Icon name=\"ChevronLeft\" size={16} />\n </button>\n <span className=\"rdb-pagination-page\">{safePage} / {totalPages}</span>\n <button type=\"button\" className=\"rdb-page-btn\" onClick={handleNext} disabled={safePage >= totalPages} aria-label=\"Next\">\n <Icon name=\"ChevronRight\" size={16} />\n </button>\n </div>\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction renderCell(column, row, dateLocale) {\n const value = row[column.accessor];\n if (column.type === \"date\") return formatDate(value, dateLocale);\n if (column.type === \"currency\") return `Rp ${formatIDR(value)}`;\n if (column.type === \"statusBadge\") {\n const status = row[column.statusAccessor] || \"pending\";\n return <Badge status={status}>{value}</Badge>;\n }\n return value || \"-\";\n}\n\nDataTable.propTypes = {\n columns: PropTypes.arrayOf(PropTypes.shape({\n id: PropTypes.string.isRequired,\n label: PropTypes.string.isRequired,\n accessor: PropTypes.string.isRequired,\n type: PropTypes.oneOf([\"date\",\"currency\",\"statusBadge\"]),\n statusAccessor: PropTypes.string,\n })).isRequired,\n data: PropTypes.arrayOf(PropTypes.object),\n labels: PropTypes.object,\n dateLocale: PropTypes.string,\n searchable: PropTypes.bool,\n sortable: PropTypes.bool,\n pageSize: PropTypes.number,\n emptyLabel: PropTypes.string,\n searchPlaceholder: PropTypes.string,\n className: PropTypes.string,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport {\n Area,\n AreaChart,\n Bar,\n BarChart,\n CartesianGrid,\n Cell,\n Legend,\n Pie,\n PieChart,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from \"recharts\";\nimport ChartHeader from \"../molecules/ChartHeader.jsx\";\nimport SkeletonLoader from \"../atoms/SkeletonLoader.jsx\";\nimport { formatIDR } from \"../../utils/formatters.js\";\n\n/**\n * Palet warna default untuk grafik.\n * @type {string[]}\n */\nconst COLORS = [\n \"#0ea5e9\",\n \"#a78bfa\",\n \"#f59e0b\",\n \"#10b981\",\n \"#ef4444\",\n \"#22d3ee\",\n];\n\n/**\n * ChartCard — Organism kartu grafik yang mengintegrasikan ChartHeader\n * dengan area visualisasi. Mendukung tipe grafik area, pie, dan bar.\n *\n * @param {object} props\n * @param {object} props.widget - Konfigurasi widget chart.\n * @param {object} props.labels - Objek label i18n.\n * @param {boolean} props.loading - Apakah sedang loading.\n * @param {object} props.filters - State filter dashboard.\n * @param {object} props.chartData - Data untuk semua jenis chart.\n * @param {string} [props.className=\"\"] - ClassName tambahan.\n */\nexport default function ChartCard({\n widget,\n labels,\n loading,\n filters,\n chartData,\n className = \"\",\n}) {\n const content = (() => {\n if (loading) return <SkeletonLoader style={{ height: 256 }} />;\n\n if (widget.type === \"dailyArea\") {\n return renderDailyArea(labels, filters, chartData.dailyTrends);\n }\n if (widget.type === \"statusPie\") {\n return renderPie(chartData.statusDistribution);\n }\n if (widget.type === \"audiencePie\") {\n return renderPie(chartData.audienceDistribution);\n }\n if (widget.type === \"topPackagesBar\") {\n return renderTopPackages(chartData.topPackages, labels, filters.sortPkgBy);\n }\n\n return <div className=\"rdb-muted\">Unsupported chart type.</div>;\n })();\n\n return (\n <div className={`rdb-card rdb-chart-card ${className}`}>\n <ChartHeader\n title={labels[widget.label] || widget.label}\n icon={widget.icon}\n />\n {content}\n </div>\n );\n}\n\n/**\n * Merender grafik area harian (daily area chart).\n * @param {object} labels - Label i18n.\n * @param {object} filters - Filter dashboard.\n * @param {Array} dailyData - Data daily trends.\n * @returns {React.ReactElement} Komponen AreaChart.\n */\nfunction renderDailyArea(labels, filters, dailyData = []) {\n return (\n <ResponsiveContainer width=\"100%\" height={256}>\n <AreaChart data={dailyData}>\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis dataKey=\"label\" />\n <YAxis yAxisId=\"left\" />\n <YAxis yAxisId=\"right\" orientation=\"right\" />\n <Tooltip\n formatter={(value, name) =>\n name === \"revenue\"\n ? [`Rp ${formatIDR(value)}`, labels.revenueMetric]\n : [value, labels.bookingsMetric]\n }\n />\n <Legend />\n <Area\n yAxisId=\"left\"\n type=\"monotone\"\n dataKey=\"count\"\n name={labels.confirmedBookingMetric}\n stroke=\"#0ea5e9\"\n fill=\"#0ea5e9\"\n fillOpacity={0.3}\n />\n <Area\n yAxisId=\"right\"\n type=\"monotone\"\n dataKey=\"revenue\"\n name={labels.confirmedRevenueMetric}\n stroke=\"#a78bfa\"\n fill=\"#a78bfa\"\n fillOpacity={0.3}\n />\n {filters.includePendingOverlay ? (\n <Area\n yAxisId=\"left\"\n type=\"monotone\"\n dataKey=\"pendingCount\"\n name={labels.pendingMetric}\n stroke=\"#ef4444\"\n fill=\"#ef4444\"\n fillOpacity={0.1}\n strokeDasharray=\"4 4\"\n />\n ) : null}\n </AreaChart>\n </ResponsiveContainer>\n );\n}\n\n/**\n * Merender diagram lingkaran (Pie/Donut Chart).\n * @param {Array} data - Data distribusi.\n * @returns {React.ReactElement} Komponen PieChart.\n */\nfunction renderPie(data = []) {\n return (\n <ResponsiveContainer width=\"100%\" height={256}>\n <PieChart>\n <Pie\n data={data}\n dataKey=\"count\"\n nameKey=\"label\"\n innerRadius={60}\n outerRadius={100}\n paddingAngle={2}\n >\n {data.map((_, index) => (\n <Cell\n key={`${index}-${data[index].label}`}\n fill={COLORS[index % COLORS.length]}\n />\n ))}\n </Pie>\n <Tooltip />\n <Legend />\n </PieChart>\n </ResponsiveContainer>\n );\n}\n\n/**\n * Merender grafik batang (Bar Chart) untuk paket teratas.\n * @param {Array} data - Data top packages.\n * @param {object} labels - Label i18n.\n * @param {string} sortPkgBy - Metrik pengurutan (bookings/revenue).\n * @returns {React.ReactElement} Komponen BarChart.\n */\nfunction renderTopPackages(data = [], labels, sortPkgBy) {\n return (\n <ResponsiveContainer width=\"100%\" height={256}>\n <BarChart data={data} layout=\"vertical\">\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis type=\"number\" allowDecimals={false} />\n <YAxis type=\"category\" dataKey=\"name\" width={120} />\n <Tooltip\n formatter={(value) =>\n sortPkgBy === \"revenue\"\n ? [`Rp ${formatIDR(value)}`, labels.revenueMetric]\n : [value, labels.bookingsMetric]\n }\n />\n <Bar\n dataKey=\"value\"\n name={\n sortPkgBy === \"revenue\"\n ? labels.revenueMetric\n : labels.bookingsMetric\n }\n fill=\"#10b981\"\n radius={[4, 4, 4, 4]}\n />\n </BarChart>\n </ResponsiveContainer>\n );\n}\n\nChartCard.propTypes = {\n /** Konfigurasi widget chart. */\n widget: PropTypes.shape({\n id: PropTypes.string.isRequired,\n type: PropTypes.string.isRequired,\n label: PropTypes.string.isRequired,\n icon: PropTypes.string,\n }).isRequired,\n /** Objek label i18n. */\n labels: PropTypes.object.isRequired,\n /** Apakah sedang loading. */\n loading: PropTypes.bool,\n /** State filter dashboard. */\n filters: PropTypes.object,\n /** Data untuk semua jenis chart. */\n chartData: PropTypes.object,\n /** ClassName tambahan. */\n className: PropTypes.string,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport Button from \"../atoms/Button.jsx\";\nimport DateRangeFilter from \"../molecules/DateRangeFilter.jsx\";\n\nconst STATUS_OPTIONS = [\"confirmed\", \"pending\", \"all\"];\nconst AUDIENCE_OPTIONS = [\"\", \"domestic\", \"foreign\"];\nconst DAY_PRESETS = [7, 30, 90, 0];\nconst SORT_BY_OPTIONS = [\"bookings\", \"revenue\"];\nconst SORT_DIR_OPTIONS = [\"desc\", \"asc\"];\n\nexport default function FilterPanel({ filters, labels, onFilterChange, onResetFilters, className = \"\" }) {\n return (\n <div className={[\"rdb-filter-panel\", className].filter(Boolean).join(\" \")}>\n {/* Row 1 */}\n <div className=\"rdb-filter-row\">\n <select className=\"rdb-select\" value={filters.statusScope}\n onChange={e => onFilterChange(\"statusScope\", e.target.value)}>\n {STATUS_OPTIONS.map(s => (\n <option key={s} value={s}>\n {s === \"confirmed\" ? labels.confirmedOnly : s === \"pending\" ? labels.pendingOnly : labels.allStatus}\n </option>\n ))}\n </select>\n\n <label className=\"rdb-filter-overlay-label\">\n <input type=\"checkbox\" checked={filters.includePendingOverlay}\n onChange={e => onFilterChange(\"includePendingOverlay\", e.target.checked)} />\n <span className=\"rdb-body\">{labels.showPendingOverlay}</span>\n </label>\n\n <select className=\"rdb-select\" value={filters.audience}\n onChange={e => onFilterChange(\"audience\", e.target.value)}>\n {AUDIENCE_OPTIONS.map(a => (\n <option key={a || \"all\"} value={a}>\n {a === \"domestic\" ? labels.audienceDomestic : a === \"foreign\" ? labels.audienceForeign : labels.allAudience}\n </option>\n ))}\n </select>\n\n <select className=\"rdb-select\" value={String(filters.daysPreset)}\n onChange={e => onFilterChange(\"daysPreset\", Number(e.target.value))}>\n {DAY_PRESETS.map(d => (\n <option key={String(d)} value={String(d)}>\n {d === 0 ? labels.customDate : labels.dayLabel(d)}\n </option>\n ))}\n </select>\n\n <DateRangeFilter\n dateFrom={filters.dateFrom || \"\"}\n dateTo={filters.dateTo || \"\"}\n onRangeChange={({ dateFrom, dateTo }) => {\n if (dateFrom !== filters.dateFrom) onFilterChange(\"dateFrom\", dateFrom);\n if (dateTo !== filters.dateTo) onFilterChange(\"dateTo\", dateTo);\n }}\n disabled={filters.daysPreset !== 0}\n className=\"rdb-filter-date\"\n />\n </div>\n\n {/* Row 2 */}\n <div className=\"rdb-filter-actions\">\n <Button variant=\"secondary\" size=\"sm\" onClick={onResetFilters}>{labels.reset}</Button>\n <div className=\"rdb-filter-sort\">\n <span className=\"rdb-caption\">{labels.topSort}:</span>\n <select className=\"rdb-select\" style={{ width: \"auto\" }} value={filters.sortPkgBy}\n onChange={e => onFilterChange(\"sortPkgBy\", e.target.value)}>\n {SORT_BY_OPTIONS.map(s => (\n <option key={s} value={s}>{s === \"bookings\" ? labels.sortBookings : labels.sortRevenue}</option>\n ))}\n </select>\n <select className=\"rdb-select\" style={{ width: \"auto\" }} value={filters.sortPkgDir}\n onChange={e => onFilterChange(\"sortPkgDir\", e.target.value)}>\n {SORT_DIR_OPTIONS.map(d => (\n <option key={d} value={d}>{d === \"desc\" ? labels.sortDesc : labels.sortAsc}</option>\n ))}\n </select>\n </div>\n </div>\n </div>\n );\n}\n\nFilterPanel.propTypes = {\n filters: PropTypes.object.isRequired,\n labels: PropTypes.object.isRequired,\n onFilterChange: PropTypes.func.isRequired,\n onResetFilters: PropTypes.func.isRequired,\n className: PropTypes.string,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport Icon from \"../atoms/Icon.jsx\";\n\nexport default function SidebarNavigation({ items = [], activeItem = \"\", onItemClick, logo = null, className = \"\" }) {\n return (\n <aside className={[\"rdb-sidebar\", className].filter(Boolean).join(\" \")}>\n {logo ? <div className=\"rdb-sidebar-logo\">{logo}</div> : null}\n <nav className=\"rdb-sidebar-nav\" aria-label=\"Sidebar navigation\">\n {items.map(item => {\n const isActive = item.id === activeItem;\n return (\n <button key={item.id} type=\"button\"\n onClick={() => onItemClick?.(item.id)}\n aria-current={isActive ? \"page\" : undefined}\n className={[\"rdb-nav-item\", isActive ? \"rdb-nav-item-active\" : \"\"].filter(Boolean).join(\" \")}>\n {item.icon ? (\n <Icon name={item.icon} size={18}\n style={{ color: isActive ? \"var(--rdb-blue-600)\" : \"var(--rdb-text-subtle)\" }} />\n ) : null}\n <span>{item.label}</span>\n {isActive ? <span className=\"rdb-nav-dot\" /> : null}\n </button>\n );\n })}\n </nav>\n </aside>\n );\n}\n\nSidebarNavigation.propTypes = {\n items: PropTypes.arrayOf(PropTypes.shape({ id: PropTypes.string.isRequired, label: PropTypes.string.isRequired, icon: PropTypes.string })),\n activeItem: PropTypes.string,\n onItemClick: PropTypes.func,\n logo: PropTypes.node,\n className: PropTypes.string,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\n\nexport default function TopbarHeader({ title = \"\", actions = null, leading = null, className = \"\" }) {\n return (\n <header className={[\"rdb-topbar\", className].filter(Boolean).join(\" \")}>\n <div className=\"rdb-topbar-left\">\n {leading}\n {title ? <span className=\"rdb-h2\" style={{ overflow:\"hidden\", textOverflow:\"ellipsis\", whiteSpace:\"nowrap\" }}>{title}</span> : null}\n </div>\n {actions ? <div className=\"rdb-topbar-right\">{actions}</div> : null}\n </header>\n );\n}\n\nTopbarHeader.propTypes = {\n title: PropTypes.string,\n actions: PropTypes.node,\n leading: PropTypes.node,\n className: PropTypes.string,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\n\nexport default function DashboardLayout({ header = null, sidebar = null, children, className = \"\" }) {\n return (\n <div className={[\"rdb-layout\", className].filter(Boolean).join(\" \")}>\n {header}\n <div className=\"rdb-layout-body\">\n {sidebar}\n <main className=\"rdb-layout-main\">{children}</main>\n </div>\n </div>\n );\n}\n\nDashboardLayout.propTypes = {\n header: PropTypes.node,\n sidebar: PropTypes.node,\n children: PropTypes.node.isRequired,\n className: PropTypes.string,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport \"./dashboard.css\";\nimport Icon from \"./atoms/Icon.jsx\";\nimport SkeletonLoader from \"./atoms/SkeletonLoader.jsx\";\nimport Button from \"./atoms/Button.jsx\";\nimport Badge from \"./atoms/Badge.jsx\";\nimport StatCard from \"./molecules/StatCard.jsx\";\nimport FilterPanel from \"./organisms/FilterPanel.jsx\";\nimport ChartCard from \"./organisms/ChartCard.jsx\";\nimport DataTable from \"./organisms/DataTable.jsx\";\nimport { SetupWizard } from \"./SetupWizard.jsx\";\nimport { validateDashboardConfig } from \"../config/createDashboardConfig.js\";\n\n/**\n * ReusableDashboardView — Komponen halaman (Page) dashboard utama.\n *\n * Fitur tambahan (revisi dosen — Opsi B):\n * - Secara otomatis mendeteksi apakah konfigurasi sudah valid.\n * - Jika belum valid, menampilkan SetupWizard (pop-up panduan interaktif).\n * - Developer dapat menutup wizard untuk lanjut tanpa konfigurasi.\n * - Prop `supabase` opsional: mengaktifkan fitur baca tabel langsung di wizard.\n * - Prop `dashboardConfig` opsional: jika diisi (hasil createDashboardConfig),\n * validasi dilakukan otomatis.\n *\n * @param {object} props\n * @param {object} props.config - Konfigurasi widget dashboard.\n * @param {object} props.labels - Objek label i18n.\n * @param {boolean} props.loading - Status loading data.\n * @param {string} [props.error] - Pesan error jika ada.\n * @param {object} [props.filters] - State filter dashboard.\n * @param {Function} props.onFilterChange - Callback perubahan filter.\n * @param {Function} props.onResetFilters - Callback reset filter.\n * @param {Function} props.onRefresh - Callback refresh data.\n * @param {object} [props.data] - Data dashboard.\n * @param {string} [props.dateLocale] - Locale untuk format tanggal.\n * @param {boolean} [props.liveUpdateEnabled] - Apakah live update aktif.\n * @param {object} [props.supabase] - Supabase client (aktifkan fitur baca tabel di wizard).\n * @param {object} [props.dashboardConfig] - Hasil createDashboardConfig() untuk validasi otomatis.\n */\nexport function ReusableDashboardView({\n config, labels, loading, error, filters,\n onFilterChange, onResetFilters, onRefresh,\n data, dateLocale, liveUpdateEnabled,\n supabase, dashboardConfig,\n}) {\n // ── Deteksi apakah setup wizard perlu ditampilkan ──────────────────\n // Validasi dilakukan berdasarkan dashboardConfig (jika ada) atau\n // pengecekan manual pada prop config & labels.\n const [wizardDismissed, setWizardDismissed] = React.useState(false);\n\n const configIssues = React.useMemo(() => {\n if (wizardDismissed) return [];\n\n // Jika developer menyertakan dashboardConfig (dari createDashboardConfig),\n // gunakan validator bawaan factory\n if (dashboardConfig) {\n const { issues } = validateDashboardConfig(dashboardConfig);\n return issues;\n }\n\n // Fallback: validasi manual pada prop langsung\n const issues = [];\n if (!config) issues.push(\"Prop 'config' (widgetConfig) belum diisi.\");\n if (!config?.widgets?.stats?.length) issues.push(\"widgetConfig.widgets.stats kosong. Tambahkan minimal 1 stat card.\");\n if (!config?.widgets?.charts?.length) issues.push(\"widgetConfig.widgets.charts kosong. Tambahkan minimal 1 chart.\");\n if (!config?.widgets?.table?.columns?.length) issues.push(\"widgetConfig.widgets.table.columns kosong.\");\n if (!labels) issues.push(\"Prop 'labels' belum diisi.\");\n if (!labels?.title) issues.push(\"labels.title belum diisi.\");\n if (!labels?.formatStatusLabel) issues.push(\"labels.formatStatusLabel (function) belum diisi.\");\n return issues;\n }, [config, labels, dashboardConfig, wizardDismissed]);\n\n const showWizard = !wizardDismissed && configIssues.length > 0;\n\n // ── Guard: jika config benar-benar null, render wizard saja ────────\n if (!config || !config.widgets) {\n return (\n <div className=\"rdb-view\">\n <SetupWizard\n issues={[\"Prop 'config' (widgetConfig) belum diisi atau tidak valid.\"]}\n onDismiss={() => setWizardDismissed(true)}\n supabase={supabase}\n />\n </div>\n );\n }\n\n return (\n <div className=\"rdb-view\">\n {/* Setup Wizard (muncul saat konfigurasi belum lengkap) */}\n {showWizard && (\n <SetupWizard\n issues={configIssues}\n onDismiss={() => setWizardDismissed(true)}\n supabase={supabase}\n />\n )}\n\n <div className=\"rdb-view-container\">\n\n {/* Header + Filter */}\n <div className=\"rdb-header-panel\">\n <div className=\"rdb-header-top\">\n <div className=\"rdb-header-title-group\">\n <span className=\"rdb-h1\">{labels?.title ?? \"Dashboard\"}</span>\n {liveUpdateEnabled ? (\n <Badge status=\"success\">{labels?.liveUpdate ?? \"Live\"}</Badge>\n ) : null}\n </div>\n <Button variant=\"secondary\" size=\"sm\" onClick={() => onRefresh()} title={labels?.refresh ?? \"Refresh\"}>\n <Icon name=\"RotateCcw\" size={16} />\n </Button>\n </div>\n\n {error ? (\n <div className=\"rdb-error-banner\">\n <span>{error}</span>\n <Button variant=\"secondary\" size=\"sm\" onClick={() => onRefresh()}>\n {labels?.retry ?? \"Retry\"}\n </Button>\n </div>\n ) : null}\n\n <FilterPanel filters={filters} labels={labels}\n onFilterChange={onFilterChange} onResetFilters={onResetFilters} />\n </div>\n\n {/* Stat Cards */}\n <div className=\"rdb-stats-grid\">\n {loading\n ? Array.from({ length: config.widgets.stats.length || 4 }).map((_, i) => (\n <SkeletonLoader key={i} style={{ height: 112 }} />\n ))\n : config.widgets.stats.map(widget => (\n <StatCard key={widget.id}\n label={labels?.[widget.label] ?? widget.label}\n value={data?.stats?.[widget.valueKey] ?? 0}\n icon={widget.icon}\n format={widget.format}\n accentColor={widget.accentColor}\n />\n ))}\n </div>\n\n {/* Chart Cards */}\n <div className=\"rdb-charts-grid\">\n {config.widgets.charts.map(widget => (\n <ChartCard key={widget.id} widget={widget} labels={labels ?? {}}\n loading={loading} filters={filters ?? {}} chartData={data?.charts ?? {}} />\n ))}\n </div>\n\n {/* Data Table */}\n <div className=\"rdb-card\" style={{ padding: 16 }}>\n <div style={{ display:\"flex\", alignItems:\"center\", gap:8, marginBottom:12 }}\n className=\"rdb-h3\">\n <Icon name={config.widgets.table.icon ?? \"Calendar\"} size={18} />\n {labels?.[config.widgets.table.label] ?? config.widgets.table.label}\n </div>\n {loading ? (\n <SkeletonLoader style={{ height: 192 }} />\n ) : (\n <DataTable\n columns={config.widgets.table.columns}\n data={data?.table?.recentBookings ?? []}\n labels={labels ?? {}}\n dateLocale={dateLocale ?? \"id-ID\"}\n emptyLabel={labels?.[config.widgets.table.emptyLabel] ?? config.widgets.table.emptyLabel}\n searchable={true}\n sortable={true}\n pageSize={10}\n />\n )}\n </div>\n\n </div>\n </div>\n );\n}\n\nReusableDashboardView.propTypes = {\n config: PropTypes.object.isRequired,\n labels: PropTypes.object.isRequired,\n loading: PropTypes.bool,\n error: PropTypes.string,\n filters: PropTypes.object,\n onFilterChange: PropTypes.func.isRequired,\n onResetFilters: PropTypes.func.isRequired,\n onRefresh: PropTypes.func.isRequired,\n data: PropTypes.object,\n dateLocale: PropTypes.string,\n liveUpdateEnabled: PropTypes.bool,\n /** Supabase client — aktifkan fitur baca tabel di wizard */\n supabase: PropTypes.object,\n /** Hasil createDashboardConfig() — untuk validasi otomatis wizard */\n dashboardConfig: PropTypes.object,\n};\n","import React, { useState } from \"react\";\r\nimport PropTypes from \"prop-types\";\r\nimport \"./dashboard.css\";\r\n\r\n/**\r\n * SetupWizard — Pop-up wizard yang muncul saat modul dashboard belum\r\n * dikonfigurasi dengan benar. Memandu developer step-by-step melalui\r\n * 3 langkah konfigurasi (Data Source → Adapter → Widget Config).\r\n *\r\n * Opsi B dari revisi dosen: \"Pop-up yang bisa setting itu langsung\r\n * dengan menggunakan API dari Supabase agar dapat membacanya secara langsung.\"\r\n *\r\n * Wizard ini:\r\n * - Mendeteksi konfigurasi yang belum lengkap secara otomatis\r\n * - Menampilkan checklist masalah yang ditemukan\r\n * - Menyediakan 3-step guide interaktif\r\n * - Pada step \"Data Source\", mencoba membaca tabel Supabase via API\r\n * sehingga developer tahu tabel apa yang tersedia di project mereka\r\n *\r\n * @param {object} props\r\n * @param {string[]} props.issues - Daftar masalah konfigurasi yang ditemukan.\r\n * @param {Function} [props.onDismiss] - Callback saat wizard ditutup (developer memilih \"Lanjutkan tanpa wizard\").\r\n * @param {object} [props.supabase] - Instance Supabase client (opsional, untuk fitur baca tabel langsung).\r\n */\r\nexport function SetupWizard({ issues = [], onDismiss, supabase }) {\r\n const [step, setStep] = useState(0); // 0=overview, 1=source, 2=adapter, 3=config\r\n const [tables, setTables] = useState(null);\r\n const [loadingTables, setLoadingTables] = useState(false);\r\n const [tableError, setTableError] = useState(\"\");\r\n const [dismissed, setDismissed] = useState(false);\r\n\r\n if (dismissed) return null;\r\n\r\n const steps = [\r\n { id: 0, label: \"Overview\", icon: \"🏠\" },\r\n { id: 1, label: \"1. Data Source\", icon: \"🗄️\" },\r\n { id: 2, label: \"2. Adapter\", icon: \"🔄\" },\r\n { id: 3, label: \"3. Widget Config\",icon: \"⚙️\" },\r\n ];\r\n\r\n async function handleReadTables() {\r\n if (!supabase) {\r\n setTableError(\"Supabase client belum tersambung. Pastikan prop supabase sudah diisi.\");\r\n return;\r\n }\r\n setLoadingTables(true);\r\n setTableError(\"\");\r\n try {\r\n // Membaca daftar tabel publik dari information_schema Supabase\r\n const { data, error } = await supabase\r\n .from(\"information_schema.tables\")\r\n .select(\"table_name\")\r\n .eq(\"table_schema\", \"public\")\r\n .eq(\"table_type\", \"BASE TABLE\")\r\n .order(\"table_name\");\r\n\r\n if (error) throw error;\r\n setTables((data || []).map(r => r.table_name));\r\n } catch (err) {\r\n // Fallback: coba via RPC jika information_schema tidak bisa diakses\r\n try {\r\n const { data: rpcData } = await supabase.rpc(\"get_tables\");\r\n if (rpcData) {\r\n setTables(rpcData.map(r => r.table_name || r));\r\n } else {\r\n setTableError(\"Tidak dapat membaca tabel. Pastikan RLS mengizinkan akses atau tambahkan policy SELECT untuk anon.\");\r\n }\r\n } catch {\r\n setTableError(\"Gagal membaca tabel dari Supabase: \" + (err?.message || \"Unknown error\"));\r\n }\r\n } finally {\r\n setLoadingTables(false);\r\n }\r\n }\r\n\r\n function handleDismiss() {\r\n setDismissed(true);\r\n if (onDismiss) onDismiss();\r\n }\r\n\r\n return (\r\n <div className=\"rdb-wizard-overlay\" role=\"dialog\" aria-modal=\"true\" aria-label=\"Dashboard Setup Wizard\">\r\n <div className=\"rdb-wizard-modal\">\r\n\r\n {/* Header */}\r\n <div className=\"rdb-wizard-header\">\r\n <div className=\"rdb-wizard-header-title\">\r\n <span className=\"rdb-wizard-logo\">🛠️</span>\r\n <div>\r\n <div className=\"rdb-h2\" style={{ margin: 0 }}>Setup Dashboard</div>\r\n <div className=\"rdb-caption\">Panduan konfigurasi modul @rozaqi02/reusable-dashboard</div>\r\n </div>\r\n </div>\r\n <button\r\n type=\"button\"\r\n className=\"rdb-wizard-close\"\r\n onClick={handleDismiss}\r\n aria-label=\"Tutup wizard\"\r\n title=\"Lanjutkan tanpa wizard\"\r\n >✕</button>\r\n </div>\r\n\r\n {/* Step Nav */}\r\n <div className=\"rdb-wizard-steps\">\r\n {steps.map(s => (\r\n <button\r\n key={s.id}\r\n type=\"button\"\r\n className={`rdb-wizard-step-btn ${step === s.id ? \"rdb-wizard-step-active\" : \"\"}`}\r\n onClick={() => setStep(s.id)}\r\n >\r\n <span>{s.icon}</span>\r\n <span>{s.label}</span>\r\n </button>\r\n ))}\r\n </div>\r\n\r\n {/* Content */}\r\n <div className=\"rdb-wizard-body\">\r\n\r\n {/* ── STEP 0: Overview ── */}\r\n {step === 0 && (\r\n <div className=\"rdb-wizard-section\">\r\n <div className=\"rdb-wizard-alert\">\r\n <span className=\"rdb-wizard-alert-icon\">⚠️</span>\r\n <div>\r\n <div className=\"rdb-body\" style={{ fontWeight: 600 }}>\r\n Dashboard belum terkonfigurasi\r\n </div>\r\n <div className=\"rdb-caption\" style={{ marginTop: 4 }}>\r\n Ditemukan {issues.length} masalah yang perlu diselesaikan sebelum dashboard dapat berjalan.\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {issues.length > 0 && (\r\n <div className=\"rdb-wizard-issues\">\r\n <div className=\"rdb-caption\" style={{ fontWeight: 600, marginBottom: 8 }}>\r\n Masalah yang ditemukan:\r\n </div>\r\n {issues.map((issue, i) => (\r\n <div key={i} className=\"rdb-wizard-issue-item\">\r\n <span className=\"rdb-wizard-issue-icon\">❌</span>\r\n <span className=\"rdb-body\">{issue}</span>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n\r\n <div className=\"rdb-wizard-flow\">\r\n <div className=\"rdb-caption\" style={{ fontWeight: 600, marginBottom: 12 }}>\r\n Alur konfigurasi yang perlu dilakukan:\r\n </div>\r\n <div className=\"rdb-wizard-flow-steps\">\r\n {[\r\n { num: \"1\", label: \"Data Source\", desc: \"Tulis fungsi query ke Supabase\" },\r\n { num: \"→\", label: \"\", desc: \"\" },\r\n { num: \"2\", label: \"Adapter\", desc: \"Petakan data mentah ke format standar\" },\r\n { num: \"→\", label: \"\", desc: \"\" },\r\n { num: \"3\", label: \"Widget Config\", desc: \"Definisikan widget yang ditampilkan\" },\r\n ].map((item, i) => item.num === \"→\" ? (\r\n <div key={i} className=\"rdb-wizard-flow-arrow\">→</div>\r\n ) : (\r\n <div key={i} className=\"rdb-wizard-flow-box\">\r\n <div className=\"rdb-wizard-flow-num\">{item.num}</div>\r\n <div className=\"rdb-wizard-flow-label\">{item.label}</div>\r\n <div className=\"rdb-wizard-flow-desc\">{item.desc}</div>\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n\r\n <div style={{ display: \"flex\", gap: 8, justifyContent: \"flex-end\", marginTop: 16 }}>\r\n <button type=\"button\" className=\"rdb-btn rdb-btn-secondary rdb-btn-sm\" onClick={handleDismiss}>\r\n Lanjutkan tanpa wizard\r\n </button>\r\n <button type=\"button\" className=\"rdb-btn rdb-btn-primary rdb-btn-sm\" onClick={() => setStep(1)}>\r\n Mulai panduan →\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* ── STEP 1: Data Source ── */}\r\n {step === 1 && (\r\n <div className=\"rdb-wizard-section\">\r\n <div className=\"rdb-wizard-step-title\">\r\n <span className=\"rdb-wizard-step-num\">1</span>\r\n <span className=\"rdb-h3\" style={{ margin: 0 }}>Data Source</span>\r\n </div>\r\n <div className=\"rdb-body\" style={{ color: \"var(--rdb-text-muted)\", marginBottom: 12 }}>\r\n Data Source adalah fungsi yang membaca data dari Supabase. Buat file\r\n <code className=\"rdb-wizard-code-inline\"> src/datasources/myDataSource.js</code> dengan isi berikut:\r\n </div>\r\n\r\n <pre className=\"rdb-wizard-code\">{`// src/datasources/myDataSource.js\r\nexport function createMySupabaseSource(supabase) {\r\n return {\r\n async fetchDashboardSnapshot({ fromISO, toISO, statusScope }) {\r\n const { data: orders = [] } = await supabase\r\n .from(\"MY_TABLE\") // ← ganti nama tabel kamu\r\n .select(\"id, created_at, total_price, status, customer_name\")\r\n .gte(\"created_at\", fromISO)\r\n .lte(\"created_at\", toISO)\r\n .order(\"created_at\", { ascending: true });\r\n\r\n const { data: recent = [] } = await supabase\r\n .from(\"MY_TABLE\")\r\n .select(\"id, created_at, customer_name, total_price, status\")\r\n .order(\"created_at\", { ascending: false })\r\n .limit(10);\r\n\r\n return {\r\n bookings: orders, // WAJIB: nama harus \"bookings\"\r\n recent, // WAJIB: nama harus \"recent\"\r\n packageLocales: [],\r\n staticCounts: { packages: 0, sections: 0 },\r\n };\r\n },\r\n\r\n // Opsional: live update\r\n subscribeLiveUpdate(onEvent) {\r\n const ch = supabase.channel(\"my-dashboard-live\")\r\n .on(\"postgres_changes\",\r\n { event: \"*\", schema: \"public\", table: \"MY_TABLE\" }, onEvent)\r\n .subscribe();\r\n return () => supabase.removeChannel(ch);\r\n },\r\n };\r\n}`}</pre>\r\n\r\n {/* Fitur baca tabel Supabase langsung */}\r\n <div className=\"rdb-wizard-supabase-reader\">\r\n <div className=\"rdb-caption\" style={{ fontWeight: 600, marginBottom: 8 }}>\r\n 🔍 Baca tabel dari Supabase project kamu secara langsung:\r\n </div>\r\n <button\r\n type=\"button\"\r\n className=\"rdb-btn rdb-btn-secondary rdb-btn-sm\"\r\n onClick={handleReadTables}\r\n disabled={loadingTables}\r\n >\r\n {loadingTables ? \"Membaca...\" : \"Tampilkan daftar tabel Supabase\"}\r\n </button>\r\n\r\n {tableError && (\r\n <div className=\"rdb-wizard-table-error\">{tableError}</div>\r\n )}\r\n\r\n {tables && tables.length > 0 && (\r\n <div className=\"rdb-wizard-table-list\">\r\n <div className=\"rdb-caption\" style={{ marginBottom: 6 }}>\r\n Tabel ditemukan ({tables.length}):\r\n </div>\r\n <div className=\"rdb-wizard-table-chips\">\r\n {tables.map(t => (\r\n <span key={t} className=\"rdb-wizard-chip\">{t}</span>\r\n ))}\r\n </div>\r\n <div className=\"rdb-caption\" style={{ marginTop: 8, color: \"var(--rdb-text-muted)\" }}>\r\n Ganti <code className=\"rdb-wizard-code-inline\">MY_TABLE</code> di contoh kode di atas dengan nama tabel yang sesuai.\r\n </div>\r\n </div>\r\n )}\r\n\r\n {!supabase && (\r\n <div className=\"rdb-wizard-table-error\">\r\n Tambahkan prop <code className=\"rdb-wizard-code-inline\">supabase</code> ke\r\n <code className=\"rdb-wizard-code-inline\"> &lt;ReusableDashboardView supabase={\"{supabase}\"} /&gt;</code> untuk mengaktifkan fitur ini.\r\n </div>\r\n )}\r\n </div>\r\n\r\n <div style={{ display: \"flex\", gap: 8, justifyContent: \"flex-end\", marginTop: 16 }}>\r\n <button type=\"button\" className=\"rdb-btn rdb-btn-secondary rdb-btn-sm\" onClick={() => setStep(0)}>← Kembali</button>\r\n <button type=\"button\" className=\"rdb-btn rdb-btn-primary rdb-btn-sm\" onClick={() => setStep(2)}>Lanjut →</button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* ── STEP 2: Adapter ── */}\r\n {step === 2 && (\r\n <div className=\"rdb-wizard-section\">\r\n <div className=\"rdb-wizard-step-title\">\r\n <span className=\"rdb-wizard-step-num\">2</span>\r\n <span className=\"rdb-h3\" style={{ margin: 0 }}>Data Adapter</span>\r\n </div>\r\n <div className=\"rdb-body\" style={{ color: \"var(--rdb-text-muted)\", marginBottom: 12 }}>\r\n Adapter mengubah data mentah dari Data Source ke format standar yang dimengerti komponen dashboard.\r\n Buat file <code className=\"rdb-wizard-code-inline\">src/adapters/myAdapter.js</code>:\r\n </div>\r\n\r\n <pre className=\"rdb-wizard-code\">{`// src/adapters/myAdapter.js\r\nimport { toNumber, buildDayBuckets } from \"@rozaqi02/reusable-dashboard\";\r\n\r\nexport function createEmptyMyData() {\r\n return {\r\n stats: { bookingsConfirm: 0, revenueConfirm: 0 },\r\n charts: {\r\n dailyTrends: [],\r\n statusDistribution: [],\r\n audienceDistribution: [],\r\n topPackages: [],\r\n },\r\n table: { recentBookings: [] },\r\n };\r\n}\r\n\r\nexport function adaptMyData({ raw, range, dateLocale, labels }) {\r\n if (!raw) return createEmptyMyData();\r\n\r\n const buckets = buildDayBuckets(range.daysWindow, range.fromISO, dateLocale);\r\n const dayMap = new Map(buckets.map(b => [b.dateKey, b]));\r\n const statusMap = new Map();\r\n let confirmed = 0, revenue = 0;\r\n\r\n (raw.bookings || []).forEach(row => {\r\n const status = String(row.status || \"pending\").toLowerCase();\r\n const amount = toNumber(row.total_price); // ← sesuaikan nama kolom\r\n const dayKey = String(row.created_at || \"\").slice(0, 10);\r\n\r\n statusMap.set(status, (statusMap.get(status) || 0) + 1);\r\n const bucket = dayMap.get(dayKey);\r\n if (bucket && status === \"confirmed\") {\r\n bucket.count += 1;\r\n bucket.revenue += amount;\r\n }\r\n if (status === \"confirmed\") { confirmed++; revenue += amount; }\r\n });\r\n\r\n return {\r\n stats: { bookingsConfirm: confirmed, revenueConfirm: revenue },\r\n charts: {\r\n dailyTrends: buckets,\r\n statusDistribution: Array.from(statusMap.entries())\r\n .map(([status, count]) => ({\r\n status,\r\n label: labels?.formatStatusLabel?.(status) || status,\r\n count,\r\n })),\r\n audienceDistribution: [],\r\n topPackages: [],\r\n },\r\n table: {\r\n recentBookings: (raw.recent || []).map(row => ({\r\n id: row.id,\r\n createdAt: row.created_at,\r\n customerName: row.customer_name || \"-\",\r\n packageName: row.service_type || \"-\", // ← sesuaikan nama kolom\r\n audienceLabel: \"-\",\r\n totalIDR: toNumber(row.total_price),\r\n status: String(row.status || \"pending\").toLowerCase(),\r\n statusLabel: labels?.formatStatusLabel?.(row.status) || row.status,\r\n })),\r\n },\r\n };\r\n}`}</pre>\r\n\r\n <div className=\"rdb-wizard-tip\">\r\n 💡 <strong>Aturan penting:</strong> key di <code className=\"rdb-wizard-code-inline\">stats</code> (mis. <code className=\"rdb-wizard-code-inline\">bookingsConfirm</code>)\r\n harus cocok dengan <code className=\"rdb-wizard-code-inline\">valueKey</code> di widget config pada Step 3.\r\n </div>\r\n\r\n <div style={{ display: \"flex\", gap: 8, justifyContent: \"flex-end\", marginTop: 16 }}>\r\n <button type=\"button\" className=\"rdb-btn rdb-btn-secondary rdb-btn-sm\" onClick={() => setStep(1)}>← Kembali</button>\r\n <button type=\"button\" className=\"rdb-btn rdb-btn-primary rdb-btn-sm\" onClick={() => setStep(3)}>Lanjut →</button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* ── STEP 3: Widget Config ── */}\r\n {step === 3 && (\r\n <div className=\"rdb-wizard-section\">\r\n <div className=\"rdb-wizard-step-title\">\r\n <span className=\"rdb-wizard-step-num\">3</span>\r\n <span className=\"rdb-h3\" style={{ margin: 0 }}>Widget Config & Rangkaian Akhir</span>\r\n </div>\r\n <div className=\"rdb-body\" style={{ color: \"var(--rdb-text-muted)\", marginBottom: 12 }}>\r\n Widget Config mendefinisikan tampilan dashboard: kartu mana, chart apa, kolom tabel apa.\r\n Gunakan <code className=\"rdb-wizard-code-inline\">createDashboardConfig()</code> untuk mengemas semuanya jadi 1 objek:\r\n </div>\r\n\r\n <pre className=\"rdb-wizard-code\">{`// src/pages/MyDashboard.jsx\r\nimport { supabase } from \"../lib/supabaseClient\";\r\nimport {\r\n ReusableDashboardView,\r\n useReusableDashboard,\r\n createDashboardConfig,\r\n} from \"@rozaqi02/reusable-dashboard\";\r\n\r\nimport { createMySupabaseSource } from \"../datasources/myDataSource\";\r\nimport { adaptMyData, createEmptyMyData } from \"../adapters/myAdapter\";\r\n\r\n// 1. Widget Config — deklaratif, tentukan apa yang tampil\r\nconst myWidgetConfig = {\r\n id: \"my.dashboard\",\r\n defaultFilters: { statusScope: \"confirmed\", daysPreset: 30 },\r\n widgets: {\r\n stats: [\r\n { id: \"orders\", label: \"confirmedBookings\", icon: \"TrendingUp\",\r\n valueKey: \"bookingsConfirm\", format: \"number\", accentColor: \"blue\" },\r\n { id: \"revenue\", label: \"confirmedRevenue\", icon: \"DollarSign\",\r\n valueKey: \"revenueConfirm\", format: \"currency\", accentColor: \"green\" },\r\n ],\r\n charts: [\r\n { id: \"trend\", type: \"dailyArea\", label: \"dailyTrends\", icon: \"BarChart3\" },\r\n { id: \"status\", type: \"statusPie\", label: \"statusDistribution\", icon: \"PieChart\" },\r\n ],\r\n table: {\r\n id: \"recent\", label: \"recentBookings\", icon: \"Calendar\",\r\n emptyLabel: \"noRecentBookings\",\r\n columns: [\r\n { id: \"date\", label: \"date\", accessor: \"createdAt\", type: \"date\" },\r\n { id: \"customer\", label: \"customer\", accessor: \"customerName\" },\r\n { id: \"total\", label: \"total\", accessor: \"totalIDR\", type: \"currency\" },\r\n { id: \"status\", label: \"status\", accessor: \"statusLabel\",\r\n type: \"statusBadge\", statusAccessor: \"status\" },\r\n ],\r\n },\r\n },\r\n};\r\n\r\n// 2. Kemas semua jadi 1 objek (buat di luar komponen, sekali saja)\r\nconst dashConfig = createDashboardConfig({\r\n widgetConfig: myWidgetConfig,\r\n dataSource: createMySupabaseSource(supabase),\r\n adapter: adaptMyData,\r\n createEmptyState: createEmptyMyData,\r\n languageCode: \"id\",\r\n dateLocale: \"id-ID\",\r\n});\r\n\r\n// 3. Labels — teks UI\r\nconst labels = { title: \"Dashboard Saya\", refresh: \"Refresh\",\r\n liveUpdate: \"Live\", loadFailed: \"Gagal memuat.\", retry: \"Coba Lagi\",\r\n confirmedBookings: \"Total Order\", confirmedRevenue: \"Total Pendapatan\",\r\n dailyTrends: \"Tren Harian\", statusDistribution: \"Distribusi Status\",\r\n recentBookings: \"Order Terbaru\", noRecentBookings: \"Belum ada order\",\r\n date: \"Tanggal\", customer: \"Pelanggan\", total: \"Total\", status: \"Status\",\r\n bookingsMetric: \"Order\", revenueMetric: \"Pendapatan\",\r\n confirmedBookingMetric: \"Order (Confirmed)\",\r\n confirmedRevenueMetric: \"Pendapatan (Confirmed)\",\r\n dayLabel: n => n + \" hari\",\r\n formatStatusLabel: s =>\r\n ({ confirmed: \"Selesai\", pending: \"Proses\", cancelled: \"Batal\" })[s] || s,\r\n formatAudienceLabel: v => v || \"-\",\r\n};\r\n\r\n// 4. Render — selesai!\r\nexport default function MyDashboard() {\r\n const state = useReusableDashboard({ ...dashConfig, labels });\r\n return (\r\n <ReusableDashboardView\r\n config={dashConfig.config}\r\n labels={labels}\r\n loading={state.loading}\r\n error={state.error}\r\n filters={state.filters}\r\n onFilterChange={state.updateFilter}\r\n onResetFilters={state.resetFilters}\r\n onRefresh={state.refresh}\r\n data={state.data}\r\n dateLocale={dashConfig.dateLocale}\r\n liveUpdateEnabled={state.liveUpdateEnabled}\r\n />\r\n );\r\n}`}</pre>\r\n\r\n <div className=\"rdb-wizard-tip\">\r\n ✅ <strong>Selesai!</strong> Jalankan <code className=\"rdb-wizard-code-inline\">npm start</code> dan\r\n buka halaman dashboard. Wizard ini tidak akan muncul lagi setelah konfigurasi valid.\r\n </div>\r\n\r\n <div style={{ display: \"flex\", gap: 8, justifyContent: \"flex-end\", marginTop: 16 }}>\r\n <button type=\"button\" className=\"rdb-btn rdb-btn-secondary rdb-btn-sm\" onClick={() => setStep(2)}>← Kembali</button>\r\n <button type=\"button\" className=\"rdb-btn rdb-btn-primary rdb-btn-sm\" onClick={handleDismiss}>\r\n Tutup & lanjutkan ✓\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nSetupWizard.propTypes = {\r\n issues: PropTypes.arrayOf(PropTypes.string),\r\n onDismiss: PropTypes.func,\r\n supabase: PropTypes.object,\r\n};\r\n","export function createDashboardLabels(t) {\n const labels = {\n title: t(\"admin.dashboard.title\", { defaultValue: \"Dashboard\" }),\n refresh: t(\"admin.dashboard.refresh\", { defaultValue: \"Refresh\" }),\n liveUpdate: t(\"admin.dashboard.liveUpdate\", { defaultValue: \"Live update\" }),\n loadFailed: t(\"admin.dashboard.loadFailed\", {\n defaultValue: \"Failed to load dashboard data.\",\n }),\n retry: t(\"admin.dashboard.retry\", { defaultValue: \"Retry\" }),\n confirmedOnly: t(\"admin.dashboard.filters.confirmedOnly\", {\n defaultValue: \"Confirmed only\",\n }),\n pendingOnly: t(\"admin.dashboard.filters.pendingOnly\", {\n defaultValue: \"Pending only\",\n }),\n allStatus: t(\"admin.dashboard.filters.allStatus\", {\n defaultValue: \"All status\",\n }),\n showPendingOverlay: t(\"admin.dashboard.filters.showPendingOverlay\", {\n defaultValue: \"Show pending overlay\",\n }),\n allAudience: t(\"admin.dashboard.filters.allAudience\", {\n defaultValue: \"All audience\",\n }),\n audienceDomestic: t(\"explore.domestic\", { defaultValue: \"Domestic\" }),\n audienceForeign: t(\"explore.foreign\", { defaultValue: \"Foreign\" }),\n customDate: t(\"admin.dashboard.filters.customDate\", {\n defaultValue: \"Custom\",\n }),\n reset: t(\"admin.dashboard.filters.reset\", { defaultValue: \"Reset\" }),\n topSort: t(\"admin.dashboard.filters.topSort\", {\n defaultValue: \"Top packages sort\",\n }),\n sortBookings: t(\"admin.dashboard.filters.sortBookings\", {\n defaultValue: \"Bookings\",\n }),\n sortRevenue: t(\"admin.dashboard.filters.sortRevenue\", {\n defaultValue: \"Revenue\",\n }),\n sortDesc: t(\"admin.dashboard.filters.sortDesc\", { defaultValue: \"Desc\" }),\n sortAsc: t(\"admin.dashboard.filters.sortAsc\", { defaultValue: \"Asc\" }),\n confirmedBookings: t(\"admin.dashboard.cards.confirmedBookings\", {\n defaultValue: \"Confirmed Bookings\",\n }),\n confirmedRevenue: t(\"admin.dashboard.cards.confirmedRevenue\", {\n defaultValue: \"Revenue (Confirmed)\",\n }),\n avgRevenue: t(\"admin.dashboard.cards.avgRevenue\", {\n defaultValue: \"Avg Revenue / Booking\",\n }),\n conversionRate: t(\"admin.dashboard.cards.conversionRate\", {\n defaultValue: \"Conversion Rate\",\n }),\n totalProducts: t(\"admin.dashboard.cards.totalProducts\", {\n defaultValue: \"Total Products\",\n }),\n totalCustomers: t(\"admin.dashboard.cards.totalCustomers\", {\n defaultValue: \"Total Customers\",\n }),\n dailyTrends: t(\"admin.dashboard.sections.dailyTrends\", {\n defaultValue: \"Daily Trends\",\n }),\n statusDistribution: t(\"admin.dashboard.sections.statusDistribution\", {\n defaultValue: \"Status Distribution\",\n }),\n audienceDistribution: t(\"admin.dashboard.sections.audienceDistribution\", {\n defaultValue: \"Audience Distribution\",\n }),\n topPackages: t(\"admin.dashboard.sections.topPackages\", {\n defaultValue: \"Top Packages\",\n }),\n recentBookings: t(\"admin.dashboard.sections.recentBookings\", {\n defaultValue: \"Recent Bookings\",\n }),\n date: t(\"admin.dashboard.table.date\", { defaultValue: \"Date\" }),\n customer: t(\"admin.dashboard.table.customer\", { defaultValue: \"Customer\" }),\n package: t(\"admin.dashboard.table.package\", { defaultValue: \"Package\" }),\n audience: t(\"admin.dashboard.table.audience\", { defaultValue: \"Audience\" }),\n total: t(\"admin.dashboard.table.total\", { defaultValue: \"Total\" }),\n status: t(\"admin.dashboard.table.status\", { defaultValue: \"Status\" }),\n noRecentBookings: t(\"admin.dashboard.emptyRecent\", {\n defaultValue: \"No recent bookings\",\n }),\n bookingsMetric: t(\"admin.dashboard.metrics.bookings\", {\n defaultValue: \"Bookings\",\n }),\n revenueMetric: t(\"admin.dashboard.metrics.revenue\", {\n defaultValue: \"Revenue\",\n }),\n pendingMetric: t(\"admin.dashboard.metrics.pendingBookings\", {\n defaultValue: \"Bookings (Pending)\",\n }),\n confirmedBookingMetric: t(\"admin.dashboard.metrics.confirmedBookings\", {\n defaultValue: \"Bookings (Confirmed)\",\n }),\n confirmedRevenueMetric: t(\"admin.dashboard.metrics.confirmedRevenue\", {\n defaultValue: \"Revenue (Confirmed)\",\n }),\n unknownAudience: t(\"admin.dashboard.filters.unknownAudience\", {\n defaultValue: \"Unknown\",\n }),\n };\n\n labels.dayLabel = (count) =>\n t(\"admin.dashboard.filters.dayWindow\", {\n count,\n defaultValue: \"{{count}} days\",\n });\n\n labels.formatStatusLabel = (status) => {\n const normalized = String(status || \"pending\").toLowerCase();\n const defaultValue =\n normalized.charAt(0).toUpperCase() + normalized.slice(1);\n\n return t(`admin.dashboard.status.${normalized}`, { defaultValue });\n };\n\n labels.formatAudienceLabel = (value) => {\n if (value === \"domestic\") return labels.audienceDomestic;\n if (value === \"foreign\") return labels.audienceForeign;\n return labels.unknownAudience;\n };\n\n return labels;\n}\n"],"mappings":"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","names":["ensureNoError","import_react","import_react","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","MIN_YEAR","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","import_react","import_prop_types","React","PropTypes","React","_a","issues","PropTypes"]}
1
+ {"version":3,"sources":["../src/index.js","../src/config/cidikaWidgetConfig.js","../src/config/dummyUmkmWidgetConfig.js","../src/config/tokoSepatuWidgetConfig.js","../src/config/createDashboardConfig.js","../src/utils/formatters.js","../src/utils/adapterHelpers.js","../src/data-adapter/cidikaDashboardAdapter.js","../src/data-adapter/dummyUmkmDashboardAdapter.js","../src/data-adapter/tokoSepatuDashboardAdapter.js","../src/data-source/cidikaSupabaseSource.js","../src/data-source/tokoSepatuSupabaseSource.js","../src/hooks/useReusableDashboard.js","../src/utils/dateRange.js","../src/hooks/useRealtimeUpdate.js","../src/presentation/atoms/Button.jsx","../src/presentation/atoms/Input.jsx","../src/presentation/atoms/Icon.jsx","../src/presentation/atoms/Typography.jsx","../src/presentation/atoms/Badge.jsx","../src/presentation/atoms/SkeletonLoader.jsx","../src/presentation/molecules/StatCard.jsx","../src/presentation/molecules/SearchBar.jsx","../src/presentation/molecules/DateRangeFilter.jsx","../src/presentation/molecules/ChartHeader.jsx","../src/presentation/organisms/DataTable.jsx","../src/presentation/organisms/ChartCard.jsx","../src/presentation/organisms/FilterPanel.jsx","../src/presentation/organisms/SidebarNavigation.jsx","../src/presentation/organisms/TopbarHeader.jsx","../src/presentation/templates/DashboardLayout.jsx","../src/presentation/ReusableDashboardView.jsx","../src/presentation/SetupWizard.jsx","../src/utils/labels.js"],"sourcesContent":["// ──────────────────────────────────────────────────────────────────────────────\n// Config\n// ──────────────────────────────────────────────────────────────────────────────\nexport { cidikaWidgetConfig } from \"./config/cidikaWidgetConfig.js\";\nexport { dummyUmkmWidgetConfig } from \"./config/dummyUmkmWidgetConfig.js\";\nexport { tokoSepatuWidgetConfig } from \"./config/tokoSepatuWidgetConfig.js\";\n\n// Factory — mengemas semua konfigurasi menjadi 1 objek tunggal (revisi dosen)\nexport {\n createDashboardConfig,\n validateDashboardConfig,\n} from \"./config/createDashboardConfig.js\";\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Data Adapter\n// ──────────────────────────────────────────────────────────────────────────────\nexport {\n adaptCidikaDashboardData,\n createEmptyDashboardData,\n} from \"./data-adapter/cidikaDashboardAdapter.js\";\nexport {\n adaptDummyUmkmData,\n createEmptyDummyUmkmData,\n} from \"./data-adapter/dummyUmkmDashboardAdapter.js\";\nexport {\n adaptTokoSepatuData,\n createEmptyTokoSepatuData,\n} from \"./data-adapter/tokoSepatuDashboardAdapter.js\";\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Data Source\n// ──────────────────────────────────────────────────────────────────────────────\nexport { createCidikaSupabaseSource } from \"./data-source/cidikaSupabaseSource.js\";\nexport { createTokoSepatuSupabaseSource } from \"./data-source/tokoSepatuSupabaseSource.js\";\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Hook\n// ──────────────────────────────────────────────────────────────────────────────\nexport { useReusableDashboard } from \"./hooks/useReusableDashboard.js\";\nexport { useRealtimeUpdate } from \"./hooks/useRealtimeUpdate.js\";\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Presentation — Atoms\n// ──────────────────────────────────────────────────────────────────────────────\nexport { default as Button } from \"./presentation/atoms/Button.jsx\";\nexport { default as Input } from \"./presentation/atoms/Input.jsx\";\nexport { default as Icon, resolveIcon } from \"./presentation/atoms/Icon.jsx\";\nexport { default as Typography } from \"./presentation/atoms/Typography.jsx\";\nexport { default as Badge } from \"./presentation/atoms/Badge.jsx\";\nexport { default as SkeletonLoader } from \"./presentation/atoms/SkeletonLoader.jsx\";\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Presentation — Molecules\n// ──────────────────────────────────────────────────────────────────────────────\nexport { default as StatCard } from \"./presentation/molecules/StatCard.jsx\";\nexport { default as SearchBar } from \"./presentation/molecules/SearchBar.jsx\";\nexport { default as DateRangeFilter } from \"./presentation/molecules/DateRangeFilter.jsx\";\nexport { default as ChartHeader } from \"./presentation/molecules/ChartHeader.jsx\";\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Presentation — Organisms\n// ──────────────────────────────────────────────────────────────────────────────\nexport { default as DataTable } from \"./presentation/organisms/DataTable.jsx\";\nexport { default as ChartCard } from \"./presentation/organisms/ChartCard.jsx\";\nexport { default as FilterPanel } from \"./presentation/organisms/FilterPanel.jsx\";\nexport { default as SidebarNavigation } from \"./presentation/organisms/SidebarNavigation.jsx\";\nexport { default as TopbarHeader } from \"./presentation/organisms/TopbarHeader.jsx\";\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Presentation — Templates\n// ──────────────────────────────────────────────────────────────────────────────\nexport { default as DashboardLayout } from \"./presentation/templates/DashboardLayout.jsx\";\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Presentation — Page-Level View\n// ──────────────────────────────────────────────────────────────────────────────\nexport { ReusableDashboardView } from \"./presentation/ReusableDashboardView.jsx\";\n\n// Setup Wizard — pop-up panduan konfigurasi (revisi dosen Opsi B)\nexport { SetupWizard } from \"./presentation/SetupWizard.jsx\";\n\n// ──────────────────────────────────────────────────────────────────────────────\n// Utils\n// ──────────────────────────────────────────────────────────────────────────────\nexport { createDashboardLabels } from \"./utils/labels.js\";\nexport {\n createDefaultFilters,\n formatYYYYMMDD,\n resolveDateRange,\n} from \"./utils/dateRange.js\";\nexport { formatDate, formatIDR, shortId } from \"./utils/formatters.js\";\nexport {\n toNumber,\n buildDayBuckets,\n sortMapEntries,\n} from \"./utils/adapterHelpers.js\";\n\n","export const cidikaWidgetConfig = {\n id: \"cidika.travel.dashboard\",\n defaultFilters: {\n statusScope: \"confirmed\",\n includePendingOverlay: false,\n audience: \"\",\n daysPreset: 30,\n sortPkgBy: \"bookings\",\n sortPkgDir: \"desc\",\n },\n widgets: {\n stats: [\n {\n id: \"bookingsConfirm\",\n label: \"confirmedBookings\",\n icon: \"TrendingUp\",\n valueKey: \"bookingsConfirm\",\n format: \"number\",\n accentColor: \"blue\",\n },\n {\n id: \"revenueConfirm\",\n label: \"confirmedRevenue\",\n icon: \"DollarSign\",\n valueKey: \"revenueConfirm\",\n format: \"currency\",\n accentColor: \"green\",\n },\n {\n id: \"avgRevenue\",\n label: \"avgRevenue\",\n icon: \"Users\",\n valueKey: \"avgRevenue\",\n format: \"currency\",\n accentColor: \"violet\",\n },\n {\n id: \"conversionRate\",\n label: \"conversionRate\",\n icon: \"PieChart\",\n valueKey: \"conversionRate\",\n format: \"percent\",\n accentColor: \"orange\",\n },\n ],\n charts: [\n {\n id: \"dailyTrends\",\n type: \"dailyArea\",\n label: \"dailyTrends\",\n icon: \"BarChart3\",\n },\n {\n id: \"statusDistribution\",\n type: \"statusPie\",\n label: \"statusDistribution\",\n icon: \"PieChart\",\n },\n {\n id: \"audienceDistribution\",\n type: \"audiencePie\",\n label: \"audienceDistribution\",\n icon: \"Users\",\n },\n {\n id: \"topPackages\",\n type: \"topPackagesBar\",\n label: \"topPackages\",\n icon: \"TrendingUp\",\n },\n ],\n table: {\n id: \"recentBookings\",\n label: \"recentBookings\",\n icon: \"Calendar\",\n emptyLabel: \"noRecentBookings\",\n columns: [\n { id: \"date\", label: \"date\", accessor: \"createdAt\", type: \"date\" },\n { id: \"customer\", label: \"customer\", accessor: \"customerName\" },\n { id: \"package\", label: \"package\", accessor: \"packageName\" },\n { id: \"audience\", label: \"audience\", accessor: \"audienceLabel\" },\n { id: \"total\", label: \"total\", accessor: \"totalIDR\", type: \"currency\" },\n {\n id: \"status\",\n label: \"status\",\n accessor: \"statusLabel\",\n type: \"statusBadge\",\n statusAccessor: \"status\",\n },\n ],\n },\n },\n};\n","export const dummyUmkmWidgetConfig = {\n id: \"dummy.umkm.dashboard\",\n defaultFilters: {\n statusScope: \"all\",\n includePendingOverlay: false,\n audience: \"\",\n daysPreset: 30,\n sortPkgBy: \"revenue\",\n sortPkgDir: \"desc\",\n },\n widgets: {\n stats: [\n {\n id: \"orders\",\n label: \"confirmedBookings\",\n icon: \"TrendingUp\",\n valueKey: \"bookingsConfirm\",\n format: \"number\",\n },\n {\n id: \"revenue\",\n label: \"confirmedRevenue\",\n icon: \"DollarSign\",\n valueKey: \"revenueConfirm\",\n format: \"currency\",\n },\n ],\n charts: [\n {\n id: \"revenueTrend\",\n type: \"dailyArea\",\n label: \"dailyTrends\",\n icon: \"BarChart3\",\n },\n {\n id: \"recentOrderStatus\",\n type: \"statusPie\",\n label: \"statusDistribution\",\n icon: \"PieChart\",\n },\n ],\n table: {\n id: \"recentOrders\",\n label: \"recentBookings\",\n icon: \"Calendar\",\n emptyLabel: \"noRecentBookings\",\n columns: [\n { id: \"date\", label: \"date\", accessor: \"createdAt\", type: \"date\" },\n { id: \"customer\", label: \"customer\", accessor: \"customerName\" },\n { id: \"total\", label: \"total\", accessor: \"totalIDR\", type: \"currency\" },\n ],\n },\n },\n};\n","/**\r\n * Widget Configuration — Toko Sepatu Online (Studi Kasus Dummy UMKM Non-Travel)\r\n *\r\n * Konfigurasi ini membuktikan bahwa modul reusable dashboard dapat digunakan\r\n * pada domain bisnis yang berbeda (retail sepatu) hanya dengan mendefinisikan\r\n * konfigurasi baru tanpa mengubah komponen inti.\r\n *\r\n * Perbedaan dengan cidikaWidgetConfig:\r\n * - 4 stat cards (orders, revenue, avg order, products)\r\n * - 2 charts (daily trends, status distribution)\r\n * - 1 tabel (recent orders) dengan 5 kolom\r\n * - Filter lebih sederhana (tanpa audience, tanpa pending overlay)\r\n */\r\nexport const tokoSepatuWidgetConfig = {\r\n id: \"toko.sepatu.dashboard\",\r\n defaultFilters: {\r\n statusScope: \"all\",\r\n includePendingOverlay: false,\r\n audience: \"\",\r\n daysPreset: 30,\r\n sortPkgBy: \"revenue\",\r\n sortPkgDir: \"desc\",\r\n },\r\n widgets: {\r\n stats: [\r\n {\r\n id: \"totalOrders\",\r\n label: \"confirmedBookings\",\r\n icon: \"TrendingUp\",\r\n valueKey: \"bookingsConfirm\",\r\n format: \"number\",\r\n accentColor: \"sky\",\r\n },\r\n {\r\n id: \"totalRevenue\",\r\n label: \"confirmedRevenue\",\r\n icon: \"DollarSign\",\r\n valueKey: \"revenueConfirm\",\r\n format: \"currency\",\r\n accentColor: \"green\",\r\n },\r\n {\r\n id: \"avgOrderValue\",\r\n label: \"avgRevenue\",\r\n icon: \"BarChart3\",\r\n valueKey: \"avgRevenue\",\r\n format: \"currency\",\r\n accentColor: \"violet\",\r\n },\r\n {\r\n id: \"totalProducts\",\r\n label: \"totalProducts\",\r\n icon: \"PieChart\",\r\n valueKey: \"packages\",\r\n format: \"number\",\r\n accentColor: \"orange\",\r\n },\r\n ],\r\n charts: [\r\n {\r\n id: \"dailyOrderTrends\",\r\n type: \"dailyArea\",\r\n label: \"dailyTrends\",\r\n icon: \"BarChart3\",\r\n },\r\n {\r\n id: \"orderStatusDistribution\",\r\n type: \"statusPie\",\r\n label: \"statusDistribution\",\r\n icon: \"PieChart\",\r\n },\r\n {\r\n id: \"topProducts\",\r\n type: \"topPackagesBar\",\r\n label: \"topPackages\",\r\n icon: \"TrendingUp\",\r\n },\r\n ],\r\n table: {\r\n id: \"recentOrders\",\r\n label: \"recentBookings\",\r\n icon: \"Calendar\",\r\n emptyLabel: \"noRecentBookings\",\r\n columns: [\r\n { id: \"date\", label: \"date\", accessor: \"createdAt\", type: \"date\" },\r\n { id: \"customer\", label: \"customer\", accessor: \"customerName\" },\r\n { id: \"product\", label: \"package\", accessor: \"packageName\" },\r\n { id: \"total\", label: \"total\", accessor: \"totalIDR\", type: \"currency\" },\r\n {\r\n id: \"status\",\r\n label: \"status\",\r\n accessor: \"statusLabel\",\r\n type: \"statusBadge\",\r\n statusAccessor: \"status\",\r\n },\r\n ],\r\n },\r\n },\r\n};\r\n","/**\r\n * createDashboardConfig — Factory function untuk mengemas semua konfigurasi\r\n * dashboard dalam satu objek tunggal.\r\n *\r\n * Sebelum adanya factory ini, developer harus menyiapkan 3 file terpisah\r\n * (widgetConfig, adapter, dataSource) dan mengimpornya satu per satu ke hook.\r\n * Dengan factory ini cukup 1 objek yang diserahkan ke useReusableDashboard.\r\n *\r\n * @param {object} options\r\n * @param {object} options.widgetConfig - Konfigurasi widget deklaratif.\r\n * @param {object} options.dataSource - Objek data source (fetchDashboardSnapshot, subscribeLiveUpdate).\r\n * @param {Function} options.adapter - Fungsi adapter pure function.\r\n * @param {Function} options.createEmptyState - Fungsi pembuat state kosong.\r\n * @param {object} [options.labels] - Objek label UI (opsional, bisa di-override di komponen).\r\n * @param {string} [options.languageCode=\"id\"] - Kode bahasa (id / en).\r\n * @param {string} [options.dateLocale=\"id-ID\"] - Locale format tanggal.\r\n *\r\n * @returns {object} Objek config terpadu yang siap dipakai useReusableDashboard.\r\n *\r\n * @example\r\n * // Sebelum (3 import terpisah):\r\n * const source = createCidikaSupabaseSource(supabase);\r\n * useReusableDashboard({ config: cidikaWidgetConfig, dataSource: source,\r\n * adapter: adaptCidikaDashboardData, createEmptyState: createEmptyDashboardData, ... })\r\n *\r\n * // Sesudah (1 file config):\r\n * const dashboardConfig = createDashboardConfig({\r\n * widgetConfig: cidikaWidgetConfig,\r\n * dataSource: createCidikaSupabaseSource(supabase),\r\n * adapter: adaptCidikaDashboardData,\r\n * createEmptyState: createEmptyDashboardData,\r\n * });\r\n * useReusableDashboard(dashboardConfig)\r\n */\r\nexport function createDashboardConfig({\r\n widgetConfig,\r\n dataSource,\r\n adapter,\r\n createEmptyState,\r\n labels,\r\n languageCode = \"id\",\r\n dateLocale = \"id-ID\",\r\n}) {\r\n // Validasi minimal — membantu developer yang lupa mengisi bagian penting\r\n const missing = [];\r\n if (!widgetConfig) missing.push(\"widgetConfig\");\r\n if (!dataSource) missing.push(\"dataSource\");\r\n if (!adapter) missing.push(\"adapter\");\r\n if (!createEmptyState) missing.push(\"createEmptyState\");\r\n\r\n return {\r\n // Properti yang langsung dibaca useReusableDashboard\r\n config: widgetConfig,\r\n dataSource,\r\n adapter,\r\n createEmptyState,\r\n languageCode,\r\n dateLocale,\r\n labels,\r\n\r\n // Metadata untuk setup wizard & validasi\r\n _meta: {\r\n isValid: missing.length === 0,\r\n missing,\r\n hasDataSource: Boolean(dataSource?.fetchDashboardSnapshot),\r\n hasRealtimeSupport: Boolean(dataSource?.subscribeLiveUpdate),\r\n hasLabels: Boolean(labels),\r\n widgetCount: {\r\n stats: widgetConfig?.widgets?.stats?.length ?? 0,\r\n charts: widgetConfig?.widgets?.charts?.length ?? 0,\r\n tableColumns: widgetConfig?.widgets?.table?.columns?.length ?? 0,\r\n },\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Memvalidasi apakah sebuah dashboardConfig sudah lengkap dan siap dipakai.\r\n * Digunakan oleh SetupWizard untuk menentukan apakah perlu menampilkan panduan.\r\n *\r\n * @param {object} dashboardConfig - Hasil dari createDashboardConfig.\r\n * @returns {{ valid: boolean, issues: string[] }}\r\n */\r\nexport function validateDashboardConfig(dashboardConfig) {\r\n const issues = [];\r\n\r\n if (!dashboardConfig) {\r\n return { valid: false, issues: [\"dashboardConfig tidak ditemukan. Pastikan sudah memanggil createDashboardConfig().\"] };\r\n }\r\n\r\n const meta = dashboardConfig?._meta;\r\n\r\n if (!meta) {\r\n issues.push(\"Config tidak dibuat melalui createDashboardConfig(). Gunakan factory function ini untuk validasi otomatis.\");\r\n } else {\r\n if (meta.missing.length > 0) {\r\n meta.missing.forEach(m => issues.push(`Properti wajib belum diisi: \"${m}\"`));\r\n }\r\n if (!meta.hasDataSource) {\r\n issues.push(\"dataSource.fetchDashboardSnapshot() tidak ditemukan. Pastikan sudah membuat data source yang benar.\");\r\n }\r\n }\r\n\r\n if (!dashboardConfig.config?.widgets?.stats?.length) {\r\n issues.push(\"widgetConfig.widgets.stats kosong. Tambahkan minimal 1 stat card.\");\r\n }\r\n if (!dashboardConfig.config?.widgets?.charts?.length) {\r\n issues.push(\"widgetConfig.widgets.charts kosong. Tambahkan minimal 1 chart.\");\r\n }\r\n if (!dashboardConfig.config?.widgets?.table?.columns?.length) {\r\n issues.push(\"widgetConfig.widgets.table.columns kosong. Tambahkan minimal 1 kolom tabel.\");\r\n }\r\n if (!dashboardConfig.labels) {\r\n issues.push(\"labels belum diisi. Sediakan objek labels agar teks UI tampil dengan benar.\");\r\n }\r\n\r\n return { valid: issues.length === 0, issues };\r\n}\r\n","export function formatIDR(value) {\n try {\n return (Number(value) || 0).toLocaleString(\"id-ID\");\n } catch (_error) {\n return String(value ?? 0);\n }\n}\n\nexport function shortId(value, length = 8) {\n if (!value) return \"-\";\n return String(value).slice(0, length);\n}\n\nexport function formatDate(value, locale) {\n if (!value) return \"-\";\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return \"-\";\n return date.toLocaleDateString(locale);\n}\n","/**\n * adapterHelpers — Fungsi utilitas bersama yang digunakan oleh semua data-adapter.\n * Diekstrak dari adapter individu untuk menghindari duplikasi kode (prinsip DRY).\n */\n\n/**\n * Mengkonversi nilai apapun ke angka yang valid.\n * Mengembalikan 0 jika nilai tidak valid atau bukan angka finite.\n *\n * @param {*} value - Nilai yang akan dikonversi.\n * @returns {number} Angka finite, atau 0 jika tidak valid.\n */\nexport function toNumber(value) {\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : 0;\n}\n\n/**\n * Membangun array bucket harian untuk chart tren.\n * Setiap bucket berisi dateKey, label terformat, dan counter awal (0).\n *\n * @param {number} daysWindow - Jumlah hari dalam rentang.\n * @param {string} fromISO - Tanggal awal dalam format ISO.\n * @param {string} dateLocale - Locale untuk format tanggal (misal: \"id-ID\").\n * @returns {Array<{dateKey: string, label: string, count: number, revenue: number, pendingCount: number}>}\n */\nexport function buildDayBuckets(daysWindow, fromISO, dateLocale) {\n const start = new Date(fromISO);\n return Array.from({ length: daysWindow }).map((_, index) => {\n const day = new Date(start);\n day.setDate(start.getDate() + index);\n return {\n dateKey: day.toISOString().slice(0, 10),\n label: day.toLocaleDateString(dateLocale, {\n day: \"2-digit\",\n month: \"short\",\n }),\n count: 0,\n revenue: 0,\n pendingCount: 0,\n };\n });\n}\n\n/**\n * Mengurutkan entri Map berdasarkan nilai numerik.\n *\n * @param {Map} map - Map yang akan diurutkan.\n * @param {\"asc\"|\"desc\"} direction - Arah pengurutan.\n * @returns {Array<[string, number]>} Array entri terurut.\n */\nexport function sortMapEntries(map, direction) {\n return Array.from(map.entries()).sort((a, b) =>\n direction === \"asc\" ? a[1] - b[1] : b[1] - a[1]\n );\n}\n","import { shortId } from \"../utils/formatters.js\";\nimport { toNumber, buildDayBuckets, sortMapEntries } from \"../utils/adapterHelpers.js\";\n\nfunction createPackageTitleResolver(packageLocales, languageCode) {\n const byPackage = new Map();\n\n packageLocales.forEach((row) => {\n if (!row.package_id) return;\n const current = byPackage.get(row.package_id) || {};\n byPackage.set(row.package_id, {\n ...current,\n [row.lang]: row.title,\n });\n });\n\n return (packageId) => {\n if (!packageId) return \"-\";\n const labels = byPackage.get(packageId);\n if (!labels) return shortId(packageId, 6);\n return (\n labels[languageCode] ||\n labels.en ||\n labels.id ||\n Object.values(labels).find(Boolean) ||\n shortId(packageId, 6)\n );\n };\n}\n\nexport function createEmptyDashboardData() {\n return {\n stats: {\n bookingsConfirm: 0,\n bookingsPending: 0,\n revenueConfirm: 0,\n packages: 0,\n sections: 0,\n avgRevenue: 0,\n conversionRate: 0,\n },\n charts: {\n dailyTrends: [],\n statusDistribution: [],\n audienceDistribution: [],\n topPackages: [],\n },\n table: {\n recentBookings: [],\n },\n };\n}\n\nexport function adaptCidikaDashboardData({\n raw,\n filters,\n range,\n dateLocale,\n languageCode,\n labels,\n}) {\n if (!raw) return createEmptyDashboardData();\n\n const dailyBuckets = buildDayBuckets(range.daysWindow, range.fromISO, dateLocale);\n const dayLookup = new Map(\n dailyBuckets.map((bucket) => [bucket.dateKey, bucket])\n );\n\n const statusMap = new Map();\n const audienceMap = new Map();\n const packageCountMap = new Map();\n const packageRevenueMap = new Map();\n const getPackageTitle = createPackageTitleResolver(\n raw.packageLocales || [],\n languageCode\n );\n\n let bookingsConfirm = 0;\n let bookingsPending = 0;\n let revenueConfirm = 0;\n\n (raw.bookings || []).forEach((row) => {\n const dayKey = String(row.created_at || \"\").slice(0, 10);\n const status = String(row.status || \"pending\").toLowerCase();\n const total = toNumber(row.total_idr);\n const audience = row.audience || \"unknown\";\n\n statusMap.set(status, (statusMap.get(status) || 0) + 1);\n audienceMap.set(audience, (audienceMap.get(audience) || 0) + 1);\n\n const bucket = dayLookup.get(dayKey);\n if (bucket) {\n if (status === \"confirmed\") {\n bucket.count += 1;\n bucket.revenue += total;\n }\n if (status === \"pending\") {\n bucket.pendingCount += 1;\n }\n }\n\n if (status === \"confirmed\") {\n bookingsConfirm += 1;\n revenueConfirm += total;\n packageCountMap.set(\n row.package_id,\n (packageCountMap.get(row.package_id) || 0) + 1\n );\n packageRevenueMap.set(\n row.package_id,\n (packageRevenueMap.get(row.package_id) || 0) + total\n );\n } else if (status === \"pending\") {\n bookingsPending += 1;\n }\n });\n\n const statusDistribution = sortMapEntries(statusMap, \"desc\").map(\n ([status, count]) => ({\n status,\n label: labels.formatStatusLabel(status),\n count,\n })\n );\n\n const audienceDistribution = sortMapEntries(audienceMap, \"desc\").map(\n ([audience, count]) => ({\n audience,\n label: labels.formatAudienceLabel(audience),\n count,\n })\n );\n\n const metricMap =\n filters.sortPkgBy === \"revenue\" ? packageRevenueMap : packageCountMap;\n\n const topPackages = sortMapEntries(metricMap, filters.sortPkgDir)\n .slice(0, 5)\n .map(([packageId, value]) => ({\n packageId,\n name: getPackageTitle(packageId),\n value: toNumber(value),\n }));\n\n const recentBookings = (raw.recent || []).map((row) => {\n const status = String(row.status || \"pending\").toLowerCase();\n return {\n id: row.id,\n createdAt: row.created_at,\n customerName: row.customer_name || \"-\",\n packageName: getPackageTitle(row.package_id),\n audienceLabel: labels.formatAudienceLabel(row.audience),\n totalIDR: toNumber(row.total_idr),\n status,\n statusLabel: labels.formatStatusLabel(status),\n };\n });\n\n const avgRevenue =\n bookingsConfirm > 0 ? Math.round(revenueConfirm / bookingsConfirm) : 0;\n const conversionRate =\n bookingsConfirm + bookingsPending > 0\n ? Math.round((bookingsConfirm / (bookingsConfirm + bookingsPending)) * 100)\n : 0;\n\n return {\n stats: {\n bookingsConfirm,\n bookingsPending,\n revenueConfirm,\n packages: toNumber(raw.staticCounts?.packages),\n sections: toNumber(raw.staticCounts?.sections),\n avgRevenue,\n conversionRate,\n },\n charts: {\n dailyTrends: dailyBuckets,\n statusDistribution,\n audienceDistribution,\n topPackages,\n },\n table: {\n recentBookings,\n },\n };\n}\n","/**\n * dummyUmkmDashboardAdapter — Data-adapter layer untuk studi kasus\n * aplikasi dummy UMKM non-travel (penjualan produk).\n *\n * Adapter ini membuktikan bahwa modul reusable dashboard dapat digunakan\n * pada domain bisnis yang berbeda dari Cidika Travel hanya dengan\n * mengganti adapter, tanpa mengubah komponen inti.\n *\n * Struktur data Supabase dummy UMKM yang diharapkan:\n * - Tabel `orders` : id, created_at, total_amount, status, customer_name, product_id\n * - Tabel `products` : id, name\n * - Tabel `customers`: id, name\n */\n\nimport { toNumber, buildDayBuckets } from \"../utils/adapterHelpers.js\";\n\n/**\n * Membuat state kosong yang sesuai dengan kontrak data dummy UMKM.\n * Dipanggil oleh useReusableDashboard sebagai initial state dan saat error.\n *\n * @returns {object} Empty dashboard data object.\n */\nexport function createEmptyDummyUmkmData() {\n return {\n stats: {\n bookingsConfirm: 0,\n revenueConfirm: 0,\n totalProducts: 0,\n totalCustomers: 0,\n },\n charts: {\n dailyTrends: [],\n statusDistribution: [],\n audienceDistribution: [],\n topPackages: [],\n },\n table: {\n recentBookings: [],\n },\n };\n}\n\n/**\n * Memetakan data mentah dari Supabase dummy UMKM ke format standar widget.\n *\n * Format `raw` yang diharapkan dari dataSource:\n * ```\n * {\n * bookings: Array<{ id, created_at, total_amount, status, customer_name, product_id }>,\n * recent: Array<{ id, created_at, customer_name, total_amount, status, product_id }>,\n * staticCounts: { packages: number, sections: number } // opsional\n * }\n * ```\n *\n * @param {object} params\n * @param {object} params.raw - Data mentah dari dataSource.\n * @param {object} params.filters - State filter aktif.\n * @param {object} params.range - Rentang tanggal { fromISO, toISO, daysWindow }.\n * @param {string} params.dateLocale - Locale untuk format tanggal (misal: \"id-ID\").\n * @param {object} [params.labels] - Label i18n (opsional, untuk format status).\n * @returns {object} Objek data standar { stats, charts, table }.\n */\nexport function adaptDummyUmkmData({ raw, filters, range, dateLocale, labels }) {\n if (!raw) return createEmptyDummyUmkmData();\n\n const orders = raw.bookings || [];\n const recent = raw.recent || [];\n\n // Bangun bucket harian untuk chart tren\n const dailyBuckets = buildDayBuckets(range.daysWindow, range.fromISO, dateLocale);\n const dayLookup = new Map(dailyBuckets.map((b) => [b.dateKey, b]));\n\n const statusMap = new Map();\n let totalOrders = 0;\n let totalRevenue = 0;\n\n orders.forEach((row) => {\n const dayKey = String(row.created_at || \"\").slice(0, 10);\n const status = String(row.status || \"pending\").toLowerCase();\n const amount = toNumber(row.total_amount);\n\n statusMap.set(status, (statusMap.get(status) || 0) + 1);\n\n const bucket = dayLookup.get(dayKey);\n if (bucket) {\n if (status === \"confirmed\") {\n bucket.count += 1;\n bucket.revenue += amount;\n }\n if (status === \"pending\") {\n bucket.pendingCount += 1;\n }\n }\n\n if (status === \"confirmed\") {\n totalOrders += 1;\n totalRevenue += amount;\n }\n });\n\n // Distribusi status untuk pie chart\n const statusDistribution = Array.from(statusMap.entries())\n .sort((a, b) => b[1] - a[1])\n .map(([status, count]) => ({\n status,\n label: labels?.formatStatusLabel ? labels.formatStatusLabel(status) : status,\n count,\n }));\n\n // Tabel recent orders — field mapping ke kontrak standar\n const recentBookings = recent.map((row) => {\n const status = String(row.status || \"pending\").toLowerCase();\n return {\n id: row.id,\n createdAt: row.created_at,\n customerName: row.customer_name || \"-\",\n packageName: row.product_name || row.product_id || \"-\",\n totalIDR: toNumber(row.total_amount),\n status,\n statusLabel: labels?.formatStatusLabel ? labels.formatStatusLabel(status) : status,\n };\n });\n\n return {\n stats: {\n bookingsConfirm: totalOrders,\n revenueConfirm: totalRevenue,\n totalProducts: toNumber(raw.staticCounts?.packages),\n totalCustomers: toNumber(raw.staticCounts?.sections),\n },\n charts: {\n dailyTrends: dailyBuckets,\n statusDistribution,\n audienceDistribution: [],\n topPackages: [],\n },\n table: {\n recentBookings,\n },\n };\n}\n","/**\r\n * tokoSepatuDashboardAdapter — Data-adapter layer untuk studi kasus\r\n * Toko Sepatu Online (domain retail/e-commerce).\r\n *\r\n * Adapter ini membuktikan bahwa modul reusable dashboard dapat digunakan\r\n * pada domain bisnis yang berbeda dari Cidika Travel hanya dengan\r\n * mengganti adapter, tanpa mengubah komponen inti.\r\n *\r\n * Struktur data Supabase Toko Sepatu yang diharapkan:\r\n * - Tabel `orders` : id, created_at, total_amount, status, customer_id\r\n * - Tabel `products` : id, name, brand, category, price_idr, stock\r\n * - Tabel `customers` : id, name, email, phone, city\r\n * - Tabel `order_items` : id, order_id, product_id, qty, price_idr, subtotal\r\n */\r\n\r\nimport { shortId } from \"../utils/formatters.js\";\r\nimport { toNumber, buildDayBuckets, sortMapEntries } from \"../utils/adapterHelpers.js\";\r\n\r\n/**\r\n * Membuat state kosong yang sesuai dengan kontrak data toko sepatu.\r\n * @returns {object} Empty dashboard data object.\r\n */\r\nexport function createEmptyTokoSepatuData() {\r\n return {\r\n stats: {\r\n bookingsConfirm: 0,\r\n bookingsPending: 0,\r\n revenueConfirm: 0,\r\n packages: 0,\r\n sections: 0,\r\n avgRevenue: 0,\r\n conversionRate: 0,\r\n },\r\n charts: {\r\n dailyTrends: [],\r\n statusDistribution: [],\r\n audienceDistribution: [],\r\n topPackages: [],\r\n },\r\n table: {\r\n recentBookings: [],\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Memetakan data mentah dari Supabase Toko Sepatu ke format standar widget.\r\n *\r\n * @param {object} params\r\n * @param {object} params.raw - Data mentah dari dataSource.\r\n * @param {object} params.filters - State filter aktif.\r\n * @param {object} params.range - Rentang tanggal { fromISO, toISO, daysWindow }.\r\n * @param {string} params.dateLocale - Locale untuk format tanggal.\r\n * @param {object} [params.labels] - Label i18n.\r\n * @returns {object} Objek data standar { stats, charts, table }.\r\n */\r\nexport function adaptTokoSepatuData({ raw, filters, range, dateLocale, labels }) {\r\n if (!raw) return createEmptyTokoSepatuData();\r\n\r\n const orders = raw.bookings || [];\r\n const recent = raw.recent || [];\r\n\r\n // Bangun bucket harian untuk chart tren\r\n const dailyBuckets = buildDayBuckets(range.daysWindow, range.fromISO, dateLocale);\r\n const dayLookup = new Map(dailyBuckets.map((b) => [b.dateKey, b]));\r\n\r\n const statusMap = new Map();\r\n const productCountMap = new Map();\r\n const productRevenueMap = new Map();\r\n\r\n let ordersConfirm = 0;\r\n let ordersPending = 0;\r\n let revenueConfirm = 0;\r\n\r\n // Buat lookup nama produk\r\n const productNameMap = new Map();\r\n (raw.products || []).forEach((p) => {\r\n productNameMap.set(p.id, p.name);\r\n });\r\n\r\n orders.forEach((row) => {\r\n const dayKey = String(row.created_at || \"\").slice(0, 10);\r\n const status = String(row.status || \"pending\").toLowerCase();\r\n const total = toNumber(row.total_amount);\r\n\r\n statusMap.set(status, (statusMap.get(status) || 0) + 1);\r\n\r\n const bucket = dayLookup.get(dayKey);\r\n if (bucket) {\r\n if (status === \"confirmed\") {\r\n bucket.count += 1;\r\n bucket.revenue += total;\r\n }\r\n if (status === \"pending\") {\r\n bucket.pendingCount += 1;\r\n }\r\n }\r\n\r\n if (status === \"confirmed\") {\r\n ordersConfirm += 1;\r\n revenueConfirm += total;\r\n\r\n // Hitung produk terlaris dari order_items\r\n const items = row.order_items || [];\r\n items.forEach((item) => {\r\n const pid = item.product_id;\r\n productCountMap.set(pid, (productCountMap.get(pid) || 0) + toNumber(item.qty));\r\n productRevenueMap.set(pid, (productRevenueMap.get(pid) || 0) + toNumber(item.subtotal));\r\n });\r\n } else if (status === \"pending\") {\r\n ordersPending += 1;\r\n }\r\n });\r\n\r\n // Distribusi status\r\n const statusDistribution = sortMapEntries(statusMap, \"desc\").map(\r\n ([status, count]) => ({\r\n status,\r\n label: labels?.formatStatusLabel ? labels.formatStatusLabel(status) : status,\r\n count,\r\n })\r\n );\r\n\r\n // Top products\r\n const metricMap =\r\n filters.sortPkgBy === \"revenue\" ? productRevenueMap : productCountMap;\r\n\r\n const topPackages = sortMapEntries(metricMap, filters.sortPkgDir || \"desc\")\r\n .slice(0, 5)\r\n .map(([productId, value]) => ({\r\n packageId: productId,\r\n name: productNameMap.get(productId) || shortId(productId, 6),\r\n value: toNumber(value),\r\n }));\r\n\r\n // Tabel recent orders\r\n const recentBookings = recent.map((row) => {\r\n const status = String(row.status || \"pending\").toLowerCase();\r\n // Ambil nama produk dari item pertama atau dari join\r\n const productName =\r\n row.product_name ||\r\n (row.order_items && row.order_items[0]\r\n ? productNameMap.get(row.order_items[0].product_id)\r\n : null) ||\r\n \"-\";\r\n\r\n return {\r\n id: row.id,\r\n createdAt: row.created_at,\r\n customerName: row.customer_name || \"-\",\r\n packageName: productName,\r\n totalIDR: toNumber(row.total_amount),\r\n status,\r\n statusLabel: labels?.formatStatusLabel ? labels.formatStatusLabel(status) : status,\r\n };\r\n });\r\n\r\n const avgRevenue =\r\n ordersConfirm > 0 ? Math.round(revenueConfirm / ordersConfirm) : 0;\r\n const conversionRate =\r\n ordersConfirm + ordersPending > 0\r\n ? Math.round((ordersConfirm / (ordersConfirm + ordersPending)) * 100)\r\n : 0;\r\n\r\n return {\r\n stats: {\r\n bookingsConfirm: ordersConfirm,\r\n bookingsPending: ordersPending,\r\n revenueConfirm,\r\n packages: toNumber(raw.staticCounts?.products),\r\n sections: toNumber(raw.staticCounts?.customers),\r\n avgRevenue,\r\n conversionRate,\r\n },\r\n charts: {\r\n dailyTrends: dailyBuckets,\r\n statusDistribution,\r\n audienceDistribution: [],\r\n topPackages,\r\n },\r\n table: {\r\n recentBookings,\r\n },\r\n };\r\n}\r\n","function ensureNoError(response, message) {\n if (response?.error) {\n const err = new Error(message);\n err.cause = response.error;\n throw err;\n }\n}\n\nexport function createCidikaSupabaseSource(supabase) {\n return {\n async fetchDashboardSnapshot({\n fromISO,\n toISO,\n audience,\n statusScope,\n languageCode,\n }) {\n const bookingsQuery = supabase\n .from(\"bookings\")\n .select(\n \"id, created_at, total_idr, status, package_id, audience, customer_name\"\n )\n .gte(\"created_at\", fromISO)\n .lte(\"created_at\", toISO)\n .order(\"created_at\", { ascending: true });\n\n if (audience) bookingsQuery.eq(\"audience\", audience);\n\n const recentQuery = supabase\n .from(\"bookings\")\n .select(\n \"id, created_at, customer_name, total_idr, status, package_id, audience\"\n )\n .gte(\"created_at\", fromISO)\n .lte(\"created_at\", toISO)\n .order(\"created_at\", { ascending: false })\n .limit(10);\n\n if (audience) recentQuery.eq(\"audience\", audience);\n if (statusScope && statusScope !== \"all\") {\n recentQuery.eq(\"status\", statusScope);\n }\n\n const [bookingsRes, recentRes, packagesRes, sectionsRes] = await Promise.all(\n [\n bookingsQuery,\n recentQuery,\n supabase.from(\"packages\").select(\"*\", { count: \"exact\", head: true }),\n supabase\n .from(\"page_sections\")\n .select(\"*\", { count: \"exact\", head: true }),\n ]\n );\n\n ensureNoError(bookingsRes, \"Failed to load booking rows.\");\n ensureNoError(recentRes, \"Failed to load recent rows.\");\n\n const bookings = bookingsRes.data || [];\n const recent = recentRes.data || [];\n\n const packageIds = Array.from(\n new Set(\n [...bookings, ...recent]\n .map((row) => row.package_id)\n .filter((value) => Boolean(value))\n )\n );\n\n let packageLocales = [];\n if (packageIds.length > 0) {\n const localeRes = await supabase\n .from(\"package_locales\")\n .select(\"package_id,title,lang\")\n .in(\"package_id\", packageIds)\n .in(\"lang\", [languageCode, \"en\", \"id\"]);\n\n if (!localeRes.error) {\n packageLocales = localeRes.data || [];\n }\n }\n\n return {\n bookings,\n recent,\n packageLocales,\n staticCounts: {\n packages: packagesRes.error ? 0 : packagesRes.count || 0,\n sections: sectionsRes.error ? 0 : sectionsRes.count || 0,\n },\n };\n },\n\n subscribeLiveUpdate(onEvent) {\n const channel = supabase\n .channel(\"reusable-dashboard-live\")\n .on(\n \"postgres_changes\",\n { event: \"*\", schema: \"public\", table: \"bookings\" },\n onEvent\n )\n .on(\n \"postgres_changes\",\n { event: \"*\", schema: \"public\", table: \"packages\" },\n onEvent\n )\n .on(\n \"postgres_changes\",\n { event: \"*\", schema: \"public\", table: \"page_sections\" },\n onEvent\n )\n .on(\n \"postgres_changes\",\n { event: \"*\", schema: \"public\", table: \"package_locales\" },\n onEvent\n )\n .subscribe();\n\n return () => {\n supabase.removeChannel(channel);\n };\n },\n };\n}\n","/**\r\n * tokoSepatuSupabaseSource — Data-source layer untuk studi kasus\r\n * Toko Sepatu Online.\r\n *\r\n * Mengimplementasikan kontrak yang sama dengan cidikaSupabaseSource:\r\n * - fetchDashboardSnapshot({ fromISO, toISO, statusScope })\r\n * - subscribeLiveUpdate(onEvent)\r\n *\r\n * Tabel yang diquery: orders, order_items, products, customers\r\n */\r\n\r\nfunction ensureNoError(response, message) {\r\n if (response?.error) {\r\n const err = new Error(message);\r\n err.cause = response.error;\r\n throw err;\r\n }\r\n}\r\n\r\n/**\r\n * Membuat data source untuk Toko Sepatu Online.\r\n *\r\n * @param {object} supabase - Instance Supabase client.\r\n * @returns {object} Objek data source { fetchDashboardSnapshot, subscribeLiveUpdate }.\r\n */\r\nexport function createTokoSepatuSupabaseSource(supabase) {\r\n return {\r\n /**\r\n * Mengambil snapshot data dashboard dari Supabase.\r\n */\r\n async fetchDashboardSnapshot({\r\n fromISO,\r\n toISO,\r\n audience,\r\n statusScope,\r\n }) {\r\n // Query semua orders dalam rentang waktu (dengan order_items untuk top products)\r\n const ordersQuery = supabase\r\n .from(\"orders\")\r\n .select(\r\n \"id, created_at, total_amount, status, customer_id, order_items(product_id, qty, price_idr, subtotal)\"\r\n )\r\n .gte(\"created_at\", fromISO)\r\n .lte(\"created_at\", toISO)\r\n .order(\"created_at\", { ascending: true });\r\n\r\n // Query recent orders (10 terbaru) dengan nama customer\r\n const recentQuery = supabase\r\n .from(\"orders\")\r\n .select(\r\n \"id, created_at, total_amount, status, customers(name), order_items(product_id, qty, products(name))\"\r\n )\r\n .gte(\"created_at\", fromISO)\r\n .lte(\"created_at\", toISO)\r\n .order(\"created_at\", { ascending: false })\r\n .limit(10);\r\n\r\n if (statusScope && statusScope !== \"all\") {\r\n recentQuery.eq(\"status\", statusScope);\r\n }\r\n\r\n const [ordersRes, recentRes, productsRes, customersRes] =\r\n await Promise.all([\r\n ordersQuery,\r\n recentQuery,\r\n supabase\r\n .from(\"products\")\r\n .select(\"id, name, brand, category, price_idr\"),\r\n supabase\r\n .from(\"customers\")\r\n .select(\"*\", { count: \"exact\", head: true }),\r\n ]);\r\n\r\n ensureNoError(ordersRes, \"Failed to load orders.\");\r\n ensureNoError(recentRes, \"Failed to load recent orders.\");\r\n\r\n const orders = ordersRes.data || [];\r\n const recentRaw = recentRes.data || [];\r\n const products = productsRes.data || [];\r\n\r\n // Map recent orders ke format yang adapter harapkan\r\n const recent = recentRaw.map((row) => ({\r\n id: row.id,\r\n created_at: row.created_at,\r\n total_amount: row.total_amount,\r\n status: row.status,\r\n customer_name: row.customers?.name || \"-\",\r\n product_name:\r\n row.order_items?.[0]?.products?.name || \"-\",\r\n order_items: row.order_items,\r\n }));\r\n\r\n return {\r\n bookings: orders,\r\n recent,\r\n products,\r\n packageLocales: [],\r\n staticCounts: {\r\n products: products.length,\r\n customers: customersRes.error ? 0 : customersRes.count || 0,\r\n },\r\n };\r\n },\r\n\r\n /**\r\n * Subscribe ke perubahan realtime pada tabel orders dan products.\r\n */\r\n subscribeLiveUpdate(onEvent) {\r\n const channel = supabase\r\n .channel(\"toko-sepatu-dashboard-live\")\r\n .on(\r\n \"postgres_changes\",\r\n { event: \"*\", schema: \"public\", table: \"orders\" },\r\n onEvent\r\n )\r\n .on(\r\n \"postgres_changes\",\r\n { event: \"*\", schema: \"public\", table: \"products\" },\r\n onEvent\r\n )\r\n .on(\r\n \"postgres_changes\",\r\n { event: \"*\", schema: \"public\", table: \"order_items\" },\r\n onEvent\r\n )\r\n .subscribe();\r\n\r\n return () => {\r\n supabase.removeChannel(channel);\r\n };\r\n },\r\n };\r\n}\r\n","import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { createDefaultFilters, resolveDateRange } from \"../utils/dateRange.js\";\nimport { useRealtimeUpdate } from \"./useRealtimeUpdate.js\";\n\nexport function useReusableDashboard({\n config,\n dataSource,\n adapter,\n createEmptyState,\n languageCode,\n dateLocale,\n labels,\n}) {\n const [filters, setFilters] = useState(() =>\n createDefaultFilters(config?.defaultFilters)\n );\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState(\"\");\n const [lastUpdatedAt, setLastUpdatedAt] = useState(null);\n const [data, setData] = useState(() => createEmptyState());\n\n\n const range = useMemo(\n () =>\n resolveDateRange({\n daysPreset: filters.daysPreset,\n dateFrom: filters.dateFrom,\n dateTo: filters.dateTo,\n }),\n [filters.daysPreset, filters.dateFrom, filters.dateTo]\n );\n\n const refresh = useCallback(\n async ({ silent = false } = {}) => {\n if (!dataSource?.fetchDashboardSnapshot) return;\n\n if (!silent) {\n setLoading(true);\n setError(\"\");\n }\n\n try {\n const raw = await dataSource.fetchDashboardSnapshot({\n fromISO: range.fromISO,\n toISO: range.toISO,\n audience: filters.audience,\n statusScope: filters.statusScope,\n languageCode,\n });\n\n const adapted = adapter({\n raw,\n filters,\n range,\n dateLocale,\n languageCode,\n labels,\n });\n\n setData(adapted);\n setLastUpdatedAt(new Date());\n if (!silent) setError(\"\");\n } catch (loadError) {\n console.error(loadError);\n if (!silent) {\n setError(labels.loadFailed);\n setData(createEmptyState());\n }\n } finally {\n if (!silent) setLoading(false);\n }\n },\n [\n dataSource,\n range,\n filters,\n languageCode,\n adapter,\n dateLocale,\n labels,\n createEmptyState,\n ]\n );\n\n useEffect(() => {\n refresh();\n }, [refresh]);\n\n const { liveUpdateEnabled } = useRealtimeUpdate({\n dataSource,\n onUpdate: () => refresh({ silent: true }),\n });\n\n const updateFilter = useCallback((field, value) => {\n setFilters((current) => ({\n ...current,\n [field]: value,\n }));\n }, []);\n\n const resetFilters = useCallback(() => {\n setFilters(createDefaultFilters(config?.defaultFilters));\n }, [config?.defaultFilters]);\n\n return {\n filters,\n updateFilter,\n resetFilters,\n loading,\n error,\n data,\n refresh,\n range,\n liveUpdateEnabled,\n lastUpdatedAt,\n };\n}\n","function startOfDayISO(date) {\n const value = new Date(date);\n value.setHours(0, 0, 0, 0);\n return value.toISOString();\n}\n\nfunction endOfDayISO(date) {\n const value = new Date(date);\n value.setHours(23, 59, 59, 999);\n return value.toISOString();\n}\n\nexport function formatYYYYMMDD(date) {\n const value = new Date(date);\n const year = value.getFullYear();\n const month = String(value.getMonth() + 1).padStart(2, \"0\");\n const day = String(value.getDate()).padStart(2, \"0\");\n return `${year}-${month}-${day}`;\n}\n\nexport function createDefaultFilters(base = {}) {\n const fromDate = new Date();\n fromDate.setDate(fromDate.getDate() - 29);\n\n return {\n statusScope: \"confirmed\",\n includePendingOverlay: false,\n audience: \"\",\n daysPreset: 30,\n dateFrom: formatYYYYMMDD(fromDate),\n dateTo: formatYYYYMMDD(new Date()),\n sortPkgBy: \"bookings\",\n sortPkgDir: \"desc\",\n ...base,\n };\n}\n\n/** Tahun minimum yang diizinkan untuk input tanggal kustom. */\nconst MIN_YEAR = 2000;\n/** Batas maksimum rentang hari untuk mencegah loop tak terhingga (5 tahun). */\nconst MAX_DAYS_WINDOW = 365 * 5;\n\n/**\n * Memvalidasi apakah tanggal masuk akal (tahun >= MIN_YEAR dan <= tahun sekarang + 1).\n * @param {Date} date\n * @returns {boolean}\n */\nfunction isReasonableDate(date) {\n if (!date || Number.isNaN(date.getTime())) return false;\n const year = date.getFullYear();\n return year >= MIN_YEAR && year <= new Date().getFullYear() + 1;\n}\n\nexport function resolveDateRange({ daysPreset, dateFrom, dateTo }) {\n if (Number(daysPreset) > 0) {\n const fromDate = new Date();\n fromDate.setDate(fromDate.getDate() - (Number(daysPreset) - 1));\n const toDate = new Date();\n return {\n fromISO: startOfDayISO(fromDate),\n toISO: endOfDayISO(toDate),\n daysWindow: Number(daysPreset),\n };\n }\n\n const fallbackFrom = new Date(Date.now() - 29 * 24 * 60 * 60 * 1000);\n const fallbackTo = new Date();\n\n let from = dateFrom ? new Date(dateFrom) : fallbackFrom;\n let to = dateTo ? new Date(dateTo) : fallbackTo;\n\n // Jika tanggal tidak masuk akal (misal tahun 0202), gunakan fallback\n if (!isReasonableDate(from)) from = fallbackFrom;\n if (!isReasonableDate(to)) to = fallbackTo;\n\n if (from.getTime() > to.getTime()) {\n const swap = from;\n from = to;\n to = swap;\n }\n\n const fromISO = startOfDayISO(from);\n const toISO = endOfDayISO(to);\n const diffMs = new Date(toISO).getTime() - new Date(fromISO).getTime();\n // Cap daysWindow agar tidak pernah melebihi MAX_DAYS_WINDOW\n const daysWindow = Math.min(\n MAX_DAYS_WINDOW,\n Math.max(1, Math.round(diffMs / 86400000) + 1)\n );\n\n return { fromISO, toISO, daysWindow };\n}\n","import { useEffect, useState } from \"react\";\n\n/**\n * useRealtimeUpdate — Custom hook untuk mengelola subscription live update\n * melalui mekanisme Supabase Realtime (Postgres Changes).\n *\n * Hook ini mengabstraksikan logika subscription dan debounce sehingga dapat\n * digunakan secara independen oleh consumer yang membutuhkan live update\n * tanpa menggunakan useReusableDashboard secara penuh.\n *\n * @param {object} params\n * @param {object} params.dataSource - Objek data source yang mengimplementasikan\n * `subscribeLiveUpdate(callback): unsubscribeFn`.\n * @param {Function} params.onUpdate - Callback yang dipanggil saat ada perubahan data.\n * Dipanggil setelah debounce selesai.\n * @param {number} [params.debounceMs=350] - Durasi debounce dalam milidetik.\n *\n * @returns {{ liveUpdateEnabled: boolean }} State apakah live update aktif.\n *\n * @example\n * const { liveUpdateEnabled } = useRealtimeUpdate({\n * dataSource,\n * onUpdate: () => refresh({ silent: true }),\n * });\n */\nexport function useRealtimeUpdate({ dataSource, onUpdate, debounceMs = 350 }) {\n const [liveUpdateEnabled, setLiveUpdateEnabled] = useState(false);\n\n useEffect(() => {\n if (!dataSource?.subscribeLiveUpdate) return undefined;\n\n let debounceId;\n setLiveUpdateEnabled(true);\n\n const unsubscribe = dataSource.subscribeLiveUpdate(() => {\n clearTimeout(debounceId);\n debounceId = setTimeout(() => {\n onUpdate?.();\n }, debounceMs);\n });\n\n return () => {\n clearTimeout(debounceId);\n setLiveUpdateEnabled(false);\n unsubscribe?.();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [dataSource, debounceMs]);\n // Note: onUpdate sengaja tidak dimasukkan dependency array untuk menghindari\n // re-subscribe yang tidak perlu saat parent re-render. Consumer harus\n // memoize callback-nya dengan useCallback jika ingin reaktivitas penuh.\n\n return { liveUpdateEnabled };\n}\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\n\nexport default function Button({\n variant = \"primary\",\n size = \"md\",\n disabled = false,\n className = \"\",\n onClick,\n children,\n ...rest\n}) {\n const classes = [\n \"rdb-btn\",\n `rdb-btn-${variant}`,\n `rdb-btn-${size}`,\n className,\n ].filter(Boolean).join(\" \");\n\n return (\n <button type=\"button\" className={classes} disabled={disabled} onClick={onClick} {...rest}>\n {children}\n </button>\n );\n}\n\nButton.propTypes = {\n variant: PropTypes.oneOf([\"primary\", \"secondary\", \"ghost\"]),\n size: PropTypes.oneOf([\"sm\", \"md\", \"lg\"]),\n disabled: PropTypes.bool,\n className: PropTypes.string,\n onClick: PropTypes.func,\n children: PropTypes.node.isRequired,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\n\nexport default function Input({\n type = \"text\",\n value,\n onChange,\n placeholder,\n label,\n disabled = false,\n className = \"\",\n ...rest\n}) {\n return (\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 4 }}>\n {label ? <label className=\"rdb-label\">{label}</label> : null}\n <input\n type={type}\n value={value}\n onChange={onChange}\n placeholder={placeholder}\n disabled={disabled}\n className={[\"rdb-input\", className].filter(Boolean).join(\" \")}\n {...rest}\n />\n </div>\n );\n}\n\nInput.propTypes = {\n type: PropTypes.string,\n value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),\n onChange: PropTypes.func,\n placeholder: PropTypes.string,\n label: PropTypes.string,\n disabled: PropTypes.bool,\n className: PropTypes.string,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport {\n BarChart3,\n Calendar,\n DollarSign,\n PieChart,\n RotateCcw,\n TrendingUp,\n TrendingDown,\n Users,\n Search,\n ChevronLeft,\n ChevronRight,\n ArrowUp,\n ArrowDown,\n AlertCircle,\n} from \"lucide-react\";\n\n/**\n * Registry ikon yang tersedia di modul dashboard.\n * @type {Object.<string, React.ComponentType>}\n */\nconst ICON_REGISTRY = {\n BarChart3,\n Calendar,\n DollarSign,\n PieChart,\n RotateCcw,\n TrendingUp,\n TrendingDown,\n Users,\n Search,\n ChevronLeft,\n ChevronRight,\n ArrowUp,\n ArrowDown,\n AlertCircle,\n};\n\n/**\n * Icon — Atom komponen ikon berbasis SVG menggunakan Lucide React.\n *\n * @param {object} props\n * @param {string} props.name - Nama ikon dari registry (misal: \"TrendingUp\").\n * @param {number} [props.size=20] - Ukuran ikon dalam piksel.\n * @param {string} [props.className=\"\"] - ClassName tambahan.\n */\nexport default function Icon({ name, size = 20, className = \"\", ...rest }) {\n const IconComponent = ICON_REGISTRY[name] || BarChart3;\n\n return <IconComponent size={size} className={className} {...rest} />;\n}\n\n/**\n * Resolves an icon name to its Lucide React component.\n * Backward-compatible utility used internally.\n *\n * @param {string} name - Nama ikon.\n * @returns {React.ComponentType} Komponen ikon.\n */\nexport function resolveIcon(name) {\n return ICON_REGISTRY[name] || BarChart3;\n}\n\nIcon.propTypes = {\n /** Nama ikon dari registry Lucide React. */\n name: PropTypes.string.isRequired,\n /** Ukuran ikon dalam piksel. */\n size: PropTypes.number,\n /** ClassName tambahan. */\n className: PropTypes.string,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\n\nconst VARIANT_CLASS = {\n h1: \"rdb-h1\",\n h2: \"rdb-h2\",\n h3: \"rdb-h3\",\n subheading: \"rdb-subheading\",\n body: \"rdb-body\",\n caption: \"rdb-caption\",\n metric: \"rdb-metric\",\n};\n\nconst VARIANT_TAG = {\n h1: \"h1\", h2: \"h2\", h3: \"h3\",\n subheading: \"p\", body: \"p\", caption: \"span\", metric: \"span\",\n};\n\nexport default function Typography({ variant = \"body\", className = \"\", children, ...rest }) {\n const Tag = VARIANT_TAG[variant] || \"p\";\n const cls = [VARIANT_CLASS[variant] || \"rdb-body\", className].filter(Boolean).join(\" \");\n return <Tag className={cls} {...rest}>{children}</Tag>;\n}\n\nTypography.propTypes = {\n variant: PropTypes.oneOf([\"h1\",\"h2\",\"h3\",\"subheading\",\"body\",\"caption\",\"metric\"]),\n className: PropTypes.string,\n children: PropTypes.node.isRequired,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\n\nconst STATUS_CLASS = {\n confirmed: \"rdb-badge-confirmed\",\n pending: \"rdb-badge-pending\",\n cancelled: \"rdb-badge-cancelled\",\n success: \"rdb-badge-success\",\n info: \"rdb-badge-info\",\n default: \"rdb-badge-default\",\n};\n\nexport default function Badge({ status = \"default\", className = \"\", children, ...rest }) {\n const statusClass = STATUS_CLASS[status] || STATUS_CLASS.default;\n return (\n <span className={[\"rdb-badge\", statusClass, className].filter(Boolean).join(\" \")} {...rest}>\n {children}\n </span>\n );\n}\n\nBadge.propTypes = {\n status: PropTypes.string,\n className: PropTypes.string,\n children: PropTypes.node.isRequired,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\n\nexport default function SkeletonLoader({ className = \"\", style = {} }) {\n return (\n <div\n className={[\"rdb-skeleton\", className].filter(Boolean).join(\" \")}\n style={{ minHeight: 20, ...style }}\n role=\"status\"\n aria-label=\"Loading...\"\n />\n );\n}\n\nSkeletonLoader.propTypes = {\n className: PropTypes.string,\n style: PropTypes.object,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport Icon from \"../atoms/Icon.jsx\";\nimport { formatIDR } from \"../../utils/formatters.js\";\n\nfunction renderValue(format, value) {\n if (format === \"currency\") return `Rp ${formatIDR(value)}`;\n if (format === \"percent\") return `${Number(value) || 0}%`;\n return String(Number(value) || 0);\n}\n\nexport default function StatCard({\n label,\n value,\n icon = \"TrendingUp\",\n format = \"number\",\n trend = null,\n accentColor = \"blue\",\n className = \"\",\n}) {\n return (\n <div className={[\"rdb-card rdb-statcard\", `rdb-accent-${accentColor}`, className].filter(Boolean).join(\" \")}>\n <div className=\"rdb-statcard-header\">\n <div className=\"rdb-statcard-label-group\">\n <div className=\"rdb-statcard-icon\">\n <Icon name={icon} size={16} />\n </div>\n <span className=\"rdb-statcard-label\">{label}</span>\n </div>\n {trend ? (\n <Icon\n name={trend === \"up\" ? \"TrendingUp\" : \"TrendingDown\"}\n size={16}\n style={{ color: trend === \"up\" ? \"#10b981\" : \"#ef4444\" }}\n />\n ) : null}\n </div>\n <div className=\"rdb-statcard-value\">{renderValue(format, value)}</div>\n </div>\n );\n}\n\nStatCard.propTypes = {\n label: PropTypes.string.isRequired,\n value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),\n icon: PropTypes.string,\n format: PropTypes.oneOf([\"number\", \"currency\", \"percent\"]),\n trend: PropTypes.oneOf([\"up\", \"down\", null]),\n accentColor: PropTypes.string,\n className: PropTypes.string,\n};\n","import React, { useState, useCallback } from \"react\";\nimport PropTypes from \"prop-types\";\nimport Icon from \"../atoms/Icon.jsx\";\n\nexport default function SearchBar({\n value: controlledValue,\n onChange,\n onSearch,\n placeholder = \"Search...\",\n className = \"\",\n}) {\n const [internalValue, setInternalValue] = useState(\"\");\n const isControlled = controlledValue !== undefined;\n const currentValue = isControlled ? controlledValue : internalValue;\n\n const handleChange = useCallback((event) => {\n const v = event.target.value;\n if (!isControlled) setInternalValue(v);\n if (onChange) onChange(v);\n if (onSearch) onSearch(v);\n }, [isControlled, onChange, onSearch]);\n\n const handleKeyDown = useCallback((event) => {\n if (event.key === \"Enter\" && onSearch) onSearch(currentValue);\n }, [currentValue, onSearch]);\n\n return (\n <div className={[\"rdb-searchbar\", className].filter(Boolean).join(\" \")}>\n <div className=\"rdb-searchbar-icon\">\n <Icon name=\"Search\" size={16} />\n </div>\n <input\n type=\"search\"\n value={currentValue}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n className=\"rdb-input rdb-searchbar-input\"\n style={{ width: \"100%\" }}\n />\n </div>\n );\n}\n\nSearchBar.propTypes = {\n value: PropTypes.string,\n onChange: PropTypes.func,\n onSearch: PropTypes.func,\n placeholder: PropTypes.string,\n className: PropTypes.string,\n};\n","import React, { useState, useCallback } from \"react\";\nimport PropTypes from \"prop-types\";\n\nconst CURRENT_YEAR = new Date().getFullYear();\nconst MIN_YEAR = 2020;\nconst MAX_YEAR = CURRENT_YEAR + 1;\nconst MONTHS = [\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"];\n\nfunction getYears() {\n const y = [];\n for (let i = MAX_YEAR; i >= MIN_YEAR; i--) y.push(i);\n return y;\n}\n\nfunction getDaysInMonth(year, month) {\n return new Date(year, month, 0).getDate();\n}\n\nfunction parseDate(value) {\n if (value && /^\\d{4}-\\d{2}-\\d{2}$/.test(value)) {\n const [y, m, d] = value.split(\"-\").map(Number);\n if (y >= MIN_YEAR && y <= MAX_YEAR && m >= 1 && m <= 12)\n return { year: y, month: m, day: d };\n }\n const now = new Date();\n return { year: now.getFullYear(), month: now.getMonth() + 1, day: now.getDate() };\n}\n\nfunction fmt({ year, month, day }) {\n return `${year}-${String(month).padStart(2,\"0\")}-${String(day).padStart(2,\"0\")}`;\n}\n\nfunction DatePicker({ value, onChange, disabled = false, label = \"\" }) {\n const p = parseDate(value);\n const years = getYears();\n const maxDay = getDaysInMonth(p.year, p.month);\n\n const handleChange = useCallback((field, val) => {\n const u = { ...p, [field]: Number(val) };\n const max = getDaysInMonth(u.year, u.month);\n if (u.day > max) u.day = max;\n onChange(fmt(u));\n }, [p, onChange]);\n\n return (\n <div style={{ display:\"flex\", flexDirection:\"column\", gap:2 }}>\n {label ? <span className=\"rdb-caption rdb-label\">{label}</span> : null}\n <div style={{ display:\"flex\", gap:4, alignItems:\"center\" }}>\n <select className=\"rdb-select\" style={{ width:52 }} value={p.day}\n onChange={e => handleChange(\"day\", e.target.value)} disabled={disabled}>\n {Array.from({ length: maxDay }, (_,i) => i+1).map(d => (\n <option key={d} value={d}>{String(d).padStart(2,\"0\")}</option>\n ))}\n </select>\n <select className=\"rdb-select\" style={{ width:62 }} value={p.month}\n onChange={e => handleChange(\"month\", e.target.value)} disabled={disabled}>\n {MONTHS.map((name, idx) => (\n <option key={idx+1} value={idx+1}>{name}</option>\n ))}\n </select>\n <select className=\"rdb-select\" style={{ width:72 }} value={p.year}\n onChange={e => handleChange(\"year\", e.target.value)} disabled={disabled}>\n {years.map(y => <option key={y} value={y}>{y}</option>)}\n </select>\n </div>\n </div>\n );\n}\n\nexport default function DateRangeFilter({\n dateFrom, dateTo, onRangeChange,\n disabled = false, labelFrom = \"From\", labelTo = \"To\", className = \"\",\n}) {\n const handleFrom = useCallback(v => onRangeChange?.({ dateFrom: v, dateTo }), [dateTo, onRangeChange]);\n const handleTo = useCallback(v => onRangeChange?.({ dateFrom, dateTo: v }), [dateFrom, onRangeChange]);\n\n return (\n <div className={[\"rdb-daterange\", className].filter(Boolean).join(\" \")}>\n <DatePicker value={dateFrom} onChange={handleFrom} disabled={disabled} label={labelFrom} />\n <DatePicker value={dateTo} onChange={handleTo} disabled={disabled} label={labelTo} />\n </div>\n );\n}\n\nDateRangeFilter.propTypes = {\n dateFrom: PropTypes.string.isRequired,\n dateTo: PropTypes.string.isRequired,\n onRangeChange: PropTypes.func.isRequired,\n disabled: PropTypes.bool,\n labelFrom: PropTypes.string,\n labelTo: PropTypes.string,\n className: PropTypes.string,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport Icon from \"../atoms/Icon.jsx\";\n\nexport default function ChartHeader({ title, icon = \"BarChart3\", actions = null, className = \"\" }) {\n return (\n <div className={[\"rdb-chart-title-wrap\", className].filter(Boolean).join(\" \")}>\n <div className=\"rdb-chart-title\">\n <Icon name={icon} size={18} />\n {title}\n </div>\n {actions}\n </div>\n );\n}\n\nChartHeader.propTypes = {\n title: PropTypes.string.isRequired,\n icon: PropTypes.string,\n actions: PropTypes.node,\n className: PropTypes.string,\n};\n","import React, { useMemo, useState, useCallback } from \"react\";\nimport PropTypes from \"prop-types\";\nimport SearchBar from \"../molecules/SearchBar.jsx\";\nimport Badge from \"../atoms/Badge.jsx\";\nimport Icon from \"../atoms/Icon.jsx\";\nimport { formatDate, formatIDR } from \"../../utils/formatters.js\";\n\nexport default function DataTable({\n columns, data = [], labels = {}, dateLocale = \"id-ID\",\n searchable = true, sortable = true, pageSize = 10,\n emptyLabel = \"No data\", searchPlaceholder = \"Search...\", className = \"\",\n}) {\n const [searchQuery, setSearchQuery] = useState(\"\");\n const [sortField, setSortField] = useState(null);\n const [sortDirection, setSortDirection] = useState(\"asc\");\n const [currentPage, setCurrentPage] = useState(1);\n\n const filteredData = useMemo(() => {\n if (!searchQuery.trim()) return data;\n const q = searchQuery.toLowerCase();\n return data.filter(row =>\n columns.some(col => {\n const v = row[col.accessor];\n return v != null && String(v).toLowerCase().includes(q);\n })\n );\n }, [data, searchQuery, columns]);\n\n const sortedData = useMemo(() => {\n if (!sortField) return filteredData;\n return [...filteredData].sort((a, b) => {\n const aV = a[sortField] ?? \"\";\n const bV = b[sortField] ?? \"\";\n if (typeof aV === \"number\" && typeof bV === \"number\")\n return sortDirection === \"asc\" ? aV - bV : bV - aV;\n const cmp = String(aV).localeCompare(String(bV), undefined, { numeric: true });\n return sortDirection === \"asc\" ? cmp : -cmp;\n });\n }, [filteredData, sortField, sortDirection]);\n\n const totalPages = Math.max(1, Math.ceil(sortedData.length / pageSize));\n const safePage = Math.min(currentPage, totalPages);\n const paginatedData = useMemo(() => {\n const start = (safePage - 1) * pageSize;\n return sortedData.slice(start, start + pageSize);\n }, [sortedData, safePage, pageSize]);\n\n const handleSearch = useCallback(v => { setSearchQuery(v); setCurrentPage(1); }, []);\n const handleSort = useCallback(acc => {\n if (!sortable) return;\n if (sortField === acc) setSortDirection(p => p === \"asc\" ? \"desc\" : \"asc\");\n else { setSortField(acc); setSortDirection(\"asc\"); }\n setCurrentPage(1);\n }, [sortable, sortField]);\n const handlePrev = useCallback(() => setCurrentPage(p => Math.max(1, p-1)), []);\n const handleNext = useCallback(() => setCurrentPage(p => Math.min(totalPages, p+1)), [totalPages]);\n\n return (\n <div style={{ display:\"flex\", flexDirection:\"column\", gap:12 }} className={className}>\n {searchable ? (\n <SearchBar value={searchQuery} onSearch={handleSearch} placeholder={searchPlaceholder} />\n ) : null}\n\n <div className=\"rdb-table-wrapper\">\n <table className=\"rdb-table\">\n <thead>\n <tr>\n {columns.map(col => (\n <th key={col.id} onClick={() => handleSort(col.accessor)}>\n <div style={{ display:\"flex\", alignItems:\"center\", gap:4 }}>\n <span>{labels[col.label] || col.label}</span>\n {sortable && sortField === col.accessor ? (\n <Icon name={sortDirection === \"asc\" ? \"ArrowUp\" : \"ArrowDown\"} size={13}\n style={{ color: \"var(--rdb-blue-500)\" }} />\n ) : null}\n </div>\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {paginatedData.map(row => (\n <tr key={row.id}>\n {columns.map(col => (\n <td key={`${row.id}-${col.id}`}>{renderCell(col, row, dateLocale)}</td>\n ))}\n </tr>\n ))}\n {paginatedData.length === 0 ? (\n <tr>\n <td className=\"rdb-table-empty\" colSpan={columns.length}>{emptyLabel}</td>\n </tr>\n ) : null}\n </tbody>\n </table>\n </div>\n\n {sortedData.length > pageSize ? (\n <div className=\"rdb-pagination\">\n <span className=\"rdb-pagination-info\">\n {(safePage-1)*pageSize+1}–{Math.min(safePage*pageSize, sortedData.length)} of {sortedData.length}\n </span>\n <div className=\"rdb-pagination-controls\">\n <button type=\"button\" className=\"rdb-page-btn\" onClick={handlePrev} disabled={safePage <= 1} aria-label=\"Previous\">\n <Icon name=\"ChevronLeft\" size={16} />\n </button>\n <span className=\"rdb-pagination-page\">{safePage} / {totalPages}</span>\n <button type=\"button\" className=\"rdb-page-btn\" onClick={handleNext} disabled={safePage >= totalPages} aria-label=\"Next\">\n <Icon name=\"ChevronRight\" size={16} />\n </button>\n </div>\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction renderCell(column, row, dateLocale) {\n const value = row[column.accessor];\n if (column.type === \"date\") return formatDate(value, dateLocale);\n if (column.type === \"currency\") return `Rp ${formatIDR(value)}`;\n if (column.type === \"statusBadge\") {\n const status = row[column.statusAccessor] || \"pending\";\n return <Badge status={status}>{value}</Badge>;\n }\n return value || \"-\";\n}\n\nDataTable.propTypes = {\n columns: PropTypes.arrayOf(PropTypes.shape({\n id: PropTypes.string.isRequired,\n label: PropTypes.string.isRequired,\n accessor: PropTypes.string.isRequired,\n type: PropTypes.oneOf([\"date\",\"currency\",\"statusBadge\"]),\n statusAccessor: PropTypes.string,\n })).isRequired,\n data: PropTypes.arrayOf(PropTypes.object),\n labels: PropTypes.object,\n dateLocale: PropTypes.string,\n searchable: PropTypes.bool,\n sortable: PropTypes.bool,\n pageSize: PropTypes.number,\n emptyLabel: PropTypes.string,\n searchPlaceholder: PropTypes.string,\n className: PropTypes.string,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport {\n Area,\n AreaChart,\n Bar,\n BarChart,\n CartesianGrid,\n Cell,\n Legend,\n Pie,\n PieChart,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from \"recharts\";\nimport ChartHeader from \"../molecules/ChartHeader.jsx\";\nimport SkeletonLoader from \"../atoms/SkeletonLoader.jsx\";\nimport { formatIDR } from \"../../utils/formatters.js\";\n\n/**\n * Palet warna default untuk grafik.\n * @type {string[]}\n */\nconst COLORS = [\n \"#0ea5e9\",\n \"#a78bfa\",\n \"#f59e0b\",\n \"#10b981\",\n \"#ef4444\",\n \"#22d3ee\",\n];\n\n/**\n * ChartCard — Organism kartu grafik yang mengintegrasikan ChartHeader\n * dengan area visualisasi. Mendukung tipe grafik area, pie, dan bar.\n *\n * @param {object} props\n * @param {object} props.widget - Konfigurasi widget chart.\n * @param {object} props.labels - Objek label i18n.\n * @param {boolean} props.loading - Apakah sedang loading.\n * @param {object} props.filters - State filter dashboard.\n * @param {object} props.chartData - Data untuk semua jenis chart.\n * @param {string} [props.className=\"\"] - ClassName tambahan.\n */\nexport default function ChartCard({\n widget,\n labels,\n loading,\n filters,\n chartData,\n className = \"\",\n}) {\n const content = (() => {\n if (loading) return <SkeletonLoader style={{ height: 256 }} />;\n\n if (widget.type === \"dailyArea\") {\n return renderDailyArea(labels, filters, chartData.dailyTrends);\n }\n if (widget.type === \"statusPie\") {\n return renderPie(chartData.statusDistribution);\n }\n if (widget.type === \"audiencePie\") {\n return renderPie(chartData.audienceDistribution);\n }\n if (widget.type === \"topPackagesBar\") {\n return renderTopPackages(chartData.topPackages, labels, filters.sortPkgBy);\n }\n\n return <div className=\"rdb-muted\">Unsupported chart type.</div>;\n })();\n\n return (\n <div className={`rdb-card rdb-chart-card ${className}`}>\n <ChartHeader\n title={labels[widget.label] || widget.label}\n icon={widget.icon}\n />\n {content}\n </div>\n );\n}\n\n/**\n * Merender grafik area harian (daily area chart).\n * @param {object} labels - Label i18n.\n * @param {object} filters - Filter dashboard.\n * @param {Array} dailyData - Data daily trends.\n * @returns {React.ReactElement} Komponen AreaChart.\n */\nfunction renderDailyArea(labels, filters, dailyData = []) {\n return (\n <ResponsiveContainer width=\"100%\" height={256}>\n <AreaChart data={dailyData}>\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis dataKey=\"label\" />\n <YAxis yAxisId=\"left\" />\n <YAxis yAxisId=\"right\" orientation=\"right\" />\n <Tooltip\n formatter={(value, name) =>\n name === \"revenue\"\n ? [`Rp ${formatIDR(value)}`, labels.revenueMetric]\n : [value, labels.bookingsMetric]\n }\n />\n <Legend />\n <Area\n yAxisId=\"left\"\n type=\"monotone\"\n dataKey=\"count\"\n name={labels.confirmedBookingMetric}\n stroke=\"#0ea5e9\"\n fill=\"#0ea5e9\"\n fillOpacity={0.3}\n />\n <Area\n yAxisId=\"right\"\n type=\"monotone\"\n dataKey=\"revenue\"\n name={labels.confirmedRevenueMetric}\n stroke=\"#a78bfa\"\n fill=\"#a78bfa\"\n fillOpacity={0.3}\n />\n {filters.includePendingOverlay ? (\n <Area\n yAxisId=\"left\"\n type=\"monotone\"\n dataKey=\"pendingCount\"\n name={labels.pendingMetric}\n stroke=\"#ef4444\"\n fill=\"#ef4444\"\n fillOpacity={0.1}\n strokeDasharray=\"4 4\"\n />\n ) : null}\n </AreaChart>\n </ResponsiveContainer>\n );\n}\n\n/**\n * Merender diagram lingkaran (Pie/Donut Chart).\n * @param {Array} data - Data distribusi.\n * @returns {React.ReactElement} Komponen PieChart.\n */\nfunction renderPie(data = []) {\n return (\n <ResponsiveContainer width=\"100%\" height={256}>\n <PieChart>\n <Pie\n data={data}\n dataKey=\"count\"\n nameKey=\"label\"\n innerRadius={60}\n outerRadius={100}\n paddingAngle={2}\n >\n {data.map((_, index) => (\n <Cell\n key={`${index}-${data[index].label}`}\n fill={COLORS[index % COLORS.length]}\n />\n ))}\n </Pie>\n <Tooltip />\n <Legend />\n </PieChart>\n </ResponsiveContainer>\n );\n}\n\n/**\n * Merender grafik batang (Bar Chart) untuk paket teratas.\n * @param {Array} data - Data top packages.\n * @param {object} labels - Label i18n.\n * @param {string} sortPkgBy - Metrik pengurutan (bookings/revenue).\n * @returns {React.ReactElement} Komponen BarChart.\n */\nfunction renderTopPackages(data = [], labels, sortPkgBy) {\n return (\n <ResponsiveContainer width=\"100%\" height={256}>\n <BarChart data={data} layout=\"vertical\">\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis type=\"number\" allowDecimals={false} />\n <YAxis type=\"category\" dataKey=\"name\" width={120} />\n <Tooltip\n formatter={(value) =>\n sortPkgBy === \"revenue\"\n ? [`Rp ${formatIDR(value)}`, labels.revenueMetric]\n : [value, labels.bookingsMetric]\n }\n />\n <Bar\n dataKey=\"value\"\n name={\n sortPkgBy === \"revenue\"\n ? labels.revenueMetric\n : labels.bookingsMetric\n }\n fill=\"#10b981\"\n radius={[4, 4, 4, 4]}\n />\n </BarChart>\n </ResponsiveContainer>\n );\n}\n\nChartCard.propTypes = {\n /** Konfigurasi widget chart. */\n widget: PropTypes.shape({\n id: PropTypes.string.isRequired,\n type: PropTypes.string.isRequired,\n label: PropTypes.string.isRequired,\n icon: PropTypes.string,\n }).isRequired,\n /** Objek label i18n. */\n labels: PropTypes.object.isRequired,\n /** Apakah sedang loading. */\n loading: PropTypes.bool,\n /** State filter dashboard. */\n filters: PropTypes.object,\n /** Data untuk semua jenis chart. */\n chartData: PropTypes.object,\n /** ClassName tambahan. */\n className: PropTypes.string,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport Button from \"../atoms/Button.jsx\";\nimport DateRangeFilter from \"../molecules/DateRangeFilter.jsx\";\n\nconst STATUS_OPTIONS = [\"confirmed\", \"pending\", \"all\"];\nconst AUDIENCE_OPTIONS = [\"\", \"domestic\", \"foreign\"];\nconst DAY_PRESETS = [7, 30, 90, 0];\nconst SORT_BY_OPTIONS = [\"bookings\", \"revenue\"];\nconst SORT_DIR_OPTIONS = [\"desc\", \"asc\"];\n\nexport default function FilterPanel({ filters, labels, onFilterChange, onResetFilters, className = \"\" }) {\n return (\n <div className={[\"rdb-filter-panel\", className].filter(Boolean).join(\" \")}>\n {/* Row 1 */}\n <div className=\"rdb-filter-row\">\n <select className=\"rdb-select\" value={filters.statusScope}\n onChange={e => onFilterChange(\"statusScope\", e.target.value)}>\n {STATUS_OPTIONS.map(s => (\n <option key={s} value={s}>\n {s === \"confirmed\" ? labels.confirmedOnly : s === \"pending\" ? labels.pendingOnly : labels.allStatus}\n </option>\n ))}\n </select>\n\n <label className=\"rdb-filter-overlay-label\">\n <input type=\"checkbox\" checked={filters.includePendingOverlay}\n onChange={e => onFilterChange(\"includePendingOverlay\", e.target.checked)} />\n <span className=\"rdb-body\">{labels.showPendingOverlay}</span>\n </label>\n\n <select className=\"rdb-select\" value={filters.audience}\n onChange={e => onFilterChange(\"audience\", e.target.value)}>\n {AUDIENCE_OPTIONS.map(a => (\n <option key={a || \"all\"} value={a}>\n {a === \"domestic\" ? labels.audienceDomestic : a === \"foreign\" ? labels.audienceForeign : labels.allAudience}\n </option>\n ))}\n </select>\n\n <select className=\"rdb-select\" value={String(filters.daysPreset)}\n onChange={e => onFilterChange(\"daysPreset\", Number(e.target.value))}>\n {DAY_PRESETS.map(d => (\n <option key={String(d)} value={String(d)}>\n {d === 0 ? labels.customDate : labels.dayLabel(d)}\n </option>\n ))}\n </select>\n\n <DateRangeFilter\n dateFrom={filters.dateFrom || \"\"}\n dateTo={filters.dateTo || \"\"}\n onRangeChange={({ dateFrom, dateTo }) => {\n if (dateFrom !== filters.dateFrom) onFilterChange(\"dateFrom\", dateFrom);\n if (dateTo !== filters.dateTo) onFilterChange(\"dateTo\", dateTo);\n }}\n disabled={filters.daysPreset !== 0}\n className=\"rdb-filter-date\"\n />\n </div>\n\n {/* Row 2 */}\n <div className=\"rdb-filter-actions\">\n <Button variant=\"secondary\" size=\"sm\" onClick={onResetFilters}>{labels.reset}</Button>\n <div className=\"rdb-filter-sort\">\n <span className=\"rdb-caption\">{labels.topSort}:</span>\n <select className=\"rdb-select\" style={{ width: \"auto\" }} value={filters.sortPkgBy}\n onChange={e => onFilterChange(\"sortPkgBy\", e.target.value)}>\n {SORT_BY_OPTIONS.map(s => (\n <option key={s} value={s}>{s === \"bookings\" ? labels.sortBookings : labels.sortRevenue}</option>\n ))}\n </select>\n <select className=\"rdb-select\" style={{ width: \"auto\" }} value={filters.sortPkgDir}\n onChange={e => onFilterChange(\"sortPkgDir\", e.target.value)}>\n {SORT_DIR_OPTIONS.map(d => (\n <option key={d} value={d}>{d === \"desc\" ? labels.sortDesc : labels.sortAsc}</option>\n ))}\n </select>\n </div>\n </div>\n </div>\n );\n}\n\nFilterPanel.propTypes = {\n filters: PropTypes.object.isRequired,\n labels: PropTypes.object.isRequired,\n onFilterChange: PropTypes.func.isRequired,\n onResetFilters: PropTypes.func.isRequired,\n className: PropTypes.string,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport Icon from \"../atoms/Icon.jsx\";\n\nexport default function SidebarNavigation({ items = [], activeItem = \"\", onItemClick, logo = null, className = \"\" }) {\n return (\n <aside className={[\"rdb-sidebar\", className].filter(Boolean).join(\" \")}>\n {logo ? <div className=\"rdb-sidebar-logo\">{logo}</div> : null}\n <nav className=\"rdb-sidebar-nav\" aria-label=\"Sidebar navigation\">\n {items.map(item => {\n const isActive = item.id === activeItem;\n return (\n <button key={item.id} type=\"button\"\n onClick={() => onItemClick?.(item.id)}\n aria-current={isActive ? \"page\" : undefined}\n className={[\"rdb-nav-item\", isActive ? \"rdb-nav-item-active\" : \"\"].filter(Boolean).join(\" \")}>\n {item.icon ? (\n <Icon name={item.icon} size={18}\n style={{ color: isActive ? \"var(--rdb-blue-600)\" : \"var(--rdb-text-subtle)\" }} />\n ) : null}\n <span>{item.label}</span>\n {isActive ? <span className=\"rdb-nav-dot\" /> : null}\n </button>\n );\n })}\n </nav>\n </aside>\n );\n}\n\nSidebarNavigation.propTypes = {\n items: PropTypes.arrayOf(PropTypes.shape({ id: PropTypes.string.isRequired, label: PropTypes.string.isRequired, icon: PropTypes.string })),\n activeItem: PropTypes.string,\n onItemClick: PropTypes.func,\n logo: PropTypes.node,\n className: PropTypes.string,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\n\nexport default function TopbarHeader({ title = \"\", actions = null, leading = null, className = \"\" }) {\n return (\n <header className={[\"rdb-topbar\", className].filter(Boolean).join(\" \")}>\n <div className=\"rdb-topbar-left\">\n {leading}\n {title ? <span className=\"rdb-h2\" style={{ overflow:\"hidden\", textOverflow:\"ellipsis\", whiteSpace:\"nowrap\" }}>{title}</span> : null}\n </div>\n {actions ? <div className=\"rdb-topbar-right\">{actions}</div> : null}\n </header>\n );\n}\n\nTopbarHeader.propTypes = {\n title: PropTypes.string,\n actions: PropTypes.node,\n leading: PropTypes.node,\n className: PropTypes.string,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\n\nexport default function DashboardLayout({ header = null, sidebar = null, children, className = \"\" }) {\n return (\n <div className={[\"rdb-layout\", className].filter(Boolean).join(\" \")}>\n {header}\n <div className=\"rdb-layout-body\">\n {sidebar}\n <main className=\"rdb-layout-main\">{children}</main>\n </div>\n </div>\n );\n}\n\nDashboardLayout.propTypes = {\n header: PropTypes.node,\n sidebar: PropTypes.node,\n children: PropTypes.node.isRequired,\n className: PropTypes.string,\n};\n","import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport \"./dashboard.css\";\nimport Icon from \"./atoms/Icon.jsx\";\nimport SkeletonLoader from \"./atoms/SkeletonLoader.jsx\";\nimport Button from \"./atoms/Button.jsx\";\nimport Badge from \"./atoms/Badge.jsx\";\nimport StatCard from \"./molecules/StatCard.jsx\";\nimport FilterPanel from \"./organisms/FilterPanel.jsx\";\nimport ChartCard from \"./organisms/ChartCard.jsx\";\nimport DataTable from \"./organisms/DataTable.jsx\";\nimport { SetupWizard } from \"./SetupWizard.jsx\";\nimport { validateDashboardConfig } from \"../config/createDashboardConfig.js\";\n\n/**\n * ReusableDashboardView — Komponen halaman (Page) dashboard utama.\n *\n * Fitur tambahan (revisi dosen — Opsi B):\n * - Secara otomatis mendeteksi apakah konfigurasi sudah valid.\n * - Jika belum valid, menampilkan SetupWizard (pop-up panduan interaktif).\n * - Developer dapat menutup wizard untuk lanjut tanpa konfigurasi.\n * - Prop `supabase` opsional: mengaktifkan fitur baca tabel langsung di wizard.\n * - Prop `dashboardConfig` opsional: jika diisi (hasil createDashboardConfig),\n * validasi dilakukan otomatis.\n *\n * @param {object} props\n * @param {object} props.config - Konfigurasi widget dashboard.\n * @param {object} props.labels - Objek label i18n.\n * @param {boolean} props.loading - Status loading data.\n * @param {string} [props.error] - Pesan error jika ada.\n * @param {object} [props.filters] - State filter dashboard.\n * @param {Function} props.onFilterChange - Callback perubahan filter.\n * @param {Function} props.onResetFilters - Callback reset filter.\n * @param {Function} props.onRefresh - Callback refresh data.\n * @param {object} [props.data] - Data dashboard.\n * @param {string} [props.dateLocale] - Locale untuk format tanggal.\n * @param {boolean} [props.liveUpdateEnabled] - Apakah live update aktif.\n * @param {object} [props.supabase] - Supabase client (aktifkan fitur baca tabel di wizard).\n * @param {object} [props.dashboardConfig] - Hasil createDashboardConfig() untuk validasi otomatis.\n */\nexport function ReusableDashboardView({\n config, labels, loading, error, filters,\n onFilterChange, onResetFilters, onRefresh,\n data, dateLocale, liveUpdateEnabled,\n supabase, dashboardConfig,\n}) {\n // ── Deteksi apakah setup wizard perlu ditampilkan ──────────────────\n // Validasi dilakukan berdasarkan dashboardConfig (jika ada) atau\n // pengecekan manual pada prop config & labels.\n const [wizardDismissed, setWizardDismissed] = React.useState(false);\n\n const configIssues = React.useMemo(() => {\n if (wizardDismissed) return [];\n\n // Jika developer menyertakan dashboardConfig (dari createDashboardConfig),\n // gunakan validator bawaan factory\n if (dashboardConfig) {\n const { issues } = validateDashboardConfig(dashboardConfig);\n return issues;\n }\n\n // Fallback: validasi manual pada prop langsung\n const issues = [];\n if (!config) issues.push(\"Prop 'config' (widgetConfig) belum diisi.\");\n if (!config?.widgets?.stats?.length) issues.push(\"widgetConfig.widgets.stats kosong. Tambahkan minimal 1 stat card.\");\n if (!config?.widgets?.charts?.length) issues.push(\"widgetConfig.widgets.charts kosong. Tambahkan minimal 1 chart.\");\n if (!config?.widgets?.table?.columns?.length) issues.push(\"widgetConfig.widgets.table.columns kosong.\");\n if (!labels) issues.push(\"Prop 'labels' belum diisi.\");\n if (!labels?.title) issues.push(\"labels.title belum diisi.\");\n if (!labels?.formatStatusLabel) issues.push(\"labels.formatStatusLabel (function) belum diisi.\");\n return issues;\n }, [config, labels, dashboardConfig, wizardDismissed]);\n\n const showWizard = !wizardDismissed && configIssues.length > 0;\n\n // ── Guard: jika config benar-benar null, render wizard saja ────────\n if (!config || !config.widgets) {\n return (\n <div className=\"rdb-view\">\n <SetupWizard\n issues={[\"Prop 'config' (widgetConfig) belum diisi atau tidak valid.\"]}\n onDismiss={() => setWizardDismissed(true)}\n supabase={supabase}\n />\n </div>\n );\n }\n\n return (\n <div className=\"rdb-view\">\n {/* Setup Wizard (muncul saat konfigurasi belum lengkap) */}\n {showWizard && (\n <SetupWizard\n issues={configIssues}\n onDismiss={() => setWizardDismissed(true)}\n supabase={supabase}\n />\n )}\n\n <div className=\"rdb-view-container\">\n\n {/* Header + Filter */}\n <div className=\"rdb-header-panel\">\n <div className=\"rdb-header-top\">\n <div className=\"rdb-header-title-group\">\n <span className=\"rdb-h1\">{labels?.title ?? \"Dashboard\"}</span>\n {liveUpdateEnabled ? (\n <Badge status=\"success\">{labels?.liveUpdate ?? \"Live\"}</Badge>\n ) : null}\n </div>\n <Button variant=\"secondary\" size=\"sm\" onClick={() => onRefresh()} title={labels?.refresh ?? \"Refresh\"}>\n <Icon name=\"RotateCcw\" size={16} />\n </Button>\n </div>\n\n {error ? (\n <div className=\"rdb-error-banner\">\n <span>{error}</span>\n <Button variant=\"secondary\" size=\"sm\" onClick={() => onRefresh()}>\n {labels?.retry ?? \"Retry\"}\n </Button>\n </div>\n ) : null}\n\n <FilterPanel filters={filters} labels={labels}\n onFilterChange={onFilterChange} onResetFilters={onResetFilters} />\n </div>\n\n {/* Stat Cards */}\n <div className=\"rdb-stats-grid\">\n {loading\n ? Array.from({ length: config.widgets.stats.length || 4 }).map((_, i) => (\n <SkeletonLoader key={i} style={{ height: 112 }} />\n ))\n : config.widgets.stats.map(widget => (\n <StatCard key={widget.id}\n label={labels?.[widget.label] ?? widget.label}\n value={data?.stats?.[widget.valueKey] ?? 0}\n icon={widget.icon}\n format={widget.format}\n accentColor={widget.accentColor}\n />\n ))}\n </div>\n\n {/* Chart Cards */}\n <div className=\"rdb-charts-grid\">\n {config.widgets.charts.map(widget => (\n <ChartCard key={widget.id} widget={widget} labels={labels ?? {}}\n loading={loading} filters={filters ?? {}} chartData={data?.charts ?? {}} />\n ))}\n </div>\n\n {/* Data Table */}\n <div className=\"rdb-card\" style={{ padding: 16 }}>\n <div style={{ display:\"flex\", alignItems:\"center\", gap:8, marginBottom:12 }}\n className=\"rdb-h3\">\n <Icon name={config.widgets.table.icon ?? \"Calendar\"} size={18} />\n {labels?.[config.widgets.table.label] ?? config.widgets.table.label}\n </div>\n {loading ? (\n <SkeletonLoader style={{ height: 192 }} />\n ) : (\n <DataTable\n columns={config.widgets.table.columns}\n data={data?.table?.recentBookings ?? []}\n labels={labels ?? {}}\n dateLocale={dateLocale ?? \"id-ID\"}\n emptyLabel={labels?.[config.widgets.table.emptyLabel] ?? config.widgets.table.emptyLabel}\n searchable={true}\n sortable={true}\n pageSize={10}\n />\n )}\n </div>\n\n </div>\n </div>\n );\n}\n\nReusableDashboardView.propTypes = {\n config: PropTypes.object.isRequired,\n labels: PropTypes.object.isRequired,\n loading: PropTypes.bool,\n error: PropTypes.string,\n filters: PropTypes.object,\n onFilterChange: PropTypes.func.isRequired,\n onResetFilters: PropTypes.func.isRequired,\n onRefresh: PropTypes.func.isRequired,\n data: PropTypes.object,\n dateLocale: PropTypes.string,\n liveUpdateEnabled: PropTypes.bool,\n /** Supabase client — aktifkan fitur baca tabel di wizard */\n supabase: PropTypes.object,\n /** Hasil createDashboardConfig() — untuk validasi otomatis wizard */\n dashboardConfig: PropTypes.object,\n};\n","import React, { useState, useEffect, useCallback } from \"react\";\r\nimport PropTypes from \"prop-types\";\r\nimport \"./dashboard.css\";\r\n\r\n// ─── Konstanta kolom standar preset ──────────────────────────────────\r\nconst PRESET_SIGNATURES = {\r\n cidika: {\r\n name: \"Cidika Travel\",\r\n tables: [\"bookings\", \"packages\", \"package_locales\"],\r\n },\r\n tokoSepatu: {\r\n name: \"Toko Sepatu / E-Commerce\",\r\n tables: [\"orders\", \"products\", \"customers\"],\r\n },\r\n};\r\n\r\nfunction detectPreset(tables) {\r\n if (!tables || tables.length === 0) return null;\r\n const tSet = new Set(tables);\r\n if (PRESET_SIGNATURES.cidika.tables.every(t => tSet.has(t))) return \"cidika\";\r\n if (PRESET_SIGNATURES.tokoSepatu.tables.every(t => tSet.has(t))) return \"tokoSepatu\";\r\n return null;\r\n}\r\n\r\n// ─── Code Generator ───────────────────────────────────────────────────\r\n// Menerima mapping yang dipilih user dan menghasilkan kode siap pakai\r\nfunction generateCode(mapping) {\r\n const {\r\n tableName,\r\n colDate, colStatus, colTotal, colCustomer, colItem,\r\n dashTitle, confirmedValue, pendingValue,\r\n } = mapping;\r\n\r\n const safeTitle = dashTitle || \"Dashboard\";\r\n const confirmed = confirmedValue || \"confirmed\";\r\n const pending = pendingValue || \"pending\";\r\n const safeCustomer = colCustomer || \"customer_name\";\r\n const safeItem = colItem || \"-\";\r\n const colTotalFull = colTotal || \"total\";\r\n\r\n const dataSource = `// src/datasources/myDashboardSource.js\r\n// AUTO-GENERATED oleh Setup Wizard @rozaqi02/reusable-dashboard\r\n// Tabel: ${tableName}\r\n\r\nexport function createMyDashboardSource(supabase) {\r\n return {\r\n async fetchDashboardSnapshot({ fromISO, toISO, statusScope }) {\r\n const allQuery = supabase\r\n .from(\"${tableName}\")\r\n .select(\"id, ${colDate}, ${colStatus}, ${colTotalFull}${colCustomer !== \"customer_name\" ? `, ${colCustomer}` : \", customer_name\"}${colItem !== \"-\" ? `, ${colItem}` : \"\"}\")\r\n .gte(\"${colDate}\", fromISO)\r\n .lte(\"${colDate}\", toISO)\r\n .order(\"${colDate}\", { ascending: true });\r\n\r\n const recentQuery = supabase\r\n .from(\"${tableName}\")\r\n .select(\"id, ${colDate}, ${colStatus}, ${colTotalFull}${colCustomer !== \"customer_name\" ? `, ${colCustomer}` : \", customer_name\"}${colItem !== \"-\" ? `, ${colItem}` : \"\"}\")\r\n .gte(\"${colDate}\", fromISO)\r\n .lte(\"${colDate}\", toISO)\r\n .order(\"${colDate}\", { ascending: false })\r\n .limit(10);\r\n\r\n if (statusScope && statusScope !== \"all\") {\r\n recentQuery.eq(\"${colStatus}\", statusScope);\r\n }\r\n\r\n const [allRes, recentRes] = await Promise.all([allQuery, recentQuery]);\r\n\r\n return {\r\n bookings: allRes.data || [], // semua transaksi (untuk chart & stats)\r\n recent: recentRes.data || [], // 10 terbaru (untuk tabel)\r\n packageLocales: [],\r\n staticCounts: { packages: 0, sections: 0 },\r\n };\r\n },\r\n\r\n subscribeLiveUpdate(onEvent) {\r\n const ch = supabase\r\n .channel(\"rdb-dashboard-live\")\r\n .on(\"postgres_changes\", { event: \"*\", schema: \"public\", table: \"${tableName}\" }, onEvent)\r\n .subscribe();\r\n return () => supabase.removeChannel(ch);\r\n },\r\n };\r\n}`;\r\n\r\n const adapter = `// src/adapters/myDashboardAdapter.js\r\n// AUTO-GENERATED oleh Setup Wizard @rozaqi02/reusable-dashboard\r\n// Mapping kolom: status=\"${colStatus}\", total=\"${colTotalFull}\", tanggal=\"${colDate}\"\r\n\r\nimport { toNumber, buildDayBuckets } from \"@rozaqi02/reusable-dashboard\";\r\n\r\nexport function createEmptyMyDashboardData() {\r\n return {\r\n stats: { bookingsConfirm: 0, revenueConfirm: 0 },\r\n charts: { dailyTrends: [], statusDistribution: [],\r\n audienceDistribution: [], topPackages: [] },\r\n table: { recentBookings: [] },\r\n };\r\n}\r\n\r\nexport function adaptMyDashboardData({ raw, range, dateLocale, labels }) {\r\n if (!raw) return createEmptyMyDashboardData();\r\n\r\n const buckets = buildDayBuckets(range.daysWindow, range.fromISO, dateLocale);\r\n const dayMap = new Map(buckets.map(b => [b.dateKey, b]));\r\n const statusMap = new Map();\r\n let confirmed = 0, revenue = 0;\r\n\r\n (raw.bookings || []).forEach(row => {\r\n const status = String(row[\"${colStatus}\"] || \"pending\").toLowerCase();\r\n const amount = toNumber(row[\"${colTotalFull}\"]);\r\n const dayKey = String(row[\"${colDate}\"] || \"\").slice(0, 10);\r\n\r\n statusMap.set(status, (statusMap.get(status) || 0) + 1);\r\n const bucket = dayMap.get(dayKey);\r\n if (bucket) {\r\n if (status === \"${confirmed}\") { bucket.count++; bucket.revenue += amount; }\r\n if (status === \"${pending}\") { bucket.pendingCount++; }\r\n }\r\n if (status === \"${confirmed}\") { confirmed++; revenue += amount; }\r\n });\r\n\r\n const avgRevenue = confirmed > 0 ? Math.round(revenue / confirmed) : 0;\r\n const totalTx = (raw.bookings || []).length;\r\n const conversionRate = totalTx > 0 ? Math.round((confirmed / totalTx) * 100) : 0;\r\n\r\n return {\r\n stats: {\r\n bookingsConfirm: confirmed,\r\n revenueConfirm: revenue,\r\n avgRevenue,\r\n conversionRate,\r\n },\r\n charts: {\r\n dailyTrends: buckets,\r\n statusDistribution: Array.from(statusMap.entries())\r\n .sort((a, b) => b[1] - a[1])\r\n .map(([status, count]) => ({\r\n status, count,\r\n label: labels?.formatStatusLabel?.(status) || status,\r\n })),\r\n audienceDistribution: [],\r\n topPackages: [],\r\n },\r\n table: {\r\n recentBookings: (raw.recent || []).map(row => ({\r\n id: row.id,\r\n createdAt: row[\"${colDate}\"],\r\n customerName: row[\"${colCustomer}\"] || \"-\",\r\n packageName: ${colItem !== \"-\" ? `row[\"${colItem}\"] || \"-\"` : '\"-\"'},\r\n audienceLabel: \"-\",\r\n totalIDR: toNumber(row[\"${colTotalFull}\"]),\r\n status: String(row[\"${colStatus}\"] || \"pending\").toLowerCase(),\r\n statusLabel: labels?.formatStatusLabel?.(row[\"${colStatus}\"]) || row[\"${colStatus}\"],\r\n })),\r\n },\r\n };\r\n}`;\r\n\r\n const widgetConfig = `// src/config/myDashboardConfig.js\r\n// AUTO-GENERATED oleh Setup Wizard @rozaqi02/reusable-dashboard\r\n\r\nexport const myDashboardConfig = {\r\n id: \"my.custom.dashboard\",\r\n defaultFilters: {\r\n statusScope: \"${confirmed}\",\r\n daysPreset: 30,\r\n sortPkgBy: \"bookings\",\r\n sortPkgDir: \"desc\",\r\n },\r\n widgets: {\r\n stats: [\r\n { id: \"orders\", label: \"confirmedBookings\", icon: \"TrendingUp\",\r\n valueKey: \"bookingsConfirm\", format: \"number\", accentColor: \"blue\" },\r\n { id: \"revenue\", label: \"confirmedRevenue\", icon: \"DollarSign\",\r\n valueKey: \"revenueConfirm\", format: \"currency\", accentColor: \"green\" },\r\n { id: \"avg\", label: \"avgRevenue\", icon: \"Users\",\r\n valueKey: \"avgRevenue\", format: \"currency\", accentColor: \"violet\" },\r\n { id: \"conversion\", label: \"conversionRate\", icon: \"PieChart\",\r\n valueKey: \"conversionRate\", format: \"percent\", accentColor: \"orange\" },\r\n ],\r\n charts: [\r\n { id: \"trend\", type: \"dailyArea\", label: \"dailyTrends\", icon: \"BarChart3\" },\r\n { id: \"status\", type: \"statusPie\", label: \"statusDistribution\", icon: \"PieChart\" },\r\n ],\r\n table: {\r\n id: \"recentTx\", label: \"recentBookings\", icon: \"Calendar\",\r\n emptyLabel: \"noRecentBookings\",\r\n columns: [\r\n { id: \"date\", label: \"date\", accessor: \"createdAt\", type: \"date\" },\r\n { id: \"customer\", label: \"customer\", accessor: \"customerName\" },${colItem !== \"-\" ? `\r\n { id: \"item\", label: \"package\", accessor: \"packageName\" },` : \"\"}\r\n { id: \"total\", label: \"total\", accessor: \"totalIDR\", type: \"currency\" },\r\n { id: \"status\", label: \"status\", accessor: \"statusLabel\",\r\n type: \"statusBadge\", statusAccessor: \"status\" },\r\n ],\r\n },\r\n },\r\n};`;\r\n\r\n const dashboard = `// src/pages/admin/Dashboard.jsx\r\n// AUTO-GENERATED oleh Setup Wizard @rozaqi02/reusable-dashboard\r\n// Salin file ini ke halaman dashboard kamu.\r\n\r\nimport React from \"react\";\r\nimport { supabase } from \"../../lib/supabaseClient.js\";\r\nimport {\r\n ReusableDashboardView,\r\n useReusableDashboard,\r\n createDashboardConfig,\r\n} from \"@rozaqi02/reusable-dashboard\";\r\n\r\n// Import 3 file yang digenerate wizard\r\nimport { myDashboardConfig } from \"./myDashboardConfig\";\r\nimport { createMyDashboardSource } from \"./myDashboardSource\";\r\nimport { adaptMyDashboardData, createEmptyMyDashboardData } from \"./myDashboardAdapter\";\r\n\r\n// Data source — dibuat sekali di luar komponen\r\nconst source = createMyDashboardSource(supabase);\r\n\r\n// Label UI — sesuaikan teks dengan bahasa/konteks bisnis kamu\r\nconst labels = {\r\n title: \"${safeTitle}\",\r\n refresh: \"Refresh\",\r\n liveUpdate: \"Live update\",\r\n loadFailed: \"Gagal memuat data.\",\r\n retry: \"Coba Lagi\",\r\n confirmedOnly: \"Selesai\",\r\n pendingOnly: \"Proses\",\r\n allStatus: \"Semua Status\",\r\n showPendingOverlay: \"Tampilkan pending\",\r\n reset: \"Reset\",\r\n confirmedBookings: \"Total Transaksi\",\r\n confirmedRevenue: \"Total Pendapatan\",\r\n avgRevenue: \"Rata-rata / Transaksi\",\r\n conversionRate: \"Conversion Rate\",\r\n dailyTrends: \"Tren Harian\",\r\n statusDistribution: \"Distribusi Status\",\r\n recentBookings: \"Transaksi Terbaru\",\r\n noRecentBookings: \"Belum ada transaksi\",\r\n date: \"Tanggal\",\r\n customer: \"Pelanggan\",\r\n package: \"Item\",\r\n total: \"Total\",\r\n status: \"Status\",\r\n bookingsMetric: \"Transaksi\",\r\n revenueMetric: \"Pendapatan\",\r\n confirmedBookingMetric: \"Transaksi (Selesai)\",\r\n confirmedRevenueMetric: \"Pendapatan (Selesai)\",\r\n dayLabel: n => n + \" hari\",\r\n formatStatusLabel: s =>\r\n ({ \"${confirmed}\": \"Selesai\", \"${pending}\": \"Proses\" })[s] || (s || \"-\"),\r\n formatAudienceLabel: v => v || \"-\",\r\n};\r\n\r\n// Kemas semua jadi 1 objek\r\nconst dashboardConfig = createDashboardConfig({\r\n widgetConfig: myDashboardConfig,\r\n dataSource: source,\r\n adapter: adaptMyDashboardData,\r\n createEmptyState: createEmptyMyDashboardData,\r\n languageCode: \"id\",\r\n dateLocale: \"id-ID\",\r\n labels,\r\n});\r\n\r\nexport default function Dashboard() {\r\n const state = useReusableDashboard({ ...dashboardConfig, labels });\r\n return (\r\n <ReusableDashboardView\r\n config={dashboardConfig.config}\r\n labels={labels}\r\n loading={state.loading}\r\n error={state.error}\r\n filters={state.filters}\r\n onFilterChange={state.updateFilter}\r\n onResetFilters={state.resetFilters}\r\n onRefresh={state.refresh}\r\n data={state.data}\r\n dateLocale={dashboardConfig.dateLocale}\r\n liveUpdateEnabled={state.liveUpdateEnabled}\r\n supabase={supabase}\r\n dashboardConfig={dashboardConfig}\r\n />\r\n );\r\n}`;\r\n\r\n return { dataSource, adapter, widgetConfig, dashboard };\r\n}\r\n\r\n// ─── Komponen utama ───────────────────────────────────────────────────\r\nexport function SetupWizard({ issues = [], onDismiss, supabase }) {\r\n const [dismissed, setDismissed] = useState(false);\r\n const [step, setStep] = useState(0);\r\n\r\n // Deteksi otomatis\r\n const [detecting, setDetecting] = useState(true);\r\n const [tables, setTables] = useState([]);\r\n const [columns, setColumns] = useState({}); // { tableName: [col1, col2, ...] }\r\n const [supabaseOk, setSupabaseOk] = useState(false);\r\n const [detectionDone, setDetectionDone] = useState(false);\r\n\r\n // Pertanyaan awal\r\n const [userHasDashboard, setUserHasDashboard] = useState(null);\r\n\r\n // Column mapping state\r\n const [selectedTable, setSelectedTable] = useState(\"\");\r\n const [colDate, setColDate] = useState(\"\");\r\n const [colStatus, setColStatus] = useState(\"\");\r\n const [colTotal, setColTotal] = useState(\"\");\r\n const [colCustomer, setColCustomer] = useState(\"\");\r\n const [colItem, setColItem] = useState(\"\");\r\n const [confirmedVal, setConfirmedVal] = useState(\"confirmed\");\r\n const [pendingVal, setPendingVal] = useState(\"pending\");\r\n const [dashTitle, setDashTitle] = useState(\"Dashboard\");\r\n const [loadingColumns, setLoadingColumns] = useState(false);\r\n\r\n // Generated code\r\n const [generatedCode, setGeneratedCode] = useState(null);\r\n const [activeCodeTab, setActiveCodeTab] = useState(\"dataSource\");\r\n const [copied, setCopied] = useState(\"\");\r\n\r\n // ── Deteksi Supabase & tabel saat mount ──────────────────────────\r\n useEffect(() => {\r\n if (!supabase) {\r\n setDetecting(false);\r\n setDetectionDone(true);\r\n return;\r\n }\r\n (async () => {\r\n try {\r\n // Strategi 1: coba RPC get_tables (jika sudah dibuat user)\r\n const { data: rpcData, error: rpcErr } = await supabase.rpc(\"rdb_get_tables\");\r\n if (!rpcErr && Array.isArray(rpcData)) {\r\n setTables(rpcData.map(r => typeof r === \"string\" ? r : (r.table_name || r.name || r)));\r\n setSupabaseOk(true);\r\n } else {\r\n // Strategi 2: coba information_schema via PostgREST\r\n const { data: schemaData, error: schemaErr } = await supabase\r\n .from(\"information_schema.tables\")\r\n .select(\"table_name\")\r\n .eq(\"table_schema\", \"public\")\r\n .eq(\"table_type\", \"BASE TABLE\")\r\n .order(\"table_name\");\r\n if (!schemaErr && schemaData) {\r\n setTables(schemaData.map(r => r.table_name));\r\n setSupabaseOk(true);\r\n } else {\r\n // Strategi 3: Supabase tersambung tapi tidak bisa baca schema\r\n // Cek koneksi saja dengan ping table yang tidak ada\r\n const { error: pingErr } = await supabase\r\n .from(\"_rdb_ping_\").select(\"*\").limit(1);\r\n // Kode 42P01 = table does not exist = koneksi OK tapi tabel tidak ada\r\n // PGRST116 = same thing via PostgREST\r\n const connected = !pingErr\r\n || pingErr.code === \"42P01\"\r\n || pingErr.code === \"PGRST116\"\r\n || (pingErr.message || \"\").includes(\"does not exist\");\r\n setSupabaseOk(connected);\r\n // Tabel harus diisi manual\r\n setTables([]);\r\n }\r\n }\r\n } catch {\r\n setSupabaseOk(false);\r\n } finally {\r\n setDetecting(false);\r\n setDetectionDone(true);\r\n }\r\n })();\r\n }, [supabase]);\r\n\r\n // ── Baca kolom saat tabel dipilih ────────────────────────────────\r\n const loadColumns = useCallback(async (tbl) => {\r\n if (!supabase || !tbl || columns[tbl]) return;\r\n setLoadingColumns(true);\r\n try {\r\n // Strategi 1: RPC rdb_get_columns\r\n const { data: rpcCols, error: rpcErr } = await supabase\r\n .rpc(\"rdb_get_columns\", { p_table: tbl });\r\n if (!rpcErr && Array.isArray(rpcCols)) {\r\n const colObjs = rpcCols.map(c =>\r\n typeof c === \"string\"\r\n ? { column_name: c, data_type: \"unknown\" }\r\n : { column_name: c.column_name || c.name || c, data_type: c.data_type || \"unknown\" }\r\n );\r\n setColumns(prev => ({ ...prev, [tbl]: colObjs }));\r\n autoDetectCols(colObjs);\r\n return;\r\n }\r\n\r\n // Strategi 2: information_schema.columns\r\n const { data: schemaCols, error: schemaErr } = await supabase\r\n .from(\"information_schema.columns\")\r\n .select(\"column_name, data_type\")\r\n .eq(\"table_schema\", \"public\")\r\n .eq(\"table_name\", tbl)\r\n .order(\"ordinal_position\");\r\n if (!schemaErr && schemaCols) {\r\n setColumns(prev => ({ ...prev, [tbl]: schemaCols }));\r\n autoDetectCols(schemaCols);\r\n return;\r\n }\r\n\r\n // Strategi 3: ambil 1 baris dan baca key-nya\r\n const { data: sampleRow, error: sampleErr } = await supabase\r\n .from(tbl).select(\"*\").limit(1);\r\n if (!sampleErr && sampleRow && sampleRow.length > 0) {\r\n const colObjs = Object.keys(sampleRow[0]).map(k => ({\r\n column_name: k,\r\n data_type: typeof sampleRow[0][k],\r\n }));\r\n setColumns(prev => ({ ...prev, [tbl]: colObjs }));\r\n autoDetectCols(colObjs);\r\n return;\r\n }\r\n\r\n // Strategi 4: tabel ada tapi kosong — ambil kolom dari error meta\r\n // Tidak ada cara lain tanpa RPC — beri tahu user\r\n setColumns(prev => ({ ...prev, [tbl]: [] }));\r\n } catch {\r\n setColumns(prev => ({ ...prev, [tbl]: [] }));\r\n } finally {\r\n setLoadingColumns(false);\r\n }\r\n }, [supabase, columns]);\r\n\r\n function autoDetectCols(colObjs) {\r\n const find = (candidates) =>\r\n colObjs.find(c => candidates.includes(c.column_name.toLowerCase()))?.column_name || \"\";\r\n setColDate(find([\"created_at\",\"tanggal\",\"date\",\"transaction_date\",\"order_date\",\"waktu\"]));\r\n setColStatus(find([\"status\",\"state\",\"kondisi\",\"order_status\",\"payment_status\"]));\r\n setColTotal(find([\"total\",\"total_idr\",\"total_amount\",\"total_price\",\"harga_total\",\"amount\",\"nominal\",\"harga\",\"biaya\"]));\r\n setColCustomer(find([\"customer_name\",\"nama_pelanggan\",\"nama\",\"name\",\"client_name\",\"buyer_name\",\"pelanggan\"]));\r\n setColItem(find([\"service_type\",\"item_name\",\"product_name\",\"package_name\",\"layanan\",\"produk\",\"nama_layanan\",\"jenis\",\"nama_produk\"]));\r\n }\r\n\r\n // ── Copy to clipboard ─────────────────────────────────────────────\r\n function copyCode(text, label) {\r\n navigator.clipboard.writeText(text).then(() => {\r\n setCopied(label);\r\n setTimeout(() => setCopied(\"\"), 2000);\r\n });\r\n }\r\n\r\n function handleDismiss() {\r\n setDismissed(true);\r\n if (onDismiss) onDismiss();\r\n }\r\n\r\n // ── Generate kode ─────────────────────────────────────────────────\r\n function handleGenerate() {\r\n if (!selectedTable || !colDate || !colStatus || !colTotal) return;\r\n const code = generateCode({\r\n tableName: selectedTable,\r\n colDate, colStatus, colTotal,\r\n colCustomer: colCustomer || \"customer_name\",\r\n colItem: colItem || \"-\",\r\n dashTitle, confirmedValue: confirmedVal, pendingValue: pendingVal,\r\n });\r\n setGeneratedCode(code);\r\n setStep(3);\r\n }\r\n\r\n if (dismissed) return null;\r\n\r\n const detectedPreset = detectPreset(tables);\r\n const tableColumns = selectedTable ? (columns[selectedTable] || []) : [];\r\n const colNames = tableColumns.map(c => c.column_name);\r\n\r\n // Validasi mapping lengkap\r\n const mappingValid = selectedTable && colDate && colStatus && colTotal;\r\n\r\n // ── Step labels ────────────────────────────────────────────────────\r\n const stepLabels = [\"Deteksi\", \"Pilih Tabel\", \"Mapping Kolom\", \"Kode Siap Pakai\"];\r\n\r\n return (\r\n <div className=\"rdb-wizard-overlay\" role=\"dialog\" aria-modal=\"true\"\r\n aria-label=\"Setup Wizard @rozaqi02/reusable-dashboard\">\r\n <div className=\"rdb-wizard-modal\">\r\n\r\n {/* ── Header ─────────────────────────────────────────────── */}\r\n <div className=\"rdb-wizard-header\">\r\n <div className=\"rdb-wizard-header-title\">\r\n <span className=\"rdb-wizard-logo\">🛠️</span>\r\n <div>\r\n <div className=\"rdb-h2\" style={{ margin: 0 }}>Setup Dashboard</div>\r\n <div className=\"rdb-caption\">\r\n {detecting\r\n ? \"Mendeteksi kondisi project…\"\r\n : supabaseOk\r\n ? `Supabase tersambung · ${tables.length} tabel ditemukan`\r\n : \"Panduan konfigurasi @rozaqi02/reusable-dashboard\"}\r\n </div>\r\n </div>\r\n </div>\r\n <button type=\"button\" className=\"rdb-wizard-close\"\r\n onClick={handleDismiss} title=\"Tutup\">✕</button>\r\n </div>\r\n\r\n {/* ── Step Nav ───────────────────────────────────────────── */}\r\n <div className=\"rdb-wizard-steps\">\r\n {stepLabels.map((label, i) => (\r\n <button key={i} type=\"button\"\r\n className={`rdb-wizard-step-btn ${step === i ? \"rdb-wizard-step-active\" : \"\"}`}\r\n onClick={() => { if (i < step || (i === step + 1 && step < 2)) setStep(i); }}>\r\n <span>{step > i ? \"✅\" : i + 1}.</span>\r\n <span>{label}</span>\r\n </button>\r\n ))}\r\n </div>\r\n\r\n {/* ── Body ───────────────────────────────────────────────── */}\r\n <div className=\"rdb-wizard-body\">\r\n <div className=\"rdb-wizard-section\">\r\n\r\n {/* ══════════════════════════════════════════════════════\r\n STEP 0 — DETEKSI OTOMATIS\r\n ══════════════════════════════════════════════════════ */}\r\n {step === 0 && (\r\n <>\r\n {issues.length > 0 && (\r\n <div className=\"rdb-wizard-issues\" style={{ marginBottom: 12 }}>\r\n <div className=\"rdb-caption\" style={{ fontWeight: 600, marginBottom: 6 }}>\r\n Konfigurasi belum lengkap:\r\n </div>\r\n {issues.map((iss, i) => (\r\n <div key={i} className=\"rdb-wizard-issue-item\">\r\n <span>❌</span><span className=\"rdb-body\">{iss}</span>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n\r\n <div className=\"rdb-wizard-flow\" style={{ marginBottom: 12 }}>\r\n <div className=\"rdb-caption\" style={{ fontWeight: 600, marginBottom: 10 }}>\r\n 🔍 Hasil deteksi otomatis:\r\n </div>\r\n {detecting ? (\r\n <div className=\"rdb-body\" style={{ color: \"var(--rdb-text-muted)\" }}>\r\n Mendeteksi…\r\n </div>\r\n ) : (\r\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 8 }}>\r\n <div className=\"rdb-wizard-issue-item\">\r\n <span>{supabaseOk ? \"✅\" : \"❌\"}</span>\r\n <span className=\"rdb-body\">\r\n Supabase {supabaseOk ? \"tersambung\" : \"tidak tersambung — pastikan supabaseClient.js sudah dikonfigurasi dan prop supabase dikirim ke ReusableDashboardView\"}\r\n </span>\r\n </div>\r\n {supabaseOk && (\r\n <div className=\"rdb-wizard-issue-item\">\r\n <span>{tables.length > 0 ? \"✅\" : \"⚠️\"}</span>\r\n <span className=\"rdb-body\">\r\n {tables.length > 0\r\n ? `${tables.length} tabel public ditemukan`\r\n : \"Daftar tabel tidak bisa dibaca otomatis (RLS aktif) — kamu bisa ketik nama tabel di step berikutnya\"}\r\n </span>\r\n </div>\r\n )}\r\n {supabaseOk && tables.length > 0 && detectedPreset && (\r\n <div className=\"rdb-wizard-issue-item\">\r\n <span>✅</span>\r\n <span className=\"rdb-body\">\r\n Tabel cocok dengan preset <strong>{PRESET_SIGNATURES[detectedPreset].name}</strong>\r\n </span>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n\r\n {!supabaseOk && detectionDone && (\r\n <div className=\"rdb-wizard-alert\" style={{ marginBottom: 12 }}>\r\n <span className=\"rdb-wizard-alert-icon\">ℹ️</span>\r\n <div>\r\n <div className=\"rdb-body\" style={{ fontWeight: 600 }}>Aktifkan koneksi Supabase</div>\r\n <div className=\"rdb-caption\" style={{ marginTop: 4 }}>\r\n Tambahkan prop ke ReusableDashboardView:{\" \"}\r\n <code className=\"rdb-wizard-code-inline\">supabase={\"{supabase}\"}</code>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n\r\n <div style={{ display: \"flex\", gap: 8, justifyContent: \"flex-end\" }}>\r\n <button type=\"button\" className=\"rdb-btn rdb-btn-secondary rdb-btn-sm\"\r\n onClick={handleDismiss}>Lanjutkan tanpa wizard</button>\r\n {supabaseOk && (\r\n <button type=\"button\" className=\"rdb-btn rdb-btn-primary rdb-btn-sm\"\r\n onClick={() => setStep(1)}>\r\n Lanjut → Pilih Tabel\r\n </button>\r\n )}\r\n </div>\r\n </>\r\n )}\r\n\r\n {/* ══════════════════════════════════════════════════════\r\n STEP 1 — PILIH TABEL\r\n ══════════════════════════════════════════════════════ */}\r\n {step === 1 && (\r\n <>\r\n <div className=\"rdb-wizard-step-title\">\r\n <span className=\"rdb-wizard-step-num\">2</span>\r\n <span className=\"rdb-h3\" style={{ margin: 0 }}>Pilih Tabel Transaksi</span>\r\n </div>\r\n <div className=\"rdb-body\" style={{ color: \"var(--rdb-text-muted)\", marginBottom: 16 }}>\r\n Pilih tabel yang berisi data transaksi bisnis kamu.\r\n </div>\r\n\r\n {/* Tabel terbaca otomatis */}\r\n {tables.length > 0 && (\r\n <>\r\n <div className=\"rdb-caption\" style={{ fontWeight: 600, marginBottom: 8 }}>\r\n Tabel yang ditemukan:\r\n </div>\r\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 6, marginBottom: 16 }}>\r\n {tables.map(tbl => (\r\n <button key={tbl} type=\"button\"\r\n onClick={() => {\r\n setSelectedTable(tbl);\r\n loadColumns(tbl);\r\n }}\r\n className={`rdb-btn rdb-btn-sm ${selectedTable === tbl ? \"rdb-btn-primary\" : \"rdb-btn-secondary\"}`}\r\n style={{ justifyContent: \"flex-start\", fontFamily: \"monospace\" }}>\r\n {selectedTable === tbl ? \"✅ \" : \"○ \"}{tbl}\r\n </button>\r\n ))}\r\n </div>\r\n </>\r\n )}\r\n\r\n {/* Input manual jika tabel tidak terbaca otomatis */}\r\n {tables.length === 0 && (\r\n <div style={{ marginBottom: 16 }}>\r\n <div className=\"rdb-wizard-alert\" style={{ marginBottom: 12 }}>\r\n <span className=\"rdb-wizard-alert-icon\">ℹ️</span>\r\n <div>\r\n <div className=\"rdb-body\" style={{ fontWeight: 600 }}>\r\n Daftar tabel tidak bisa terbaca otomatis\r\n </div>\r\n <div className=\"rdb-caption\" style={{ marginTop: 4 }}>\r\n Ini normal — Supabase memblokir akses ke <code>information_schema</code> via API publik.\r\n Ketik nama tabel secara manual di bawah.\r\n </div>\r\n </div>\r\n </div>\r\n <label className=\"rdb-label\">Nama tabel transaksi kamu</label>\r\n <div style={{ display: \"flex\", gap: 8 }}>\r\n <input className=\"rdb-input\" value={selectedTable}\r\n onChange={e => setSelectedTable(e.target.value)}\r\n placeholder=\"cth: orders, transaksi, bookings, penjualan\"\r\n style={{ maxWidth: 320 }} />\r\n <button type=\"button\"\r\n className=\"rdb-btn rdb-btn-secondary rdb-btn-sm\"\r\n disabled={!selectedTable || loadingColumns}\r\n onClick={() => loadColumns(selectedTable)}>\r\n {loadingColumns ? \"Membaca…\" : \"Baca kolom\"}\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Input manual tambahan meski tabel sudah terdeteksi */}\r\n {tables.length > 0 && !selectedTable && (\r\n <div className=\"rdb-caption\" style={{ color: \"var(--rdb-text-muted)\", marginBottom: 12 }}>\r\n Atau ketik nama tabel secara manual:\r\n <input className=\"rdb-input\" style={{ marginTop: 6, maxWidth: 280 }}\r\n placeholder=\"nama tabel lain\"\r\n onChange={e => {\r\n setSelectedTable(e.target.value);\r\n if (e.target.value) loadColumns(e.target.value);\r\n }} />\r\n </div>\r\n )}\r\n\r\n {selectedTable && (\r\n <div className=\"rdb-wizard-tip\" style={{ marginBottom: 12 }}>\r\n Tabel <strong>{selectedTable}</strong> dipilih.\r\n {loadingColumns\r\n ? \" Membaca kolom…\"\r\n : tableColumns.length > 0\r\n ? ` ${tableColumns.length} kolom ditemukan — kolom sudah ter-auto-detect di step berikutnya.`\r\n : tableColumns.length === 0 && !loadingColumns && columns[selectedTable] !== undefined\r\n ? \" Tabel kosong atau tidak ada kolom terbaca — kamu bisa ketik nama kolom manual di step berikutnya.\"\r\n : \"\"}\r\n </div>\r\n )}\r\n\r\n <div style={{ marginBottom: 12 }}>\r\n <label className=\"rdb-label\">Judul dashboard (opsional)</label>\r\n <input className=\"rdb-input\" value={dashTitle} style={{ maxWidth: 280 }}\r\n onChange={e => setDashTitle(e.target.value)}\r\n placeholder=\"cth: Dashboard Laundry Bersih\" />\r\n </div>\r\n\r\n <div style={{ display: \"flex\", gap: 8, justifyContent: \"flex-end\" }}>\r\n <button type=\"button\" className=\"rdb-btn rdb-btn-secondary rdb-btn-sm\"\r\n onClick={() => setStep(0)}>← Kembali</button>\r\n <button type=\"button\" className=\"rdb-btn rdb-btn-primary rdb-btn-sm\"\r\n disabled={!selectedTable || loadingColumns}\r\n onClick={() => setStep(2)}>\r\n Lanjut → Mapping Kolom\r\n </button>\r\n </div>\r\n </>\r\n )}\r\n\r\n {/* ══════════════════════════════════════════════════════\r\n STEP 2 — MAPPING KOLOM\r\n ══════════════════════════════════════════════════════ */}\r\n {step === 2 && (\r\n <>\r\n <div className=\"rdb-wizard-step-title\">\r\n <span className=\"rdb-wizard-step-num\">3</span>\r\n <span className=\"rdb-h3\" style={{ margin: 0 }}>\r\n Mapping Kolom — Tabel: <code style={{ fontSize: \"0.9rem\" }}>{selectedTable}</code>\r\n </span>\r\n </div>\r\n <div className=\"rdb-body\" style={{ color: \"var(--rdb-text-muted)\", marginBottom: 16 }}>\r\n Pilih kolom yang berperan sebagai masing-masing data.\r\n Kolom sudah ter-deteksi otomatis — cukup verifikasi dan sesuaikan jika perlu.\r\n </div>\r\n\r\n <div style={{ display: \"grid\", gridTemplateColumns: \"1fr 1fr\", gap: 12, marginBottom: 16 }}>\r\n {/* Tanggal */}\r\n <div>\r\n <label className=\"rdb-label\">\r\n Kolom Tanggal <span style={{ color: \"red\" }}>*</span>\r\n </label>\r\n {colNames.length > 0 ? (\r\n <select className=\"rdb-select\" value={colDate}\r\n onChange={e => setColDate(e.target.value)}>\r\n <option value=\"\">— pilih kolom —</option>\r\n {colNames.map(c => <option key={c} value={c}>{c}</option>)}\r\n </select>\r\n ) : (\r\n <input className=\"rdb-input\" value={colDate}\r\n onChange={e => setColDate(e.target.value)}\r\n placeholder=\"cth: created_at\" />\r\n )}\r\n <div className=\"rdb-caption\" style={{ marginTop: 2 }}>Tipe timestamp/date</div>\r\n </div>\r\n\r\n {/* Status */}\r\n <div>\r\n <label className=\"rdb-label\">\r\n Kolom Status <span style={{ color: \"red\" }}>*</span>\r\n </label>\r\n {colNames.length > 0 ? (\r\n <select className=\"rdb-select\" value={colStatus}\r\n onChange={e => setColStatus(e.target.value)}>\r\n <option value=\"\">— pilih kolom —</option>\r\n {colNames.map(c => <option key={c} value={c}>{c}</option>)}\r\n </select>\r\n ) : (\r\n <input className=\"rdb-input\" value={colStatus}\r\n onChange={e => setColStatus(e.target.value)}\r\n placeholder=\"cth: status\" />\r\n )}\r\n <div className=\"rdb-caption\" style={{ marginTop: 2 }}>Nilai selesai/pending</div>\r\n </div>\r\n\r\n {/* Total */}\r\n <div>\r\n <label className=\"rdb-label\">\r\n Kolom Total (uang) <span style={{ color: \"red\" }}>*</span>\r\n </label>\r\n {colNames.length > 0 ? (\r\n <select className=\"rdb-select\" value={colTotal}\r\n onChange={e => setColTotal(e.target.value)}>\r\n <option value=\"\">— pilih kolom —</option>\r\n {colNames.map(c => <option key={c} value={c}>{c}</option>)}\r\n </select>\r\n ) : (\r\n <input className=\"rdb-input\" value={colTotal}\r\n onChange={e => setColTotal(e.target.value)}\r\n placeholder=\"cth: total_amount\" />\r\n )}\r\n <div className=\"rdb-caption\" style={{ marginTop: 2 }}>Integer Rupiah</div>\r\n </div>\r\n\r\n {/* Customer */}\r\n <div>\r\n <label className=\"rdb-label\">Kolom Nama Pelanggan</label>\r\n {colNames.length > 0 ? (\r\n <select className=\"rdb-select\" value={colCustomer}\r\n onChange={e => setColCustomer(e.target.value)}>\r\n <option value=\"\">— opsional —</option>\r\n {colNames.map(c => <option key={c} value={c}>{c}</option>)}\r\n </select>\r\n ) : (\r\n <input className=\"rdb-input\" value={colCustomer}\r\n onChange={e => setColCustomer(e.target.value)}\r\n placeholder=\"cth: customer_name (opsional)\" />\r\n )}\r\n </div>\r\n\r\n {/* Item */}\r\n <div>\r\n <label className=\"rdb-label\">Kolom Nama Item/Layanan</label>\r\n {colNames.length > 0 ? (\r\n <select className=\"rdb-select\" value={colItem}\r\n onChange={e => setColItem(e.target.value)}>\r\n <option value=\"\">— opsional —</option>\r\n {colNames.map(c => <option key={c} value={c}>{c}</option>)}\r\n </select>\r\n ) : (\r\n <input className=\"rdb-input\" value={colItem}\r\n onChange={e => setColItem(e.target.value)}\r\n placeholder=\"cth: service_type (opsional)\" />\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Nilai status */}\r\n <div className=\"rdb-wizard-flow\" style={{ marginBottom: 16 }}>\r\n <div className=\"rdb-caption\" style={{ fontWeight: 600, marginBottom: 8 }}>\r\n Nilai status di tabel kamu:\r\n </div>\r\n <div style={{ display: \"grid\", gridTemplateColumns: \"1fr 1fr\", gap: 12 }}>\r\n <div>\r\n <label className=\"rdb-label\">Nilai \"Selesai/Confirmed\"</label>\r\n <input className=\"rdb-input\" value={confirmedVal}\r\n onChange={e => setConfirmedVal(e.target.value)}\r\n placeholder=\"cth: confirmed, selesai, lunas\" />\r\n </div>\r\n <div>\r\n <label className=\"rdb-label\">Nilai \"Pending/Proses\"</label>\r\n <input className=\"rdb-input\" value={pendingVal}\r\n onChange={e => setPendingVal(e.target.value)}\r\n placeholder=\"cth: pending, proses, menunggu\" />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {!mappingValid && (\r\n <div className=\"rdb-error-banner\" style={{ marginBottom: 12 }}>\r\n Pilih minimal kolom Tanggal, Status, dan Total untuk generate kode.\r\n </div>\r\n )}\r\n\r\n <div style={{ display: \"flex\", gap: 8, justifyContent: \"flex-end\" }}>\r\n <button type=\"button\" className=\"rdb-btn rdb-btn-secondary rdb-btn-sm\"\r\n onClick={() => setStep(1)}>← Kembali</button>\r\n <button type=\"button\" className=\"rdb-btn rdb-btn-primary rdb-btn-sm\"\r\n disabled={!mappingValid}\r\n onClick={handleGenerate}>\r\n ✨ Generate Kode →\r\n </button>\r\n </div>\r\n </>\r\n )}\r\n\r\n {/* ══════════════════════════════════════════════════════\r\n STEP 3 — KODE SIAP PAKAI\r\n ══════════════════════════════════════════════════════ */}\r\n {step === 3 && generatedCode && (\r\n <>\r\n <div className=\"rdb-wizard-step-title\">\r\n <span className=\"rdb-wizard-step-num\">✅</span>\r\n <span className=\"rdb-h3\" style={{ margin: 0 }}>Kode Siap Pakai</span>\r\n </div>\r\n <div className=\"rdb-wizard-tip\" style={{ marginBottom: 16 }}>\r\n <strong>4 file sudah digenerate.</strong> Salin masing-masing ke project kamu.\r\n Tidak perlu memahami logika di dalamnya — cukup save dan jalankan.\r\n </div>\r\n\r\n {/* Instruksi singkat */}\r\n <div className=\"rdb-wizard-issues\" style={{ marginBottom: 16 }}>\r\n {[\r\n [\"myDashboardSource.js\", \"src/datasources/\", \"File koneksi ke Supabase\"],\r\n [\"myDashboardAdapter.js\", \"src/adapters/\", \"Transformasi data → format dashboard\"],\r\n [\"myDashboardConfig.js\", \"src/config/ (atau langsung di Dashboard.jsx)\", \"Konfigurasi widget\"],\r\n [\"Dashboard.jsx\", \"src/pages/admin/\", \"Ganti halaman dashboard lama\"],\r\n ].map(([file, path, desc], i) => (\r\n <div key={i} className=\"rdb-wizard-issue-item\">\r\n <span style={{ color: \"var(--rdb-blue-500)\", fontWeight: 700 }}>{i + 1}.</span>\r\n <span className=\"rdb-body\">\r\n Simpan <code className=\"rdb-wizard-code-inline\">{file}</code> ke{\" \"}\r\n <code className=\"rdb-wizard-code-inline\">{path}</code> — {desc}\r\n </span>\r\n </div>\r\n ))}\r\n <div className=\"rdb-wizard-issue-item\">\r\n <span style={{ color: \"var(--rdb-blue-500)\", fontWeight: 700 }}>5.</span>\r\n <span className=\"rdb-body\">\r\n Import CSS di <code className=\"rdb-wizard-code-inline\">src/index.css</code>:{\" \"}\r\n <code className=\"rdb-wizard-code-inline\">\r\n @import \"../node_modules/@rozaqi02/reusable-dashboard/dist/index.css\";\r\n </code>\r\n </span>\r\n </div>\r\n </div>\r\n\r\n {/* Tab selector */}\r\n <div style={{ display: \"flex\", gap: 4, marginBottom: 8, flexWrap: \"wrap\" }}>\r\n {[\r\n [\"dataSource\", \"myDashboardSource.js\"],\r\n [\"adapter\", \"myDashboardAdapter.js\"],\r\n [\"widgetConfig\",\"myDashboardConfig.js\"],\r\n [\"dashboard\", \"Dashboard.jsx\"],\r\n ].map(([key, label]) => (\r\n <button key={key} type=\"button\"\r\n onClick={() => setActiveCodeTab(key)}\r\n className={`rdb-btn rdb-btn-sm ${activeCodeTab === key ? \"rdb-btn-primary\" : \"rdb-btn-secondary\"}`}\r\n style={{ fontFamily: \"monospace\", fontSize: \"0.75rem\" }}>\r\n {label}\r\n </button>\r\n ))}\r\n </div>\r\n\r\n {/* Kode + tombol copy */}\r\n <div style={{ position: \"relative\" }}>\r\n <button type=\"button\"\r\n onClick={() => copyCode(generatedCode[activeCodeTab], activeCodeTab)}\r\n className=\"rdb-btn rdb-btn-sm rdb-btn-secondary\"\r\n style={{ position: \"absolute\", top: 8, right: 8, zIndex: 1 }}>\r\n {copied === activeCodeTab ? \"✅ Disalin!\" : \"📋 Salin\"}\r\n </button>\r\n <pre className=\"rdb-wizard-code\" style={{ maxHeight: 320, overflow: \"auto\" }}>\r\n {generatedCode[activeCodeTab]}\r\n </pre>\r\n </div>\r\n\r\n <div className=\"rdb-wizard-tip\" style={{ marginTop: 12 }}>\r\n Setelah semua file tersimpan dan dev server direstart, wizard tidak akan muncul lagi.\r\n </div>\r\n\r\n <div style={{ display: \"flex\", gap: 8, justifyContent: \"flex-end\", marginTop: 12 }}>\r\n <button type=\"button\" className=\"rdb-btn rdb-btn-secondary rdb-btn-sm\"\r\n onClick={() => setStep(2)}>← Edit mapping</button>\r\n <button type=\"button\" className=\"rdb-btn rdb-btn-primary rdb-btn-sm\"\r\n onClick={handleDismiss}>\r\n Tutup wizard ✓\r\n </button>\r\n </div>\r\n </>\r\n )}\r\n\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nSetupWizard.propTypes = {\r\n issues: PropTypes.arrayOf(PropTypes.string),\r\n onDismiss: PropTypes.func,\r\n supabase: PropTypes.object,\r\n};\r\n","export function createDashboardLabels(t) {\n const labels = {\n title: t(\"admin.dashboard.title\", { defaultValue: \"Dashboard\" }),\n refresh: t(\"admin.dashboard.refresh\", { defaultValue: \"Refresh\" }),\n liveUpdate: t(\"admin.dashboard.liveUpdate\", { defaultValue: \"Live update\" }),\n loadFailed: t(\"admin.dashboard.loadFailed\", {\n defaultValue: \"Failed to load dashboard data.\",\n }),\n retry: t(\"admin.dashboard.retry\", { defaultValue: \"Retry\" }),\n confirmedOnly: t(\"admin.dashboard.filters.confirmedOnly\", {\n defaultValue: \"Confirmed only\",\n }),\n pendingOnly: t(\"admin.dashboard.filters.pendingOnly\", {\n defaultValue: \"Pending only\",\n }),\n allStatus: t(\"admin.dashboard.filters.allStatus\", {\n defaultValue: \"All status\",\n }),\n showPendingOverlay: t(\"admin.dashboard.filters.showPendingOverlay\", {\n defaultValue: \"Show pending overlay\",\n }),\n allAudience: t(\"admin.dashboard.filters.allAudience\", {\n defaultValue: \"All audience\",\n }),\n audienceDomestic: t(\"explore.domestic\", { defaultValue: \"Domestic\" }),\n audienceForeign: t(\"explore.foreign\", { defaultValue: \"Foreign\" }),\n customDate: t(\"admin.dashboard.filters.customDate\", {\n defaultValue: \"Custom\",\n }),\n reset: t(\"admin.dashboard.filters.reset\", { defaultValue: \"Reset\" }),\n topSort: t(\"admin.dashboard.filters.topSort\", {\n defaultValue: \"Top packages sort\",\n }),\n sortBookings: t(\"admin.dashboard.filters.sortBookings\", {\n defaultValue: \"Bookings\",\n }),\n sortRevenue: t(\"admin.dashboard.filters.sortRevenue\", {\n defaultValue: \"Revenue\",\n }),\n sortDesc: t(\"admin.dashboard.filters.sortDesc\", { defaultValue: \"Desc\" }),\n sortAsc: t(\"admin.dashboard.filters.sortAsc\", { defaultValue: \"Asc\" }),\n confirmedBookings: t(\"admin.dashboard.cards.confirmedBookings\", {\n defaultValue: \"Confirmed Bookings\",\n }),\n confirmedRevenue: t(\"admin.dashboard.cards.confirmedRevenue\", {\n defaultValue: \"Revenue (Confirmed)\",\n }),\n avgRevenue: t(\"admin.dashboard.cards.avgRevenue\", {\n defaultValue: \"Avg Revenue / Booking\",\n }),\n conversionRate: t(\"admin.dashboard.cards.conversionRate\", {\n defaultValue: \"Conversion Rate\",\n }),\n totalProducts: t(\"admin.dashboard.cards.totalProducts\", {\n defaultValue: \"Total Products\",\n }),\n totalCustomers: t(\"admin.dashboard.cards.totalCustomers\", {\n defaultValue: \"Total Customers\",\n }),\n dailyTrends: t(\"admin.dashboard.sections.dailyTrends\", {\n defaultValue: \"Daily Trends\",\n }),\n statusDistribution: t(\"admin.dashboard.sections.statusDistribution\", {\n defaultValue: \"Status Distribution\",\n }),\n audienceDistribution: t(\"admin.dashboard.sections.audienceDistribution\", {\n defaultValue: \"Audience Distribution\",\n }),\n topPackages: t(\"admin.dashboard.sections.topPackages\", {\n defaultValue: \"Top Packages\",\n }),\n recentBookings: t(\"admin.dashboard.sections.recentBookings\", {\n defaultValue: \"Recent Bookings\",\n }),\n date: t(\"admin.dashboard.table.date\", { defaultValue: \"Date\" }),\n customer: t(\"admin.dashboard.table.customer\", { defaultValue: \"Customer\" }),\n package: t(\"admin.dashboard.table.package\", { defaultValue: \"Package\" }),\n audience: t(\"admin.dashboard.table.audience\", { defaultValue: \"Audience\" }),\n total: t(\"admin.dashboard.table.total\", { defaultValue: \"Total\" }),\n status: t(\"admin.dashboard.table.status\", { defaultValue: \"Status\" }),\n noRecentBookings: t(\"admin.dashboard.emptyRecent\", {\n defaultValue: \"No recent bookings\",\n }),\n bookingsMetric: t(\"admin.dashboard.metrics.bookings\", {\n defaultValue: \"Bookings\",\n }),\n revenueMetric: t(\"admin.dashboard.metrics.revenue\", {\n defaultValue: \"Revenue\",\n }),\n pendingMetric: t(\"admin.dashboard.metrics.pendingBookings\", {\n defaultValue: \"Bookings (Pending)\",\n }),\n confirmedBookingMetric: t(\"admin.dashboard.metrics.confirmedBookings\", {\n defaultValue: \"Bookings (Confirmed)\",\n }),\n confirmedRevenueMetric: t(\"admin.dashboard.metrics.confirmedRevenue\", {\n defaultValue: \"Revenue (Confirmed)\",\n }),\n unknownAudience: t(\"admin.dashboard.filters.unknownAudience\", {\n defaultValue: \"Unknown\",\n }),\n };\n\n labels.dayLabel = (count) =>\n t(\"admin.dashboard.filters.dayWindow\", {\n count,\n defaultValue: \"{{count}} days\",\n });\n\n labels.formatStatusLabel = (status) => {\n const normalized = String(status || \"pending\").toLowerCase();\n const defaultValue =\n normalized.charAt(0).toUpperCase() + normalized.slice(1);\n\n return t(`admin.dashboard.status.${normalized}`, { defaultValue });\n };\n\n labels.formatAudienceLabel = (value) => {\n if (value === \"domestic\") return labels.audienceDomestic;\n if (value === \"foreign\") return labels.audienceForeign;\n return labels.unknownAudience;\n };\n\n return labels;\n}\n"],"mappings":"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","names":["ensureNoError","import_react","import_react","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","MIN_YEAR","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","React","PropTypes","import_react","import_prop_types","import_react","import_prop_types","React","PropTypes","React","_a","issues","PropTypes"]}