@bagdja/kumpul 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/server.cjs CHANGED
@@ -1,434 +1,470 @@
1
- npm pack --dry-run
2
- npm publish --access public --registry=https://registry.npmjs.org/const React = require('react');
3
-
4
- const h = React.createElement;
5
-
6
- const defaultColors = {
7
- background: '#F0F7F8',
8
- surface: '#FFFFFF',
9
- text: '#0F172A',
10
- textMuted: '#64748B',
11
- accent: '#006699',
12
- accentHover: '#00557A',
13
- border: '#B3D4DD',
14
- success: '#0E9F6E',
15
- warning: '#C27803',
1
+ // src/server.cjs
2
+ var React = require("react");
3
+ var h = React.createElement;
4
+ var defaultColors = {
5
+ background: "#F0F7F8",
6
+ surface: "#FFFFFF",
7
+ text: "#0F172A",
8
+ textMuted: "#64748B",
9
+ accent: "#006699",
10
+ accentHover: "#00557A",
11
+ border: "#B3D4DD",
12
+ success: "#0E9F6E",
13
+ warning: "#C27803"
16
14
  };
17
-
18
- function text(value, fallback = '') {
19
- return typeof value === 'string' && value.trim() ? value : fallback;
15
+ function text(value, fallback = "") {
16
+ return typeof value === "string" && value.trim() ? value : fallback;
20
17
  }
21
-
22
18
  function list(value) {
23
19
  return Array.isArray(value) ? value : [];
24
20
  }
25
-
26
21
  function slug(value) {
27
- return String(value || '')
28
- .normalize('NFKD')
29
- .replace(/[\u0300-\u036f]/g, '')
30
- .toLowerCase()
31
- .trim()
32
- .replace(/[^a-z0-9]+/g, '-')
33
- .replace(/^-+|-+$/g, '');
22
+ return String(value || "").normalize("NFKD").replace(/[\u0300-\u036f]/g, "").toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
34
23
  }
35
-
36
24
  function isGatheringCatalogPage(sections) {
37
25
  const visibleSections = sections.filter((section) => section && section.type);
38
- return visibleSections.length === 1 && visibleSections[0].type === 'products_grid';
26
+ return visibleSections.length === 1 && visibleSections[0].type === "products_grid";
39
27
  }
40
-
41
28
  function pageSlugForSections(sections) {
42
- if (isGatheringCatalogPage(sections)) return 'gathering';
43
- const orderDetail = sections.find((section) => section?.type === 'order_detail');
44
- if (orderDetail?.content?.gatheringPlan) return 'plan-detail';
45
- if (orderDetail) return 'transaction-detail';
46
- if (sections.some((section) => section?.type === 'gathering_calendar')) return 'calendar';
47
- if (sections.some((section) => section?.type === 'about' || section?.type === 'gallery')) return 'about';
48
- if (sections.some((section) => section?.type === 'service_process_section' || section?.type === 'faq_list')) {
49
- return 'how-it-works';
29
+ if (isGatheringCatalogPage(sections)) return "gathering";
30
+ const orderDetail = sections.find((section) => section?.type === "order_detail");
31
+ if (orderDetail?.content?.gatheringPlan) return "plan-detail";
32
+ if (orderDetail) return "transaction-detail";
33
+ if (sections.some((section) => section?.type === "gathering_calendar")) return "calendar";
34
+ if (sections.some((section) => section?.type === "about" || section?.type === "gallery")) return "about";
35
+ if (sections.some((section) => section?.type === "service_process_section" || section?.type === "faq_list")) {
36
+ return "how-it-works";
50
37
  }
51
- return '';
38
+ return "";
52
39
  }
53
-
54
40
  function billingStatus(invoice) {
55
- if (invoice.kind === 'gathering') {
56
- if (!invoice.invoice_issued_at || invoice.invoice_status === 'SCHEDULED') return 'scheduled';
57
- if (invoice.payment_status === 'REFUNDED') return 'refunded';
58
- if (invoice.payment_status === 'PAID') return 'paid';
59
- return 'issued';
41
+ if (invoice.kind === "gathering") {
42
+ if (!invoice.invoice_issued_at || invoice.invoice_status === "SCHEDULED") return "scheduled";
43
+ if (invoice.payment_status === "REFUNDED") return "refunded";
44
+ if (invoice.payment_status === "PAID") return "paid";
45
+ return "issued";
60
46
  }
61
- return ({
62
- SCHEDULED: 'scheduled',
63
- ISSUED: 'issued',
64
- PAID: 'paid',
65
- CANCELLED: 'cancelled',
66
- })[invoice.status] || 'scheduled';
47
+ return {
48
+ SCHEDULED: "scheduled",
49
+ ISSUED: "issued",
50
+ PAID: "paid",
51
+ CANCELLED: "cancelled"
52
+ }[invoice.status] || "scheduled";
67
53
  }
68
-
69
- const billingStatuses = {
70
- scheduled: { label: 'Menunggu diterbitkan', tone: 'muted' },
71
- issued: { label: 'Perlu dibayar', tone: 'warning' },
72
- paid: { label: 'Lunas', tone: 'success' },
73
- refunded: { label: 'Direfund', tone: 'muted' },
74
- cancelled: { label: 'Dibatalkan', tone: 'muted' },
54
+ var billingStatuses = {
55
+ scheduled: { label: "Menunggu diterbitkan", tone: "muted" },
56
+ issued: { label: "Perlu dibayar", tone: "warning" },
57
+ paid: { label: "Lunas", tone: "success" },
58
+ refunded: { label: "Direfund", tone: "muted" },
59
+ cancelled: { label: "Dibatalkan", tone: "muted" }
75
60
  };
76
-
77
- const billingFilters = [
78
- ['all', 'Semua'],
79
- ['scheduled', 'Menunggu diterbitkan'],
80
- ['issued', 'Perlu dibayar'],
81
- ['paid', 'Lunas'],
82
- ['refunded', 'Direfund'],
83
- ['cancelled', 'Dibatalkan'],
61
+ var billingFilters = [
62
+ ["all", "Semua"],
63
+ ["scheduled", "Menunggu diterbitkan"],
64
+ ["issued", "Perlu dibayar"],
65
+ ["paid", "Lunas"],
66
+ ["refunded", "Direfund"],
67
+ ["cancelled", "Dibatalkan"]
84
68
  ];
85
-
86
- const transactionStatuses = {
87
- PENDING: { label: 'Menunggu pembayaran', tone: 'warning', filter: 'awaiting' },
88
- PENDING_PAYMENT: { label: 'Menunggu pembayaran', tone: 'warning', filter: 'awaiting' },
89
- HELD: { label: 'Diproses', tone: 'info', filter: 'process' },
90
- COMPLETED: { label: 'Selesai', tone: 'success', filter: 'done' },
91
- REFUNDED: { label: 'Direfund', tone: 'danger', filter: 'cancelled' },
92
- CLOSED: { label: 'Ditutup', tone: 'muted', filter: 'cancelled' },
93
- DISPUTED: { label: 'Dalam sengketa', tone: 'danger', filter: 'process' },
94
- CANCELLED: { label: 'Dibatalkan', tone: 'muted', filter: 'cancelled' },
69
+ var transactionStatuses = {
70
+ PENDING: { label: "Menunggu pembayaran", tone: "warning", filter: "awaiting" },
71
+ PENDING_PAYMENT: { label: "Menunggu pembayaran", tone: "warning", filter: "awaiting" },
72
+ HELD: { label: "Diproses", tone: "info", filter: "process" },
73
+ COMPLETED: { label: "Selesai", tone: "success", filter: "done" },
74
+ REFUNDED: { label: "Direfund", tone: "danger", filter: "cancelled" },
75
+ CLOSED: { label: "Ditutup", tone: "muted", filter: "cancelled" },
76
+ DISPUTED: { label: "Dalam sengketa", tone: "danger", filter: "process" },
77
+ CANCELLED: { label: "Dibatalkan", tone: "muted", filter: "cancelled" }
95
78
  };
96
-
97
- const transactionFilters = [
98
- ['all', 'Semua'],
99
- ['awaiting', 'Menunggu Bayar'],
100
- ['process', 'Diproses'],
101
- ['done', 'Selesai'],
102
- ['cancelled', 'Dibatalkan'],
79
+ var transactionFilters = [
80
+ ["all", "Semua"],
81
+ ["awaiting", "Menunggu Bayar"],
82
+ ["process", "Diproses"],
83
+ ["done", "Selesai"],
84
+ ["cancelled", "Dibatalkan"]
103
85
  ];
104
-
105
86
  function CartSection({ props }) {
106
87
  const cartItems = props.isPreview === true ? list(props.previewCart) : [];
107
- const displayCount = cartItems
108
- .filter((item) => item.kind !== 'gathering_plan')
109
- .reduce((count, item) => count + (Number(item.quantity) || 1), 0);
110
- const selectableCount = cartItems.filter((item) => item.can_checkout !== false && item.kind !== 'gathering_plan').length;
111
-
112
- return h('section', { className: 'kumpul-cart', 'data-cart-page': '' },
113
- cartItems.length
114
- ? h(React.Fragment, null,
115
- h('header', { className: 'kumpul-cart-heading' },
116
- h('div', null,
117
- h('p', { className: 'kumpul-eyebrow' }, 'Pilihan Anda'),
118
- h('h1', null, 'Keranjang', h('span', { 'data-cart-display-count': '' }, `(${displayCount} item)`)),
119
- h('p', null, 'Tinjau item gathering sebelum melanjutkan ke checkout.'),
88
+ const displayCount = cartItems.filter((item) => item.kind !== "gathering_plan").reduce((count, item) => count + (Number(item.quantity) || 1), 0);
89
+ const selectableCount = cartItems.filter((item) => item.can_checkout !== false && item.kind !== "gathering_plan").length;
90
+ return h(
91
+ "section",
92
+ { className: "kumpul-cart", "data-cart-page": "" },
93
+ cartItems.length ? h(
94
+ React.Fragment,
95
+ null,
96
+ h(
97
+ "header",
98
+ { className: "kumpul-cart-heading" },
99
+ h(
100
+ "div",
101
+ null,
102
+ h("p", { className: "kumpul-eyebrow" }, "Pilihan Anda"),
103
+ h("h1", null, "Keranjang", h("span", { "data-cart-display-count": "" }, `(${displayCount} item)`)),
104
+ h("p", null, "Tinjau item gathering sebelum melanjutkan ke checkout.")
105
+ )
106
+ ),
107
+ h(
108
+ "p",
109
+ { className: "kumpul-cart-preview-note", role: "note" },
110
+ "Preview desainer \xB7 data contoh saja. Perubahan hanya berlaku di halaman ini; checkout dikelola oleh host Bagdja."
111
+ ),
112
+ h(
113
+ "div",
114
+ { className: "kumpul-cart-layout" },
115
+ h(
116
+ "div",
117
+ { className: "kumpul-cart-items" },
118
+ h(
119
+ "div",
120
+ { className: "kumpul-cart-select-all" },
121
+ h("button", {
122
+ type: "button",
123
+ "data-cart-select-all": "",
124
+ "aria-pressed": selectableCount > 0 ? "true" : "false"
125
+ }, selectableCount ? "Batalkan semua" : "Pilih semua")
120
126
  ),
121
- ),
122
- h('p', { className: 'kumpul-cart-preview-note', role: 'note' },
123
- 'Preview desainer · data contoh saja. Perubahan hanya berlaku di halaman ini; checkout dikelola oleh host Bagdja.',
124
- ),
125
- h('div', { className: 'kumpul-cart-layout' },
126
- h('div', { className: 'kumpul-cart-items' },
127
- h('div', { className: 'kumpul-cart-select-all' },
128
- h('button', {
129
- type: 'button',
130
- 'data-cart-select-all': '',
131
- 'aria-pressed': selectableCount > 0 ? 'true' : 'false',
132
- }, selectableCount ? 'Batalkan semua' : 'Pilih semua'),
133
- ),
134
- h('div', { className: 'kumpul-cart-list', 'data-cart-list': '' },
135
- ...cartItems.map((item, index) => {
136
- const isPlan = item.kind === 'gathering_plan';
137
- const canCheckout = item.can_checkout !== false && !isPlan;
138
- const quantity = Math.max(1, Number(item.quantity) || 1);
139
- return h('article', {
140
- className: 'kumpul-cart-item',
141
- 'data-cart-item': '',
142
- 'data-cart-id': text(item.id, String(index)),
143
- 'data-cart-unit-price': Number(item.price) || 0,
144
- 'data-cart-checkoutable': canCheckout ? 'true' : 'false',
145
- key: item.id || index,
127
+ h(
128
+ "div",
129
+ { className: "kumpul-cart-list", "data-cart-list": "" },
130
+ ...cartItems.map((item, index) => {
131
+ const isPlan = item.kind === "gathering_plan";
132
+ const canCheckout = item.can_checkout !== false && !isPlan;
133
+ const quantity = Math.max(1, Number(item.quantity) || 1);
134
+ return h(
135
+ "article",
136
+ {
137
+ className: "kumpul-cart-item",
138
+ "data-cart-item": "",
139
+ "data-cart-id": text(item.id, String(index)),
140
+ "data-cart-unit-price": Number(item.price) || 0,
141
+ "data-cart-checkoutable": canCheckout ? "true" : "false",
142
+ key: item.id || index
146
143
  },
147
- h('label', { className: 'kumpul-cart-choice' },
148
- h('input', {
149
- type: 'checkbox',
144
+ h(
145
+ "label",
146
+ { className: "kumpul-cart-choice" },
147
+ h("input", {
148
+ type: "checkbox",
150
149
  defaultChecked: canCheckout,
151
150
  disabled: !canCheckout,
152
- 'data-cart-select': '',
153
- 'aria-label': canCheckout ? `Pilih ${text(item.name, 'item keranjang')}` : `${text(item.name, 'Item')} belum bisa checkout`,
154
- }),
155
- ),
156
- h('div', { className: 'kumpul-cart-art', 'aria-hidden': 'true' }, text(item.emoji, isPlan ? '◷' : '✳')),
157
- h('div', { className: 'kumpul-cart-copy' },
158
- h('span', { className: 'kumpul-cart-kind' }, isPlan ? 'Rencana gathering' : text(item.category, 'Gathering')),
159
- h('h2', null, text(item.name, 'Item gathering')),
160
- item.variant ? h('p', { className: 'kumpul-cart-variant' }, item.variant) : null,
161
- h('p', { className: 'kumpul-cart-detail' }, isPlan
162
- ? text(item.blocked_reason, 'Rencana gathering belum masuk tahap pembayaran')
163
- : text(item.subtitle, 'Informasi gathering dan pilihan peserta')),
164
- item.blocked_reason && !isPlan
165
- ? h('p', { className: 'kumpul-cart-blocked' }, item.blocked_reason)
166
- : null,
151
+ "data-cart-select": "",
152
+ "aria-label": canCheckout ? `Pilih ${text(item.name, "item keranjang")}` : `${text(item.name, "Item")} belum bisa checkout`
153
+ })
167
154
  ),
168
- h('div', { className: 'kumpul-cart-item-controls' },
169
- h('strong', { className: 'kumpul-cart-price', 'data-cart-line-total': '' }, formatCurrency((Number(item.price) || 0) * quantity)),
170
- !isPlan
171
- ? h('div', { className: 'kumpul-cart-quantity', 'aria-label': `Jumlah ${text(item.name, 'item')}` },
172
- h('button', {
173
- type: 'button',
174
- 'aria-label': `Kurangi jumlah ${text(item.name, 'item')}`,
175
- 'data-cart-quantity-decrease': '',
176
- disabled: quantity <= 1,
177
- }, '−'),
178
- h('span', { 'data-cart-quantity' : '' }, String(quantity)),
179
- h('button', {
180
- type: 'button',
181
- 'aria-label': `Tambah jumlah ${text(item.name, 'item')}`,
182
- 'data-cart-quantity-increase': '',
183
- }, '+'),
184
- )
185
- : null,
186
- h('button', {
187
- type: 'button',
188
- className: 'kumpul-cart-remove',
189
- 'data-cart-remove': '',
190
- 'aria-label': `Hapus ${text(item.name, 'item')}`,
191
- }, 'Hapus'),
155
+ h("div", { className: "kumpul-cart-art", "aria-hidden": "true" }, text(item.emoji, isPlan ? "\u25F7" : "\u2733")),
156
+ h(
157
+ "div",
158
+ { className: "kumpul-cart-copy" },
159
+ h("span", { className: "kumpul-cart-kind" }, isPlan ? "Rencana gathering" : text(item.category, "Gathering")),
160
+ h("h2", null, text(item.name, "Item gathering")),
161
+ item.variant ? h("p", { className: "kumpul-cart-variant" }, item.variant) : null,
162
+ h("p", { className: "kumpul-cart-detail" }, isPlan ? text(item.blocked_reason, "Rencana gathering belum masuk tahap pembayaran") : text(item.subtitle, "Informasi gathering dan pilihan peserta")),
163
+ item.blocked_reason && !isPlan ? h("p", { className: "kumpul-cart-blocked" }, item.blocked_reason) : null
192
164
  ),
193
- );
194
- }),
195
- ),
165
+ h(
166
+ "div",
167
+ { className: "kumpul-cart-item-controls" },
168
+ h("strong", { className: "kumpul-cart-price", "data-cart-line-total": "" }, formatCurrency((Number(item.price) || 0) * quantity)),
169
+ !isPlan ? h(
170
+ "div",
171
+ { className: "kumpul-cart-quantity", "aria-label": `Jumlah ${text(item.name, "item")}` },
172
+ h("button", {
173
+ type: "button",
174
+ "aria-label": `Kurangi jumlah ${text(item.name, "item")}`,
175
+ "data-cart-quantity-decrease": "",
176
+ disabled: quantity <= 1
177
+ }, "\u2212"),
178
+ h("span", { "data-cart-quantity": "" }, String(quantity)),
179
+ h("button", {
180
+ type: "button",
181
+ "aria-label": `Tambah jumlah ${text(item.name, "item")}`,
182
+ "data-cart-quantity-increase": ""
183
+ }, "+")
184
+ ) : null,
185
+ h("button", {
186
+ type: "button",
187
+ className: "kumpul-cart-remove",
188
+ "data-cart-remove": "",
189
+ "aria-label": `Hapus ${text(item.name, "item")}`
190
+ }, "Hapus")
191
+ )
192
+ );
193
+ })
194
+ )
195
+ ),
196
+ h(
197
+ "aside",
198
+ { className: "kumpul-cart-summary", "data-cart-summary": "" },
199
+ h("h2", null, "Ringkasan checkout"),
200
+ h(
201
+ "div",
202
+ { className: "kumpul-cart-summary-row" },
203
+ h("span", null, "Item dipilih"),
204
+ h("strong", { "data-cart-selected-count": "" }, "0 item")
196
205
  ),
197
- h('aside', { className: 'kumpul-cart-summary', 'data-cart-summary': '' },
198
- h('h2', null, 'Ringkasan checkout'),
199
- h('div', { className: 'kumpul-cart-summary-row' },
200
- h('span', null, 'Item dipilih'),
201
- h('strong', { 'data-cart-selected-count': '' }, '0 item'),
202
- ),
203
- h('div', { className: 'kumpul-cart-summary-total' },
204
- h('span', null, 'Total sementara'),
205
- h('strong', { 'data-cart-selected-total': '' }, 'Rp 0'),
206
- ),
207
- h('button', { type: 'button', className: 'kumpul-cart-checkout', disabled: true }, 'Lanjut ke Checkout'),
208
- h('p', null, 'Item yang belum dapat dibayar akan tetap tersimpan di keranjang.'),
206
+ h(
207
+ "div",
208
+ { className: "kumpul-cart-summary-total" },
209
+ h("span", null, "Total sementara"),
210
+ h("strong", { "data-cart-selected-total": "" }, "Rp 0")
209
211
  ),
210
- ),
211
- h('p', { className: 'kumpul-cart-empty', hidden: true, 'data-cart-empty': '' },
212
- 'Keranjang Anda kosong. Tambahkan gathering yang ingin diikuti.',
213
- ),
214
- )
215
- : h('div', { className: 'kumpul-cart-empty-state' },
216
- h('span', { className: 'kumpul-cart-empty-icon', 'aria-hidden': 'true' }, '🛒'),
217
- h('h1', null, 'Keranjang Anda kosong'),
218
- h('p', null, props.isPreview === true
219
- ? 'Belum ada item pada preview keranjang ini.'
220
- : 'Item keranjang dan rencana gathering dikelola oleh host Bagdja.'),
221
- h('a', { href: tenantPath(props, '/gathering'), className: 'kumpul-cart-browse' }, 'Jelajahi Gathering'),
212
+ h("button", { type: "button", className: "kumpul-cart-checkout", disabled: true }, "Lanjut ke Checkout"),
213
+ h("p", null, "Item yang belum dapat dibayar akan tetap tersimpan di keranjang.")
214
+ )
222
215
  ),
216
+ h(
217
+ "p",
218
+ { className: "kumpul-cart-empty", hidden: true, "data-cart-empty": "" },
219
+ "Keranjang Anda kosong. Tambahkan gathering yang ingin diikuti."
220
+ )
221
+ ) : h(
222
+ "div",
223
+ { className: "kumpul-cart-empty-state" },
224
+ h("span", { className: "kumpul-cart-empty-icon", "aria-hidden": "true" }, "\u{1F6D2}"),
225
+ h("h1", null, "Keranjang Anda kosong"),
226
+ h("p", null, props.isPreview === true ? "Belum ada item pada preview keranjang ini." : "Item keranjang dan rencana gathering dikelola oleh host Bagdja."),
227
+ h("a", { href: tenantPath(props, "/gathering"), className: "kumpul-cart-browse" }, "Jelajahi Gathering")
228
+ )
223
229
  );
224
230
  }
225
-
226
231
  function formatCurrency(value) {
227
232
  const amount = Number(value);
228
- return Number.isFinite(amount)
229
- ? `Rp ${amount.toLocaleString('id-ID')}`
230
- : 'Nominal belum tersedia';
233
+ return Number.isFinite(amount) ? `Rp ${amount.toLocaleString("id-ID")}` : "Nominal belum tersedia";
231
234
  }
232
-
233
235
  function transactionStatus(transaction) {
234
236
  if (transaction.has_outstanding_invoice === true) {
235
- return { label: text(transaction.outstanding_label, 'Menunggu pelunasan'), tone: 'warning', filter: 'process' };
237
+ return { label: text(transaction.outstanding_label, "Menunggu pelunasan"), tone: "warning", filter: "process" };
236
238
  }
237
239
  return transactionStatuses[transaction.status] || {
238
- label: text(transaction.status, 'Status belum tersedia'),
239
- tone: 'muted',
240
- filter: 'all',
240
+ label: text(transaction.status, "Status belum tersedia"),
241
+ tone: "muted",
242
+ filter: "all"
241
243
  };
242
244
  }
243
-
244
245
  function TransactionsSection({ props }) {
245
246
  const transactions = props.isPreview === true ? list(props.previewTransactions) : [];
246
247
  const counts = Object.fromEntries(transactionFilters.map(([key]) => [
247
248
  key,
248
- key === 'all' ? transactions.length : transactions.filter((transaction) => transactionStatus(transaction).filter === key).length,
249
+ key === "all" ? transactions.length : transactions.filter((transaction) => transactionStatus(transaction).filter === key).length
249
250
  ]));
250
-
251
- return h('section', { className: 'kumpul-transactions', 'data-transactions-page': '' },
252
- h('header', { className: 'kumpul-transactions-heading' },
253
- h('div', null,
254
- h('p', { className: 'kumpul-eyebrow' }, 'Akun Anda'),
255
- h('h1', null, 'Daftar Transaksi'),
256
- h('p', null, 'Lihat semua pesanan, status pembayaran, dan riwayat pembelian Anda.'),
257
- ),
258
- h('div', { className: 'kumpul-transactions-total' },
259
- h('strong', null, String(counts.all)),
260
- h('span', null, 'transaksi tercatat'),
251
+ return h(
252
+ "section",
253
+ { className: "kumpul-transactions", "data-transactions-page": "" },
254
+ h(
255
+ "header",
256
+ { className: "kumpul-transactions-heading" },
257
+ h(
258
+ "div",
259
+ null,
260
+ h("p", { className: "kumpul-eyebrow" }, "Akun Anda"),
261
+ h("h1", null, "Daftar Transaksi"),
262
+ h("p", null, "Lihat semua pesanan, status pembayaran, dan riwayat pembelian Anda.")
261
263
  ),
262
- ),
263
- props.isPreview === true
264
- ? h('p', { className: 'kumpul-transactions-preview-note', role: 'note' },
265
- 'Preview desainer · data contoh saja. Status dan tindakan transaksi dikelola oleh host Bagdja.',
264
+ h(
265
+ "div",
266
+ { className: "kumpul-transactions-total" },
267
+ h("strong", null, String(counts.all)),
268
+ h("span", null, "transaksi tercatat")
266
269
  )
267
- : null,
268
- h('div', { className: 'kumpul-transactions-filters', role: 'group', 'aria-label': 'Filter status transaksi' },
269
- ...transactionFilters.map(([key, label]) => h('button', {
270
- type: 'button',
271
- 'aria-pressed': key === 'all' ? 'true' : 'false',
272
- 'data-transaction-filter': key,
273
- key,
274
- },
275
- label,
276
- h('span', null, String(counts[key])),
277
- )),
278
270
  ),
279
- h('div', { className: 'kumpul-transactions-list', 'data-transactions-list': '' },
271
+ props.isPreview === true ? h(
272
+ "p",
273
+ { className: "kumpul-transactions-preview-note", role: "note" },
274
+ "Preview desainer \xB7 data contoh saja. Status dan tindakan transaksi dikelola oleh host Bagdja."
275
+ ) : null,
276
+ h(
277
+ "div",
278
+ { className: "kumpul-transactions-filters", role: "group", "aria-label": "Filter status transaksi" },
279
+ ...transactionFilters.map(([key, label]) => h(
280
+ "button",
281
+ {
282
+ type: "button",
283
+ "aria-pressed": key === "all" ? "true" : "false",
284
+ "data-transaction-filter": key,
285
+ key
286
+ },
287
+ label,
288
+ h("span", null, String(counts[key]))
289
+ ))
290
+ ),
291
+ h(
292
+ "div",
293
+ { className: "kumpul-transactions-list", "data-transactions-list": "" },
280
294
  ...transactions.map((transaction, index) => {
281
295
  const status = transactionStatus(transaction);
282
296
  const items = list(transaction.items);
283
297
  const firstItem = items[0] || {};
284
- const productName = text(firstItem.product_name, 'Gathering');
298
+ const productName = text(firstItem.product_name, "Gathering");
285
299
  const extraCount = Math.max(0, items.length - 1);
286
300
  const createdAt = formatCalendarDate(transaction.created_at);
287
301
  const refNumber = text(transaction.ref_number, `#${text(transaction.id).slice(0, 8)}`);
288
- return h('article', {
289
- className: 'kumpul-transaction-card',
290
- 'data-transaction-item': '',
291
- 'data-transaction-status': status.filter,
292
- key: transaction.id || index,
293
- },
294
- h('div', { className: 'kumpul-transaction-top' },
295
- h('div', null,
296
- h('span', { className: 'kumpul-transaction-ref' }, refNumber),
297
- h('span', { className: 'kumpul-transaction-separator', 'aria-hidden': 'true' }, '·'),
298
- h('time', null, createdAt),
299
- ),
300
- h('span', { className: `kumpul-transaction-status kumpul-transaction-status-${status.tone}` }, status.label),
301
- ),
302
- h('div', { className: 'kumpul-transaction-body' },
303
- h('div', { className: 'kumpul-transaction-item' },
304
- h('span', { className: 'kumpul-transaction-art', 'aria-hidden': 'true' }, '✳'),
305
- h('div', null,
306
- h('h2', null, `${productName}${extraCount ? ` + ${extraCount} produk lainnya` : ''}`),
307
- h('p', null, `${items.length || Number(transaction.item_count) || 1} item${transaction.courier ? ` · Kurir: ${transaction.courier}` : ''}`),
302
+ return h(
303
+ "article",
304
+ {
305
+ className: "kumpul-transaction-card",
306
+ "data-transaction-item": "",
307
+ "data-transaction-status": status.filter,
308
+ key: transaction.id || index
309
+ },
310
+ h(
311
+ "div",
312
+ { className: "kumpul-transaction-top" },
313
+ h(
314
+ "div",
315
+ null,
316
+ h("span", { className: "kumpul-transaction-ref" }, refNumber),
317
+ h("span", { className: "kumpul-transaction-separator", "aria-hidden": "true" }, "\xB7"),
318
+ h("time", null, createdAt)
308
319
  ),
320
+ h("span", { className: `kumpul-transaction-status kumpul-transaction-status-${status.tone}` }, status.label)
309
321
  ),
310
- h('div', { className: 'kumpul-transaction-total' },
311
- h('span', null, 'Total'),
312
- h('strong', null, formatCurrency(transaction.total_amount)),
322
+ h(
323
+ "div",
324
+ { className: "kumpul-transaction-body" },
325
+ h(
326
+ "div",
327
+ { className: "kumpul-transaction-item" },
328
+ h("span", { className: "kumpul-transaction-art", "aria-hidden": "true" }, "\u2733"),
329
+ h(
330
+ "div",
331
+ null,
332
+ h("h2", null, `${productName}${extraCount ? ` + ${extraCount} produk lainnya` : ""}`),
333
+ h("p", null, `${items.length || Number(transaction.item_count) || 1} item${transaction.courier ? ` \xB7 Kurir: ${transaction.courier}` : ""}`)
334
+ )
335
+ ),
336
+ h(
337
+ "div",
338
+ { className: "kumpul-transaction-total" },
339
+ h("span", null, "Total"),
340
+ h("strong", null, formatCurrency(transaction.total_amount))
341
+ )
313
342
  ),
314
- ),
315
- h('div', { className: 'kumpul-transaction-actions' },
316
- transaction.status === 'PENDING_PAYMENT'
317
- ? h('button', { type: 'button', disabled: true }, 'Lanjutkan Pembayaran')
318
- : null,
319
- h('button', { type: 'button', disabled: true }, 'Detail Transaksi'),
320
- h('button', { type: 'button', disabled: true }, 'Chat Order'),
321
- ),
343
+ h(
344
+ "div",
345
+ { className: "kumpul-transaction-actions" },
346
+ transaction.status === "PENDING_PAYMENT" ? h("button", { type: "button", disabled: true }, "Lanjutkan Pembayaran") : null,
347
+ h("button", { type: "button", disabled: true }, "Detail Transaksi"),
348
+ h("button", { type: "button", disabled: true }, "Chat Order")
349
+ )
322
350
  );
323
351
  }),
324
- h('p', {
325
- className: 'kumpul-transactions-empty',
352
+ h("p", {
353
+ className: "kumpul-transactions-empty",
326
354
  hidden: transactions.length > 0,
327
- 'data-transactions-empty': '',
328
- }, props.isPreview === true
329
- ? 'Belum ada transaksi pada preview ini.'
330
- : 'Data transaksi dikelola oleh host Bagdja.'),
331
- h('p', {
332
- className: 'kumpul-transactions-empty',
355
+ "data-transactions-empty": ""
356
+ }, props.isPreview === true ? "Belum ada transaksi pada preview ini." : "Data transaksi dikelola oleh host Bagdja."),
357
+ h("p", {
358
+ className: "kumpul-transactions-empty",
333
359
  hidden: true,
334
- 'data-transactions-filter-empty': '',
335
- }, 'Belum ada transaksi dengan status ini. Coba pilih filter lain.'),
336
- ),
360
+ "data-transactions-filter-empty": ""
361
+ }, "Belum ada transaksi dengan status ini. Coba pilih filter lain.")
362
+ )
337
363
  );
338
364
  }
339
-
340
365
  function invoiceDetailStatus(invoice) {
341
- if (invoice.payment_status === 'PAID') return { label: 'Lunas', tone: 'success' };
342
- if (invoice.payment_status === 'REFUNDED') return { label: 'Direfund', tone: 'muted' };
343
- if (invoice.payment_status === 'PENDING_PAYMENT') return { label: 'Pembayaran sedang diproses', tone: 'info' };
366
+ if (invoice.payment_status === "PAID") return { label: "Lunas", tone: "success" };
367
+ if (invoice.payment_status === "REFUNDED") return { label: "Direfund", tone: "muted" };
368
+ if (invoice.payment_status === "PENDING_PAYMENT") return { label: "Pembayaran sedang diproses", tone: "info" };
344
369
  return {
345
- label: invoice.payment_open === false ? 'Pembayaran belum dibuka' : 'Belum dibayar',
346
- tone: 'warning',
370
+ label: invoice.payment_open === false ? "Pembayaran belum dibuka" : "Belum dibayar",
371
+ tone: "warning"
347
372
  };
348
373
  }
349
-
350
374
  function InvoiceDetailSection({ props }) {
351
375
  if (props.isPreview !== true) {
352
- return h('section', { className: 'kumpul-detail-page', 'data-invoice-detail': '' },
353
- h('h1', null, 'Detail Tagihan'),
354
- h('p', null, 'Data tagihan dan status pembayaran dikelola oleh host Bagdja.'),
376
+ return h(
377
+ "section",
378
+ { className: "kumpul-detail-page", "data-invoice-detail": "" },
379
+ h("h1", null, "Detail Tagihan"),
380
+ h("p", null, "Data tagihan dan status pembayaran dikelola oleh host Bagdja.")
355
381
  );
356
382
  }
357
383
  const invoice = props.isPreview === true ? props.previewInvoice || {} : {};
358
384
  const status = invoiceDetailStatus(invoice);
359
- const amount = new Intl.NumberFormat('id-ID', {
360
- style: 'currency',
361
- currency: text(invoice.currency, 'IDR'),
362
- maximumFractionDigits: 0,
385
+ const amount = new Intl.NumberFormat("id-ID", {
386
+ style: "currency",
387
+ currency: text(invoice.currency, "IDR"),
388
+ maximumFractionDigits: 0
363
389
  }).format(Number(invoice.amount) || 0);
364
- const isPaid = ['PAID', 'REFUNDED'].includes(invoice.payment_status);
365
- const isPending = invoice.payment_status === 'PENDING_PAYMENT';
390
+ const isPaid = ["PAID", "REFUNDED"].includes(invoice.payment_status);
391
+ const isPending = invoice.payment_status === "PENDING_PAYMENT";
366
392
  const paymentOpen = invoice.payment_open === true;
367
393
  const fields = [
368
- ['Nomor tagihan', invoice.invoice_id],
369
- ['Nomor rencana gathering', invoice.plan_number],
370
- ['Nama peserta', invoice.attendee_name],
371
- ['Initiator gathering', invoice.initiator_name],
372
- ['Batas pembayaran', invoice.payment_deadline],
373
- ['Tanggal acara', invoice.event_date],
394
+ ["Nomor tagihan", invoice.invoice_id],
395
+ ["Nomor rencana gathering", invoice.plan_number],
396
+ ["Nama peserta", invoice.attendee_name],
397
+ ["Initiator gathering", invoice.initiator_name],
398
+ ["Batas pembayaran", invoice.payment_deadline],
399
+ ["Tanggal acara", invoice.event_date]
374
400
  ];
375
-
376
- return h('section', { className: 'kumpul-detail-page', 'data-invoice-detail': '' },
377
- h('a', { className: 'kumpul-detail-back', href: tenantPath(props, '/tagihan') }, '← Kembali ke Tagihan'),
378
- h('header', { className: 'kumpul-detail-heading' },
379
- h('div', null,
380
- h('p', { className: 'kumpul-eyebrow' }, 'Tagihan gathering'),
381
- h('h1', null, text(invoice.gathering_title, 'Detail Tagihan Gathering')),
401
+ return h(
402
+ "section",
403
+ { className: "kumpul-detail-page", "data-invoice-detail": "" },
404
+ h("a", { className: "kumpul-detail-back", href: tenantPath(props, "/tagihan") }, "\u2190 Kembali ke Tagihan"),
405
+ h(
406
+ "header",
407
+ { className: "kumpul-detail-heading" },
408
+ h(
409
+ "div",
410
+ null,
411
+ h("p", { className: "kumpul-eyebrow" }, "Tagihan gathering"),
412
+ h("h1", null, text(invoice.gathering_title, "Detail Tagihan Gathering"))
382
413
  ),
383
- h('span', { className: `kumpul-transaction-status kumpul-transaction-status-${status.tone}` }, status.label),
414
+ h("span", { className: `kumpul-transaction-status kumpul-transaction-status-${status.tone}` }, status.label)
384
415
  ),
385
- props.isPreview === true
386
- ? h('p', { className: 'kumpul-detail-preview-note', role: 'note' },
387
- 'Preview desainer · data contoh saja. Status tagihan dan pembayaran dikelola oleh host Bagdja.',
388
- )
389
- : null,
390
- h('div', { className: 'kumpul-detail-layout' },
391
- h('section', { className: 'kumpul-detail-card' },
392
- h('h2', null, 'Informasi tagihan'),
393
- h('dl', { className: 'kumpul-detail-fields' },
394
- ...fields.map(([label, value]) => h('div', { key: label },
395
- h('dt', null, label),
396
- h('dd', null, label.toLowerCase().includes('tanggal') || label.toLowerCase().includes('pembayaran')
397
- ? formatCalendarDate(value) || 'Belum ditentukan'
398
- : text(value, 'Belum tersedia')),
399
- )),
400
- ),
401
- h('div', { className: 'kumpul-detail-total' },
402
- h('span', null, 'Total tagihan'),
403
- h('strong', null, amount),
416
+ props.isPreview === true ? h(
417
+ "p",
418
+ { className: "kumpul-detail-preview-note", role: "note" },
419
+ "Preview desainer \xB7 data contoh saja. Status tagihan dan pembayaran dikelola oleh host Bagdja."
420
+ ) : null,
421
+ h(
422
+ "div",
423
+ { className: "kumpul-detail-layout" },
424
+ h(
425
+ "section",
426
+ { className: "kumpul-detail-card" },
427
+ h("h2", null, "Informasi tagihan"),
428
+ h(
429
+ "dl",
430
+ { className: "kumpul-detail-fields" },
431
+ ...fields.map(([label, value]) => h(
432
+ "div",
433
+ { key: label },
434
+ h("dt", null, label),
435
+ h("dd", null, label.toLowerCase().includes("tanggal") || label.toLowerCase().includes("pembayaran") ? formatCalendarDate(value) || "Belum ditentukan" : text(value, "Belum tersedia"))
436
+ ))
404
437
  ),
438
+ h(
439
+ "div",
440
+ { className: "kumpul-detail-total" },
441
+ h("span", null, "Total tagihan"),
442
+ h("strong", null, amount)
443
+ )
405
444
  ),
406
- h('aside', { className: 'kumpul-detail-card kumpul-detail-aside' },
407
- h('h2', null, 'Status pembayaran'),
408
- h('span', { className: `kumpul-transaction-status kumpul-transaction-status-${status.tone}` }, status.label),
409
- isPending
410
- ? h('p', null, 'Pembayaran untuk tagihan ini sedang diproses. Tidak perlu memulai pembayaran baru.')
411
- : null,
412
- !isPaid && !isPending
413
- ? h('div', { className: 'kumpul-detail-login-info' },
414
- h('h3', null, 'Mengapa perlu login untuk membayar?'),
415
- h('p', null, 'Akun Bagdja menghubungkan pembayaran escrow dengan peserta. Gunakan email yang sama dengan email saat RSVP. Initiator juga dapat membayar beberapa tagihan dari halaman gathering.'),
416
- )
417
- : null,
418
- !isPaid
419
- ? h('button', { type: 'button', disabled: props.isPreview === true || !paymentOpen },
420
- paymentOpen ? (isPending ? 'Lanjutkan pembayaran' : 'Login untuk membayar') : 'Pembayaran belum dibuka',
421
- )
422
- : null,
423
- ),
424
- ),
445
+ h(
446
+ "aside",
447
+ { className: "kumpul-detail-card kumpul-detail-aside" },
448
+ h("h2", null, "Status pembayaran"),
449
+ h("span", { className: `kumpul-transaction-status kumpul-transaction-status-${status.tone}` }, status.label),
450
+ isPending ? h("p", null, "Pembayaran untuk tagihan ini sedang diproses. Tidak perlu memulai pembayaran baru.") : null,
451
+ !isPaid && !isPending ? h(
452
+ "div",
453
+ { className: "kumpul-detail-login-info" },
454
+ h("h3", null, "Mengapa perlu login untuk membayar?"),
455
+ h("p", null, "Akun Bagdja menghubungkan pembayaran escrow dengan peserta. Gunakan email yang sama dengan email saat RSVP. Initiator juga dapat membayar beberapa tagihan dari halaman gathering.")
456
+ ) : null,
457
+ !isPaid ? h(
458
+ "button",
459
+ { type: "button", disabled: props.isPreview === true || !paymentOpen },
460
+ paymentOpen ? isPending ? "Lanjutkan pembayaran" : "Login untuk membayar" : "Pembayaran belum dibuka"
461
+ ) : null
462
+ )
463
+ )
425
464
  );
426
465
  }
427
-
428
466
  function TransactionDetailSection({ props, section }) {
429
- const transaction = props.isPreview === true
430
- ? props.previewTransaction || {}
431
- : section?.content?.transaction || {};
467
+ const transaction = props.isPreview === true ? props.previewTransaction || {} : section?.content?.transaction || {};
432
468
  const items = list(transaction.items);
433
469
  const status = transactionStatus(transaction);
434
470
  const subtotal = items.reduce((sum, item) => sum + (Number(item.total_amount) || 0), 0);
@@ -441,698 +477,813 @@ function TransactionDetailSection({ props, section }) {
441
477
  transaction.address,
442
478
  transaction.district,
443
479
  transaction.city,
444
- transaction.postal_code,
480
+ transaction.postal_code
445
481
  ].filter(Boolean);
446
-
447
- return h('section', { className: 'kumpul-detail-page', 'data-transaction-detail': '' },
448
- h('a', { className: 'kumpul-detail-back', href: tenantPath(props, '/orders') }, '← Kembali ke Transaksi'),
449
- h('header', { className: 'kumpul-detail-heading' },
450
- h('div', null,
451
- h('p', { className: 'kumpul-eyebrow' }, 'Ringkasan pesanan'),
452
- h('h1', null, 'Detail Transaksi'),
453
- h('p', { className: 'kumpul-detail-reference' }, text(transaction.ref_number, `Transaksi #${text(transaction.id, '—')}`)),
482
+ return h(
483
+ "section",
484
+ { className: "kumpul-detail-page", "data-transaction-detail": "" },
485
+ h("a", { className: "kumpul-detail-back", href: tenantPath(props, "/orders") }, "\u2190 Kembali ke Transaksi"),
486
+ h(
487
+ "header",
488
+ { className: "kumpul-detail-heading" },
489
+ h(
490
+ "div",
491
+ null,
492
+ h("p", { className: "kumpul-eyebrow" }, "Ringkasan pesanan"),
493
+ h("h1", null, "Detail Transaksi"),
494
+ h("p", { className: "kumpul-detail-reference" }, text(transaction.ref_number, `Transaksi #${text(transaction.id, "\u2014")}`))
454
495
  ),
455
- h('span', { className: `kumpul-transaction-status kumpul-transaction-status-${status.tone}` }, status.label),
496
+ h("span", { className: `kumpul-transaction-status kumpul-transaction-status-${status.tone}` }, status.label)
456
497
  ),
457
- props.isPreview === true
458
- ? h('p', { className: 'kumpul-detail-preview-note', role: 'note' },
459
- 'Preview desainer · data contoh saja. Detail dan tindakan transaksi dikelola oleh host Bagdja.',
460
- )
461
- : null,
462
- h('div', { className: 'kumpul-detail-layout' },
463
- h('div', { className: 'kumpul-detail-main' },
464
- h('section', { className: 'kumpul-detail-card' },
465
- h('h2', null, `Detail pemesanan · ${items.length} item`),
466
- h('div', { className: 'kumpul-detail-items' },
498
+ props.isPreview === true ? h(
499
+ "p",
500
+ { className: "kumpul-detail-preview-note", role: "note" },
501
+ "Preview desainer \xB7 data contoh saja. Detail dan tindakan transaksi dikelola oleh host Bagdja."
502
+ ) : null,
503
+ h(
504
+ "div",
505
+ { className: "kumpul-detail-layout" },
506
+ h(
507
+ "div",
508
+ { className: "kumpul-detail-main" },
509
+ h(
510
+ "section",
511
+ { className: "kumpul-detail-card" },
512
+ h("h2", null, `Detail pemesanan \xB7 ${items.length} item`),
513
+ h(
514
+ "div",
515
+ { className: "kumpul-detail-items" },
467
516
  ...items.map((item, index) => {
468
517
  const product = item.order?.product || {};
469
- const title = text(product.name, text(item.product_name, 'Gathering'));
518
+ const title = text(product.name, text(item.product_name, "Gathering"));
470
519
  const gatheringInvoice = item.order?.gathering_invoice;
471
520
  const quantity = Number(item.quantity) || 1;
472
- return h('article', { className: 'kumpul-detail-item', key: item.id || index },
473
- h('span', { className: 'kumpul-detail-item-art', 'aria-hidden': 'true' }, text(item.emoji, title.slice(0, 1))),
474
- h('div', { className: 'kumpul-detail-item-copy' },
475
- h('h3', null, title),
476
- h('p', null, gatheringInvoice
477
- ? `Peserta: ${text(gatheringInvoice.attendee_name, 'Peserta')} · Invoice ${text(gatheringInvoice.invoice_id, 'tersedia')}`
478
- : `${quantity} × ${formatCurrency(item.unit_price)}`),
479
- gatheringInvoice
480
- ? h('small', { className: 'kumpul-detail-escrow-note' }, 'Dana seat ditahan di escrow sampai acara dikonfirmasi pengelola.')
481
- : null,
521
+ return h(
522
+ "article",
523
+ { className: "kumpul-detail-item", key: item.id || index },
524
+ h("span", { className: "kumpul-detail-item-art", "aria-hidden": "true" }, text(item.emoji, title.slice(0, 1))),
525
+ h(
526
+ "div",
527
+ { className: "kumpul-detail-item-copy" },
528
+ h("h3", null, title),
529
+ h("p", null, gatheringInvoice ? `Peserta: ${text(gatheringInvoice.attendee_name, "Peserta")} \xB7 Invoice ${text(gatheringInvoice.invoice_id, "tersedia")}` : `${quantity} \xD7 ${formatCurrency(item.unit_price)}`),
530
+ gatheringInvoice ? h("small", { className: "kumpul-detail-escrow-note" }, "Dana seat ditahan di escrow sampai acara dikonfirmasi pengelola.") : null
482
531
  ),
483
- h('strong', null, formatCurrency(item.total_amount)),
532
+ h("strong", null, formatCurrency(item.total_amount))
484
533
  );
485
- }),
486
- ),
487
- ),
488
- address.length
489
- ? h('section', { className: 'kumpul-detail-card' },
490
- h('h2', null, 'Alamat pengiriman'),
491
- h('p', { className: 'kumpul-detail-address' }, address.join(' · ')),
534
+ })
492
535
  )
493
- : null,
494
- shipping.courier_code || transaction.courier
495
- ? h('section', { className: 'kumpul-detail-card' },
496
- h('h2', null, 'Kurir pengiriman'),
497
- h('dl', { className: 'kumpul-detail-fields' },
498
- h('div', null, h('dt', null, 'Kurir'), h('dd', null, text(shipping.courier_code, transaction.courier))),
499
- shipping.courier_service_name
500
- ? h('div', null, h('dt', null, 'Layanan'), h('dd', null, shipping.courier_service_name))
501
- : null,
502
- shipping.destination_area_name
503
- ? h('div', null, h('dt', null, 'Area tujuan'), h('dd', null, shipping.destination_area_name))
504
- : null,
505
- h('div', null, h('dt', null, 'Biaya ongkir'), h('dd', null, formatCurrency(shippingCost))),
506
- ),
536
+ ),
537
+ address.length ? h(
538
+ "section",
539
+ { className: "kumpul-detail-card" },
540
+ h("h2", null, "Alamat pengiriman"),
541
+ h("p", { className: "kumpul-detail-address" }, address.join(" \xB7 "))
542
+ ) : null,
543
+ shipping.courier_code || transaction.courier ? h(
544
+ "section",
545
+ { className: "kumpul-detail-card" },
546
+ h("h2", null, "Kurir pengiriman"),
547
+ h(
548
+ "dl",
549
+ { className: "kumpul-detail-fields" },
550
+ h("div", null, h("dt", null, "Kurir"), h("dd", null, text(shipping.courier_code, transaction.courier))),
551
+ shipping.courier_service_name ? h("div", null, h("dt", null, "Layanan"), h("dd", null, shipping.courier_service_name)) : null,
552
+ shipping.destination_area_name ? h("div", null, h("dt", null, "Area tujuan"), h("dd", null, shipping.destination_area_name)) : null,
553
+ h("div", null, h("dt", null, "Biaya ongkir"), h("dd", null, formatCurrency(shippingCost)))
507
554
  )
508
- : null,
555
+ ) : null
509
556
  ),
510
- h('aside', { className: 'kumpul-detail-card kumpul-detail-aside' },
511
- h('h2', null, 'Ringkasan'),
512
- h('dl', { className: 'kumpul-detail-totals' },
513
- h('div', null, h('dt', null, `${itemCount} item`), h('dd', null, formatCurrency(subtotal))),
514
- h('div', null, h('dt', null, 'Ongkir'), h('dd', null, shipping.courier_code ? formatCurrency(shippingCost) : 'Ditentukan penjual')),
515
- h('div', { className: 'kumpul-detail-grand-total' }, h('dt', null, 'Total'), h('dd', null, formatCurrency(transaction.total_amount))),
557
+ h(
558
+ "aside",
559
+ { className: "kumpul-detail-card kumpul-detail-aside" },
560
+ h("h2", null, "Ringkasan"),
561
+ h(
562
+ "dl",
563
+ { className: "kumpul-detail-totals" },
564
+ h("div", null, h("dt", null, `${itemCount} item`), h("dd", null, formatCurrency(subtotal))),
565
+ h("div", null, h("dt", null, "Ongkir"), h("dd", null, shipping.courier_code ? formatCurrency(shippingCost) : "Ditentukan penjual")),
566
+ h("div", { className: "kumpul-detail-grand-total" }, h("dt", null, "Total"), h("dd", null, formatCurrency(transaction.total_amount)))
516
567
  ),
517
- h('dl', { className: 'kumpul-detail-fields kumpul-detail-payment-fields' },
518
- transaction.escrow_id
519
- ? h('div', null, h('dt', null, 'Escrow ID'), h('dd', { className: 'kumpul-detail-mono' }, transaction.escrow_id))
520
- : null,
521
- transaction.created_at
522
- ? h('div', null, h('dt', null, 'Tanggal transaksi'), h('dd', null, formatCalendarDate(transaction.created_at)))
523
- : null,
568
+ h(
569
+ "dl",
570
+ { className: "kumpul-detail-fields kumpul-detail-payment-fields" },
571
+ transaction.escrow_id ? h("div", null, h("dt", null, "Escrow ID"), h("dd", { className: "kumpul-detail-mono" }, transaction.escrow_id)) : null,
572
+ transaction.created_at ? h("div", null, h("dt", null, "Tanggal transaksi"), h("dd", null, formatCalendarDate(transaction.created_at))) : null
524
573
  ),
525
- transaction.status === 'PENDING_PAYMENT' || transaction.status === 'PENDING'
526
- ? h(React.Fragment, null,
527
- h('button', { type: 'button', disabled: true }, 'Lanjutkan Pembayaran'),
528
- transaction.payment_mode === 'ESCROW'
529
- ? h('p', { className: 'kumpul-detail-payment-note' }, 'Dana escrow disimpan sampai proses konfirmasi pesanan selesai.')
530
- : null,
531
- )
532
- : h('p', { className: 'kumpul-detail-payment-note' },
533
- transaction.payment_mode === 'ESCROW'
534
- ? 'Dana escrow disimpan sampai proses konfirmasi pesanan selesai.'
535
- : status.label,
536
- ),
537
- ),
538
- ),
574
+ transaction.status === "PENDING_PAYMENT" || transaction.status === "PENDING" ? h(
575
+ React.Fragment,
576
+ null,
577
+ h("button", { type: "button", disabled: true }, "Lanjutkan Pembayaran"),
578
+ transaction.payment_mode === "ESCROW" ? h("p", { className: "kumpul-detail-payment-note" }, "Dana escrow disimpan sampai proses konfirmasi pesanan selesai.") : null
579
+ ) : h(
580
+ "p",
581
+ { className: "kumpul-detail-payment-note" },
582
+ transaction.payment_mode === "ESCROW" ? "Dana escrow disimpan sampai proses konfirmasi pesanan selesai." : status.label
583
+ )
584
+ )
585
+ )
539
586
  );
540
587
  }
541
-
542
- const gatheringWorkflowSteps = [
543
- { key: 'PLAN', label: 'Atur rencana' },
544
- { key: 'INVITATIONS', label: 'Buat undangan' },
545
- { key: 'INVITATION_CONFIRMATION', label: 'Konfirmasi undangan' },
546
- { key: 'PAYMENT_CONFIRMATION', label: 'Konfirmasi pembayaran' },
588
+ var gatheringWorkflowSteps = [
589
+ { key: "PLAN", label: "Atur rencana" },
590
+ { key: "INVITATIONS", label: "Buat undangan" },
591
+ { key: "INVITATION_CONFIRMATION", label: "Konfirmasi undangan" },
592
+ { key: "PAYMENT_CONFIRMATION", label: "Konfirmasi pembayaran" }
547
593
  ];
548
-
549
- const gatheringPlanStatuses = {
550
- PREORDER: 'Praorder',
551
- RSVP_OPEN: 'Pendaftaran dibuka',
552
- PAYMENT_OPEN: 'Pembayaran dibuka',
553
- CONFIRMED: 'Acara dikonfirmasi',
554
- IN_PROGRESS: 'Sedang berlangsung',
555
- COMPLETED: 'Selesai',
556
- CANCELLED: 'Dibatalkan',
557
- LOCKED: 'Dikunci',
594
+ var gatheringPlanStatuses = {
595
+ PREORDER: "Praorder",
596
+ RSVP_OPEN: "Pendaftaran dibuka",
597
+ PAYMENT_OPEN: "Pembayaran dibuka",
598
+ CONFIRMED: "Acara dikonfirmasi",
599
+ IN_PROGRESS: "Sedang berlangsung",
600
+ COMPLETED: "Selesai",
601
+ CANCELLED: "Dibatalkan",
602
+ LOCKED: "Dikunci"
558
603
  };
559
-
560
604
  function GatheringPlanSimulator({ plan, props }) {
561
605
  const occurrence = plan.occurrence || {};
562
606
  const options = list(occurrence.option_groups_snapshot);
563
607
  const openedIds = new Set(list(occurrence.opened_option_ids_snapshot));
564
608
  const invitees = list(props.previewPlanInvitees);
565
- const localDatePart = (value) => typeof value === 'string' ? value.slice(0, 10) : '';
566
- const localTimePart = (value) => typeof value === 'string' ? value.slice(11, 16) : '';
567
-
568
- return h('section', {
569
- className: 'kumpul-plan-simulator',
570
- 'data-plan-simulator': '',
571
- 'data-current-step': 'PLAN',
572
- 'data-min-attendees': String(Number(occurrence.min_attendees) || 0),
573
- 'data-max-attendees': String(Number(occurrence.max_attendees) || 0),
574
- },
575
- h('div', { className: 'kumpul-plan-simulator-heading' },
576
- h('div', null,
577
- h('p', { className: 'kumpul-eyebrow' }, 'Simulasi interaktif'),
578
- h('h2', null, 'Coba alur rencana gathering'),
579
- h('p', null, 'Mulai dari menyusun rencana, kirim undangan contoh, tinjau RSVP, lalu simulasikan konfirmasi acara.'),
580
- ),
581
- h('span', { className: 'kumpul-plan-simulation-badge' }, 'Lokal · tanpa API'),
582
- ),
583
- h('style', null, '.kumpul-plan-sim-steps{position:sticky;top:var(--kumpul-header-height,0px);z-index:8;padding-top:10px;background:var(--kt-surface)}.kumpul-plan-sim-form.kumpul-plan-sim-dates{grid-template-columns:repeat(3,minmax(0,1fr))}.kumpul-plan-sim-date-time{display:grid;grid-template-columns:minmax(0,1fr) 92px;gap:6px}.kumpul-plan-sim-options .kumpul-plan-sim-option{width:100%;margin:7px 0;display:flex;align-items:flex-start}.kumpul-plan-sim-option>span{display:grid;gap:3px}.kumpul-plan-sim-option small{color:var(--kt-muted);font-size:8px;font-weight:400;line-height:1.45}.kumpul-plan-sim-invite-form{grid-template-columns:repeat(3,minmax(0,1fr)) auto}.kumpul-plan-sim-invitees li>div{grid-template-columns:repeat(3,minmax(0,1fr))}@media(max-width:760px){.kumpul-plan-sim-form.kumpul-plan-sim-dates{grid-template-columns:1fr}.kumpul-plan-sim-invite-form{grid-template-columns:1fr}.kumpul-plan-sim-invitees li>div{grid-template-columns:1fr}}'),
584
- h('p', { className: 'kumpul-plan-simulation-note', role: 'note' },
585
- 'Semua perubahan hanya tersimpan sementara di halaman preview ini. Tidak ada undangan terkirim, pembayaran diproses, atau data akun yang diubah. Muat ulang untuk mengulang simulasi.',
586
- ),
587
- h('ol', { className: 'kumpul-plan-sim-steps', 'aria-label': 'Langkah simulasi' },
588
- ...gatheringWorkflowSteps.map((step, index) => h('li', {
589
- key: step.key,
590
- className: index === 0 ? 'is-current' : '',
591
- 'data-sim-step-item': step.key,
592
- },
593
- h('button', {
594
- type: 'button',
595
- 'data-sim-step': step.key,
596
- 'aria-current': index === 0 ? 'step' : undefined,
597
- disabled: index > 0,
609
+ const localDatePart = (value) => typeof value === "string" ? value.slice(0, 10) : "";
610
+ const localTimePart = (value) => typeof value === "string" ? value.slice(11, 16) : "";
611
+ return h(
612
+ "section",
613
+ {
614
+ className: "kumpul-plan-simulator",
615
+ "data-plan-simulator": "",
616
+ "data-current-step": "PLAN",
617
+ "data-min-attendees": String(Number(occurrence.min_attendees) || 0),
618
+ "data-max-attendees": String(Number(occurrence.max_attendees) || 0)
598
619
  },
599
- h('span', { 'data-sim-step-number': '' }, String(index + 1)),
600
- h('span', null, step.label),
601
- )),
602
- )),
603
- h('div', { className: 'kumpul-plan-sim-panel', 'data-sim-panel': 'PLAN' },
604
- h('h3', null, '1. Atur rencana'),
605
- h('p', { className: 'kumpul-plan-sim-help' }, 'Tetapkan akses undangan, tenggat, tanggal acara, dan pilihan dari produk yang akan dibuka. Harga dan batas peserta mengikuti data produk.'),
606
- h('div', { className: 'kumpul-plan-sim-form' },
607
- h('label', null, 'Nama rencana',
608
- h('input', { type: 'text', required: true, defaultValue: text(plan.title), 'data-sim-title': '' }),
609
- ),
610
- h('label', null, 'Akses peserta',
611
- h('select', { defaultValue: plan.invite_policy === 'INVITE_ONLY' ? 'INVITE_ONLY' : 'OPEN', 'data-sim-policy': '' },
612
- h('option', { value: 'OPEN' }, 'Terbuka'),
613
- h('option', { value: 'INVITE_ONLY' }, 'Khusus undangan'),
614
- ),
620
+ h(
621
+ "div",
622
+ { className: "kumpul-plan-simulator-heading" },
623
+ h(
624
+ "div",
625
+ null,
626
+ h("p", { className: "kumpul-eyebrow" }, "Simulasi interaktif"),
627
+ h("h2", null, "Coba alur rencana gathering"),
628
+ h("p", null, "Mulai dari menyusun rencana, kirim undangan contoh, tinjau RSVP, lalu simulasikan konfirmasi acara.")
615
629
  ),
630
+ h("span", { className: "kumpul-plan-simulation-badge" }, "Lokal \xB7 tanpa API")
616
631
  ),
617
- h('div', { className: 'kumpul-plan-sim-form kumpul-plan-sim-dates' },
618
- h('label', null, 'Batas reservasi',
619
- h('span', { className: 'kumpul-plan-sim-date-time' },
620
- h('input', { type: 'date', defaultValue: localDatePart(occurrence.rsvp_close_at), 'data-sim-rsvp-date': '' }),
621
- h('input', { type: 'time', defaultValue: localTimePart(occurrence.rsvp_close_at), 'aria-label': 'Jam batas reservasi', 'data-sim-rsvp-time': '' }),
632
+ h("style", null, ".kumpul-plan-sim-steps{position:sticky;top:var(--kumpul-header-height,0px);z-index:8;padding-top:10px;background:var(--kt-surface)}.kumpul-plan-sim-form.kumpul-plan-sim-dates{grid-template-columns:repeat(3,minmax(0,1fr))}.kumpul-plan-sim-date-time{display:grid;grid-template-columns:minmax(0,1fr) 92px;gap:6px}.kumpul-plan-sim-options .kumpul-plan-sim-option{width:100%;margin:7px 0;display:flex;align-items:flex-start}.kumpul-plan-sim-option>span{display:grid;gap:3px}.kumpul-plan-sim-option small{color:var(--kt-muted);font-size:8px;font-weight:400;line-height:1.45}.kumpul-plan-sim-invite-form{grid-template-columns:repeat(3,minmax(0,1fr)) auto}.kumpul-plan-sim-invitees li>div{grid-template-columns:repeat(3,minmax(0,1fr))}@media(max-width:760px){.kumpul-plan-sim-form.kumpul-plan-sim-dates{grid-template-columns:1fr}.kumpul-plan-sim-invite-form{grid-template-columns:1fr}.kumpul-plan-sim-invitees li>div{grid-template-columns:1fr}}"),
633
+ h(
634
+ "p",
635
+ { className: "kumpul-plan-simulation-note", role: "note" },
636
+ "Semua perubahan hanya tersimpan sementara di halaman preview ini. Tidak ada undangan terkirim, pembayaran diproses, atau data akun yang diubah. Muat ulang untuk mengulang simulasi."
637
+ ),
638
+ h(
639
+ "ol",
640
+ { className: "kumpul-plan-sim-steps", "aria-label": "Langkah simulasi" },
641
+ ...gatheringWorkflowSteps.map(
642
+ (step, index) => h(
643
+ "li",
644
+ {
645
+ key: step.key,
646
+ className: index === 0 ? "is-current" : "",
647
+ "data-sim-step-item": step.key
648
+ },
649
+ h(
650
+ "button",
651
+ {
652
+ type: "button",
653
+ "data-sim-step": step.key,
654
+ "aria-current": index === 0 ? "step" : void 0,
655
+ disabled: index > 0
656
+ },
657
+ h("span", { "data-sim-step-number": "" }, String(index + 1)),
658
+ h("span", null, step.label)
659
+ )
660
+ )
661
+ )
662
+ ),
663
+ h(
664
+ "div",
665
+ { className: "kumpul-plan-sim-panel", "data-sim-panel": "PLAN" },
666
+ h("h3", null, "1. Atur rencana"),
667
+ h("p", { className: "kumpul-plan-sim-help" }, "Tetapkan akses undangan, tenggat, tanggal acara, dan pilihan dari produk yang akan dibuka. Harga dan batas peserta mengikuti data produk."),
668
+ h(
669
+ "div",
670
+ { className: "kumpul-plan-sim-form" },
671
+ h(
672
+ "label",
673
+ null,
674
+ "Nama rencana",
675
+ h("input", { type: "text", required: true, defaultValue: text(plan.title), "data-sim-title": "" })
622
676
  ),
677
+ h(
678
+ "label",
679
+ null,
680
+ "Akses peserta",
681
+ h(
682
+ "select",
683
+ { defaultValue: plan.invite_policy === "INVITE_ONLY" ? "INVITE_ONLY" : "OPEN", "data-sim-policy": "" },
684
+ h("option", { value: "OPEN" }, "Terbuka"),
685
+ h("option", { value: "INVITE_ONLY" }, "Khusus undangan")
686
+ )
687
+ )
623
688
  ),
624
- h('label', null, 'Batas pembayaran',
625
- h('span', { className: 'kumpul-plan-sim-date-time' },
626
- h('input', { type: 'date', defaultValue: localDatePart(occurrence.payment_deadline), 'data-sim-payment-date': '' }),
627
- h('input', { type: 'time', defaultValue: localTimePart(occurrence.payment_deadline), 'aria-label': 'Jam batas pembayaran', 'data-sim-payment-time': '' }),
689
+ h(
690
+ "div",
691
+ { className: "kumpul-plan-sim-form kumpul-plan-sim-dates" },
692
+ h(
693
+ "label",
694
+ null,
695
+ "Batas reservasi",
696
+ h(
697
+ "span",
698
+ { className: "kumpul-plan-sim-date-time" },
699
+ h("input", { type: "date", defaultValue: localDatePart(occurrence.rsvp_close_at), "data-sim-rsvp-date": "" }),
700
+ h("input", { type: "time", defaultValue: localTimePart(occurrence.rsvp_close_at), "aria-label": "Jam batas reservasi", "data-sim-rsvp-time": "" })
701
+ )
628
702
  ),
629
- ),
630
- h('label', null, 'Tanggal acara',
631
- h('span', { className: 'kumpul-plan-sim-date-time' },
632
- h('input', { type: 'date', defaultValue: localDatePart(occurrence.final_schedule), 'data-sim-event-date': '' }),
633
- h('input', { type: 'time', defaultValue: localTimePart(occurrence.final_schedule), 'aria-label': 'Jam acara', 'data-sim-event-time': '' }),
703
+ h(
704
+ "label",
705
+ null,
706
+ "Batas pembayaran",
707
+ h(
708
+ "span",
709
+ { className: "kumpul-plan-sim-date-time" },
710
+ h("input", { type: "date", defaultValue: localDatePart(occurrence.payment_deadline), "data-sim-payment-date": "" }),
711
+ h("input", { type: "time", defaultValue: localTimePart(occurrence.payment_deadline), "aria-label": "Jam batas pembayaran", "data-sim-payment-time": "" })
712
+ )
634
713
  ),
714
+ h(
715
+ "label",
716
+ null,
717
+ "Tanggal acara",
718
+ h(
719
+ "span",
720
+ { className: "kumpul-plan-sim-date-time" },
721
+ h("input", { type: "date", defaultValue: localDatePart(occurrence.final_schedule), "data-sim-event-date": "" }),
722
+ h("input", { type: "time", defaultValue: localTimePart(occurrence.final_schedule), "aria-label": "Jam acara", "data-sim-event-time": "" })
723
+ )
724
+ )
635
725
  ),
636
- ),
637
- h('fieldset', { className: 'kumpul-plan-sim-options' },
638
- h('legend', null, 'Pilihan dari produk yang dibuka'),
639
- h('p', { className: 'kumpul-plan-sim-help' }, 'Pilihan hanya berasal dari snapshot opsi produk gathering.'),
640
- options.length
641
- ? options.map((option) => h('label', { key: option.product_option_id, className: 'kumpul-plan-sim-option' },
642
- h('input', {
643
- type: 'checkbox',
726
+ h(
727
+ "fieldset",
728
+ { className: "kumpul-plan-sim-options" },
729
+ h("legend", null, "Pilihan dari produk yang dibuka"),
730
+ h("p", { className: "kumpul-plan-sim-help" }, "Pilihan hanya berasal dari snapshot opsi produk gathering."),
731
+ options.length ? options.map((option) => h(
732
+ "label",
733
+ { key: option.product_option_id, className: "kumpul-plan-sim-option" },
734
+ h("input", {
735
+ type: "checkbox",
644
736
  value: option.product_option_id,
645
737
  defaultChecked: openedIds.has(option.product_option_id),
646
- 'data-sim-option-group': text(option.option_group_key, 'Pilihan'),
647
- 'data-sim-option-label': text(option.label, text(option.option_key)),
648
- 'data-sim-option-description': text(option.description),
649
- 'data-sim-option-location': text(option.venue_location),
650
- 'data-sim-option-final': option.is_final_selection ? 'true' : 'false',
651
- 'data-sim-option': '',
738
+ "data-sim-option-group": text(option.option_group_key, "Pilihan"),
739
+ "data-sim-option-label": text(option.label, text(option.option_key)),
740
+ "data-sim-option-description": text(option.description),
741
+ "data-sim-option-location": text(option.venue_location),
742
+ "data-sim-option-final": option.is_final_selection ? "true" : "false",
743
+ "data-sim-option": ""
652
744
  }),
653
- h('span', { style: { display: 'grid', minWidth: 0, gap: '3px' } },
654
- h('strong', null, `${text(option.option_group_key, 'Pilihan')} · ${text(option.label, text(option.option_key))}`),
655
- option.venue_location || option.description
656
- ? h('small', { style: { display: 'block', color: 'var(--kt-muted)', fontSize: '8px', fontWeight: 400, lineHeight: 1.45 } }, [option.venue_location, option.description].filter(Boolean).join(' · '))
657
- : null,
658
- ),
659
- ))
660
- : h('p', null, 'Belum ada opsi dari produk pada contoh rencana ini.'),
661
- ),
662
- h('p', { className: 'kumpul-plan-sim-status', role: 'status', hidden: true, 'data-sim-saved': '' }),
663
- h('p', { className: 'kumpul-plan-sim-error', role: 'alert', hidden: true, 'data-sim-error': '' }),
664
- h('div', { className: 'kumpul-plan-sim-actions' },
665
- h('button', { type: 'button', className: 'kumpul-plan-sim-secondary', 'data-sim-save-plan': '' }, 'Simpan'),
666
- h('button', { type: 'button', className: 'kumpul-plan-sim-primary', 'data-sim-submit-plan': '' }, 'Submit'),
667
- ),
668
- ),
669
- h('div', { className: 'kumpul-plan-sim-panel', 'data-sim-panel': 'INVITATIONS', hidden: true },
670
- h('h3', null, '2. Buat undangan'),
671
- h('p', { className: 'kumpul-plan-sim-help' }, 'Tambahkan kontak undangan melalui email atau WhatsApp. Preview hanya menyimulasikan submit dan tidak mengirim pesan.'),
672
- h('div', { className: 'kumpul-plan-sim-invite-form' },
673
- h('label', null, 'Nama calon peserta',
674
- h('input', { type: 'text', placeholder: 'Nama peserta', 'data-sim-invite-name': '' }),
675
- ),
676
- h('label', null, 'Email',
677
- h('input', { type: 'email', placeholder: 'nama@email.test', 'data-sim-invite-email': '' }),
678
- ),
679
- h('label', null, 'WhatsApp',
680
- h('input', { type: 'tel', placeholder: '+628123456789', 'data-sim-invite-whatsapp': '' }),
745
+ h(
746
+ "span",
747
+ { style: { display: "grid", minWidth: 0, gap: "3px" } },
748
+ h("strong", null, `${text(option.option_group_key, "Pilihan")} \xB7 ${text(option.label, text(option.option_key))}`),
749
+ option.venue_location || option.description ? h("small", { style: { display: "block", color: "var(--kt-muted)", fontSize: "8px", fontWeight: 400, lineHeight: 1.45 } }, [option.venue_location, option.description].filter(Boolean).join(" \xB7 ")) : null
750
+ )
751
+ )) : h("p", null, "Belum ada opsi dari produk pada contoh rencana ini.")
681
752
  ),
682
- h('button', { type: 'button', 'data-sim-add-invite': '' }, 'Tambah peserta'),
753
+ h("p", { className: "kumpul-plan-sim-status", role: "status", hidden: true, "data-sim-saved": "" }),
754
+ h("p", { className: "kumpul-plan-sim-error", role: "alert", hidden: true, "data-sim-error": "" }),
755
+ h(
756
+ "div",
757
+ { className: "kumpul-plan-sim-actions" },
758
+ h("button", { type: "button", className: "kumpul-plan-sim-secondary", "data-sim-save-plan": "" }, "Simpan"),
759
+ h("button", { type: "button", className: "kumpul-plan-sim-primary", "data-sim-submit-plan": "" }, "Submit")
760
+ )
683
761
  ),
684
- h('ul', { className: 'kumpul-plan-sim-invitees', 'data-sim-invitees': '' },
685
- ...invitees.map((invitee, index) => h('li', {
686
- key: invitee.email || index,
687
- 'data-sim-invitee': '',
688
- 'data-sim-rsvp-status': invitee.rsvp_status === 'ACCEPTED' ? 'ACCEPTED' : 'PENDING',
689
- },
690
- h('div', null,
691
- h('input', { type: 'text', 'aria-label': `Nama calon peserta ${index + 1}`, defaultValue: text(invitee.name), 'data-sim-invitee-name': '' }),
692
- h('input', { type: 'email', 'aria-label': `Email calon peserta ${index + 1}`, defaultValue: text(invitee.email), 'data-sim-invitee-email': '' }),
693
- h('input', { type: 'tel', 'aria-label': `WhatsApp calon peserta ${index + 1}`, defaultValue: text(invitee.whatsapp), 'data-sim-invitee-whatsapp': '' }),
762
+ h(
763
+ "div",
764
+ { className: "kumpul-plan-sim-panel", "data-sim-panel": "INVITATIONS", hidden: true },
765
+ h("h3", null, "2. Buat undangan"),
766
+ h("p", { className: "kumpul-plan-sim-help" }, "Tambahkan kontak undangan melalui email atau WhatsApp. Preview hanya menyimulasikan submit dan tidak mengirim pesan."),
767
+ h(
768
+ "div",
769
+ { className: "kumpul-plan-sim-invite-form" },
770
+ h(
771
+ "label",
772
+ null,
773
+ "Nama calon peserta",
774
+ h("input", { type: "text", placeholder: "Nama peserta", "data-sim-invite-name": "" })
694
775
  ),
695
- h('button', { type: 'button', 'aria-label': `Hapus peserta ${index + 1}`, 'data-sim-remove-invite': '' }, 'Hapus'),
696
- )),
697
- ),
698
- h('p', { className: 'kumpul-plan-sim-error', role: 'alert', hidden: true, 'data-sim-error': '' }),
699
- h('div', { className: 'kumpul-plan-sim-actions' },
700
- h('button', { type: 'button', className: 'kumpul-plan-sim-secondary', 'data-sim-back': '' }, 'Kembali'),
701
- h('button', { type: 'button', className: 'kumpul-plan-sim-primary', 'data-sim-send-invites': '' }, 'Simulasikan kirim undangan'),
702
- ),
703
- ),
704
- h('div', { className: 'kumpul-plan-sim-panel', 'data-sim-panel': 'INVITATION_CONFIRMATION', hidden: true },
705
- h('h3', null, '3. Konfirmasi undangan'),
706
- h('p', { className: 'kumpul-plan-sim-help' }, 'Daftar ini hanya menampilkan peserta yang sudah mengonfirmasi hadir. Jumlah peserta harus memenuhi batas produk sebelum RSVP ditutup.'),
707
- h('section', {
708
- className: 'kumpul-plan-sim-public-invitation',
709
- 'data-sim-public-invitation': '',
710
- 'data-sim-public-invitation-url': tenantPath(props, `/gathering/invite/${encodeURIComponent(text(plan.id, 'preview'))}`),
711
- hidden: plan.invite_policy === 'INVITE_ONLY',
712
- },
713
- h('h4', null, 'Undangan terbuka'),
714
- h('p', { className: 'kumpul-plan-sim-help' }, 'Bagikan tautan ini atau pindai QR untuk membuka undangan publik.'),
715
- h('div', { className: 'kumpul-plan-sim-public-invitation-content' },
716
- h('div', { className: 'kumpul-plan-sim-qr' },
717
- h('img', { alt: 'QR undangan terbuka', 'data-sim-public-qr': '', hidden: true }),
718
- h('span', { role: 'status', 'data-sim-public-qr-status': '' }, 'Menyiapkan QR undangan…'),
776
+ h(
777
+ "label",
778
+ null,
779
+ "Email",
780
+ h("input", { type: "email", placeholder: "nama@email.test", "data-sim-invite-email": "" })
781
+ ),
782
+ h(
783
+ "label",
784
+ null,
785
+ "WhatsApp",
786
+ h("input", { type: "tel", placeholder: "+628123456789", "data-sim-invite-whatsapp": "" })
787
+ ),
788
+ h("button", { type: "button", "data-sim-add-invite": "" }, "Tambah peserta")
719
789
  ),
720
- h('a', {
721
- href: tenantPath(props, `/gathering/invite/${encodeURIComponent(text(plan.id, 'preview'))}`),
722
- target: '_blank',
723
- rel: 'noopener noreferrer',
724
- 'data-sim-public-invitation-link': '',
725
- }),
726
- ),
727
- ),
728
- h('div', { className: 'kumpul-plan-sim-participants', 'data-sim-participants': '' }),
729
- h('p', { className: 'kumpul-plan-sim-error', role: 'alert', hidden: true, 'data-sim-error': '' }),
730
- h('div', { className: 'kumpul-plan-sim-actions' },
731
- h('button', { type: 'button', className: 'kumpul-plan-sim-secondary', 'data-sim-back': '' }, 'Kembali'),
732
- h('button', { type: 'button', className: 'kumpul-plan-sim-primary', 'data-sim-confirm-participants': '' }, 'Tutup RSVP & buka pembayaran (simulasi)'),
790
+ h(
791
+ "ul",
792
+ { className: "kumpul-plan-sim-invitees", "data-sim-invitees": "" },
793
+ ...invitees.map((invitee, index) => h(
794
+ "li",
795
+ {
796
+ key: invitee.email || index,
797
+ "data-sim-invitee": "",
798
+ "data-sim-rsvp-status": invitee.rsvp_status === "ACCEPTED" ? "ACCEPTED" : "PENDING"
799
+ },
800
+ h(
801
+ "div",
802
+ null,
803
+ h("input", { type: "text", "aria-label": `Nama calon peserta ${index + 1}`, defaultValue: text(invitee.name), "data-sim-invitee-name": "" }),
804
+ h("input", { type: "email", "aria-label": `Email calon peserta ${index + 1}`, defaultValue: text(invitee.email), "data-sim-invitee-email": "" }),
805
+ h("input", { type: "tel", "aria-label": `WhatsApp calon peserta ${index + 1}`, defaultValue: text(invitee.whatsapp), "data-sim-invitee-whatsapp": "" })
806
+ ),
807
+ h("button", { type: "button", "aria-label": `Hapus peserta ${index + 1}`, "data-sim-remove-invite": "" }, "Hapus")
808
+ ))
809
+ ),
810
+ h("p", { className: "kumpul-plan-sim-error", role: "alert", hidden: true, "data-sim-error": "" }),
811
+ h(
812
+ "div",
813
+ { className: "kumpul-plan-sim-actions" },
814
+ h("button", { type: "button", className: "kumpul-plan-sim-secondary", "data-sim-back": "" }, "Kembali"),
815
+ h("button", { type: "button", className: "kumpul-plan-sim-primary", "data-sim-send-invites": "" }, "Simulasikan kirim undangan")
816
+ )
733
817
  ),
734
- ),
735
- h('div', { className: 'kumpul-plan-sim-panel', 'data-sim-panel': 'PAYMENT_CONFIRMATION', hidden: true },
736
- h('h3', null, '4. Konfirmasi pembayaran dan acara'),
737
- h('p', { className: 'kumpul-plan-sim-help' }, 'Simulasikan pembayaran peserta, pilih opsi final dari hasil voting, lalu konfirmasi acara. Pembayaran nyata tidak diproses.'),
738
- h('div', { className: 'kumpul-plan-sim-payments', 'data-sim-payments': '' }),
739
- h('fieldset', { className: 'kumpul-plan-sim-options kumpul-plan-sim-final-options' },
740
- h('legend', null, 'Opsi final gathering'),
741
- h('div', { 'data-sim-final-options': '' }),
818
+ h(
819
+ "div",
820
+ { className: "kumpul-plan-sim-panel", "data-sim-panel": "INVITATION_CONFIRMATION", hidden: true },
821
+ h("h3", null, "3. Konfirmasi undangan"),
822
+ h("p", { className: "kumpul-plan-sim-help" }, "Daftar ini hanya menampilkan peserta yang sudah mengonfirmasi hadir. Jumlah peserta harus memenuhi batas produk sebelum RSVP ditutup."),
823
+ h(
824
+ "section",
825
+ {
826
+ className: "kumpul-plan-sim-public-invitation",
827
+ "data-sim-public-invitation": "",
828
+ "data-sim-public-invitation-url": tenantPath(props, `/gathering/invite/${encodeURIComponent(text(plan.id, "preview"))}`),
829
+ hidden: plan.invite_policy === "INVITE_ONLY"
830
+ },
831
+ h("h4", null, "Undangan terbuka"),
832
+ h("p", { className: "kumpul-plan-sim-help" }, "Bagikan tautan ini atau pindai QR untuk membuka undangan publik."),
833
+ h(
834
+ "div",
835
+ { className: "kumpul-plan-sim-public-invitation-content" },
836
+ h(
837
+ "div",
838
+ { className: "kumpul-plan-sim-qr" },
839
+ h("img", { alt: "QR undangan terbuka", "data-sim-public-qr": "", hidden: true }),
840
+ h("span", { role: "status", "data-sim-public-qr-status": "" }, "Menyiapkan QR undangan\u2026")
841
+ ),
842
+ h("a", {
843
+ href: tenantPath(props, `/gathering/invite/${encodeURIComponent(text(plan.id, "preview"))}`),
844
+ target: "_blank",
845
+ rel: "noopener noreferrer",
846
+ "data-sim-public-invitation-link": ""
847
+ })
848
+ )
849
+ ),
850
+ h("div", { className: "kumpul-plan-sim-participants", "data-sim-participants": "" }),
851
+ h("p", { className: "kumpul-plan-sim-error", role: "alert", hidden: true, "data-sim-error": "" }),
852
+ h(
853
+ "div",
854
+ { className: "kumpul-plan-sim-actions" },
855
+ h("button", { type: "button", className: "kumpul-plan-sim-secondary", "data-sim-back": "" }, "Kembali"),
856
+ h("button", { type: "button", className: "kumpul-plan-sim-primary", "data-sim-confirm-participants": "" }, "Tutup RSVP & buka pembayaran (simulasi)")
857
+ )
742
858
  ),
743
- h('p', { className: 'kumpul-plan-sim-error', role: 'alert', hidden: true, 'data-sim-error': '' }),
744
- h('div', { className: 'kumpul-plan-sim-actions' },
745
- h('button', { type: 'button', className: 'kumpul-plan-sim-secondary', 'data-sim-back': '' }, 'Kembali'),
746
- h('button', { type: 'button', className: 'kumpul-plan-sim-primary', 'data-sim-confirm-event': '' }, 'Konfirmasi acara (simulasi)'),
859
+ h(
860
+ "div",
861
+ { className: "kumpul-plan-sim-panel", "data-sim-panel": "PAYMENT_CONFIRMATION", hidden: true },
862
+ h("h3", null, "4. Konfirmasi pembayaran dan acara"),
863
+ h("p", { className: "kumpul-plan-sim-help" }, "Simulasikan pembayaran peserta, pilih opsi final dari hasil voting, lalu konfirmasi acara. Pembayaran nyata tidak diproses."),
864
+ h("div", { className: "kumpul-plan-sim-payments", "data-sim-payments": "" }),
865
+ h(
866
+ "fieldset",
867
+ { className: "kumpul-plan-sim-options kumpul-plan-sim-final-options" },
868
+ h("legend", null, "Opsi final gathering"),
869
+ h("div", { "data-sim-final-options": "" })
870
+ ),
871
+ h("p", { className: "kumpul-plan-sim-error", role: "alert", hidden: true, "data-sim-error": "" }),
872
+ h(
873
+ "div",
874
+ { className: "kumpul-plan-sim-actions" },
875
+ h("button", { type: "button", className: "kumpul-plan-sim-secondary", "data-sim-back": "" }, "Kembali"),
876
+ h("button", { type: "button", className: "kumpul-plan-sim-primary", "data-sim-confirm-event": "" }, "Konfirmasi acara (simulasi)")
877
+ )
747
878
  ),
748
- ),
749
- h('div', { className: 'kumpul-plan-sim-complete', hidden: true, 'data-sim-complete': '' },
750
- h('span', { 'aria-hidden': 'true' }, '✓'),
751
- h('h3', null, 'Simulasi gathering selesai'),
752
- h('p', null, 'Rencana, undangan, RSVP, dan konfirmasi acara sudah dicoba. Tidak ada data yang dikirim ke Bagdja.'),
753
- h('button', { type: 'button', 'data-sim-restart': '' }, 'Ulangi simulasi'),
754
- ),
879
+ h(
880
+ "div",
881
+ { className: "kumpul-plan-sim-complete", hidden: true, "data-sim-complete": "" },
882
+ h("span", { "aria-hidden": "true" }, "\u2713"),
883
+ h("h3", null, "Simulasi gathering selesai"),
884
+ h("p", null, "Rencana, undangan, RSVP, dan konfirmasi acara sudah dicoba. Tidak ada data yang dikirim ke Bagdja."),
885
+ h("button", { type: "button", "data-sim-restart": "" }, "Ulangi simulasi")
886
+ )
755
887
  );
756
888
  }
757
-
758
889
  function GatheringPlanDetailSection({ props, section }) {
759
890
  const sectionContent = section?.content || {};
760
- const plan = props.isPreview === true
761
- ? props.previewGatheringPlan || {}
762
- : sectionContent.gatheringPlan || {};
763
- const order = props.isPreview === true
764
- ? props.previewGatheringOrder || {}
765
- : sectionContent.order || {};
891
+ const plan = props.isPreview === true ? props.previewGatheringPlan || {} : sectionContent.gatheringPlan || {};
892
+ const order = props.isPreview === true ? props.previewGatheringOrder || {} : sectionContent.order || {};
766
893
  const occurrence = plan.occurrence || {};
767
894
  const openedIds = new Set(list(occurrence.opened_option_ids_snapshot));
768
- const openedOptions = list(occurrence.option_groups_snapshot)
769
- .filter((option) => openedIds.has(option.product_option_id));
770
- const currentStepIndex = plan.workflow_step === 'LOCKED'
771
- ? gatheringWorkflowSteps.length
772
- : Math.max(0, gatheringWorkflowSteps.findIndex((step) => step.key === plan.workflow_step));
773
- const currentStep = plan.workflow_step === 'LOCKED'
774
- ? 'Selesai'
775
- : gatheringWorkflowSteps.find((step) => step.key === plan.workflow_step)?.label || 'Tahap belum tersedia';
895
+ const openedOptions = list(occurrence.option_groups_snapshot).filter((option) => openedIds.has(option.product_option_id));
896
+ const currentStepIndex = plan.workflow_step === "LOCKED" ? gatheringWorkflowSteps.length : Math.max(0, gatheringWorkflowSteps.findIndex((step) => step.key === plan.workflow_step));
897
+ const currentStep = plan.workflow_step === "LOCKED" ? "Selesai" : gatheringWorkflowSteps.find((step) => step.key === plan.workflow_step)?.label || "Tahap belum tersedia";
776
898
  const dateTime = (value) => {
777
899
  const date = formatCalendarDate(value);
778
900
  const time = formatCalendarTime(value);
779
- return date ? `${date}${time ? ` · ${time} WIB` : ''}` : 'Belum ditentukan';
901
+ return date ? `${date}${time ? ` \xB7 ${time} WIB` : ""}` : "Belum ditentukan";
780
902
  };
781
- const workflowStatus = text(gatheringPlanStatuses[plan.status], text(plan.status, 'Status belum tersedia'));
903
+ const workflowStatus = text(gatheringPlanStatuses[plan.status], text(plan.status, "Status belum tersedia"));
782
904
  const seatPrice = Number(occurrence.price_per_seat);
783
905
  const depositPerSeat = Number(occurrence.deposit_amount_per_seat);
784
-
785
906
  if (!plan.id && !plan.plan_number && !plan.title) {
786
- return h('section', { className: 'kumpul-plan-detail', 'data-plan-detail': '' },
787
- h('h1', null, 'Detail Rencana Gathering'),
788
- h('p', null, props.isPreview === true
789
- ? 'Belum ada contoh rencana gathering pada preview ini.'
790
- : 'Data rencana gathering dikelola oleh host Bagdja.'),
907
+ return h(
908
+ "section",
909
+ { className: "kumpul-plan-detail", "data-plan-detail": "" },
910
+ h("h1", null, "Detail Rencana Gathering"),
911
+ h("p", null, props.isPreview === true ? "Belum ada contoh rencana gathering pada preview ini." : "Data rencana gathering dikelola oleh host Bagdja.")
791
912
  );
792
913
  }
793
-
794
- return h('section', { className: 'kumpul-plan-detail', 'data-plan-detail': '' },
795
- h('a', { className: 'kumpul-detail-back', href: tenantPath(props, '/cart') }, '← Kembali ke Keranjang'),
796
- h('header', { className: 'kumpul-plan-heading' },
797
- h('div', null,
798
- h('p', { className: 'kumpul-eyebrow' }, 'Detail rencana gathering'),
799
- h('h1', null, text(plan.title, 'Rencana Gathering')),
800
- h('p', { className: 'kumpul-plan-number' }, `Nomor rencana · ${text(plan.plan_number, 'Belum tersedia')}`),
914
+ return h(
915
+ "section",
916
+ { className: "kumpul-plan-detail", "data-plan-detail": "" },
917
+ h("a", { className: "kumpul-detail-back", href: tenantPath(props, "/cart") }, "\u2190 Kembali ke Keranjang"),
918
+ h(
919
+ "header",
920
+ { className: "kumpul-plan-heading" },
921
+ h(
922
+ "div",
923
+ null,
924
+ h("p", { className: "kumpul-eyebrow" }, "Detail rencana gathering"),
925
+ h("h1", null, text(plan.title, "Rencana Gathering")),
926
+ h("p", { className: "kumpul-plan-number" }, `Nomor rencana \xB7 ${text(plan.plan_number, "Belum tersedia")}`)
801
927
  ),
802
- h('span', { className: 'kumpul-transaction-status kumpul-transaction-status-info' }, workflowStatus),
928
+ h("span", { className: "kumpul-transaction-status kumpul-transaction-status-info" }, workflowStatus)
803
929
  ),
804
- props.isPreview === true
805
- ? h('p', { className: 'kumpul-detail-preview-note', role: 'note' },
806
- 'Preview desainer · data contoh saja. Status dan pengelolaan rencana dilakukan oleh host Bagdja.',
807
- )
808
- : null,
930
+ props.isPreview === true ? h(
931
+ "p",
932
+ { className: "kumpul-detail-preview-note", role: "note" },
933
+ "Preview desainer \xB7 data contoh saja. Status dan pengelolaan rencana dilakukan oleh host Bagdja."
934
+ ) : null,
809
935
  props.isPreview === true ? h(GatheringPlanSimulator, { plan, props }) : null,
810
- props.isPreview === true
811
- ? null
812
- : h('section', { className: 'kumpul-plan-workflow', 'aria-label': 'Tahapan gathering' },
813
- h('p', { className: 'kumpul-plan-current-step' }, 'Tahap saat ini: ', h('strong', { 'data-plan-current-step': '' }, currentStep)),
814
- h('ol', null,
815
- ...gatheringWorkflowSteps.map((step, index) => h('li', {
936
+ props.isPreview === true ? null : h(
937
+ "section",
938
+ { className: "kumpul-plan-workflow", "aria-label": "Tahapan gathering" },
939
+ h("p", { className: "kumpul-plan-current-step" }, "Tahap saat ini: ", h("strong", { "data-plan-current-step": "" }, currentStep)),
940
+ h(
941
+ "ol",
942
+ null,
943
+ ...gatheringWorkflowSteps.map((step, index) => h(
944
+ "li",
945
+ {
816
946
  key: step.key,
817
- className: index < currentStepIndex ? 'is-complete' : index === currentStepIndex ? 'is-current' : '',
818
- 'aria-current': index === currentStepIndex ? 'step' : undefined,
947
+ className: index < currentStepIndex ? "is-complete" : index === currentStepIndex ? "is-current" : "",
948
+ "aria-current": index === currentStepIndex ? "step" : void 0
819
949
  },
820
- h('span', { className: 'kumpul-plan-step-marker', 'aria-hidden': 'true' }, index < currentStepIndex ? '✓' : String(index + 1)),
821
- h('span', null, step.label),
822
- )),
823
- ),
824
- h('p', { className: 'kumpul-plan-readonly' }, 'Ringkasan ini hanya untuk melihat progres. Aksi rencana tersedia melalui host Bagdja.'),
950
+ h("span", { className: "kumpul-plan-step-marker", "aria-hidden": "true" }, index < currentStepIndex ? "\u2713" : String(index + 1)),
951
+ h("span", null, step.label)
952
+ ))
825
953
  ),
826
- h('div', { className: 'kumpul-plan-layout' },
827
- h('div', { className: 'kumpul-plan-main' },
828
- h('section', { className: 'kumpul-detail-card' },
829
- h('h2', null, 'Ringkasan gathering'),
830
- h('dl', { className: 'kumpul-detail-fields' },
831
- h('div', null, h('dt', null, 'Status acara'), h('dd', null, text(gatheringPlanStatuses[occurrence.status], text(occurrence.status, 'Belum tersedia')))),
832
- h('div', null, h('dt', null, 'Akses undangan'), h('dd', null, plan.invite_policy === 'INVITE_ONLY' ? 'Khusus undangan' : 'Terbuka')),
833
- h('div', null, h('dt', null, 'Harga per peserta'), h('dd', null, Number.isFinite(seatPrice) ? formatCurrency(seatPrice) : 'Belum ditentukan')),
834
- Number.isFinite(depositPerSeat) && depositPerSeat > 0
835
- ? h('div', null, h('dt', null, 'Uang muka per peserta'), h('dd', null, formatCurrency(depositPerSeat)))
836
- : null,
837
- h('div', null, h('dt', null, 'Batas peserta'), h('dd', null, `Min. ${Number(occurrence.min_attendees) || 0} · Maks. ${Number(occurrence.max_attendees) || 0}`)),
838
- h('div', null, h('dt', null, 'Terakhir reservasi'), h('dd', null, dateTime(occurrence.rsvp_close_at))),
839
- h('div', null, h('dt', null, 'Batas pembayaran'), h('dd', null, dateTime(occurrence.payment_deadline))),
840
- h('div', null, h('dt', null, 'Jadwal acara'), h('dd', null, dateTime(occurrence.final_schedule))),
841
- h('div', null, h('dt', null, 'Lokasi acara'), h('dd', null, text(occurrence.final_location, 'Belum ditentukan'))),
842
- order.created_at
843
- ? h('div', null, h('dt', null, 'Tanggal dibuat'), h('dd', null, formatCalendarDate(order.created_at)))
844
- : null,
845
- ),
954
+ h("p", { className: "kumpul-plan-readonly" }, "Ringkasan ini hanya untuk melihat progres. Aksi rencana tersedia melalui host Bagdja.")
955
+ ),
956
+ h(
957
+ "div",
958
+ { className: "kumpul-plan-layout" },
959
+ h(
960
+ "div",
961
+ { className: "kumpul-plan-main" },
962
+ h(
963
+ "section",
964
+ { className: "kumpul-detail-card" },
965
+ h("h2", null, "Ringkasan gathering"),
966
+ h(
967
+ "dl",
968
+ { className: "kumpul-detail-fields" },
969
+ h("div", null, h("dt", null, "Status acara"), h("dd", null, text(gatheringPlanStatuses[occurrence.status], text(occurrence.status, "Belum tersedia")))),
970
+ h("div", null, h("dt", null, "Akses undangan"), h("dd", null, plan.invite_policy === "INVITE_ONLY" ? "Khusus undangan" : "Terbuka")),
971
+ h("div", null, h("dt", null, "Harga per peserta"), h("dd", null, Number.isFinite(seatPrice) ? formatCurrency(seatPrice) : "Belum ditentukan")),
972
+ Number.isFinite(depositPerSeat) && depositPerSeat > 0 ? h("div", null, h("dt", null, "Uang muka per peserta"), h("dd", null, formatCurrency(depositPerSeat))) : null,
973
+ h("div", null, h("dt", null, "Batas peserta"), h("dd", null, `Min. ${Number(occurrence.min_attendees) || 0} \xB7 Maks. ${Number(occurrence.max_attendees) || 0}`)),
974
+ h("div", null, h("dt", null, "Terakhir reservasi"), h("dd", null, dateTime(occurrence.rsvp_close_at))),
975
+ h("div", null, h("dt", null, "Batas pembayaran"), h("dd", null, dateTime(occurrence.payment_deadline))),
976
+ h("div", null, h("dt", null, "Jadwal acara"), h("dd", null, dateTime(occurrence.final_schedule))),
977
+ h("div", null, h("dt", null, "Lokasi acara"), h("dd", null, text(occurrence.final_location, "Belum ditentukan"))),
978
+ order.created_at ? h("div", null, h("dt", null, "Tanggal dibuat"), h("dd", null, formatCalendarDate(order.created_at))) : null
979
+ )
846
980
  ),
847
- h('section', { className: 'kumpul-detail-card' },
848
- h('h2', null, 'Pilihan dari produk'),
849
- h('ul', {
850
- className: 'kumpul-plan-options',
851
- 'data-plan-opened-options': '',
852
- hidden: openedOptions.length === 0,
853
- },
854
- ...openedOptions.map((option) => {
855
- const voteResult = occurrence.voting_results?.[option.option_group_key];
856
- const vote = voteResult?.options?.[String(option.product_option_id)];
857
- return h('li', { key: option.product_option_id },
858
- h('div', { className: 'kumpul-plan-option-heading' },
859
- h('div', null,
860
- h('span', { className: 'kumpul-plan-option-group' }, text(option.option_group_key, 'Pilihan')),
861
- h('h3', null, text(option.label, text(option.option_key, 'Opsi gathering'))),
862
- ),
863
- option.is_final_selection
864
- ? h('span', { className: 'kumpul-plan-final-option' }, 'Opsi final')
865
- : null,
981
+ h(
982
+ "section",
983
+ { className: "kumpul-detail-card" },
984
+ h("h2", null, "Pilihan dari produk"),
985
+ h(
986
+ "ul",
987
+ {
988
+ className: "kumpul-plan-options",
989
+ "data-plan-opened-options": "",
990
+ hidden: openedOptions.length === 0
991
+ },
992
+ ...openedOptions.map((option) => {
993
+ const voteResult = occurrence.voting_results?.[option.option_group_key];
994
+ const vote = voteResult?.options?.[String(option.product_option_id)];
995
+ return h(
996
+ "li",
997
+ { key: option.product_option_id },
998
+ h(
999
+ "div",
1000
+ { className: "kumpul-plan-option-heading" },
1001
+ h(
1002
+ "div",
1003
+ null,
1004
+ h("span", { className: "kumpul-plan-option-group" }, text(option.option_group_key, "Pilihan")),
1005
+ h("h3", null, text(option.label, text(option.option_key, "Opsi gathering")))
866
1006
  ),
867
- h('p', null, [option.venue_location, option.description].filter(Boolean).join(' · ') || 'Detail pilihan belum ditambahkan.'),
868
- vote
869
- ? h('span', { className: 'kumpul-plan-votes' }, `${vote.votes} suara · ${vote.percentage}%`)
870
- : null,
871
- );
872
- }),
1007
+ option.is_final_selection ? h("span", { className: "kumpul-plan-final-option" }, "Opsi final") : null
1008
+ ),
1009
+ h("p", null, [option.venue_location, option.description].filter(Boolean).join(" \xB7 ") || "Detail pilihan belum ditambahkan."),
1010
+ vote ? h("span", { className: "kumpul-plan-votes" }, `${vote.votes} suara \xB7 ${vote.percentage}%`) : null
1011
+ );
1012
+ })
873
1013
  ),
874
- h('p', {
875
- className: 'kumpul-plan-empty-options',
876
- 'data-plan-opened-options-empty': '',
877
- hidden: openedOptions.length > 0,
878
- }, 'Belum ada pilihan yang dibuka untuk peserta.'),
879
- ),
880
- ),
881
- h('aside', { className: 'kumpul-detail-card kumpul-plan-aside' },
882
- h('h2', null, 'Status rencana'),
883
- h('span', { className: 'kumpul-transaction-status kumpul-transaction-status-info' }, workflowStatus),
884
- h('p', null, 'Tahap kerja · ', h('span', { 'data-plan-aside-step': '' }, currentStep)),
885
- h('p', null, 'Rencana gathering dikelola terpisah dari keranjang. Pembayaran peserta hanya tersedia setelah tahap konfirmasi melalui host Bagdja.'),
886
- order.id
887
- ? h('p', { className: 'kumpul-plan-order-ref' }, `Referensi pesanan · ${order.id}`)
888
- : null,
889
- h('a', { className: 'kumpul-plan-account-link', href: tenantPath(props, '/cart') }, 'Kembali ke Keranjang'),
1014
+ h("p", {
1015
+ className: "kumpul-plan-empty-options",
1016
+ "data-plan-opened-options-empty": "",
1017
+ hidden: openedOptions.length > 0
1018
+ }, "Belum ada pilihan yang dibuka untuk peserta.")
1019
+ )
890
1020
  ),
891
- ),
1021
+ h(
1022
+ "aside",
1023
+ { className: "kumpul-detail-card kumpul-plan-aside" },
1024
+ h("h2", null, "Status rencana"),
1025
+ h("span", { className: "kumpul-transaction-status kumpul-transaction-status-info" }, workflowStatus),
1026
+ h("p", null, "Tahap kerja \xB7 ", h("span", { "data-plan-aside-step": "" }, currentStep)),
1027
+ h("p", null, "Rencana gathering dikelola terpisah dari keranjang. Pembayaran peserta hanya tersedia setelah tahap konfirmasi melalui host Bagdja."),
1028
+ order.id ? h("p", { className: "kumpul-plan-order-ref" }, `Referensi pesanan \xB7 ${order.id}`) : null,
1029
+ h("a", { className: "kumpul-plan-account-link", href: tenantPath(props, "/cart") }, "Kembali ke Keranjang")
1030
+ )
1031
+ )
892
1032
  );
893
1033
  }
894
-
895
1034
  function BillingSection({ props }) {
896
1035
  const previewInvoices = props.isPreview === true ? list(props.previewInvoices) : [];
897
- const outstandingCount = previewInvoices.filter((invoice) => billingStatus(invoice) === 'issued').length;
1036
+ const outstandingCount = previewInvoices.filter((invoice) => billingStatus(invoice) === "issued").length;
898
1037
  const counts = Object.fromEntries(billingFilters.map(([key]) => [
899
1038
  key,
900
- key === 'all' ? previewInvoices.length : previewInvoices.filter((invoice) => billingStatus(invoice) === key).length,
1039
+ key === "all" ? previewInvoices.length : previewInvoices.filter((invoice) => billingStatus(invoice) === key).length
901
1040
  ]));
902
-
903
- return h('section', { className: 'kumpul-billing', 'data-billing-page': '' },
904
- h('header', { className: 'kumpul-billing-heading' },
905
- h('div', null,
906
- h('p', { className: 'kumpul-eyebrow' }, 'Akun Anda'),
907
- h('h1', null, 'Tagihan Saya'),
908
- h('p', { className: 'kumpul-billing-description' }, 'Semua termin dan tagihan gathering Anda, tersusun dalam satu halaman.'),
1041
+ return h(
1042
+ "section",
1043
+ { className: "kumpul-billing", "data-billing-page": "" },
1044
+ h(
1045
+ "header",
1046
+ { className: "kumpul-billing-heading" },
1047
+ h(
1048
+ "div",
1049
+ null,
1050
+ h("p", { className: "kumpul-eyebrow" }, "Akun Anda"),
1051
+ h("h1", null, "Tagihan Saya"),
1052
+ h("p", { className: "kumpul-billing-description" }, "Semua termin dan tagihan gathering Anda, tersusun dalam satu halaman.")
909
1053
  ),
910
- h('div', { className: 'kumpul-billing-summary', 'aria-label': 'Ringkasan tagihan' },
911
- h('div', { className: 'kumpul-billing-summary-card' },
912
- h('strong', null, String(counts.all)),
913
- h('span', null, 'total tagihan'),
1054
+ h(
1055
+ "div",
1056
+ { className: "kumpul-billing-summary", "aria-label": "Ringkasan tagihan" },
1057
+ h(
1058
+ "div",
1059
+ { className: "kumpul-billing-summary-card" },
1060
+ h("strong", null, String(counts.all)),
1061
+ h("span", null, "total tagihan")
914
1062
  ),
915
- h('div', { className: 'kumpul-billing-summary-card' },
916
- h('strong', null, String(outstandingCount)),
917
- h('span', null, 'perlu dibayar'),
918
- ),
919
- ),
920
- ),
921
- props.isPreview === true
922
- ? h('p', { className: 'kumpul-billing-preview-note', role: 'note' },
923
- 'Preview desainer · data contoh saja. Pembayaran dan detail tagihan dikelola oleh host Bagdja.',
1063
+ h(
1064
+ "div",
1065
+ { className: "kumpul-billing-summary-card" },
1066
+ h("strong", null, String(outstandingCount)),
1067
+ h("span", null, "perlu dibayar")
1068
+ )
924
1069
  )
925
- : null,
926
- h('div', { className: 'kumpul-billing-filters', role: 'group', 'aria-label': 'Filter status tagihan' },
927
- ...billingFilters.map(([key, label]) => h('button', {
928
- type: 'button',
929
- 'aria-pressed': key === 'all' ? 'true' : 'false',
930
- 'data-billing-filter': key,
931
- key,
932
- },
933
- label,
934
- h('span', null, String(counts[key])),
935
- )),
936
1070
  ),
937
- h('section', { className: 'kumpul-billing-results' },
938
- h('div', { className: 'kumpul-billing-results-heading' },
939
- h('h2', null, 'Daftar tagihan'),
940
- h('span', { 'data-billing-count': '' }, `${counts.all} tagihan`),
1071
+ props.isPreview === true ? h(
1072
+ "p",
1073
+ { className: "kumpul-billing-preview-note", role: "note" },
1074
+ "Preview desainer \xB7 data contoh saja. Pembayaran dan detail tagihan dikelola oleh host Bagdja."
1075
+ ) : null,
1076
+ h(
1077
+ "div",
1078
+ { className: "kumpul-billing-filters", role: "group", "aria-label": "Filter status tagihan" },
1079
+ ...billingFilters.map(([key, label]) => h(
1080
+ "button",
1081
+ {
1082
+ type: "button",
1083
+ "aria-pressed": key === "all" ? "true" : "false",
1084
+ "data-billing-filter": key,
1085
+ key
1086
+ },
1087
+ label,
1088
+ h("span", null, String(counts[key]))
1089
+ ))
1090
+ ),
1091
+ h(
1092
+ "section",
1093
+ { className: "kumpul-billing-results" },
1094
+ h(
1095
+ "div",
1096
+ { className: "kumpul-billing-results-heading" },
1097
+ h("h2", null, "Daftar tagihan"),
1098
+ h("span", { "data-billing-count": "" }, `${counts.all} tagihan`)
941
1099
  ),
942
- h('div', { className: 'kumpul-billing-list', 'data-billing-list': '' },
1100
+ h(
1101
+ "div",
1102
+ { className: "kumpul-billing-list", "data-billing-list": "" },
943
1103
  ...previewInvoices.map((invoice, index) => {
944
1104
  const status = billingStatus(invoice);
945
1105
  const statusInfo = billingStatuses[status];
946
- const isGathering = invoice.kind === 'gathering';
947
- const title = text(isGathering ? invoice.gathering_title : invoice.productName, 'Tagihan gathering');
948
- const reference = isGathering
949
- ? `${text(invoice.invoice_id, 'Invoice')} · ${text(invoice.attendee_name, 'Peserta')}`
950
- : `${text(invoice.label, 'Termin pembayaran')} · ${text(invoice.anchorStepName, text(invoice.orderId, 'Pesanan'))}`;
1106
+ const isGathering = invoice.kind === "gathering";
1107
+ const title = text(isGathering ? invoice.gathering_title : invoice.productName, "Tagihan gathering");
1108
+ const reference = isGathering ? `${text(invoice.invoice_id, "Invoice")} \xB7 ${text(invoice.attendee_name, "Peserta")}` : `${text(invoice.label, "Termin pembayaran")} \xB7 ${text(invoice.anchorStepName, text(invoice.orderId, "Pesanan"))}`;
951
1109
  const dueDate = invoice.payment_deadline || invoice.dueDate;
952
- return h('article', {
953
- className: `kumpul-billing-card kumpul-billing-card-${status}`,
954
- 'data-billing-item': '',
955
- 'data-billing-status': status,
956
- key: invoice.id || index,
957
- },
958
- h('div', { className: 'kumpul-billing-card-top' },
959
- h('div', null,
960
- h('span', { className: 'kumpul-billing-kind' }, isGathering ? 'Tagihan gathering' : `Termin ${invoice.sequence || ''}`.trim()),
961
- h('h3', null, title),
962
- h('p', null, reference),
963
- ),
964
- h('span', { className: `kumpul-billing-status kumpul-billing-status-${statusInfo.tone}` }, statusInfo.label),
965
- ),
966
- h('div', { className: 'kumpul-billing-card-bottom' },
967
- h('div', null,
968
- h('strong', null, formatCurrency(invoice.amount)),
969
- dueDate ? h('p', null, `Batas pembayaran · ${formatCalendarDate(dueDate)}`) : null,
1110
+ return h(
1111
+ "article",
1112
+ {
1113
+ className: `kumpul-billing-card kumpul-billing-card-${status}`,
1114
+ "data-billing-item": "",
1115
+ "data-billing-status": status,
1116
+ key: invoice.id || index
1117
+ },
1118
+ h(
1119
+ "div",
1120
+ { className: "kumpul-billing-card-top" },
1121
+ h(
1122
+ "div",
1123
+ null,
1124
+ h("span", { className: "kumpul-billing-kind" }, isGathering ? "Tagihan gathering" : `Termin ${invoice.sequence || ""}`.trim()),
1125
+ h("h3", null, title),
1126
+ h("p", null, reference)
1127
+ ),
1128
+ h("span", { className: `kumpul-billing-status kumpul-billing-status-${statusInfo.tone}` }, statusInfo.label)
970
1129
  ),
971
- status === 'issued'
972
- ? h('button', { type: 'button', className: 'kumpul-billing-action', disabled: true }, isGathering ? 'Lihat detail tagihan' : 'Bayar')
973
- : null,
974
- ),
1130
+ h(
1131
+ "div",
1132
+ { className: "kumpul-billing-card-bottom" },
1133
+ h(
1134
+ "div",
1135
+ null,
1136
+ h("strong", null, formatCurrency(invoice.amount)),
1137
+ dueDate ? h("p", null, `Batas pembayaran \xB7 ${formatCalendarDate(dueDate)}`) : null
1138
+ ),
1139
+ status === "issued" ? h("button", { type: "button", className: "kumpul-billing-action", disabled: true }, isGathering ? "Lihat detail tagihan" : "Bayar") : null
1140
+ )
975
1141
  );
976
1142
  }),
977
- h('p', {
978
- className: 'kumpul-billing-empty',
1143
+ h("p", {
1144
+ className: "kumpul-billing-empty",
979
1145
  hidden: previewInvoices.length > 0,
980
- 'data-billing-empty': '',
981
- }, props.isPreview === true
982
- ? 'Belum ada tagihan pada preview ini.'
983
- : 'Data tagihan dan status pembayaran dikelola oleh host Bagdja.'),
984
- h('p', {
985
- className: 'kumpul-billing-empty',
1146
+ "data-billing-empty": ""
1147
+ }, props.isPreview === true ? "Belum ada tagihan pada preview ini." : "Data tagihan dan status pembayaran dikelola oleh host Bagdja."),
1148
+ h("p", {
1149
+ className: "kumpul-billing-empty",
986
1150
  hidden: true,
987
- 'data-billing-filter-empty': '',
988
- }, 'Tidak ada tagihan dengan status ini.'),
989
- ),
990
- ),
1151
+ "data-billing-filter-empty": ""
1152
+ }, "Tidak ada tagihan dengan status ini.")
1153
+ )
1154
+ )
991
1155
  );
992
1156
  }
993
-
994
1157
  function formatGatheringDate(value) {
995
- if (typeof value !== 'string' || !value.trim()) return '';
1158
+ if (typeof value !== "string" || !value.trim()) return "";
996
1159
  const date = new Date(value);
997
- if (Number.isNaN(date.getTime())) return '';
998
- return new Intl.DateTimeFormat('id-ID', {
999
- day: '2-digit',
1000
- month: 'short',
1001
- year: 'numeric',
1002
- timeZone: 'UTC',
1160
+ if (Number.isNaN(date.getTime())) return "";
1161
+ return new Intl.DateTimeFormat("id-ID", {
1162
+ day: "2-digit",
1163
+ month: "short",
1164
+ year: "numeric",
1165
+ timeZone: "UTC"
1003
1166
  }).format(date);
1004
1167
  }
1005
-
1006
1168
  function tenantPath(props, path) {
1007
- const base = text(props.websiteSlug).replace(/\/+$/, '');
1008
- const suffix = path.startsWith('/') ? path : `/${path}`;
1009
- return `${base}${suffix}` || '/';
1169
+ const base = text(props.websiteSlug).replace(/\/+$/, "");
1170
+ const suffix = path.startsWith("/") ? path : `/${path}`;
1171
+ return `${base}${suffix}` || "/";
1010
1172
  }
1011
-
1012
1173
  function themeColors(props) {
1013
1174
  const templateColors = props.templateTheme?.colors || {};
1014
1175
  const websiteColors = props.websiteTheme?.colors || {};
1015
1176
  const colors = {};
1016
-
1017
1177
  for (const [key, fallback] of Object.entries(defaultColors)) {
1018
1178
  const candidate = websiteColors[key] ?? templateColors[key];
1019
- colors[key] = typeof candidate === 'string' && /^#[\da-f]{3,8}$/i.test(candidate)
1020
- ? candidate
1021
- : fallback;
1179
+ colors[key] = typeof candidate === "string" && /^#[\da-f]{3,8}$/i.test(candidate) ? candidate : fallback;
1022
1180
  }
1023
1181
  return colors;
1024
1182
  }
1025
-
1026
1183
  function Icon({ name }) {
1027
1184
  const paths = {
1028
- arrow: h('path', { d: 'M5 12h14m-6-6 6 6-6 6' }),
1029
- calendar: h('path', { d: 'M8 3v3m8-3v3M4 9h16M5 5h14a1 1 0 0 1 1 1v13H4V6a1 1 0 0 1 1-1Z' }),
1030
- cart: h('path', { d: 'M3 4h2l2.2 11h10.9L21 8H6M9 19h.01M17 19h.01' }),
1031
- chat: h('path', { d: 'M21 11.5a8.4 8.4 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.4 8.4 0 0 1-3.8-.9L3 21l1.9-5.7a8.4 8.4 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.4 8.4 0 0 1 3.8-.9h.5a8.5 8.5 0 0 1 8 8v.5Z' }),
1032
- orders: h('path', { d: 'M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01' }),
1033
- profile: h('path', { d: 'M20 21a8 8 0 0 0-16 0m8-10a4 4 0 1 0 0-8 4 4 0 0 0 0 8Z' }),
1034
- receipt: h('path', { d: 'M6 3h12v18l-3-2-3 2-3-2-3 2V3Zm3 5h6m-6 4h6' }),
1035
- search: h('path', { d: 'm20 20-4.3-4.3M18 10.5a7.5 7.5 0 1 1-15 0 7.5 7.5 0 0 1 15 0Z' }),
1036
- ticket: h('path', { d: 'M4 7V5h16v2a2 2 0 0 0 0 4v2a2 2 0 0 0 0 4v2H4v-2a2 2 0 0 0 0-4v-2a2 2 0 0 0 0-4Z M12 7v2m0 2v2m0 2v2' }),
1185
+ arrow: h("path", { d: "M5 12h14m-6-6 6 6-6 6" }),
1186
+ calendar: h("path", { d: "M8 3v3m8-3v3M4 9h16M5 5h14a1 1 0 0 1 1 1v13H4V6a1 1 0 0 1 1-1Z" }),
1187
+ cart: h("path", { d: "M3 4h2l2.2 11h10.9L21 8H6M9 19h.01M17 19h.01" }),
1188
+ chat: h("path", { d: "M21 11.5a8.4 8.4 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.4 8.4 0 0 1-3.8-.9L3 21l1.9-5.7a8.4 8.4 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.4 8.4 0 0 1 3.8-.9h.5a8.5 8.5 0 0 1 8 8v.5Z" }),
1189
+ orders: h("path", { d: "M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01" }),
1190
+ profile: h("path", { d: "M20 21a8 8 0 0 0-16 0m8-10a4 4 0 1 0 0-8 4 4 0 0 0 0 8Z" }),
1191
+ receipt: h("path", { d: "M6 3h12v18l-3-2-3 2-3-2-3 2V3Zm3 5h6m-6 4h6" }),
1192
+ search: h("path", { d: "m20 20-4.3-4.3M18 10.5a7.5 7.5 0 1 1-15 0 7.5 7.5 0 0 1 15 0Z" }),
1193
+ ticket: h("path", { d: "M4 7V5h16v2a2 2 0 0 0 0 4v2a2 2 0 0 0 0 4v2H4v-2a2 2 0 0 0 0-4v-2a2 2 0 0 0 0-4Z M12 7v2m0 2v2m0 2v2" })
1037
1194
  };
1038
-
1039
- return h('svg', {
1040
- 'aria-hidden': 'true',
1041
- viewBox: '0 0 24 24',
1042
- fill: 'none',
1043
- stroke: 'currentColor',
1195
+ return h("svg", {
1196
+ "aria-hidden": "true",
1197
+ viewBox: "0 0 24 24",
1198
+ fill: "none",
1199
+ stroke: "currentColor",
1044
1200
  strokeWidth: 1.8,
1045
- strokeLinecap: 'round',
1046
- strokeLinejoin: 'round',
1047
- className: 'kumpul-icon',
1201
+ strokeLinecap: "round",
1202
+ strokeLinejoin: "round",
1203
+ className: "kumpul-icon"
1048
1204
  }, paths[name] || paths.arrow);
1049
1205
  }
1050
-
1051
1206
  function Section(props, type) {
1052
1207
  return list(props.sections).find((section) => section?.type === type) || null;
1053
1208
  }
1054
-
1055
1209
  function gatheringProducts(props) {
1056
- const section = Section(props, 'products_grid');
1057
- const filterType = text(section?.content?.filter_type, 'gathering');
1210
+ const section = Section(props, "products_grid");
1211
+ const filterType = text(section?.content?.filter_type, "gathering");
1058
1212
  return list(props.products).filter((product) => !product.type || product.type === filterType);
1059
1213
  }
1060
-
1061
- function SectionHeading({ eyebrow, title, description, titleTag = 'h2' }) {
1062
- return h('div', { className: 'kumpul-section-heading' },
1063
- eyebrow ? h('p', { className: 'kumpul-eyebrow' }, eyebrow) : null,
1064
- title ? h(titleTag, { className: 'kumpul-section-title' }, title) : null,
1065
- description ? h('p', { className: 'kumpul-section-description' }, description) : null,
1214
+ function SectionHeading({ eyebrow, title, description, titleTag = "h2" }) {
1215
+ return h(
1216
+ "div",
1217
+ { className: "kumpul-section-heading" },
1218
+ eyebrow ? h("p", { className: "kumpul-eyebrow" }, eyebrow) : null,
1219
+ title ? h(titleTag, { className: "kumpul-section-title" }, title) : null,
1220
+ description ? h("p", { className: "kumpul-section-description" }, description) : null
1066
1221
  );
1067
1222
  }
1068
-
1069
1223
  function Header(props) {
1070
1224
  const profile = props.profile || {};
1071
1225
  const auth = props.auth || {};
1072
- const pages = list(props.pages).filter((page) => page.placement !== 'footer').slice(0, 5);
1226
+ const pages = list(props.pages).filter((page) => page.placement !== "footer").slice(0, 5);
1073
1227
  const activePage = pages.find((page) => {
1074
- const identity = `${page.slug} ${page.title}`.toLocaleLowerCase('id-ID');
1075
- if (props.activePageSlug === 'gathering') return /gather|event|katalog/.test(identity);
1076
- if (props.activePageSlug === 'about') return /about|tentang/.test(identity);
1077
- if (props.activePageSlug === 'how-it-works') return /cara|how|flow/.test(identity);
1228
+ const identity = `${page.slug} ${page.title}`.toLocaleLowerCase("id-ID");
1229
+ if (props.activePageSlug === "gathering") return /gather|event|katalog/.test(identity);
1230
+ if (props.activePageSlug === "about") return /about|tentang/.test(identity);
1231
+ if (props.activePageSlug === "how-it-works") return /cara|how|flow/.test(identity);
1078
1232
  return false;
1079
1233
  });
1080
1234
  const accountLinks = [
1081
- ['Keranjang', auth.cartHref, 'cart'],
1082
- ['Tagihan', auth.tagihanHref, 'receipt'],
1083
- ['Transaksi', auth.ordersHref, 'orders'],
1084
- ['Kalender', auth.calendarHref, 'calendar'],
1085
- ['Inbox', auth.chatHref, 'chat'],
1086
- ['Profil', auth.profileHref, 'profile'],
1087
- ].filter(([, href]) => typeof href === 'string' && href.length > 0);
1088
-
1089
- return h('header', { className: 'kumpul-header' },
1090
- h('div', { className: 'kumpul-header-main' },
1091
- h('a', { className: 'kumpul-brand', href: tenantPath(props, '/') },
1092
- profile.logoUrl
1093
- ? h('img', { className: 'kumpul-logo', src: profile.logoUrl, alt: text(profile.name, 'Logo') })
1094
- : h('span', { className: 'kumpul-logo-mark', 'aria-hidden': 'true' }, text(profile.name, 'K').slice(0, 2).toLowerCase()),
1095
- h('span', { className: 'kumpul-brand-copy' },
1096
- h('strong', null, text(profile.name, 'Kumpul')),
1097
- h('small', null, text(profile.tagline, 'Deep Teal • Family Trust')),
1098
- ),
1235
+ ["Keranjang", auth.cartHref, "cart"],
1236
+ ["Tagihan", auth.tagihanHref, "receipt"],
1237
+ ["Transaksi", auth.ordersHref, "orders"],
1238
+ ["Kalender", auth.calendarHref, "calendar"],
1239
+ ["Inbox", auth.chatHref, "chat"],
1240
+ ["Profil", auth.profileHref, "profile"]
1241
+ ].filter(([, href]) => typeof href === "string" && href.length > 0);
1242
+ return h(
1243
+ "header",
1244
+ { className: "kumpul-header" },
1245
+ h(
1246
+ "div",
1247
+ { className: "kumpul-header-main" },
1248
+ h(
1249
+ "a",
1250
+ { className: "kumpul-brand", href: tenantPath(props, "/") },
1251
+ profile.logoUrl ? h("img", { className: "kumpul-logo", src: profile.logoUrl, alt: text(profile.name, "Logo") }) : h("span", { className: "kumpul-logo-mark", "aria-hidden": "true" }, text(profile.name, "K").slice(0, 2).toLowerCase()),
1252
+ h(
1253
+ "span",
1254
+ { className: "kumpul-brand-copy" },
1255
+ h("strong", null, text(profile.name, "Kumpul")),
1256
+ h("small", null, text(profile.tagline, "Deep Teal \u2022 Family Trust"))
1257
+ )
1099
1258
  ),
1100
- h('nav', { className: 'kumpul-utilities', 'aria-label': 'Menu akun' },
1101
- ...accountLinks.map(([label, href, icon]) =>
1102
- h('a', {
1259
+ h(
1260
+ "nav",
1261
+ { className: "kumpul-utilities", "aria-label": "Menu akun" },
1262
+ ...accountLinks.map(
1263
+ ([label, href, icon]) => h("a", {
1103
1264
  href,
1104
1265
  key: label,
1105
- 'aria-label': label,
1266
+ "aria-label": label,
1106
1267
  title: label,
1107
- 'aria-current': (
1108
- props.activePageSlug === 'calendar' && label === 'Kalender'
1109
- || (props.activePageSlug === 'tagihan' || props.activePageSlug === 'invoice-detail') && label === 'Tagihan'
1110
- || (props.activePageSlug === 'orders' || props.activePageSlug === 'transaction-detail') && label === 'Transaksi'
1111
- || (props.activePageSlug === 'cart' || props.activePageSlug === 'plan-detail') && label === 'Keranjang'
1112
- ) ? 'page' : undefined,
1113
- }, h(Icon, { name: icon }), h('span', null, label)),
1268
+ "aria-current": props.activePageSlug === "calendar" && label === "Kalender" || (props.activePageSlug === "tagihan" || props.activePageSlug === "invoice-detail") && label === "Tagihan" || (props.activePageSlug === "orders" || props.activePageSlug === "transaction-detail") && label === "Transaksi" || (props.activePageSlug === "cart" || props.activePageSlug === "plan-detail") && label === "Keranjang" ? "page" : void 0
1269
+ }, h(Icon, { name: icon }), h("span", null, label))
1114
1270
  ),
1115
- !auth.isLoggedIn && auth.loginHref
1116
- ? h('a', { className: 'kumpul-login', href: auth.loginHref }, 'Masuk')
1117
- : null,
1118
- ),
1271
+ !auth.isLoggedIn && auth.loginHref ? h("a", { className: "kumpul-login", href: auth.loginHref }, "Masuk") : null
1272
+ )
1119
1273
  ),
1120
- pages.length
1121
- ? h('nav', { className: 'kumpul-page-nav', 'aria-label': 'Navigasi halaman' },
1122
- ...pages.map((page) =>
1123
- h('a', {
1124
- href: tenantPath(props, page.isHome ? '/' : `/${encodeURIComponent(page.slug)}`),
1125
- key: page.slug,
1126
- 'aria-current': activePage
1127
- ? page.slug === activePage.slug ? 'page' : undefined
1128
- : props.activePageSlug ? undefined : page.isHome ? 'page' : undefined,
1129
- }, page.title),
1130
- ),
1274
+ pages.length ? h(
1275
+ "nav",
1276
+ { className: "kumpul-page-nav", "aria-label": "Navigasi halaman" },
1277
+ ...pages.map(
1278
+ (page) => h("a", {
1279
+ href: tenantPath(props, page.isHome ? "/" : `/${encodeURIComponent(page.slug)}`),
1280
+ key: page.slug,
1281
+ "aria-current": activePage ? page.slug === activePage.slug ? "page" : void 0 : props.activePageSlug ? void 0 : page.isHome ? "page" : void 0
1282
+ }, page.title)
1131
1283
  )
1132
- : null,
1284
+ ) : null
1133
1285
  );
1134
1286
  }
1135
-
1136
1287
  function Hero(props) {
1137
1288
  const section = props.section;
1138
1289
  const content = section?.content || {};
@@ -1142,277 +1293,304 @@ function Hero(props) {
1142
1293
  const pages = list(props.pages);
1143
1294
  const gatheringPage = pages.find((page) => /gather|event|katalog/i.test(`${page.slug} ${page.title}`));
1144
1295
  const flowPage = pages.find((page) => /cara|how|flow/i.test(`${page.slug} ${page.title}`));
1145
- const detailHref = featured?.slug
1146
- ? tenantPath(props, `/products/${encodeURIComponent(featured.slug)}`)
1147
- : tenantPath(props, gatheringPage ? `/${encodeURIComponent(gatheringPage.slug)}` : '/gathering');
1148
- const flowHref = tenantPath(props, flowPage ? `/${encodeURIComponent(flowPage.slug)}` : '/cara-kerja');
1149
-
1150
- return h('section', { className: 'kumpul-hero' },
1151
- h('div', { className: 'kumpul-hero-copy' },
1152
- h('span', { className: 'kumpul-pill kumpul-community-pill' },
1153
- h('span', { className: 'kumpul-status-dot' }),
1154
- text(content.subtitle, 'Komunitas aktif • saatnya berkumpul'),
1296
+ const detailHref = featured?.slug ? tenantPath(props, `/products/${encodeURIComponent(featured.slug)}`) : tenantPath(props, gatheringPage ? `/${encodeURIComponent(gatheringPage.slug)}` : "/gathering");
1297
+ const flowHref = tenantPath(props, flowPage ? `/${encodeURIComponent(flowPage.slug)}` : "/cara-kerja");
1298
+ return h(
1299
+ "section",
1300
+ { className: "kumpul-hero" },
1301
+ h(
1302
+ "div",
1303
+ { className: "kumpul-hero-copy" },
1304
+ h(
1305
+ "span",
1306
+ { className: "kumpul-pill kumpul-community-pill" },
1307
+ h("span", { className: "kumpul-status-dot" }),
1308
+ text(content.subtitle, "Komunitas aktif \u2022 saatnya berkumpul")
1155
1309
  ),
1156
- h('h1', null, text(content.headline, 'Kumpul bareng jadi lebih mudah.')),
1157
- h('p', { className: 'kumpul-hero-description' },
1158
- text(content.lede, text(profile.tagline, 'Platform gathering untuk keluarga, workshop, dan komunitas. Dari perencanaan hingga hari acara, semua dalam satu alur.')),
1310
+ h("h1", null, text(content.headline, "Kumpul bareng jadi lebih mudah.")),
1311
+ h(
1312
+ "p",
1313
+ { className: "kumpul-hero-description" },
1314
+ text(content.lede, text(profile.tagline, "Platform gathering untuk keluarga, workshop, dan komunitas. Dari perencanaan hingga hari acara, semua dalam satu alur."))
1159
1315
  ),
1160
- h('div', { className: 'kumpul-hero-actions' },
1161
- h('a', { className: 'kumpul-button kumpul-button-primary', href: detailHref },
1162
- 'Lihat Gathering Terdekat', h(Icon, { name: 'arrow' }),
1316
+ h(
1317
+ "div",
1318
+ { className: "kumpul-hero-actions" },
1319
+ h(
1320
+ "a",
1321
+ { className: "kumpul-button kumpul-button-primary", href: detailHref },
1322
+ "Lihat Gathering Terdekat",
1323
+ h(Icon, { name: "arrow" })
1163
1324
  ),
1164
- h('a', { className: 'kumpul-button kumpul-button-secondary', href: flowHref },
1165
- 'Cara kerja 90 detik',
1166
- ),
1167
- ),
1168
- h('div', { className: 'kumpul-stats' },
1169
- ...list(content.stats).slice(0, 3).map((stat, index) => h('div', { className: 'kumpul-stat', key: stat.label || index },
1170
- h('strong', null, text(stat.value)),
1171
- h('span', null, text(stat.label)),
1172
- )),
1325
+ h(
1326
+ "a",
1327
+ { className: "kumpul-button kumpul-button-secondary", href: flowHref },
1328
+ "Cara kerja 90 detik"
1329
+ )
1173
1330
  ),
1331
+ h(
1332
+ "div",
1333
+ { className: "kumpul-stats" },
1334
+ ...list(content.stats).slice(0, 3).map((stat, index) => h(
1335
+ "div",
1336
+ { className: "kumpul-stat", key: stat.label || index },
1337
+ h("strong", null, text(stat.value)),
1338
+ h("span", null, text(stat.label))
1339
+ ))
1340
+ )
1174
1341
  ),
1175
- h('div', { className: 'kumpul-feature-card' },
1176
- h('div', { className: 'kumpul-feature-location' },
1177
- h(Icon, { name: 'calendar' }),
1178
- h('span', null, 'Gathering unggulan'),
1342
+ h(
1343
+ "div",
1344
+ { className: "kumpul-feature-card" },
1345
+ h(
1346
+ "div",
1347
+ { className: "kumpul-feature-location" },
1348
+ h(Icon, { name: "calendar" }),
1349
+ h("span", null, "Gathering unggulan")
1179
1350
  ),
1180
- h('div', { className: 'kumpul-feature-art', 'aria-hidden': 'true' },
1181
- h('span', null, 'K'),
1182
- h('i', null),
1183
- h('i', null),
1351
+ h(
1352
+ "div",
1353
+ { className: "kumpul-feature-art", "aria-hidden": "true" },
1354
+ h("span", null, "K"),
1355
+ h("i", null),
1356
+ h("i", null)
1184
1357
  ),
1185
- h('a', { className: 'kumpul-feature-note', href: detailHref },
1186
- h('span', { className: 'kumpul-avatar' }, 'K'),
1187
- h('span', null,
1188
- h('strong', null, text(featured?.name, 'Temukan gathering untukmu')),
1189
- h('small', null, text(featured?.category, 'Bersama keluarga dan komunitas')),
1358
+ h(
1359
+ "a",
1360
+ { className: "kumpul-feature-note", href: detailHref },
1361
+ h("span", { className: "kumpul-avatar" }, "K"),
1362
+ h(
1363
+ "span",
1364
+ null,
1365
+ h("strong", null, text(featured?.name, "Temukan gathering untukmu")),
1366
+ h("small", null, text(featured?.category, "Bersama keluarga dan komunitas"))
1190
1367
  ),
1191
- h('span', { className: 'kumpul-check', 'aria-hidden': 'true' }, '✓'),
1192
- ),
1193
- ),
1368
+ h("span", { className: "kumpul-check", "aria-hidden": "true" }, "\u2713")
1369
+ )
1370
+ )
1194
1371
  );
1195
1372
  }
1196
-
1197
1373
  function FeaturesSection(section) {
1198
1374
  const content = section?.content || {};
1199
1375
  const steps = list(content.features).slice(0, 6).map((feature, index) => [
1200
1376
  text(feature.icon, String(index + 1)),
1201
1377
  text(feature.title, `Tahap ${index + 1}`),
1202
- text(feature.desc),
1378
+ text(feature.desc)
1203
1379
  ]);
1204
-
1205
- return h('section', { className: 'kumpul-section kumpul-flow', id: section?.id || 'cara-kerja' },
1380
+ return h(
1381
+ "section",
1382
+ { className: "kumpul-section kumpul-flow", id: section?.id || "cara-kerja" },
1206
1383
  h(SectionHeading, {
1207
- eyebrow: text(content.eyebrow, 'Alur Kumpul'),
1208
- title: text(content.title, 'Dari ide sampai absensi, rapi.'),
1209
- description: text(content.subtitle, 'Perjalanan acara yang jelas, dari rencana pertama sampai peserta pulang dengan cerita.'),
1384
+ eyebrow: text(content.eyebrow, "Alur Kumpul"),
1385
+ title: text(content.title, "Dari ide sampai absensi, rapi."),
1386
+ description: text(content.subtitle, "Perjalanan acara yang jelas, dari rencana pertama sampai peserta pulang dengan cerita.")
1210
1387
  }),
1211
- h('ol', { className: 'kumpul-flow-list' },
1212
- ...steps.map(([number, title, description], index) =>
1213
- h('li', { className: 'kumpul-flow-step', key: number },
1214
- h('span', { className: 'kumpul-flow-number' }, number || String(index + 1)),
1215
- h('strong', null, title),
1216
- h('span', null, description),
1217
- ),
1388
+ h(
1389
+ "ol",
1390
+ { className: "kumpul-flow-list" },
1391
+ ...steps.map(
1392
+ ([number, title, description], index) => h(
1393
+ "li",
1394
+ { className: "kumpul-flow-step", key: number },
1395
+ h("span", { className: "kumpul-flow-number" }, number || String(index + 1)),
1396
+ h("strong", null, title),
1397
+ h("span", null, description)
1398
+ )
1218
1399
  ),
1219
- steps.length === 0
1220
- ? h('li', { className: 'kumpul-flow-empty' }, 'Alur gathering akan ditampilkan di sini.')
1221
- : null,
1222
- ),
1400
+ steps.length === 0 ? h("li", { className: "kumpul-flow-empty" }, "Alur gathering akan ditampilkan di sini.") : null
1401
+ )
1223
1402
  );
1224
1403
  }
1225
-
1226
1404
  function AboutSection(section) {
1227
1405
  const content = section?.content || {};
1228
- const title = text(content.title, 'Kumpul bukan sekadar datang, tapi bertumbuh bareng.');
1406
+ const title = text(content.title, "Kumpul bukan sekadar datang, tapi bertumbuh bareng.");
1229
1407
  const body = text(content.body);
1230
1408
  const image = text(content.image_url);
1231
-
1232
1409
  if (!body && !image) return null;
1233
-
1234
- return h('section', { className: 'kumpul-about-section' },
1235
- image
1236
- ? h('div', { className: 'kumpul-about-image' },
1237
- h('img', { src: image, alt: '', loading: 'lazy' }),
1238
- )
1239
- : h('div', { className: 'kumpul-about-art', 'aria-hidden': 'true' },
1240
- h('span', null, '🌿'),
1241
- h('span', null, '🏕️'),
1242
- ),
1243
- h('div', { className: 'kumpul-about-copy' },
1244
- h('p', { className: 'kumpul-eyebrow' }, text(content.eyebrow, 'Tentang Kumpul')),
1245
- h('h1', null, title),
1246
- body ? h('p', { className: 'kumpul-about-body' }, body) : null,
1410
+ return h(
1411
+ "section",
1412
+ { className: "kumpul-about-section" },
1413
+ image ? h(
1414
+ "div",
1415
+ { className: "kumpul-about-image" },
1416
+ h("img", { src: image, alt: "", loading: "lazy" })
1417
+ ) : h(
1418
+ "div",
1419
+ { className: "kumpul-about-art", "aria-hidden": "true" },
1420
+ h("span", null, "\u{1F33F}"),
1421
+ h("span", null, "\u{1F3D5}\uFE0F")
1247
1422
  ),
1423
+ h(
1424
+ "div",
1425
+ { className: "kumpul-about-copy" },
1426
+ h("p", { className: "kumpul-eyebrow" }, text(content.eyebrow, "Tentang Kumpul")),
1427
+ h("h1", null, title),
1428
+ body ? h("p", { className: "kumpul-about-body" }, body) : null
1429
+ )
1248
1430
  );
1249
1431
  }
1250
-
1251
1432
  function GallerySection(section) {
1252
1433
  const content = section?.content || {};
1253
- const images = list(content.images).filter((image) => image && typeof image === 'object');
1434
+ const images = list(content.images).filter((image) => image && typeof image === "object");
1254
1435
  if (!images.length) return null;
1255
-
1256
- return h('section', { className: 'kumpul-section kumpul-gallery', id: section.id || 'galeri' },
1436
+ return h(
1437
+ "section",
1438
+ { className: "kumpul-section kumpul-gallery", id: section.id || "galeri" },
1257
1439
  h(SectionHeading, {
1258
- eyebrow: text(content.eyebrow, 'Momen kebersamaan'),
1259
- title: text(content.title, 'Galeri Kumpul'),
1440
+ eyebrow: text(content.eyebrow, "Momen kebersamaan"),
1441
+ title: text(content.title, "Galeri Kumpul")
1260
1442
  }),
1261
- h('div', { className: 'kumpul-gallery-grid' },
1262
- ...images.map((image, index) => h('figure', { className: `kumpul-gallery-item kumpul-gallery-${index % 4}`, key: image.url || image.caption || index },
1263
- image.url
1264
- ? h('img', { src: image.url, alt: text(image.alt, text(image.caption, 'Momen Kumpul')), loading: 'lazy' })
1265
- : h('span', { 'aria-hidden': 'true' }, ['⛺', '🎪', '🎨', '🏃', '📚', '🌳'][index % 6]),
1266
- image.caption ? h('figcaption', null, image.caption) : null,
1267
- )),
1268
- ),
1443
+ h(
1444
+ "div",
1445
+ { className: "kumpul-gallery-grid" },
1446
+ ...images.map((image, index) => h(
1447
+ "figure",
1448
+ { className: `kumpul-gallery-item kumpul-gallery-${index % 4}`, key: image.url || image.caption || index },
1449
+ image.url ? h("img", { src: image.url, alt: text(image.alt, text(image.caption, "Momen Kumpul")), loading: "lazy" }) : h("span", { "aria-hidden": "true" }, ["\u26FA", "\u{1F3AA}", "\u{1F3A8}", "\u{1F3C3}", "\u{1F4DA}", "\u{1F333}"][index % 6]),
1450
+ image.caption ? h("figcaption", null, image.caption) : null
1451
+ ))
1452
+ )
1269
1453
  );
1270
1454
  }
1271
-
1272
1455
  function ProcessSection(section) {
1273
1456
  const content = section?.content || {};
1274
- const steps = list(content.flow_steps)
1275
- .filter((step) => step && typeof step === 'object')
1276
- .sort((left, right) => (Number(left.sequence) || 0) - (Number(right.sequence) || 0));
1277
-
1278
- return h('section', { className: 'kumpul-section kumpul-process', id: section.id || 'cara-kerja' },
1457
+ const steps = list(content.flow_steps).filter((step) => step && typeof step === "object").sort((left, right) => (Number(left.sequence) || 0) - (Number(right.sequence) || 0));
1458
+ return h(
1459
+ "section",
1460
+ { className: "kumpul-section kumpul-process", id: section.id || "cara-kerja" },
1279
1461
  h(SectionHeading, {
1280
- eyebrow: text(content.eyebrow, 'Cara Kerja'),
1281
- title: text(content.title, '5 langkah, gathering jalan. Tanpa drama WA.'),
1282
- description: text(content.subtitle, 'Alur yang jelas membantu panitia dan peserta menikmati setiap momen.'),
1283
- titleTag: 'h1',
1462
+ eyebrow: text(content.eyebrow, "Cara Kerja"),
1463
+ title: text(content.title, "5 langkah, gathering jalan. Tanpa drama WA."),
1464
+ description: text(content.subtitle, "Alur yang jelas membantu panitia dan peserta menikmati setiap momen."),
1465
+ titleTag: "h1"
1284
1466
  }),
1285
- steps.length
1286
- ? h('ol', { className: 'kumpul-process-list' },
1287
- ...steps.map((step, index) => h('li', { className: 'kumpul-process-step', key: step.id || step.sequence || index },
1288
- h('span', { className: 'kumpul-flow-number' }, String(step.sequence || index + 1)),
1289
- h('div', null,
1290
- h('h2', null, text(step.status_name, `Tahap ${index + 1}`)),
1291
- step.description ? h('p', null, step.description) : null,
1292
- typeof step.process_day === 'number' && Number.isFinite(step.process_day)
1293
- ? h('small', null, `± ${step.process_day} hari`)
1294
- : null,
1295
- ),
1296
- )),
1297
- )
1298
- : h('div', { className: 'kumpul-empty-state' },
1299
- h('h3', null, 'Alur gathering belum tersedia'),
1300
- h('p', null, 'Langkah acara akan ditampilkan setelah alur dipilih di pengaturan halaman.'),
1301
- ),
1467
+ steps.length ? h(
1468
+ "ol",
1469
+ { className: "kumpul-process-list" },
1470
+ ...steps.map((step, index) => h(
1471
+ "li",
1472
+ { className: "kumpul-process-step", key: step.id || step.sequence || index },
1473
+ h("span", { className: "kumpul-flow-number" }, String(step.sequence || index + 1)),
1474
+ h(
1475
+ "div",
1476
+ null,
1477
+ h("h2", null, text(step.status_name, `Tahap ${index + 1}`)),
1478
+ step.description ? h("p", null, step.description) : null,
1479
+ typeof step.process_day === "number" && Number.isFinite(step.process_day) ? h("small", null, `\xB1 ${step.process_day} hari`) : null
1480
+ )
1481
+ ))
1482
+ ) : h(
1483
+ "div",
1484
+ { className: "kumpul-empty-state" },
1485
+ h("h3", null, "Alur gathering belum tersedia"),
1486
+ h("p", null, "Langkah acara akan ditampilkan setelah alur dipilih di pengaturan halaman.")
1487
+ )
1302
1488
  );
1303
1489
  }
1304
-
1305
1490
  function FaqSection({ props, section }) {
1306
1491
  const content = section?.content || {};
1307
- const category = text(content.filter_category).toLocaleLowerCase('id-ID');
1308
- const faqs = list(props.faqs).filter((faq) => !category || text(faq.category).toLocaleLowerCase('id-ID') === category);
1492
+ const category = text(content.filter_category).toLocaleLowerCase("id-ID");
1493
+ const faqs = list(props.faqs).filter((faq) => !category || text(faq.category).toLocaleLowerCase("id-ID") === category);
1309
1494
  if (!faqs.length) return null;
1310
-
1311
- return h('section', { className: 'kumpul-section kumpul-faq', id: section.id || 'faq' },
1495
+ return h(
1496
+ "section",
1497
+ { className: "kumpul-section kumpul-faq", id: section.id || "faq" },
1312
1498
  h(SectionHeading, {
1313
- eyebrow: text(content.eyebrow, 'Pertanyaan umum'),
1314
- title: text(content.title, 'FAQ Gathering'),
1499
+ eyebrow: text(content.eyebrow, "Pertanyaan umum"),
1500
+ title: text(content.title, "FAQ Gathering")
1315
1501
  }),
1316
- h('div', { className: 'kumpul-faq-list' },
1317
- ...faqs.map((faq, index) => h('details', { className: 'kumpul-faq-item', key: faq.id || faq.question || index },
1318
- h('summary', null, faq.question),
1319
- h('p', null, faq.answer),
1320
- )),
1321
- ),
1502
+ h(
1503
+ "div",
1504
+ { className: "kumpul-faq-list" },
1505
+ ...faqs.map((faq, index) => h(
1506
+ "details",
1507
+ { className: "kumpul-faq-item", key: faq.id || faq.question || index },
1508
+ h("summary", null, faq.question),
1509
+ h("p", null, faq.answer)
1510
+ ))
1511
+ )
1322
1512
  );
1323
1513
  }
1324
-
1325
- const calendarStatuses = [
1326
- ['all', 'Semua'],
1327
- ['planning', 'Perencanaan'],
1328
- ['rsvp', 'RSVP'],
1329
- ['payment', 'Pembayaran'],
1330
- ['confirmed', 'Dikonfirmasi'],
1331
- ['completed', 'Selesai'],
1332
- ['cancelled', 'Dibatalkan'],
1514
+ var calendarStatuses = [
1515
+ ["all", "Semua"],
1516
+ ["planning", "Perencanaan"],
1517
+ ["rsvp", "RSVP"],
1518
+ ["payment", "Pembayaran"],
1519
+ ["confirmed", "Dikonfirmasi"],
1520
+ ["completed", "Selesai"],
1521
+ ["cancelled", "Dibatalkan"]
1333
1522
  ];
1334
-
1335
- const calendarStatusLabels = {
1336
- PREORDER: 'Perencanaan',
1337
- RSVP_OPEN: 'RSVP dibuka',
1338
- PAYMENT_OPEN: 'Menunggu pembayaran',
1339
- CONFIRMED: 'Dikonfirmasi',
1340
- IN_PROGRESS: 'Sedang berlangsung',
1341
- COMPLETED: 'Selesai',
1342
- CANCELLED: 'Dibatalkan',
1523
+ var calendarStatusLabels = {
1524
+ PREORDER: "Perencanaan",
1525
+ RSVP_OPEN: "RSVP dibuka",
1526
+ PAYMENT_OPEN: "Menunggu pembayaran",
1527
+ CONFIRMED: "Dikonfirmasi",
1528
+ IN_PROGRESS: "Sedang berlangsung",
1529
+ COMPLETED: "Selesai",
1530
+ CANCELLED: "Dibatalkan"
1343
1531
  };
1344
-
1345
1532
  function calendarStatusFilter(status) {
1346
- if (status === 'PREORDER') return 'planning';
1347
- if (status === 'RSVP_OPEN') return 'rsvp';
1348
- if (status === 'PAYMENT_OPEN') return 'payment';
1349
- if (status === 'CONFIRMED' || status === 'IN_PROGRESS') return 'confirmed';
1350
- if (status === 'COMPLETED') return 'completed';
1351
- if (status === 'CANCELLED') return 'cancelled';
1352
- return 'other';
1533
+ if (status === "PREORDER") return "planning";
1534
+ if (status === "RSVP_OPEN") return "rsvp";
1535
+ if (status === "PAYMENT_OPEN") return "payment";
1536
+ if (status === "CONFIRMED" || status === "IN_PROGRESS") return "confirmed";
1537
+ if (status === "COMPLETED") return "completed";
1538
+ if (status === "CANCELLED") return "cancelled";
1539
+ return "other";
1353
1540
  }
1354
-
1355
1541
  function calendarDateKey(value) {
1356
- if (typeof value !== 'string') return '';
1542
+ if (typeof value !== "string") return "";
1357
1543
  const match = /^(\d{4})-(\d{2})-(\d{2})/.exec(value);
1358
- if (!match) return '';
1544
+ if (!match) return "";
1359
1545
  const [, year, month, day] = match;
1360
1546
  const date = new Date(Date.UTC(Number(year), Number(month) - 1, Number(day)));
1361
- return date.getUTCFullYear() === Number(year)
1362
- && date.getUTCMonth() === Number(month) - 1
1363
- && date.getUTCDate() === Number(day)
1364
- ? `${year}-${month}-${day}`
1365
- : '';
1547
+ return date.getUTCFullYear() === Number(year) && date.getUTCMonth() === Number(month) - 1 && date.getUTCDate() === Number(day) ? `${year}-${month}-${day}` : "";
1366
1548
  }
1367
-
1368
- function formatCalendarDate(value, options = { day: 'numeric', month: 'long', year: 'numeric' }) {
1549
+ function formatCalendarDate(value, options = { day: "numeric", month: "long", year: "numeric" }) {
1369
1550
  const key = calendarDateKey(value);
1370
- if (!key) return '';
1371
- return new Intl.DateTimeFormat('id-ID', { ...options, timeZone: 'UTC' }).format(new Date(`${key}T12:00:00Z`));
1551
+ if (!key) return "";
1552
+ return new Intl.DateTimeFormat("id-ID", { ...options, timeZone: "UTC" }).format(/* @__PURE__ */ new Date(`${key}T12:00:00Z`));
1372
1553
  }
1373
-
1374
1554
  function formatCalendarTime(value) {
1375
- if (typeof value !== 'string' || !value) return '';
1555
+ if (typeof value !== "string" || !value) return "";
1376
1556
  const date = new Date(value);
1377
- if (Number.isNaN(date.getTime())) return '';
1378
- return new Intl.DateTimeFormat('id-ID', {
1379
- hour: '2-digit',
1380
- minute: '2-digit',
1381
- timeZone: 'Asia/Jakarta',
1557
+ if (Number.isNaN(date.getTime())) return "";
1558
+ return new Intl.DateTimeFormat("id-ID", {
1559
+ hour: "2-digit",
1560
+ minute: "2-digit",
1561
+ timeZone: "Asia/Jakarta"
1382
1562
  }).format(date);
1383
1563
  }
1384
-
1385
1564
  function calendarMonthKey(value, fallback) {
1386
- if (typeof value === 'string' && /^\d{4}-(0[1-9]|1[0-2])$/.test(value)) return value;
1387
- return calendarDateKey(fallback).slice(0, 7) || new Date().toISOString().slice(0, 7);
1565
+ if (typeof value === "string" && /^\d{4}-(0[1-9]|1[0-2])$/.test(value)) return value;
1566
+ return calendarDateKey(fallback).slice(0, 7) || (/* @__PURE__ */ new Date()).toISOString().slice(0, 7);
1388
1567
  }
1389
-
1390
1568
  function calendarMonthCells(monthKey, events, selectedDate) {
1391
- const [year, month] = monthKey.split('-').map(Number);
1569
+ const [year, month] = monthKey.split("-").map(Number);
1392
1570
  const firstDay = new Date(Date.UTC(year, month - 1, 1));
1393
1571
  const offset = (firstDay.getUTCDay() + 6) % 7;
1394
1572
  const start = new Date(Date.UTC(year, month - 1, 1 - offset));
1395
-
1396
1573
  return Array.from({ length: 42 }, (_, index) => {
1397
1574
  const date = new Date(start);
1398
1575
  date.setUTCDate(start.getUTCDate() + index);
1399
1576
  const key = date.toISOString().slice(0, 10);
1400
1577
  const eventCount = events.filter((event) => calendarDateKey(event.event_date) === key).length;
1401
- return h('button', {
1402
- type: 'button',
1403
- className: 'kumpul-calendar-day',
1404
- 'aria-label': `${formatCalendarDate(key, { day: 'numeric', month: 'long' })}${eventCount ? `, ${eventCount} acara` : ''}`,
1405
- 'aria-pressed': key === selectedDate ? 'true' : 'false',
1406
- 'data-calendar-day': key,
1407
- 'data-outside-month': date.getUTCMonth() !== month - 1 ? 'true' : undefined,
1408
- key,
1409
- },
1410
- h('span', null, String(date.getUTCDate())),
1411
- eventCount ? h('small', null, String(eventCount)) : null,
1578
+ return h(
1579
+ "button",
1580
+ {
1581
+ type: "button",
1582
+ className: "kumpul-calendar-day",
1583
+ "aria-label": `${formatCalendarDate(key, { day: "numeric", month: "long" })}${eventCount ? `, ${eventCount} acara` : ""}`,
1584
+ "aria-pressed": key === selectedDate ? "true" : "false",
1585
+ "data-calendar-day": key,
1586
+ "data-outside-month": date.getUTCMonth() !== month - 1 ? "true" : void 0,
1587
+ key
1588
+ },
1589
+ h("span", null, String(date.getUTCDate())),
1590
+ eventCount ? h("small", null, String(eventCount)) : null
1412
1591
  );
1413
1592
  });
1414
1593
  }
1415
-
1416
1594
  function CalendarSection({ props, section }) {
1417
1595
  const content = section?.content || {};
1418
1596
  const isPreview = props.isPreview === true;
@@ -1422,505 +1600,601 @@ function CalendarSection({ props, section }) {
1422
1600
  const events = [
1423
1601
  ...plans.filter((plan) => calendarDateKey(plan.event_date)).map((plan) => ({
1424
1602
  id: plan.id || plan.plan_number,
1425
- type: 'plan',
1426
- typeLabel: 'Rencana',
1427
- title: text(plan.title, 'Rencana gathering'),
1428
- statusLabel: text(plan.status_label, calendarStatusLabels[plan.status] || 'Status belum tersedia'),
1603
+ type: "plan",
1604
+ typeLabel: "Rencana",
1605
+ title: text(plan.title, "Rencana gathering"),
1606
+ statusLabel: text(plan.status_label, calendarStatusLabels[plan.status] || "Status belum tersedia"),
1429
1607
  event_date: plan.event_date,
1430
- location: text(plan.event_location),
1608
+ location: text(plan.event_location)
1431
1609
  })),
1432
1610
  ...invitations.filter((invitation) => calendarDateKey(invitation.event_date)).map((invitation) => ({
1433
1611
  id: invitation.id || invitation.plan_number,
1434
- type: 'invitation',
1435
- typeLabel: 'Undangan',
1436
- title: text(invitation.gathering_title, 'Undangan gathering'),
1437
- statusLabel: text(invitation.action_label, 'Undangan diterima'),
1612
+ type: "invitation",
1613
+ typeLabel: "Undangan",
1614
+ title: text(invitation.gathering_title, "Undangan gathering"),
1615
+ statusLabel: text(invitation.action_label, "Undangan diterima"),
1438
1616
  event_date: invitation.event_date,
1439
- location: text(invitation.event_location),
1440
- })),
1617
+ location: text(invitation.event_location)
1618
+ }))
1441
1619
  ].sort((left, right) => new Date(left.event_date).getTime() - new Date(right.event_date).getTime());
1442
1620
  const initialMonth = calendarMonthKey(content.preview_month, events[0]?.event_date);
1443
1621
  const initialDate = events.find((event) => calendarDateKey(event.event_date).startsWith(`${initialMonth}-`));
1444
1622
  const selectedDate = initialDate ? calendarDateKey(initialDate.event_date) : `${initialMonth}-01`;
1445
- const monthLabel = formatCalendarDate(`${initialMonth}-01`, { month: 'long', year: 'numeric' });
1446
-
1447
- return h('section', { className: 'kumpul-calendar', id: section.id || 'kalender-acara', 'data-calendar-page': '' },
1448
- h('header', { className: 'kumpul-calendar-heading' },
1449
- h('div', null,
1450
- h('p', { className: 'kumpul-eyebrow' }, 'Acara Anda'),
1451
- h('h1', { className: 'kumpul-calendar-title' }, text(content.title, 'Kalender Acara')),
1452
- h('p', { className: 'kumpul-calendar-description', 'data-calendar-description': '' },
1453
- 'Lihat jadwal gathering, rencana, dan undangan Anda dalam satu kalender.',
1454
- ),
1623
+ const monthLabel = formatCalendarDate(`${initialMonth}-01`, { month: "long", year: "numeric" });
1624
+ return h(
1625
+ "section",
1626
+ { className: "kumpul-calendar", id: section.id || "kalender-acara", "data-calendar-page": "" },
1627
+ h(
1628
+ "header",
1629
+ { className: "kumpul-calendar-heading" },
1630
+ h(
1631
+ "div",
1632
+ null,
1633
+ h("p", { className: "kumpul-eyebrow" }, "Acara Anda"),
1634
+ h("h1", { className: "kumpul-calendar-title" }, text(content.title, "Kalender Acara")),
1635
+ h(
1636
+ "p",
1637
+ { className: "kumpul-calendar-description", "data-calendar-description": "" },
1638
+ "Lihat jadwal gathering, rencana, dan undangan Anda dalam satu kalender."
1639
+ )
1455
1640
  ),
1456
- h('div', { className: 'kumpul-calendar-stats', 'aria-label': 'Ringkasan kalender' },
1641
+ h(
1642
+ "div",
1643
+ { className: "kumpul-calendar-stats", "aria-label": "Ringkasan kalender" },
1457
1644
  ...[
1458
- [plans.length, 'rencana'],
1459
- [invitations.length, 'undangan'],
1460
- [attentionCount, 'perlu tindakan'],
1461
- ].map(([value, label]) => h('div', { className: 'kumpul-calendar-stat', key: label },
1462
- h('strong', null, String(value)),
1463
- h('span', null, label),
1464
- )),
1465
- ),
1645
+ [plans.length, "rencana"],
1646
+ [invitations.length, "undangan"],
1647
+ [attentionCount, "perlu tindakan"]
1648
+ ].map(([value, label]) => h(
1649
+ "div",
1650
+ { className: "kumpul-calendar-stat", key: label },
1651
+ h("strong", null, String(value)),
1652
+ h("span", null, label)
1653
+ ))
1654
+ )
1466
1655
  ),
1467
- isPreview
1468
- ? h('p', { className: 'kumpul-calendar-preview-note', role: 'note' },
1469
- 'Preview desainer · data contoh saja. RSVP, pembayaran, dan detail acara dikelola oleh host Bagdja.',
1656
+ isPreview ? h(
1657
+ "p",
1658
+ { className: "kumpul-calendar-preview-note", role: "note" },
1659
+ "Preview desainer \xB7 data contoh saja. RSVP, pembayaran, dan detail acara dikelola oleh host Bagdja."
1660
+ ) : null,
1661
+ h(
1662
+ "div",
1663
+ { className: "kumpul-calendar-tabs", role: "tablist", "aria-label": "Kalender acara" },
1664
+ h("button", {
1665
+ type: "button",
1666
+ role: "tab",
1667
+ id: "calendar-tab-calendar",
1668
+ "aria-controls": "calendar-panel-calendar",
1669
+ "aria-selected": "true",
1670
+ "data-calendar-tab": "calendar"
1671
+ }, "Kalender", h("span", null, String(events.length))),
1672
+ h("button", {
1673
+ type: "button",
1674
+ role: "tab",
1675
+ id: "calendar-tab-plans",
1676
+ "aria-controls": "calendar-panel-plans",
1677
+ "aria-selected": "false",
1678
+ "data-calendar-tab": "plans"
1679
+ }, "Rencana Saya", h("span", null, String(plans.length))),
1680
+ h(
1681
+ "button",
1682
+ {
1683
+ type: "button",
1684
+ role: "tab",
1685
+ id: "calendar-tab-invitations",
1686
+ "aria-controls": "calendar-panel-invitations",
1687
+ "aria-selected": "false",
1688
+ "data-calendar-tab": "invitations"
1689
+ },
1690
+ "Undangan",
1691
+ h("span", null, String(invitations.length)),
1692
+ attentionCount ? h("b", { "aria-label": `${attentionCount} perlu tindakan` }, String(attentionCount)) : null
1470
1693
  )
1471
- : null,
1472
- h('div', { className: 'kumpul-calendar-tabs', role: 'tablist', 'aria-label': 'Kalender acara' },
1473
- h('button', {
1474
- type: 'button',
1475
- role: 'tab',
1476
- id: 'calendar-tab-calendar',
1477
- 'aria-controls': 'calendar-panel-calendar',
1478
- 'aria-selected': 'true',
1479
- 'data-calendar-tab': 'calendar',
1480
- }, 'Kalender', h('span', null, String(events.length))),
1481
- h('button', {
1482
- type: 'button',
1483
- role: 'tab',
1484
- id: 'calendar-tab-plans',
1485
- 'aria-controls': 'calendar-panel-plans',
1486
- 'aria-selected': 'false',
1487
- 'data-calendar-tab': 'plans',
1488
- }, 'Rencana Saya', h('span', null, String(plans.length))),
1489
- h('button', {
1490
- type: 'button',
1491
- role: 'tab',
1492
- id: 'calendar-tab-invitations',
1493
- 'aria-controls': 'calendar-panel-invitations',
1494
- 'aria-selected': 'false',
1495
- 'data-calendar-tab': 'invitations',
1496
- }, 'Undangan', h('span', null, String(invitations.length)),
1497
- attentionCount ? h('b', { 'aria-label': `${attentionCount} perlu tindakan` }, String(attentionCount)) : null,
1498
- ),
1499
1694
  ),
1500
- h('div', {
1501
- id: 'calendar-panel-calendar',
1502
- role: 'tabpanel',
1503
- 'aria-labelledby': 'calendar-tab-calendar',
1504
- 'data-calendar-panel': 'calendar',
1505
- 'data-initial-month': initialMonth,
1506
- 'data-initial-date': selectedDate,
1507
- },
1508
- h('div', { className: 'kumpul-calendar-month-toolbar' },
1509
- h('div', { className: 'kumpul-calendar-month-title' },
1510
- h('h2', { 'data-calendar-month-label': '' }, monthLabel),
1511
- h('p', null, 'Pilih tanggal untuk melihat agenda.'),
1512
- ),
1513
- h('div', { className: 'kumpul-calendar-month-actions' },
1514
- h('button', { type: 'button', 'aria-label': 'Bulan sebelumnya', 'data-calendar-previous': '' }, '‹'),
1515
- h('button', { type: 'button', 'data-calendar-today': '' }, 'Hari ini'),
1516
- h('button', { type: 'button', 'aria-label': 'Bulan berikutnya', 'data-calendar-next': '' }, '›'),
1695
+ h(
1696
+ "div",
1697
+ {
1698
+ id: "calendar-panel-calendar",
1699
+ role: "tabpanel",
1700
+ "aria-labelledby": "calendar-tab-calendar",
1701
+ "data-calendar-panel": "calendar",
1702
+ "data-initial-month": initialMonth,
1703
+ "data-initial-date": selectedDate
1704
+ },
1705
+ h(
1706
+ "div",
1707
+ { className: "kumpul-calendar-month-toolbar" },
1708
+ h(
1709
+ "div",
1710
+ { className: "kumpul-calendar-month-title" },
1711
+ h("h2", { "data-calendar-month-label": "" }, monthLabel),
1712
+ h("p", null, "Pilih tanggal untuk melihat agenda.")
1517
1713
  ),
1714
+ h(
1715
+ "div",
1716
+ { className: "kumpul-calendar-month-actions" },
1717
+ h("button", { type: "button", "aria-label": "Bulan sebelumnya", "data-calendar-previous": "" }, "\u2039"),
1718
+ h("button", { type: "button", "data-calendar-today": "" }, "Hari ini"),
1719
+ h("button", { type: "button", "aria-label": "Bulan berikutnya", "data-calendar-next": "" }, "\u203A")
1720
+ )
1518
1721
  ),
1519
- h('div', { className: 'kumpul-calendar-month-view' },
1520
- h('div', { className: 'kumpul-calendar-weekdays', 'aria-hidden': 'true' },
1521
- ...['Sen', 'Sel', 'Rab', 'Kam', 'Jum', 'Sab', 'Min'].map((day) => h('span', { key: day }, day)),
1522
- ),
1523
- h('div', { className: 'kumpul-calendar-grid', role: 'group', 'aria-label': `Kalender ${monthLabel}` },
1524
- ...calendarMonthCells(initialMonth, events, selectedDate),
1722
+ h(
1723
+ "div",
1724
+ { className: "kumpul-calendar-month-view" },
1725
+ h(
1726
+ "div",
1727
+ { className: "kumpul-calendar-weekdays", "aria-hidden": "true" },
1728
+ ...["Sen", "Sel", "Rab", "Kam", "Jum", "Sab", "Min"].map((day) => h("span", { key: day }, day))
1525
1729
  ),
1730
+ h(
1731
+ "div",
1732
+ { className: "kumpul-calendar-grid", role: "group", "aria-label": `Kalender ${monthLabel}` },
1733
+ ...calendarMonthCells(initialMonth, events, selectedDate)
1734
+ )
1526
1735
  ),
1527
- h('dialog', {
1528
- className: 'kumpul-calendar-agenda',
1529
- 'aria-labelledby': 'calendar-agenda-title',
1530
- 'data-calendar-agenda-dialog': '',
1531
- },
1532
- h('div', { className: 'kumpul-calendar-agenda-handle', 'aria-hidden': 'true' }),
1533
- h('header', { className: 'kumpul-calendar-agenda-heading' },
1534
- h('div', null,
1535
- h('p', { className: 'kumpul-eyebrow' }, 'Agenda tanggal'),
1536
- h('h2', { id: 'calendar-agenda-title', 'data-calendar-selected-label': '' }, formatCalendarDate(selectedDate)),
1537
- ),
1538
- h('button', {
1539
- type: 'button',
1540
- className: 'kumpul-calendar-agenda-close',
1541
- 'aria-label': 'Tutup agenda tanggal',
1542
- 'data-calendar-close': '',
1543
- }, '×'),
1544
- ),
1545
- h('div', { className: 'kumpul-calendar-agenda-content', 'aria-live': 'polite' },
1546
- h('div', { className: 'kumpul-calendar-list kumpul-calendar-agenda-list', 'data-calendar-agenda': '' },
1547
- ...events.map((event, index) => h('article', {
1548
- className: `kumpul-calendar-event kumpul-calendar-event-${event.type}`,
1549
- 'data-calendar-event': '',
1550
- 'data-calendar-date': calendarDateKey(event.event_date),
1551
- hidden: calendarDateKey(event.event_date) !== selectedDate,
1552
- key: event.id || index,
1553
- },
1554
- h('div', { className: 'kumpul-calendar-event-time' }, formatCalendarTime(event.event_date) || 'Acara'),
1555
- h('div', { className: 'kumpul-calendar-event-copy' },
1556
- h('span', { className: 'kumpul-calendar-event-kind' }, event.typeLabel),
1557
- h('h4', null, event.title),
1558
- h('p', null, `${event.statusLabel}${event.location ? ` · ${event.location}` : ''}`),
1736
+ h(
1737
+ "dialog",
1738
+ {
1739
+ className: "kumpul-calendar-agenda",
1740
+ "aria-labelledby": "calendar-agenda-title",
1741
+ "data-calendar-agenda-dialog": ""
1742
+ },
1743
+ h("div", { className: "kumpul-calendar-agenda-handle", "aria-hidden": "true" }),
1744
+ h(
1745
+ "header",
1746
+ { className: "kumpul-calendar-agenda-heading" },
1747
+ h(
1748
+ "div",
1749
+ null,
1750
+ h("p", { className: "kumpul-eyebrow" }, "Agenda tanggal"),
1751
+ h("h2", { id: "calendar-agenda-title", "data-calendar-selected-label": "" }, formatCalendarDate(selectedDate))
1559
1752
  ),
1560
- )),
1561
- h('p', {
1562
- className: 'kumpul-calendar-empty',
1563
- hidden: events.some((event) => calendarDateKey(event.event_date) === selectedDate),
1564
- 'data-calendar-agenda-empty': '',
1565
- }, isPreview ? 'Belum ada acara pada tanggal ini.' : 'Data agenda kalender dikelola oleh host Bagdja.'),
1753
+ h("button", {
1754
+ type: "button",
1755
+ className: "kumpul-calendar-agenda-close",
1756
+ "aria-label": "Tutup agenda tanggal",
1757
+ "data-calendar-close": ""
1758
+ }, "\xD7")
1566
1759
  ),
1567
- ),
1568
- ),
1760
+ h(
1761
+ "div",
1762
+ { className: "kumpul-calendar-agenda-content", "aria-live": "polite" },
1763
+ h(
1764
+ "div",
1765
+ { className: "kumpul-calendar-list kumpul-calendar-agenda-list", "data-calendar-agenda": "" },
1766
+ ...events.map((event, index) => h(
1767
+ "article",
1768
+ {
1769
+ className: `kumpul-calendar-event kumpul-calendar-event-${event.type}`,
1770
+ "data-calendar-event": "",
1771
+ "data-calendar-date": calendarDateKey(event.event_date),
1772
+ hidden: calendarDateKey(event.event_date) !== selectedDate,
1773
+ key: event.id || index
1774
+ },
1775
+ h("div", { className: "kumpul-calendar-event-time" }, formatCalendarTime(event.event_date) || "Acara"),
1776
+ h(
1777
+ "div",
1778
+ { className: "kumpul-calendar-event-copy" },
1779
+ h("span", { className: "kumpul-calendar-event-kind" }, event.typeLabel),
1780
+ h("h4", null, event.title),
1781
+ h("p", null, `${event.statusLabel}${event.location ? ` \xB7 ${event.location}` : ""}`)
1782
+ )
1783
+ )),
1784
+ h("p", {
1785
+ className: "kumpul-calendar-empty",
1786
+ hidden: events.some((event) => calendarDateKey(event.event_date) === selectedDate),
1787
+ "data-calendar-agenda-empty": ""
1788
+ }, isPreview ? "Belum ada acara pada tanggal ini." : "Data agenda kalender dikelola oleh host Bagdja.")
1789
+ )
1790
+ )
1791
+ )
1569
1792
  ),
1570
- h('div', {
1571
- id: 'calendar-panel-plans',
1572
- role: 'tabpanel',
1573
- 'aria-labelledby': 'calendar-tab-plans',
1574
- 'data-calendar-panel': 'plans',
1575
- hidden: true,
1576
- },
1577
- h('nav', { className: 'kumpul-calendar-filters', 'aria-label': 'Filter status rencana' },
1793
+ h(
1794
+ "div",
1795
+ {
1796
+ id: "calendar-panel-plans",
1797
+ role: "tabpanel",
1798
+ "aria-labelledby": "calendar-tab-plans",
1799
+ "data-calendar-panel": "plans",
1800
+ hidden: true
1801
+ },
1802
+ h(
1803
+ "nav",
1804
+ { className: "kumpul-calendar-filters", "aria-label": "Filter status rencana" },
1578
1805
  ...calendarStatuses.map(([filter, label]) => {
1579
- const count = filter === 'all'
1580
- ? plans.length
1581
- : plans.filter((plan) => calendarStatusFilter(plan.status) === filter).length;
1582
- return h('button', {
1583
- type: 'button',
1584
- 'aria-pressed': filter === 'all' ? 'true' : 'false',
1585
- 'data-calendar-filter': filter,
1586
- key: filter,
1587
- }, label, h('span', null, String(count)));
1588
- }),
1806
+ const count = filter === "all" ? plans.length : plans.filter((plan) => calendarStatusFilter(plan.status) === filter).length;
1807
+ return h("button", {
1808
+ type: "button",
1809
+ "aria-pressed": filter === "all" ? "true" : "false",
1810
+ "data-calendar-filter": filter,
1811
+ key: filter
1812
+ }, label, h("span", null, String(count)));
1813
+ })
1589
1814
  ),
1590
- h('div', { className: 'kumpul-calendar-list', 'data-calendar-list': 'plans' },
1591
- ...plans.map((plan, index) => h('article', {
1592
- className: 'kumpul-calendar-card',
1593
- 'data-calendar-card': '',
1594
- 'data-calendar-status': calendarStatusFilter(plan.status),
1595
- key: plan.id || plan.plan_number || index,
1596
- },
1597
- h('div', { className: 'kumpul-calendar-card-copy' },
1598
- h('div', { className: 'kumpul-calendar-card-title' },
1599
- h('h2', null, text(plan.title, 'Rencana gathering')),
1600
- h('span', { className: 'kumpul-calendar-status' }, text(plan.status_label, calendarStatusLabels[plan.status] || 'Status belum tersedia')),
1601
- ),
1602
- h('p', { className: 'kumpul-calendar-meta' }, `Nomor rencana: ${text(plan.plan_number, '—')}`),
1603
- h('p', { className: 'kumpul-calendar-meta' }, text(plan.workflow_step_label, 'Tahap acara')),
1604
- h('p', { className: 'kumpul-calendar-meta' },
1605
- `Jadwal: ${formatCalendarDate(plan.event_date) || 'Belum ditentukan'} · Peserta: min. ${Number(plan.min_attendees) || 0}, maks. ${Number(plan.max_attendees) || 0}`,
1815
+ h(
1816
+ "div",
1817
+ { className: "kumpul-calendar-list", "data-calendar-list": "plans" },
1818
+ ...plans.map((plan, index) => h(
1819
+ "article",
1820
+ {
1821
+ className: "kumpul-calendar-card",
1822
+ "data-calendar-card": "",
1823
+ "data-calendar-status": calendarStatusFilter(plan.status),
1824
+ key: plan.id || plan.plan_number || index
1825
+ },
1826
+ h(
1827
+ "div",
1828
+ { className: "kumpul-calendar-card-copy" },
1829
+ h(
1830
+ "div",
1831
+ { className: "kumpul-calendar-card-title" },
1832
+ h("h2", null, text(plan.title, "Rencana gathering")),
1833
+ h("span", { className: "kumpul-calendar-status" }, text(plan.status_label, calendarStatusLabels[plan.status] || "Status belum tersedia"))
1834
+ ),
1835
+ h("p", { className: "kumpul-calendar-meta" }, `Nomor rencana: ${text(plan.plan_number, "\u2014")}`),
1836
+ h("p", { className: "kumpul-calendar-meta" }, text(plan.workflow_step_label, "Tahap acara")),
1837
+ h(
1838
+ "p",
1839
+ { className: "kumpul-calendar-meta" },
1840
+ `Jadwal: ${formatCalendarDate(plan.event_date) || "Belum ditentukan"} \xB7 Peserta: min. ${Number(plan.min_attendees) || 0}, maks. ${Number(plan.max_attendees) || 0}`
1841
+ ),
1842
+ plan.payment_deadline ? h("p", { className: "kumpul-calendar-meta" }, `Batas pembayaran: ${formatCalendarDate(plan.payment_deadline)}`) : null
1606
1843
  ),
1607
- plan.payment_deadline
1608
- ? h('p', { className: 'kumpul-calendar-meta' }, `Batas pembayaran: ${formatCalendarDate(plan.payment_deadline)}`)
1609
- : null,
1610
- ),
1611
- h('button', { type: 'button', className: 'kumpul-calendar-action', disabled: true }, 'Lanjutkan rencana'),
1844
+ h("button", { type: "button", className: "kumpul-calendar-action", disabled: true }, "Lanjutkan rencana")
1612
1845
  )),
1613
- h('p', {
1614
- className: 'kumpul-calendar-empty',
1846
+ h("p", {
1847
+ className: "kumpul-calendar-empty",
1615
1848
  hidden: plans.length > 0,
1616
- 'data-calendar-empty': '',
1617
- }, 'Belum ada rencana acara. Rencana gathering yang Anda buat akan dikelola dari kalender ini.'),
1618
- plans.length
1619
- ? h('p', { className: 'kumpul-calendar-empty', hidden: true, 'data-calendar-filter-empty': '' }, 'Tidak ada acara pada status ini.')
1620
- : null,
1621
- ),
1849
+ "data-calendar-empty": ""
1850
+ }, "Belum ada rencana acara. Rencana gathering yang Anda buat akan dikelola dari kalender ini."),
1851
+ plans.length ? h("p", { className: "kumpul-calendar-empty", hidden: true, "data-calendar-filter-empty": "" }, "Tidak ada acara pada status ini.") : null
1852
+ )
1622
1853
  ),
1623
- h('div', {
1624
- id: 'calendar-panel-invitations',
1625
- role: 'tabpanel',
1626
- 'aria-labelledby': 'calendar-tab-invitations',
1627
- 'data-calendar-panel': 'invitations',
1628
- hidden: true,
1629
- },
1630
- h('div', { className: 'kumpul-calendar-list', 'data-calendar-list': 'invitations' },
1631
- ...invitations.map((invitation, index) => h('article', {
1632
- className: 'kumpul-calendar-card',
1633
- key: invitation.id || invitation.plan_number || index,
1634
- },
1635
- h('div', { className: 'kumpul-calendar-card-copy' },
1636
- h('div', { className: 'kumpul-calendar-card-title' },
1637
- h('h2', null, text(invitation.gathering_title, 'Undangan gathering')),
1638
- invitation.is_new ? h('span', { className: 'kumpul-calendar-new' }, 'Undangan baru') : null,
1639
- ),
1640
- h('p', { className: 'kumpul-calendar-meta' },
1641
- `${formatGatheringDate(invitation.event_date) || 'Belum dijadwalkan'}${invitation.event_location ? ` · ${invitation.event_location}` : ''}`,
1642
- ),
1643
- h('p', { className: 'kumpul-calendar-meta' },
1644
- `Diundang oleh ${text(invitation.initiator_name, 'Penyelenggara')} · ${text(invitation.plan_number, '—')}`,
1854
+ h(
1855
+ "div",
1856
+ {
1857
+ id: "calendar-panel-invitations",
1858
+ role: "tabpanel",
1859
+ "aria-labelledby": "calendar-tab-invitations",
1860
+ "data-calendar-panel": "invitations",
1861
+ hidden: true
1862
+ },
1863
+ h(
1864
+ "div",
1865
+ { className: "kumpul-calendar-list", "data-calendar-list": "invitations" },
1866
+ ...invitations.map((invitation, index) => h(
1867
+ "article",
1868
+ {
1869
+ className: "kumpul-calendar-card",
1870
+ key: invitation.id || invitation.plan_number || index
1871
+ },
1872
+ h(
1873
+ "div",
1874
+ { className: "kumpul-calendar-card-copy" },
1875
+ h(
1876
+ "div",
1877
+ { className: "kumpul-calendar-card-title" },
1878
+ h("h2", null, text(invitation.gathering_title, "Undangan gathering")),
1879
+ invitation.is_new ? h("span", { className: "kumpul-calendar-new" }, "Undangan baru") : null
1880
+ ),
1881
+ h(
1882
+ "p",
1883
+ { className: "kumpul-calendar-meta" },
1884
+ `${formatGatheringDate(invitation.event_date) || "Belum dijadwalkan"}${invitation.event_location ? ` \xB7 ${invitation.event_location}` : ""}`
1885
+ ),
1886
+ h(
1887
+ "p",
1888
+ { className: "kumpul-calendar-meta" },
1889
+ `Diundang oleh ${text(invitation.initiator_name, "Penyelenggara")} \xB7 ${text(invitation.plan_number, "\u2014")}`
1890
+ )
1645
1891
  ),
1646
- ),
1647
- h('div', { className: 'kumpul-calendar-invitation-action' },
1648
- invitation.action_label ? h('span', null, invitation.action_label) : null,
1649
- h('button', { type: 'button', className: 'kumpul-calendar-action', disabled: true }, 'Lihat undangan'),
1650
- ),
1892
+ h(
1893
+ "div",
1894
+ { className: "kumpul-calendar-invitation-action" },
1895
+ invitation.action_label ? h("span", null, invitation.action_label) : null,
1896
+ h("button", { type: "button", className: "kumpul-calendar-action", disabled: true }, "Lihat undangan")
1897
+ )
1651
1898
  )),
1652
- h('p', {
1653
- className: 'kumpul-calendar-empty',
1654
- hidden: invitations.length > 0,
1655
- }, 'Belum ada undangan. Undangan acara yang dikirim ke akun Anda akan muncul di sini.'),
1656
- ),
1657
- ),
1899
+ h("p", {
1900
+ className: "kumpul-calendar-empty",
1901
+ hidden: invitations.length > 0
1902
+ }, "Belum ada undangan. Undangan acara yang dikirim ke akun Anda akan muncul di sini.")
1903
+ )
1904
+ )
1658
1905
  );
1659
1906
  }
1660
-
1661
1907
  function GatheringCard({ product, index, props, catalogPage = false }) {
1662
- const href = tenantPath(props, `/products/${encodeURIComponent(text(product.slug, product.id || ''))}`);
1908
+ const href = tenantPath(props, `/products/${encodeURIComponent(text(product.slug, product.id || ""))}`);
1663
1909
  const image = text(product.image, text(product.images?.[0]?.url));
1664
1910
  const gathering = product.gatheringMeta || {};
1665
1911
  const eventDate = formatGatheringDate(gathering.eventDate);
1666
1912
  const eventTime = text(gathering.eventTime);
1667
- return h('article', {
1668
- className: 'kumpul-gathering-card',
1669
- key: product.id || product.slug || index,
1670
- ...(catalogPage ? {
1671
- 'data-gathering-name': `${product.name || ''} ${product.description || ''}`.toLocaleLowerCase('id-ID'),
1672
- 'data-gathering-category': slug(product.category),
1673
- } : {}),
1674
- },
1675
- h('a', { className: `kumpul-gathering-art kumpul-art-${index % 4}`, href, 'aria-label': `Lihat ${text(product.name, 'gathering')}` },
1676
- image
1677
- ? h('img', { src: image, alt: text(product.name, 'Foto gathering'), loading: 'lazy' })
1678
- : h('span', { 'aria-hidden': 'true' }, catalogPage ? h(Icon, { name: 'ticket' }) : ['⛺', '🎨', '🏃', '📚'][index % 4]),
1913
+ return h(
1914
+ "article",
1915
+ {
1916
+ className: "kumpul-gathering-card",
1917
+ key: product.id || product.slug || index,
1918
+ ...catalogPage ? {
1919
+ "data-gathering-name": `${product.name || ""} ${product.description || ""}`.toLocaleLowerCase("id-ID"),
1920
+ "data-gathering-category": slug(product.category)
1921
+ } : {}
1922
+ },
1923
+ h(
1924
+ "a",
1925
+ { className: `kumpul-gathering-art kumpul-art-${index % 4}`, href, "aria-label": `Lihat ${text(product.name, "gathering")}` },
1926
+ image ? h("img", { src: image, alt: text(product.name, "Foto gathering"), loading: "lazy" }) : h("span", { "aria-hidden": "true" }, catalogPage ? h(Icon, { name: "ticket" }) : ["\u26FA", "\u{1F3A8}", "\u{1F3C3}", "\u{1F4DA}"][index % 4])
1679
1927
  ),
1680
- h('div', { className: 'kumpul-card-content' },
1681
- h('p', { className: 'kumpul-card-meta' },
1682
- text(product.category, text(product.type, 'Gathering')),
1683
- catalogPage && eventDate ? h('span', null, `${eventDate}${eventTime ? ` · ${eventTime}` : ''}`) : null,
1684
- ),
1685
- h('h3', null, h('a', { href }, text(product.name, 'Gathering komunitas'))),
1686
- catalogPage && gathering.location
1687
- ? h('p', { className: 'kumpul-card-location' }, h(Icon, { name: 'calendar' }), gathering.location)
1688
- : null,
1689
- product.description ? h('p', { className: 'kumpul-card-description' }, product.description) : null,
1690
- h('div', { className: 'kumpul-card-bottom' },
1691
- h('strong', null, text(product.priceLabel, 'Lihat detail')),
1692
- catalogPage && gathering.maxAttendees
1693
- ? h('span', null, `Maks. ${gathering.maxAttendees} peserta`)
1694
- : null,
1695
- h('a', { href }, 'Lihat detail'),
1928
+ h(
1929
+ "div",
1930
+ { className: "kumpul-card-content" },
1931
+ h(
1932
+ "p",
1933
+ { className: "kumpul-card-meta" },
1934
+ text(product.category, text(product.type, "Gathering")),
1935
+ catalogPage && eventDate ? h("span", null, `${eventDate}${eventTime ? ` \xB7 ${eventTime}` : ""}`) : null
1696
1936
  ),
1697
- ),
1937
+ h("h3", null, h("a", { href }, text(product.name, "Gathering komunitas"))),
1938
+ catalogPage && gathering.location ? h("p", { className: "kumpul-card-location" }, h(Icon, { name: "calendar" }), gathering.location) : null,
1939
+ product.description ? h("p", { className: "kumpul-card-description" }, product.description) : null,
1940
+ h(
1941
+ "div",
1942
+ { className: "kumpul-card-bottom" },
1943
+ h("strong", null, text(product.priceLabel, "Lihat detail")),
1944
+ catalogPage && gathering.maxAttendees ? h("span", null, `Maks. ${gathering.maxAttendees} peserta`) : null,
1945
+ h("a", { href }, "Lihat detail")
1946
+ )
1947
+ )
1698
1948
  );
1699
1949
  }
1700
-
1701
1950
  function GatheringCategories({ categories, products }) {
1702
- const counts = new Map();
1951
+ const counts = /* @__PURE__ */ new Map();
1703
1952
  for (const product of products) {
1704
1953
  const key = slug(product.category);
1705
1954
  if (key) counts.set(key, (counts.get(key) || 0) + 1);
1706
1955
  }
1707
-
1708
1956
  const availableCategories = categories.filter((category) => counts.has(slug(category.label))).slice(0, 8);
1709
-
1710
- return h('div', { className: 'kumpul-category-filters', 'aria-label': 'Filter kategori gathering' },
1711
- h('button', { type: 'button', className: 'kumpul-category-filter', 'data-category-filter': 'all', 'aria-pressed': 'true' }, 'Semua'),
1957
+ return h(
1958
+ "div",
1959
+ { className: "kumpul-category-filters", "aria-label": "Filter kategori gathering" },
1960
+ h("button", { type: "button", className: "kumpul-category-filter", "data-category-filter": "all", "aria-pressed": "true" }, "Semua"),
1712
1961
  ...availableCategories.map((category) => {
1713
1962
  const key = slug(category.label);
1714
- return h('button', {
1715
- type: 'button',
1716
- className: 'kumpul-category-filter',
1717
- 'data-category-filter': key,
1718
- 'aria-pressed': 'false',
1719
- key: category.id || key,
1720
- },
1721
- h('span', { className: 'kumpul-category-icon', 'aria-hidden': 'true' }, category.label.slice(0, 1)),
1722
- h('span', null,
1723
- h('strong', null, category.label),
1724
- h('small', null, text(category.description, `${counts.get(key)} gathering`)),
1725
- ));
1726
- }),
1963
+ return h(
1964
+ "button",
1965
+ {
1966
+ type: "button",
1967
+ className: "kumpul-category-filter",
1968
+ "data-category-filter": key,
1969
+ "aria-pressed": "false",
1970
+ key: category.id || key
1971
+ },
1972
+ h("span", { className: "kumpul-category-icon", "aria-hidden": "true" }, category.label.slice(0, 1)),
1973
+ h(
1974
+ "span",
1975
+ null,
1976
+ h("strong", null, category.label),
1977
+ h("small", null, text(category.description, `${counts.get(key)} gathering`))
1978
+ )
1979
+ );
1980
+ })
1727
1981
  );
1728
1982
  }
1729
-
1730
1983
  function GatheringsSection({ props, section, catalogPage = false }) {
1731
1984
  const content = section?.content || {};
1732
1985
  const products = gatheringProducts(props);
1733
1986
  const categories = list(props.categories);
1734
1987
  const gatheringPage = list(props.pages).find((page) => /gather|event|katalog/i.test(`${page.slug} ${page.title}`));
1735
- const catalogHref = tenantPath(props, gatheringPage ? `/${encodeURIComponent(gatheringPage.slug)}` : '/gathering');
1736
-
1737
- return h('section', {
1738
- className: 'kumpul-section kumpul-gatherings',
1739
- id: section?.id || 'gathering',
1740
- ...(catalogPage ? { 'data-gathering-catalog': '' } : {}),
1741
- },
1742
- catalogPage
1743
- ? h('div', { className: 'kumpul-catalog-heading' },
1744
- h(SectionHeading, {
1745
- eyebrow: text(content.eyebrow, 'Temukan acara berikutnya'),
1746
- title: text(content.title, 'Katalog Gathering'),
1747
- description: text(content.subtitle, 'Pilih pengalaman berikutnya bersama keluarga dan komunitas.'),
1748
- }),
1749
- h('label', { className: 'kumpul-catalog-search' },
1750
- h(Icon, { name: 'search' }),
1751
- h('input', {
1752
- type: 'search',
1753
- placeholder: 'Cari gathering...',
1754
- 'aria-label': 'Cari gathering',
1755
- 'data-gathering-search': '',
1756
- }),
1757
- ),
1988
+ const catalogHref = tenantPath(props, gatheringPage ? `/${encodeURIComponent(gatheringPage.slug)}` : "/gathering");
1989
+ return h(
1990
+ "section",
1991
+ {
1992
+ className: "kumpul-section kumpul-gatherings",
1993
+ id: section?.id || "gathering",
1994
+ ...catalogPage ? { "data-gathering-catalog": "" } : {}
1995
+ },
1996
+ catalogPage ? h(
1997
+ "div",
1998
+ { className: "kumpul-catalog-heading" },
1999
+ h(SectionHeading, {
2000
+ eyebrow: text(content.eyebrow, "Temukan acara berikutnya"),
2001
+ title: text(content.title, "Katalog Gathering"),
2002
+ description: text(content.subtitle, "Pilih pengalaman berikutnya bersama keluarga dan komunitas.")
2003
+ }),
2004
+ h(
2005
+ "label",
2006
+ { className: "kumpul-catalog-search" },
2007
+ h(Icon, { name: "search" }),
2008
+ h("input", {
2009
+ type: "search",
2010
+ placeholder: "Cari gathering...",
2011
+ "aria-label": "Cari gathering",
2012
+ "data-gathering-search": ""
2013
+ })
1758
2014
  )
1759
- : h('div', { className: 'kumpul-section-topline' },
1760
- h(SectionHeading, {
1761
- eyebrow: text(content.eyebrow, 'Cari kegiatan berikutnya'),
1762
- title: text(content.title, 'Gathering Terdekat'),
1763
- description: text(content.subtitle),
1764
- }),
1765
- h('a', { className: 'kumpul-text-link', href: catalogHref },
1766
- 'Lihat semua', h(Icon, { name: 'arrow' }),
1767
- ),
1768
- ),
2015
+ ) : h(
2016
+ "div",
2017
+ { className: "kumpul-section-topline" },
2018
+ h(SectionHeading, {
2019
+ eyebrow: text(content.eyebrow, "Cari kegiatan berikutnya"),
2020
+ title: text(content.title, "Gathering Terdekat"),
2021
+ description: text(content.subtitle)
2022
+ }),
2023
+ h(
2024
+ "a",
2025
+ { className: "kumpul-text-link", href: catalogHref },
2026
+ "Lihat semua",
2027
+ h(Icon, { name: "arrow" })
2028
+ )
2029
+ ),
1769
2030
  catalogPage ? h(GatheringCategories, { categories, products }) : null,
1770
- catalogPage
1771
- ? h('p', { className: 'kumpul-catalog-results', 'aria-live': 'polite', hidden: true, 'data-gathering-results': '' })
1772
- : null,
1773
- products.length
1774
- ? h('div', {
1775
- className: `kumpul-gathering-grid${catalogPage ? ' kumpul-catalog-grid' : ''}`,
2031
+ catalogPage ? h("p", { className: "kumpul-catalog-results", "aria-live": "polite", hidden: true, "data-gathering-results": "" }) : null,
2032
+ products.length ? h(
2033
+ "div",
2034
+ {
2035
+ className: `kumpul-gathering-grid${catalogPage ? " kumpul-catalog-grid" : ""}`
1776
2036
  },
1777
- ...products.map((product, index) => h(GatheringCard, {
1778
- product,
1779
- index,
1780
- props,
1781
- catalogPage,
1782
- key: product.id || product.slug || index,
1783
- })),
1784
- )
1785
- : h('div', { className: 'kumpul-empty-state' },
1786
- h('span', { className: 'kumpul-empty-icon', 'aria-hidden': 'true' }, '✳'),
1787
- h('h3', null, text(content.empty_title, 'Gathering baru sedang disiapkan')),
1788
- h('p', null, text(content.empty_description, 'Belum ada acara untuk ditampilkan. Silakan kembali lagi segera.')),
1789
- ),
1790
- catalogPage && products.length
1791
- ? h('p', { className: 'kumpul-no-results', hidden: true, 'data-gathering-no-results': '' }, 'Tidak ada gathering yang cocok. Coba ubah kata kunci atau kategori.')
1792
- : null,
1793
- catalogPage && products.length
1794
- ? h('nav', { className: 'kumpul-pagination', 'aria-label': 'Halaman katalog gathering', hidden: true, 'data-gathering-pagination': '' },
1795
- h('button', { type: 'button', 'data-page-previous': '', disabled: true }, 'Sebelumnya'),
1796
- h('span', { 'aria-live': 'polite', 'data-page-status': '' }),
1797
- h('button', { type: 'button', 'data-page-next': '' }, 'Berikutnya'),
1798
- )
1799
- : null,
2037
+ ...products.map((product, index) => h(GatheringCard, {
2038
+ product,
2039
+ index,
2040
+ props,
2041
+ catalogPage,
2042
+ key: product.id || product.slug || index
2043
+ }))
2044
+ ) : h(
2045
+ "div",
2046
+ { className: "kumpul-empty-state" },
2047
+ h("span", { className: "kumpul-empty-icon", "aria-hidden": "true" }, "\u2733"),
2048
+ h("h3", null, text(content.empty_title, "Gathering baru sedang disiapkan")),
2049
+ h("p", null, text(content.empty_description, "Belum ada acara untuk ditampilkan. Silakan kembali lagi segera."))
2050
+ ),
2051
+ catalogPage && products.length ? h("p", { className: "kumpul-no-results", hidden: true, "data-gathering-no-results": "" }, "Tidak ada gathering yang cocok. Coba ubah kata kunci atau kategori.") : null,
2052
+ catalogPage && products.length ? h(
2053
+ "nav",
2054
+ { className: "kumpul-pagination", "aria-label": "Halaman katalog gathering", hidden: true, "data-gathering-pagination": "" },
2055
+ h("button", { type: "button", "data-page-previous": "", disabled: true }, "Sebelumnya"),
2056
+ h("span", { "aria-live": "polite", "data-page-status": "" }),
2057
+ h("button", { type: "button", "data-page-next": "" }, "Berikutnya")
2058
+ ) : null
1800
2059
  );
1801
2060
  }
1802
-
1803
2061
  function TestimonialsSection(section) {
1804
2062
  const content = section?.content || {};
1805
2063
  const items = list(content.items).slice(0, 3);
1806
-
1807
2064
  if (!items.length) return null;
1808
-
1809
- return h('section', { className: 'kumpul-section kumpul-testimonials', id: section?.id || 'cerita-komunitas' },
2065
+ return h(
2066
+ "section",
2067
+ { className: "kumpul-section kumpul-testimonials", id: section?.id || "cerita-komunitas" },
1810
2068
  h(SectionHeading, {
1811
- eyebrow: text(content.eyebrow, 'Cerita komunitas'),
1812
- title: text(content.title, 'Komunitas yang balik lagi.'),
1813
- description: text(content.subtitle, 'Pengalaman hangat dari orang-orang yang sudah berkumpul bersama.'),
2069
+ eyebrow: text(content.eyebrow, "Cerita komunitas"),
2070
+ title: text(content.title, "Komunitas yang balik lagi."),
2071
+ description: text(content.subtitle, "Pengalaman hangat dari orang-orang yang sudah berkumpul bersama.")
1814
2072
  }),
1815
- h('div', { className: 'kumpul-testimonial-grid' },
1816
- ...items.map((item, index) => h('figure', { className: 'kumpul-testimonial', key: item.name || index },
1817
- h('div', { className: 'kumpul-rating', 'aria-label': 'Rating bintang 5' }, '★★★★★'),
1818
- h('blockquote', null, `“${text(item.quote)}”`),
1819
- h('figcaption', null,
1820
- h('span', { className: 'kumpul-avatar' }, text(item.location, 'K').slice(0, 1)),
1821
- h('span', null,
1822
- h('strong', null, text(item.location, 'Komunitas Kumpul')),
1823
- item.context ? h('small', null, item.context) : null,
1824
- ),
1825
- ),
1826
- )),
1827
- ),
2073
+ h(
2074
+ "div",
2075
+ { className: "kumpul-testimonial-grid" },
2076
+ ...items.map((item, index) => h(
2077
+ "figure",
2078
+ { className: "kumpul-testimonial", key: item.name || index },
2079
+ h("div", { className: "kumpul-rating", "aria-label": "Rating bintang 5" }, "\u2605\u2605\u2605\u2605\u2605"),
2080
+ h("blockquote", null, `\u201C${text(item.quote)}\u201D`),
2081
+ h(
2082
+ "figcaption",
2083
+ null,
2084
+ h("span", { className: "kumpul-avatar" }, text(item.location, "K").slice(0, 1)),
2085
+ h(
2086
+ "span",
2087
+ null,
2088
+ h("strong", null, text(item.location, "Komunitas Kumpul")),
2089
+ item.context ? h("small", null, item.context) : null
2090
+ )
2091
+ )
2092
+ ))
2093
+ )
1828
2094
  );
1829
2095
  }
1830
-
1831
2096
  function LocationsSection({ props, section }) {
1832
2097
  const content = section?.content || {};
1833
2098
  const locations = list(props.locations).slice(0, 4);
1834
2099
  if (!locations.length) return null;
1835
-
1836
- return h('section', { className: 'kumpul-section kumpul-locations', id: section?.id || 'lokasi' },
2100
+ return h(
2101
+ "section",
2102
+ { className: "kumpul-section kumpul-locations", id: section?.id || "lokasi" },
1837
2103
  h(SectionHeading, {
1838
- eyebrow: text(content.eyebrow, 'Temukan suasana baru'),
1839
- title: text(content.title, 'Lokasi Kumpul'),
1840
- description: text(content.subtitle, 'Tempat-tempat pilihan untuk bertemu dan berbagi cerita.'),
2104
+ eyebrow: text(content.eyebrow, "Temukan suasana baru"),
2105
+ title: text(content.title, "Lokasi Kumpul"),
2106
+ description: text(content.subtitle, "Tempat-tempat pilihan untuk bertemu dan berbagi cerita.")
1841
2107
  }),
1842
- h('div', { className: 'kumpul-location-list' },
1843
- ...locations.map((location, index) => h('article', { className: 'kumpul-location', key: location.id || location.name || index },
1844
- h('span', { className: 'kumpul-location-icon', 'aria-hidden': 'true' }, text(location.emoji, ['🌳', '⛰', '🏔', '🏘'][index % 4])),
1845
- h('span', null, h('strong', null, text(location.name, 'Lokasi gathering')), h('small', null, text(location.city || location.address_line || location.address))),
1846
- )),
1847
- ),
2108
+ h(
2109
+ "div",
2110
+ { className: "kumpul-location-list" },
2111
+ ...locations.map((location, index) => h(
2112
+ "article",
2113
+ { className: "kumpul-location", key: location.id || location.name || index },
2114
+ h("span", { className: "kumpul-location-icon", "aria-hidden": "true" }, text(location.emoji, ["\u{1F333}", "\u26F0", "\u{1F3D4}", "\u{1F3D8}"][index % 4])),
2115
+ h("span", null, h("strong", null, text(location.name, "Lokasi gathering")), h("small", null, text(location.city || location.address_line || location.address)))
2116
+ ))
2117
+ )
1848
2118
  );
1849
2119
  }
1850
-
1851
2120
  function CallToAction({ props, section }) {
1852
2121
  const content = section?.content || {};
1853
- const action = text(content.button_action, 'whatsapp');
1854
- let href = tenantPath(props, '/gathering');
1855
-
1856
- if (action === 'whatsapp') {
1857
- const phone = text(content.button_whatsapp, props.profile?.whatsapp).replace(/\D/g, '');
2122
+ const action = text(content.button_action, "whatsapp");
2123
+ let href = tenantPath(props, "/gathering");
2124
+ if (action === "whatsapp") {
2125
+ const phone = text(content.button_whatsapp, props.profile?.whatsapp).replace(/\D/g, "");
1858
2126
  if (phone) {
1859
2127
  const message = text(content.button_message);
1860
- href = `https://wa.me/${phone}${message ? `?text=${encodeURIComponent(message)}` : ''}`;
2128
+ href = `https://wa.me/${phone}${message ? `?text=${encodeURIComponent(message)}` : ""}`;
1861
2129
  }
1862
- } else if (action === 'phone') {
1863
- const phone = text(content.button_phone, props.profile?.phone).replace(/[^\d+(). -]/g, '');
2130
+ } else if (action === "phone") {
2131
+ const phone = text(content.button_phone, props.profile?.phone).replace(/[^\d+(). -]/g, "");
1864
2132
  if (phone) href = `tel:${phone}`;
1865
- } else if (action === 'email') {
2133
+ } else if (action === "email") {
1866
2134
  const email = text(content.button_email);
1867
2135
  if (/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) href = `mailto:${email}`;
1868
- } else if (action === 'link') {
2136
+ } else if (action === "link") {
1869
2137
  const target = text(content.button_url);
1870
- if (target.startsWith('/') && !target.startsWith('//')) {
2138
+ if (target.startsWith("/") && !target.startsWith("//")) {
1871
2139
  href = tenantPath(props, target);
1872
2140
  } else {
1873
2141
  try {
1874
2142
  const url = new URL(target);
1875
- if (url.protocol === 'https:' || url.protocol === 'http:') href = url.href;
2143
+ if (url.protocol === "https:" || url.protocol === "http:") href = url.href;
1876
2144
  } catch {
1877
- href = tenantPath(props, '/gathering');
2145
+ href = tenantPath(props, "/gathering");
1878
2146
  }
1879
2147
  }
1880
2148
  }
1881
-
1882
- return h('section', { className: 'kumpul-cta' },
1883
- h('div', null,
1884
- h('p', { className: 'kumpul-eyebrow' }, text(content.eyebrow, 'Mulai cerita baru')),
1885
- h('h2', null, text(content.title, 'Siap bikin gathering pertamamu?')),
1886
- h('p', null, text(content.subtitle, 'Rencanakan acara, undang komunitas, dan nikmati momen bersama.')),
1887
- ),
1888
- h('div', { className: 'kumpul-cta-actions' },
1889
- h('a', { className: 'kumpul-button kumpul-button-light', href },
1890
- text(content.button_text, 'Lihat Gathering'), h(Icon, { name: 'arrow' }),
1891
- ),
2149
+ return h(
2150
+ "section",
2151
+ { className: "kumpul-cta" },
2152
+ h(
2153
+ "div",
2154
+ null,
2155
+ h("p", { className: "kumpul-eyebrow" }, text(content.eyebrow, "Mulai cerita baru")),
2156
+ h("h2", null, text(content.title, "Siap bikin gathering pertamamu?")),
2157
+ h("p", null, text(content.subtitle, "Rencanakan acara, undang komunitas, dan nikmati momen bersama."))
1892
2158
  ),
2159
+ h(
2160
+ "div",
2161
+ { className: "kumpul-cta-actions" },
2162
+ h(
2163
+ "a",
2164
+ { className: "kumpul-button kumpul-button-light", href },
2165
+ text(content.button_text, "Lihat Gathering"),
2166
+ h(Icon, { name: "arrow" })
2167
+ )
2168
+ )
1893
2169
  );
1894
2170
  }
1895
-
1896
2171
  function MobileDock(props) {
1897
2172
  const auth = props.auth || {};
1898
2173
  const links = [
1899
- ['Keranjang', auth.cartHref, 'cart'],
1900
- ['Tagihan', auth.tagihanHref, 'receipt'],
1901
- ['Transaksi', auth.ordersHref, 'orders'],
1902
- ['Kalender', auth.calendarHref, 'calendar'],
1903
- ['Inbox', auth.chatHref, 'chat'],
1904
- ['Profil', auth.profileHref, 'profile'],
1905
- ].filter(([, href]) => typeof href === 'string' && href.length > 0);
1906
-
2174
+ ["Keranjang", auth.cartHref, "cart"],
2175
+ ["Tagihan", auth.tagihanHref, "receipt"],
2176
+ ["Transaksi", auth.ordersHref, "orders"],
2177
+ ["Kalender", auth.calendarHref, "calendar"],
2178
+ ["Inbox", auth.chatHref, "chat"],
2179
+ ["Profil", auth.profileHref, "profile"]
2180
+ ].filter(([, href]) => typeof href === "string" && href.length > 0);
1907
2181
  if (!links.length) return null;
1908
- return h('nav', { className: 'kumpul-mobile-dock', 'aria-label': 'Menu akun' },
1909
- ...links.map(([label, href, icon]) => h('a', {
1910
- href,
1911
- key: label,
1912
- 'aria-label': label,
1913
- 'aria-current': (
1914
- (props.activePageSlug === 'tagihan' || props.activePageSlug === 'invoice-detail') && label === 'Tagihan'
1915
- || (props.activePageSlug === 'orders' || props.activePageSlug === 'transaction-detail') && label === 'Transaksi'
1916
- || (props.activePageSlug === 'cart' || props.activePageSlug === 'plan-detail') && label === 'Keranjang'
1917
- ) ? 'page' : undefined,
1918
- },
1919
- h(Icon, { name: icon }), h('span', null, label),
1920
- )),
2182
+ return h(
2183
+ "nav",
2184
+ { className: "kumpul-mobile-dock", "aria-label": "Menu akun" },
2185
+ ...links.map(([label, href, icon]) => h(
2186
+ "a",
2187
+ {
2188
+ href,
2189
+ key: label,
2190
+ "aria-label": label,
2191
+ "aria-current": (props.activePageSlug === "tagihan" || props.activePageSlug === "invoice-detail") && label === "Tagihan" || (props.activePageSlug === "orders" || props.activePageSlug === "transaction-detail") && label === "Transaksi" || (props.activePageSlug === "cart" || props.activePageSlug === "plan-detail") && label === "Keranjang" ? "page" : void 0
2192
+ },
2193
+ h(Icon, { name: icon }),
2194
+ h("span", null, label)
2195
+ ))
1921
2196
  );
1922
2197
  }
1923
-
1924
2198
  function styles(colors) {
1925
2199
  return `
1926
2200
  .kumpul-cart{max-width:1080px;margin:0 auto}.kumpul-cart-heading h1{margin:0;font-size:clamp(30px,4vw,40px);line-height:1.15;letter-spacing:-.04em}.kumpul-cart-heading h1 span{margin-left:9px;color:var(--kt-muted);font-size:14px;font-weight:500;letter-spacing:0}.kumpul-cart-heading>div>p:last-child{margin:8px 0 0;color:var(--kt-muted);font-size:12px}.kumpul-cart-preview-note{margin:18px 0 0;padding:10px 13px;border:1px solid var(--kt-border);border-radius:12px;background:var(--kt-surface);color:var(--kt-muted);font-size:10px}.kumpul-cart-layout{margin-top:22px;display:grid;grid-template-columns:minmax(0,1fr) 300px;align-items:start;gap:22px}.kumpul-cart-select-all{margin-bottom:10px}.kumpul-cart-select-all button{padding:8px 0;border:0;background:none;color:var(--kt-muted);font:inherit;font-size:10px;font-weight:750;cursor:pointer}.kumpul-cart-list{display:grid;gap:11px}.kumpul-cart-item{padding:15px;display:grid;grid-template-columns:24px 70px minmax(0,1fr) auto;align-items:start;gap:13px;border:1px solid var(--kt-border);border-radius:16px;background:var(--kt-surface)}.kumpul-cart-choice{padding-top:4px;display:flex;justify-content:center}.kumpul-cart-choice input{width:17px;height:17px;accent-color:var(--kt-accent)}.kumpul-cart-choice input:disabled{opacity:.4}.kumpul-cart-art{width:70px;height:70px;display:grid;place-items:center;border:1px solid var(--kt-border);border-radius:14px;background:var(--kt-bg);color:var(--kt-accent);font-size:29px}.kumpul-cart-copy{min-width:0}.kumpul-cart-kind{color:var(--kt-accent);font-size:8px;font-weight:800;letter-spacing:.1em;text-transform:uppercase}.kumpul-cart-copy h2{margin:4px 0 0;font-size:13px}.kumpul-cart-detail,.kumpul-cart-variant{margin:5px 0 0;color:var(--kt-muted);font-size:10px}.kumpul-cart-blocked{margin:7px 0 0;color:#a15c00;font-size:9px;font-weight:700}.kumpul-cart-item-controls{min-width:130px;display:grid;justify-items:end;gap:10px}.kumpul-cart-price{color:var(--kt-accent);font-size:13px}.kumpul-cart-quantity{display:flex;align-items:center;border:1px solid var(--kt-border);border-radius:9px;overflow:hidden}.kumpul-cart-quantity button{width:30px;height:28px;border:0;background:var(--kt-bg);color:var(--kt-text);font:inherit;font-weight:700;cursor:pointer}.kumpul-cart-quantity button:disabled{opacity:.4;cursor:not-allowed}.kumpul-cart-quantity span{min-width:28px;text-align:center;font-size:10px}.kumpul-cart-remove{padding:0;border:0;background:none;color:#b91c1c;font:inherit;font-size:9px;font-weight:700;cursor:pointer}.kumpul-cart-summary{position:sticky;top:20px;padding:18px;border:1px solid var(--kt-border);border-radius:17px;background:var(--kt-surface)}.kumpul-cart-summary h2{margin:0 0 15px;font-size:15px}.kumpul-cart-summary-row,.kumpul-cart-summary-total{display:flex;justify-content:space-between;gap:12px}.kumpul-cart-summary-row{padding-bottom:13px;border-bottom:1px solid var(--kt-border);color:var(--kt-muted);font-size:10px}.kumpul-cart-summary-row strong{color:var(--kt-text)}.kumpul-cart-summary-total{padding:14px 0;align-items:baseline;color:var(--kt-muted);font-size:10px}.kumpul-cart-summary-total strong{color:var(--kt-accent);font-size:18px}.kumpul-cart-checkout{width:100%;min-height:42px;border:0;border-radius:11px;background:var(--kt-accent);color:#fff;font:inherit;font-size:11px;font-weight:800;opacity:.56;cursor:not-allowed}.kumpul-cart-summary>p{margin:11px 0 0;color:var(--kt-muted);font-size:9px;line-height:1.5}.kumpul-cart-empty{margin:8px 0 0;padding:20px;border:1px dashed var(--kt-border);border-radius:13px;color:var(--kt-muted);font-size:11px;text-align:center}.kumpul-cart-empty-state{max-width:600px;margin:20px auto;padding:50px 20px;text-align:center;border:1px solid var(--kt-border);border-radius:22px;background:var(--kt-surface)}.kumpul-cart-empty-icon{width:58px;height:58px;margin:auto;display:grid;place-items:center;border-radius:50%;background:var(--kt-bg);font-size:27px}.kumpul-cart-empty-state h1{margin:15px 0 0;font-size:25px}.kumpul-cart-empty-state p{margin:8px 0 0;color:var(--kt-muted);font-size:12px}.kumpul-cart-browse{margin-top:18px;padding:11px 17px;display:inline-flex;border-radius:11px;background:var(--kt-accent);color:#fff;font-size:10px;font-weight:800}
@@ -1952,7 +2226,7 @@ function styles(colors) {
1952
2226
  .kumpul-about-section{max-width:1180px;min-height:390px;margin:12px auto 0;padding:clamp(26px,5vw,58px);display:grid;grid-template-columns:1fr .85fr;align-items:center;gap:clamp(28px,6vw,72px);overflow:hidden;border:1px solid var(--kt-border);border-radius:26px;background:var(--kt-surface)}.kumpul-about-copy h1{max-width:650px;margin:0;font-size:clamp(34px,5vw,60px);line-height:1.03;font-weight:850;letter-spacing:-.06em}.kumpul-about-body{max-width:620px;margin:20px 0 0;color:var(--kt-muted);font-size:15px;line-height:1.8;white-space:pre-line}.kumpul-about-art,.kumpul-about-image{position:relative;min-height:270px;display:grid;place-items:center;overflow:hidden;border-radius:22px;background:radial-gradient(ellipse at 60% 40%,#58a3b8 0,#006699 58%,#00557a 100%)}.kumpul-about-art:before,.kumpul-about-art:after{position:absolute;width:270px;height:270px;border:1px solid #ffffff50;border-radius:50%;content:""}.kumpul-about-art:after{width:360px;height:360px}.kumpul-about-art span{position:absolute;z-index:1;display:grid;place-items:center;width:104px;height:104px;border:1px solid #ffffff70;border-radius:30px;background:#ffffff25;font-size:55px;box-shadow:0 16px 36px #002b443d}.kumpul-about-art span:first-child{transform:translate(-42px,-18px) rotate(-9deg)}.kumpul-about-art span:last-child{transform:translate(48px,40px) rotate(9deg)}.kumpul-about-image img{position:absolute;width:100%;height:100%;inset:0;object-fit:cover}
1953
2227
  .kumpul-gallery-grid{margin-top:24px;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));grid-auto-rows:180px;gap:14px}.kumpul-gallery-item{position:relative;margin:0;display:grid;place-items:center;overflow:hidden;border:1px solid var(--kt-border);border-radius:18px;background:linear-gradient(135deg,#d9eff0,#91c4c9)}.kumpul-gallery-item:nth-child(3n+2){grid-row:span 2}.kumpul-gallery-item img{position:absolute;width:100%;height:100%;inset:0;object-fit:cover;transition:transform .25s}.kumpul-gallery-item:hover img{transform:scale(1.04)}.kumpul-gallery-item>span{font-size:48px;filter:drop-shadow(0 10px 12px #163c3b25)}.kumpul-gallery-item figcaption{position:absolute;right:10px;bottom:10px;left:10px;padding:8px 10px;border:1px solid #ffffff80;border-radius:10px;background:#fffffff0;color:var(--kt-text);font-size:11px;font-weight:700}
1954
2228
  .kumpul-process-list{margin:28px 0 0;padding:0;display:grid;grid-template-columns:repeat(5,minmax(0,1fr));list-style:none;border:1px solid var(--kt-border);border-radius:20px;background:var(--kt-surface)}.kumpul-process-step{min-width:0;padding:22px 18px;display:flex;flex-direction:column;align-items:flex-start;gap:10px}.kumpul-process-step+.kumpul-process-step{border-left:1px solid var(--kt-border)}.kumpul-process-step h2{margin:0;font-size:14px}.kumpul-process-step p{margin:0;color:var(--kt-muted);font-size:11px;line-height:1.6}.kumpul-process-step small{margin-top:auto;color:var(--kt-accent);font-size:10px;font-weight:750}
1955
- .kumpul-faq-list{margin-top:24px;display:grid;gap:10px}.kumpul-faq-item{padding:17px 19px;border:1px solid var(--kt-border);border-radius:15px;background:var(--kt-surface)}.kumpul-faq-item summary{font-size:13px;font-weight:750;cursor:pointer;list-style:none}.kumpul-faq-item summary::-webkit-details-marker{display:none}.kumpul-faq-item summary:after{float:right;color:var(--kt-accent);content:"+";font-size:18px;line-height:1}.kumpul-faq-item[open] summary:after{content:"−"}.kumpul-faq-item p{margin:12px 0 0;color:var(--kt-muted);font-size:12px;line-height:1.7;white-space:pre-line}
2229
+ .kumpul-faq-list{margin-top:24px;display:grid;gap:10px}.kumpul-faq-item{padding:17px 19px;border:1px solid var(--kt-border);border-radius:15px;background:var(--kt-surface)}.kumpul-faq-item summary{font-size:13px;font-weight:750;cursor:pointer;list-style:none}.kumpul-faq-item summary::-webkit-details-marker{display:none}.kumpul-faq-item summary:after{float:right;color:var(--kt-accent);content:"+";font-size:18px;line-height:1}.kumpul-faq-item[open] summary:after{content:"\u2212"}.kumpul-faq-item p{margin:12px 0 0;color:var(--kt-muted);font-size:12px;line-height:1.7;white-space:pre-line}
1956
2230
  .kumpul-feature-location{position:relative;z-index:1;align-self:flex-start;display:flex;align-items:center;gap:8px;padding:8px 12px;border:1px solid #ffffff44;border-radius:999px;background:#ffffffec;color:#28576a;font-size:11px;font-weight:700}.kumpul-feature-location .kumpul-icon{width:16px;height:16px}
1957
2231
  .kumpul-feature-art{position:absolute;inset:0;display:grid;place-items:center;overflow:hidden}.kumpul-feature-art:before,.kumpul-feature-art:after{position:absolute;content:"";border:1px solid #ffffff2c;border-radius:50%;width:310px;height:310px}.kumpul-feature-art:after{width:430px;height:430px}.kumpul-feature-art>span{position:relative;z-index:1;width:112px;height:112px;display:grid;place-items:center;border:1px solid #ffffff66;border-radius:34px;background:#ffffff20;font-size:56px;font-weight:800;letter-spacing:-.1em;transform:rotate(-8deg);box-shadow:0 18px 48px #002b443d}.kumpul-feature-art i{position:absolute;width:8px;height:8px;border-radius:50%;background:#c9edf2;box-shadow:0 0 18px #fff}.kumpul-feature-art i:first-of-type{top:29%;right:22%}.kumpul-feature-art i:last-of-type{bottom:27%;left:19%;width:6px;height:6px}
1958
2232
  .kumpul-feature-note{position:relative;z-index:1;display:flex;align-items:center;gap:12px;padding:11px 13px;border:1px solid #ffffffaa;border-radius:17px;background:#fff;color:var(--kt-text);box-shadow:0 10px 24px #002b4433}.kumpul-feature-note>span:nth-child(2){min-width:0;display:grid}.kumpul-feature-note strong{overflow:hidden;font-size:12px;text-overflow:ellipsis;white-space:nowrap}.kumpul-feature-note small{margin-top:3px;color:var(--kt-muted);font-size:10px}.kumpul-avatar{width:36px;height:36px;flex:none;display:grid;place-items:center;border:1px solid var(--kt-border);border-radius:50%;background:var(--kt-bg);color:var(--kt-accent);font-size:12px;font-weight:800}.kumpul-check{width:25px;height:25px;flex:none;margin-left:auto;display:grid;place-items:center;border-radius:50%;background:var(--kt-success);color:#fff;font-weight:800}
@@ -1978,43 +2252,41 @@ function styles(colors) {
1978
2252
  @media(prefers-reduced-motion:reduce){.kumpul-template *{scroll-behavior:auto!important;transition:none!important}}
1979
2253
  `;
1980
2254
  }
1981
-
1982
2255
  function render(props = {}) {
1983
2256
  const colors = themeColors(props);
1984
2257
  const sections = list(props.sections);
1985
- const orderDetailSection = sections.find((section) => section?.type === 'order_detail');
1986
- const activePageSlug = orderDetailSection
1987
- ? orderDetailSection.content?.gatheringPlan ? 'plan-detail' : 'transaction-detail'
1988
- : ['cart', 'orders', 'tagihan', 'invoice-detail', 'transaction-detail', 'plan-detail'].includes(props.activePageSlug)
1989
- ? props.activePageSlug
1990
- : pageSlugForSections(sections);
1991
- const catalogPage = activePageSlug === 'gathering';
1992
- const billingPage = activePageSlug === 'tagihan';
1993
- const transactionsPage = activePageSlug === 'orders';
1994
- const cartPage = activePageSlug === 'cart';
1995
- const invoiceDetailPage = activePageSlug === 'invoice-detail';
1996
- const transactionDetailPage = activePageSlug === 'transaction-detail';
1997
- const gatheringPlanDetailPage = activePageSlug === 'plan-detail';
1998
- const hero = Section(props, 'hero');
1999
- const features = Section(props, 'features_grid');
2000
- const gatherings = Section(props, 'products_grid');
2001
- const testimonials = Section(props, 'testimonial');
2002
- const locations = Section(props, 'locations_list');
2003
- const cta = Section(props, 'cta');
2258
+ const orderDetailSection = sections.find((section) => section?.type === "order_detail");
2259
+ const activePageSlug = orderDetailSection ? orderDetailSection.content?.gatheringPlan ? "plan-detail" : "transaction-detail" : ["cart", "orders", "tagihan", "invoice-detail", "transaction-detail", "plan-detail"].includes(props.activePageSlug) ? props.activePageSlug : pageSlugForSections(sections);
2260
+ const catalogPage = activePageSlug === "gathering";
2261
+ const billingPage = activePageSlug === "tagihan";
2262
+ const transactionsPage = activePageSlug === "orders";
2263
+ const cartPage = activePageSlug === "cart";
2264
+ const invoiceDetailPage = activePageSlug === "invoice-detail";
2265
+ const transactionDetailPage = activePageSlug === "transaction-detail";
2266
+ const gatheringPlanDetailPage = activePageSlug === "plan-detail";
2267
+ const hero = Section(props, "hero");
2268
+ const features = Section(props, "features_grid");
2269
+ const gatherings = Section(props, "products_grid");
2270
+ const testimonials = Section(props, "testimonial");
2271
+ const locations = Section(props, "locations_list");
2272
+ const cta = Section(props, "cta");
2004
2273
  const profile = props.profile || {};
2005
-
2006
- return h('div', { className: 'kumpul-template' },
2007
- h('style', { dangerouslySetInnerHTML: { __html: styles(colors) } }),
2274
+ return h(
2275
+ "div",
2276
+ { className: "kumpul-template" },
2277
+ h("style", { dangerouslySetInnerHTML: { __html: styles(colors) } }),
2008
2278
  h(Header, { ...props, activePageSlug }),
2009
- h('main', { className: 'kumpul-main' },
2279
+ h(
2280
+ "main",
2281
+ { className: "kumpul-main" },
2010
2282
  hero ? h(Hero, { ...props, section: hero }) : null,
2011
- sections.filter((section) => section?.type === 'about').map((section) => h(AboutSection, { ...section, key: section.id || 'about' })),
2283
+ sections.filter((section) => section?.type === "about").map((section) => h(AboutSection, { ...section, key: section.id || "about" })),
2012
2284
  features ? h(FeaturesSection, features) : null,
2013
- sections.filter((section) => section?.type === 'gallery').map((section) => h(GallerySection, { ...section, key: section.id || 'gallery' })),
2285
+ sections.filter((section) => section?.type === "gallery").map((section) => h(GallerySection, { ...section, key: section.id || "gallery" })),
2014
2286
  gatherings ? h(GatheringsSection, { props, section: gatherings, catalogPage }) : null,
2015
- sections.filter((section) => section?.type === 'service_process_section').map((section) => h(ProcessSection, { ...section, key: section.id || 'process' })),
2016
- sections.filter((section) => section?.type === 'faq_list').map((section) => h(FaqSection, { props, section, key: section.id || 'faq' })),
2017
- sections.filter((section) => section?.type === 'gathering_calendar').map((section) => h(CalendarSection, { props, section, key: section.id || 'calendar' })),
2287
+ sections.filter((section) => section?.type === "service_process_section").map((section) => h(ProcessSection, { ...section, key: section.id || "process" })),
2288
+ sections.filter((section) => section?.type === "faq_list").map((section) => h(FaqSection, { props, section, key: section.id || "faq" })),
2289
+ sections.filter((section) => section?.type === "gathering_calendar").map((section) => h(CalendarSection, { props, section, key: section.id || "calendar" })),
2018
2290
  billingPage ? h(BillingSection, { props }) : null,
2019
2291
  transactionsPage ? h(TransactionsSection, { props }) : null,
2020
2292
  cartPage ? h(CartSection, { props }) : null,
@@ -2024,19 +2296,20 @@ function render(props = {}) {
2024
2296
  testimonials ? h(TestimonialsSection, testimonials) : null,
2025
2297
  locations ? h(LocationsSection, { props, section: locations }) : null,
2026
2298
  cta ? h(CallToAction, { props, section: cta }) : null,
2027
- sections.length === 0 && !activePageSlug
2028
- ? h('section', { className: 'kumpul-empty-state', 'aria-label': 'Belum ada section' },
2029
- h('h1', null, text(profile.name, 'Kumpul')),
2030
- h('p', null, 'Tambahkan section melalui editor website untuk mulai menampilkan konten.'),
2031
- )
2032
- : null,
2299
+ sections.length === 0 && !activePageSlug ? h(
2300
+ "section",
2301
+ { className: "kumpul-empty-state", "aria-label": "Belum ada section" },
2302
+ h("h1", null, text(profile.name, "Kumpul")),
2303
+ h("p", null, "Tambahkan section melalui editor website untuk mulai menampilkan konten.")
2304
+ ) : null
2033
2305
  ),
2034
- h('footer', { className: 'kumpul-footer' },
2035
- h('strong', null, text(profile.name, 'Kumpul')),
2036
- h('span', null, text(profile.tagline, 'Tempat cerita dan kebersamaan dimulai.')),
2306
+ h(
2307
+ "footer",
2308
+ { className: "kumpul-footer" },
2309
+ h("strong", null, text(profile.name, "Kumpul")),
2310
+ h("span", null, text(profile.tagline, "Tempat cerita dan kebersamaan dimulai."))
2037
2311
  ),
2038
- h(MobileDock, { ...props, activePageSlug }),
2312
+ h(MobileDock, { ...props, activePageSlug })
2039
2313
  );
2040
2314
  }
2041
-
2042
2315
  module.exports = { render };