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