@bagdja/kumpul 0.0.0-stage → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +101 -2
- package/dist/client.js +2886 -0
- package/dist/server.cjs +2041 -0
- package/manifest.json +23 -0
- package/package.json +34 -4
package/dist/server.cjs
ADDED
|
@@ -0,0 +1,2041 @@
|
|
|
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',
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function text(value, fallback = '') {
|
|
18
|
+
return typeof value === 'string' && value.trim() ? value : fallback;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function list(value) {
|
|
22
|
+
return Array.isArray(value) ? value : [];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
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, '');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function isGatheringCatalogPage(sections) {
|
|
36
|
+
const visibleSections = sections.filter((section) => section && section.type);
|
|
37
|
+
return visibleSections.length === 1 && visibleSections[0].type === 'products_grid';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
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';
|
|
49
|
+
}
|
|
50
|
+
return '';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
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';
|
|
59
|
+
}
|
|
60
|
+
return ({
|
|
61
|
+
SCHEDULED: 'scheduled',
|
|
62
|
+
ISSUED: 'issued',
|
|
63
|
+
PAID: 'paid',
|
|
64
|
+
CANCELLED: 'cancelled',
|
|
65
|
+
})[invoice.status] || 'scheduled';
|
|
66
|
+
}
|
|
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' },
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const billingFilters = [
|
|
77
|
+
['all', 'Semua'],
|
|
78
|
+
['scheduled', 'Menunggu diterbitkan'],
|
|
79
|
+
['issued', 'Perlu dibayar'],
|
|
80
|
+
['paid', 'Lunas'],
|
|
81
|
+
['refunded', 'Direfund'],
|
|
82
|
+
['cancelled', 'Dibatalkan'],
|
|
83
|
+
];
|
|
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' },
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const transactionFilters = [
|
|
97
|
+
['all', 'Semua'],
|
|
98
|
+
['awaiting', 'Menunggu Bayar'],
|
|
99
|
+
['process', 'Diproses'],
|
|
100
|
+
['done', 'Selesai'],
|
|
101
|
+
['cancelled', 'Dibatalkan'],
|
|
102
|
+
];
|
|
103
|
+
|
|
104
|
+
function CartSection({ props }) {
|
|
105
|
+
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.'),
|
|
119
|
+
),
|
|
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,
|
|
145
|
+
},
|
|
146
|
+
h('label', { className: 'kumpul-cart-choice' },
|
|
147
|
+
h('input', {
|
|
148
|
+
type: 'checkbox',
|
|
149
|
+
defaultChecked: canCheckout,
|
|
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,
|
|
166
|
+
),
|
|
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'),
|
|
191
|
+
),
|
|
192
|
+
);
|
|
193
|
+
}),
|
|
194
|
+
),
|
|
195
|
+
),
|
|
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.'),
|
|
208
|
+
),
|
|
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'),
|
|
221
|
+
),
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function formatCurrency(value) {
|
|
226
|
+
const amount = Number(value);
|
|
227
|
+
return Number.isFinite(amount)
|
|
228
|
+
? `Rp ${amount.toLocaleString('id-ID')}`
|
|
229
|
+
: 'Nominal belum tersedia';
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function transactionStatus(transaction) {
|
|
233
|
+
if (transaction.has_outstanding_invoice === true) {
|
|
234
|
+
return { label: text(transaction.outstanding_label, 'Menunggu pelunasan'), tone: 'warning', filter: 'process' };
|
|
235
|
+
}
|
|
236
|
+
return transactionStatuses[transaction.status] || {
|
|
237
|
+
label: text(transaction.status, 'Status belum tersedia'),
|
|
238
|
+
tone: 'muted',
|
|
239
|
+
filter: 'all',
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function TransactionsSection({ props }) {
|
|
244
|
+
const transactions = props.isPreview === true ? list(props.previewTransactions) : [];
|
|
245
|
+
const counts = Object.fromEntries(transactionFilters.map(([key]) => [
|
|
246
|
+
key,
|
|
247
|
+
key === 'all' ? transactions.length : transactions.filter((transaction) => transactionStatus(transaction).filter === key).length,
|
|
248
|
+
]));
|
|
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'),
|
|
260
|
+
),
|
|
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.',
|
|
265
|
+
)
|
|
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
|
+
),
|
|
278
|
+
h('div', { className: 'kumpul-transactions-list', 'data-transactions-list': '' },
|
|
279
|
+
...transactions.map((transaction, index) => {
|
|
280
|
+
const status = transactionStatus(transaction);
|
|
281
|
+
const items = list(transaction.items);
|
|
282
|
+
const firstItem = items[0] || {};
|
|
283
|
+
const productName = text(firstItem.product_name, 'Gathering');
|
|
284
|
+
const extraCount = Math.max(0, items.length - 1);
|
|
285
|
+
const createdAt = formatCalendarDate(transaction.created_at);
|
|
286
|
+
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}` : ''}`),
|
|
307
|
+
),
|
|
308
|
+
),
|
|
309
|
+
h('div', { className: 'kumpul-transaction-total' },
|
|
310
|
+
h('span', null, 'Total'),
|
|
311
|
+
h('strong', null, formatCurrency(transaction.total_amount)),
|
|
312
|
+
),
|
|
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
|
+
),
|
|
321
|
+
);
|
|
322
|
+
}),
|
|
323
|
+
h('p', {
|
|
324
|
+
className: 'kumpul-transactions-empty',
|
|
325
|
+
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',
|
|
332
|
+
hidden: true,
|
|
333
|
+
'data-transactions-filter-empty': '',
|
|
334
|
+
}, 'Belum ada transaksi dengan status ini. Coba pilih filter lain.'),
|
|
335
|
+
),
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
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' };
|
|
343
|
+
return {
|
|
344
|
+
label: invoice.payment_open === false ? 'Pembayaran belum dibuka' : 'Belum dibayar',
|
|
345
|
+
tone: 'warning',
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function InvoiceDetailSection({ props }) {
|
|
350
|
+
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.'),
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
const invoice = props.isPreview === true ? props.previewInvoice || {} : {};
|
|
357
|
+
const status = invoiceDetailStatus(invoice);
|
|
358
|
+
const amount = new Intl.NumberFormat('id-ID', {
|
|
359
|
+
style: 'currency',
|
|
360
|
+
currency: text(invoice.currency, 'IDR'),
|
|
361
|
+
maximumFractionDigits: 0,
|
|
362
|
+
}).format(Number(invoice.amount) || 0);
|
|
363
|
+
const isPaid = ['PAID', 'REFUNDED'].includes(invoice.payment_status);
|
|
364
|
+
const isPending = invoice.payment_status === 'PENDING_PAYMENT';
|
|
365
|
+
const paymentOpen = invoice.payment_open === true;
|
|
366
|
+
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],
|
|
373
|
+
];
|
|
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')),
|
|
381
|
+
),
|
|
382
|
+
h('span', { className: `kumpul-transaction-status kumpul-transaction-status-${status.tone}` }, status.label),
|
|
383
|
+
),
|
|
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),
|
|
403
|
+
),
|
|
404
|
+
),
|
|
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
|
+
),
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function TransactionDetailSection({ props, section }) {
|
|
428
|
+
const transaction = props.isPreview === true
|
|
429
|
+
? props.previewTransaction || {}
|
|
430
|
+
: section?.content?.transaction || {};
|
|
431
|
+
const items = list(transaction.items);
|
|
432
|
+
const status = transactionStatus(transaction);
|
|
433
|
+
const subtotal = items.reduce((sum, item) => sum + (Number(item.total_amount) || 0), 0);
|
|
434
|
+
const itemCount = items.reduce((sum, item) => sum + (Number(item.quantity) || 1), 0);
|
|
435
|
+
const shipping = transaction.metadata?.shipping || {};
|
|
436
|
+
const shippingCost = Number(transaction.shipping_cost) || 0;
|
|
437
|
+
const address = [
|
|
438
|
+
transaction.recipient_name,
|
|
439
|
+
transaction.phone,
|
|
440
|
+
transaction.address,
|
|
441
|
+
transaction.district,
|
|
442
|
+
transaction.city,
|
|
443
|
+
transaction.postal_code,
|
|
444
|
+
].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, '—')}`)),
|
|
453
|
+
),
|
|
454
|
+
h('span', { className: `kumpul-transaction-status kumpul-transaction-status-${status.tone}` }, status.label),
|
|
455
|
+
),
|
|
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' },
|
|
466
|
+
...items.map((item, index) => {
|
|
467
|
+
const product = item.order?.product || {};
|
|
468
|
+
const title = text(product.name, text(item.product_name, 'Gathering'));
|
|
469
|
+
const gatheringInvoice = item.order?.gathering_invoice;
|
|
470
|
+
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,
|
|
481
|
+
),
|
|
482
|
+
h('strong', null, formatCurrency(item.total_amount)),
|
|
483
|
+
);
|
|
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(' · ')),
|
|
491
|
+
)
|
|
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
|
+
),
|
|
506
|
+
)
|
|
507
|
+
: null,
|
|
508
|
+
),
|
|
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))),
|
|
515
|
+
),
|
|
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,
|
|
523
|
+
),
|
|
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
|
+
),
|
|
538
|
+
);
|
|
539
|
+
}
|
|
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' },
|
|
546
|
+
];
|
|
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',
|
|
557
|
+
};
|
|
558
|
+
|
|
559
|
+
function GatheringPlanSimulator({ plan, props }) {
|
|
560
|
+
const occurrence = plan.occurrence || {};
|
|
561
|
+
const options = list(occurrence.option_groups_snapshot);
|
|
562
|
+
const openedIds = new Set(list(occurrence.opened_option_ids_snapshot));
|
|
563
|
+
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,
|
|
597
|
+
},
|
|
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
|
+
),
|
|
614
|
+
),
|
|
615
|
+
),
|
|
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': '' }),
|
|
621
|
+
),
|
|
622
|
+
),
|
|
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': '' }),
|
|
627
|
+
),
|
|
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': '' }),
|
|
633
|
+
),
|
|
634
|
+
),
|
|
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',
|
|
643
|
+
value: option.product_option_id,
|
|
644
|
+
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': '',
|
|
651
|
+
}),
|
|
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': '' }),
|
|
680
|
+
),
|
|
681
|
+
h('button', { type: 'button', 'data-sim-add-invite': '' }, 'Tambah peserta'),
|
|
682
|
+
),
|
|
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': '' }),
|
|
693
|
+
),
|
|
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…'),
|
|
718
|
+
),
|
|
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)'),
|
|
732
|
+
),
|
|
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': '' }),
|
|
741
|
+
),
|
|
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)'),
|
|
746
|
+
),
|
|
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
|
+
),
|
|
754
|
+
);
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
function GatheringPlanDetailSection({ props, section }) {
|
|
758
|
+
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 || {};
|
|
765
|
+
const occurrence = plan.occurrence || {};
|
|
766
|
+
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';
|
|
775
|
+
const dateTime = (value) => {
|
|
776
|
+
const date = formatCalendarDate(value);
|
|
777
|
+
const time = formatCalendarTime(value);
|
|
778
|
+
return date ? `${date}${time ? ` · ${time} WIB` : ''}` : 'Belum ditentukan';
|
|
779
|
+
};
|
|
780
|
+
const workflowStatus = text(gatheringPlanStatuses[plan.status], text(plan.status, 'Status belum tersedia'));
|
|
781
|
+
const seatPrice = Number(occurrence.price_per_seat);
|
|
782
|
+
const depositPerSeat = Number(occurrence.deposit_amount_per_seat);
|
|
783
|
+
|
|
784
|
+
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.'),
|
|
790
|
+
);
|
|
791
|
+
}
|
|
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')}`),
|
|
800
|
+
),
|
|
801
|
+
h('span', { className: 'kumpul-transaction-status kumpul-transaction-status-info' }, workflowStatus),
|
|
802
|
+
),
|
|
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,
|
|
808
|
+
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', {
|
|
815
|
+
key: step.key,
|
|
816
|
+
className: index < currentStepIndex ? 'is-complete' : index === currentStepIndex ? 'is-current' : '',
|
|
817
|
+
'aria-current': index === currentStepIndex ? 'step' : undefined,
|
|
818
|
+
},
|
|
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.'),
|
|
824
|
+
),
|
|
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
|
+
),
|
|
845
|
+
),
|
|
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,
|
|
865
|
+
),
|
|
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
|
+
}),
|
|
872
|
+
),
|
|
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'),
|
|
889
|
+
),
|
|
890
|
+
),
|
|
891
|
+
);
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
function BillingSection({ props }) {
|
|
895
|
+
const previewInvoices = props.isPreview === true ? list(props.previewInvoices) : [];
|
|
896
|
+
const outstandingCount = previewInvoices.filter((invoice) => billingStatus(invoice) === 'issued').length;
|
|
897
|
+
const counts = Object.fromEntries(billingFilters.map(([key]) => [
|
|
898
|
+
key,
|
|
899
|
+
key === 'all' ? previewInvoices.length : previewInvoices.filter((invoice) => billingStatus(invoice) === key).length,
|
|
900
|
+
]));
|
|
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.'),
|
|
908
|
+
),
|
|
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'),
|
|
913
|
+
),
|
|
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.',
|
|
923
|
+
)
|
|
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
|
+
),
|
|
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`),
|
|
940
|
+
),
|
|
941
|
+
h('div', { className: 'kumpul-billing-list', 'data-billing-list': '' },
|
|
942
|
+
...previewInvoices.map((invoice, index) => {
|
|
943
|
+
const status = billingStatus(invoice);
|
|
944
|
+
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'))}`;
|
|
950
|
+
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,
|
|
969
|
+
),
|
|
970
|
+
status === 'issued'
|
|
971
|
+
? h('button', { type: 'button', className: 'kumpul-billing-action', disabled: true }, isGathering ? 'Lihat detail tagihan' : 'Bayar')
|
|
972
|
+
: null,
|
|
973
|
+
),
|
|
974
|
+
);
|
|
975
|
+
}),
|
|
976
|
+
h('p', {
|
|
977
|
+
className: 'kumpul-billing-empty',
|
|
978
|
+
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',
|
|
985
|
+
hidden: true,
|
|
986
|
+
'data-billing-filter-empty': '',
|
|
987
|
+
}, 'Tidak ada tagihan dengan status ini.'),
|
|
988
|
+
),
|
|
989
|
+
),
|
|
990
|
+
);
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
function formatGatheringDate(value) {
|
|
994
|
+
if (typeof value !== 'string' || !value.trim()) return '';
|
|
995
|
+
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',
|
|
1002
|
+
}).format(date);
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
function tenantPath(props, path) {
|
|
1006
|
+
const base = text(props.websiteSlug).replace(/\/+$/, '');
|
|
1007
|
+
const suffix = path.startsWith('/') ? path : `/${path}`;
|
|
1008
|
+
return `${base}${suffix}` || '/';
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
function themeColors(props) {
|
|
1012
|
+
const templateColors = props.templateTheme?.colors || {};
|
|
1013
|
+
const websiteColors = props.websiteTheme?.colors || {};
|
|
1014
|
+
const colors = {};
|
|
1015
|
+
|
|
1016
|
+
for (const [key, fallback] of Object.entries(defaultColors)) {
|
|
1017
|
+
const candidate = websiteColors[key] ?? templateColors[key];
|
|
1018
|
+
colors[key] = typeof candidate === 'string' && /^#[\da-f]{3,8}$/i.test(candidate)
|
|
1019
|
+
? candidate
|
|
1020
|
+
: fallback;
|
|
1021
|
+
}
|
|
1022
|
+
return colors;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
function Icon({ name }) {
|
|
1026
|
+
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' }),
|
|
1036
|
+
};
|
|
1037
|
+
|
|
1038
|
+
return h('svg', {
|
|
1039
|
+
'aria-hidden': 'true',
|
|
1040
|
+
viewBox: '0 0 24 24',
|
|
1041
|
+
fill: 'none',
|
|
1042
|
+
stroke: 'currentColor',
|
|
1043
|
+
strokeWidth: 1.8,
|
|
1044
|
+
strokeLinecap: 'round',
|
|
1045
|
+
strokeLinejoin: 'round',
|
|
1046
|
+
className: 'kumpul-icon',
|
|
1047
|
+
}, paths[name] || paths.arrow);
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
function Section(props, type) {
|
|
1051
|
+
return list(props.sections).find((section) => section?.type === type) || null;
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
function gatheringProducts(props) {
|
|
1055
|
+
const section = Section(props, 'products_grid');
|
|
1056
|
+
const filterType = text(section?.content?.filter_type, 'gathering');
|
|
1057
|
+
return list(props.products).filter((product) => !product.type || product.type === filterType);
|
|
1058
|
+
}
|
|
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,
|
|
1065
|
+
);
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
function Header(props) {
|
|
1069
|
+
const profile = props.profile || {};
|
|
1070
|
+
const auth = props.auth || {};
|
|
1071
|
+
const pages = list(props.pages).filter((page) => page.placement !== 'footer').slice(0, 5);
|
|
1072
|
+
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);
|
|
1077
|
+
return false;
|
|
1078
|
+
});
|
|
1079
|
+
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
|
+
),
|
|
1098
|
+
),
|
|
1099
|
+
h('nav', { className: 'kumpul-utilities', 'aria-label': 'Menu akun' },
|
|
1100
|
+
...accountLinks.map(([label, href, icon]) =>
|
|
1101
|
+
h('a', {
|
|
1102
|
+
href,
|
|
1103
|
+
key: label,
|
|
1104
|
+
'aria-label': label,
|
|
1105
|
+
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)),
|
|
1113
|
+
),
|
|
1114
|
+
!auth.isLoggedIn && auth.loginHref
|
|
1115
|
+
? h('a', { className: 'kumpul-login', href: auth.loginHref }, 'Masuk')
|
|
1116
|
+
: null,
|
|
1117
|
+
),
|
|
1118
|
+
),
|
|
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
|
+
),
|
|
1130
|
+
)
|
|
1131
|
+
: null,
|
|
1132
|
+
);
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
function Hero(props) {
|
|
1136
|
+
const section = props.section;
|
|
1137
|
+
const content = section?.content || {};
|
|
1138
|
+
const profile = props.profile || {};
|
|
1139
|
+
const products = gatheringProducts(props);
|
|
1140
|
+
const featured = products[0];
|
|
1141
|
+
const pages = list(props.pages);
|
|
1142
|
+
const gatheringPage = pages.find((page) => /gather|event|katalog/i.test(`${page.slug} ${page.title}`));
|
|
1143
|
+
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'),
|
|
1154
|
+
),
|
|
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.')),
|
|
1158
|
+
),
|
|
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' }),
|
|
1162
|
+
),
|
|
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
|
+
)),
|
|
1172
|
+
),
|
|
1173
|
+
),
|
|
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'),
|
|
1178
|
+
),
|
|
1179
|
+
h('div', { className: 'kumpul-feature-art', 'aria-hidden': 'true' },
|
|
1180
|
+
h('span', null, 'K'),
|
|
1181
|
+
h('i', null),
|
|
1182
|
+
h('i', null),
|
|
1183
|
+
),
|
|
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')),
|
|
1189
|
+
),
|
|
1190
|
+
h('span', { className: 'kumpul-check', 'aria-hidden': 'true' }, '✓'),
|
|
1191
|
+
),
|
|
1192
|
+
),
|
|
1193
|
+
);
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
function FeaturesSection(section) {
|
|
1197
|
+
const content = section?.content || {};
|
|
1198
|
+
const steps = list(content.features).slice(0, 6).map((feature, index) => [
|
|
1199
|
+
text(feature.icon, String(index + 1)),
|
|
1200
|
+
text(feature.title, `Tahap ${index + 1}`),
|
|
1201
|
+
text(feature.desc),
|
|
1202
|
+
]);
|
|
1203
|
+
|
|
1204
|
+
return h('section', { className: 'kumpul-section kumpul-flow', id: section?.id || 'cara-kerja' },
|
|
1205
|
+
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.'),
|
|
1209
|
+
}),
|
|
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
|
+
),
|
|
1217
|
+
),
|
|
1218
|
+
steps.length === 0
|
|
1219
|
+
? h('li', { className: 'kumpul-flow-empty' }, 'Alur gathering akan ditampilkan di sini.')
|
|
1220
|
+
: null,
|
|
1221
|
+
),
|
|
1222
|
+
);
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
function AboutSection(section) {
|
|
1226
|
+
const content = section?.content || {};
|
|
1227
|
+
const title = text(content.title, 'Kumpul bukan sekadar datang, tapi bertumbuh bareng.');
|
|
1228
|
+
const body = text(content.body);
|
|
1229
|
+
const image = text(content.image_url);
|
|
1230
|
+
|
|
1231
|
+
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,
|
|
1246
|
+
),
|
|
1247
|
+
);
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
function GallerySection(section) {
|
|
1251
|
+
const content = section?.content || {};
|
|
1252
|
+
const images = list(content.images).filter((image) => image && typeof image === 'object');
|
|
1253
|
+
if (!images.length) return null;
|
|
1254
|
+
|
|
1255
|
+
return h('section', { className: 'kumpul-section kumpul-gallery', id: section.id || 'galeri' },
|
|
1256
|
+
h(SectionHeading, {
|
|
1257
|
+
eyebrow: text(content.eyebrow, 'Momen kebersamaan'),
|
|
1258
|
+
title: text(content.title, 'Galeri Kumpul'),
|
|
1259
|
+
}),
|
|
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
|
+
),
|
|
1268
|
+
);
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
function ProcessSection(section) {
|
|
1272
|
+
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' },
|
|
1278
|
+
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',
|
|
1283
|
+
}),
|
|
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
|
+
),
|
|
1301
|
+
);
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
function FaqSection({ props, section }) {
|
|
1305
|
+
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);
|
|
1308
|
+
if (!faqs.length) return null;
|
|
1309
|
+
|
|
1310
|
+
return h('section', { className: 'kumpul-section kumpul-faq', id: section.id || 'faq' },
|
|
1311
|
+
h(SectionHeading, {
|
|
1312
|
+
eyebrow: text(content.eyebrow, 'Pertanyaan umum'),
|
|
1313
|
+
title: text(content.title, 'FAQ Gathering'),
|
|
1314
|
+
}),
|
|
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
|
+
),
|
|
1321
|
+
);
|
|
1322
|
+
}
|
|
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'],
|
|
1332
|
+
];
|
|
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',
|
|
1342
|
+
};
|
|
1343
|
+
|
|
1344
|
+
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';
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
function calendarDateKey(value) {
|
|
1355
|
+
if (typeof value !== 'string') return '';
|
|
1356
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})/.exec(value);
|
|
1357
|
+
if (!match) return '';
|
|
1358
|
+
const [, year, month, day] = match;
|
|
1359
|
+
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
|
+
: '';
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
function formatCalendarDate(value, options = { day: 'numeric', month: 'long', year: 'numeric' }) {
|
|
1368
|
+
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`));
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
function formatCalendarTime(value) {
|
|
1374
|
+
if (typeof value !== 'string' || !value) return '';
|
|
1375
|
+
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',
|
|
1381
|
+
}).format(date);
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
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);
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
function calendarMonthCells(monthKey, events, selectedDate) {
|
|
1390
|
+
const [year, month] = monthKey.split('-').map(Number);
|
|
1391
|
+
const firstDay = new Date(Date.UTC(year, month - 1, 1));
|
|
1392
|
+
const offset = (firstDay.getUTCDay() + 6) % 7;
|
|
1393
|
+
const start = new Date(Date.UTC(year, month - 1, 1 - offset));
|
|
1394
|
+
|
|
1395
|
+
return Array.from({ length: 42 }, (_, index) => {
|
|
1396
|
+
const date = new Date(start);
|
|
1397
|
+
date.setUTCDate(start.getUTCDate() + index);
|
|
1398
|
+
const key = date.toISOString().slice(0, 10);
|
|
1399
|
+
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,
|
|
1411
|
+
);
|
|
1412
|
+
});
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
function CalendarSection({ props, section }) {
|
|
1416
|
+
const content = section?.content || {};
|
|
1417
|
+
const isPreview = props.isPreview === true;
|
|
1418
|
+
const plans = isPreview ? list(content.preview_plans) : [];
|
|
1419
|
+
const invitations = isPreview ? list(content.preview_invitations) : [];
|
|
1420
|
+
const attentionCount = invitations.filter((invitation) => invitation.needs_action === true).length;
|
|
1421
|
+
const events = [
|
|
1422
|
+
...plans.filter((plan) => calendarDateKey(plan.event_date)).map((plan) => ({
|
|
1423
|
+
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'),
|
|
1428
|
+
event_date: plan.event_date,
|
|
1429
|
+
location: text(plan.event_location),
|
|
1430
|
+
})),
|
|
1431
|
+
...invitations.filter((invitation) => calendarDateKey(invitation.event_date)).map((invitation) => ({
|
|
1432
|
+
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'),
|
|
1437
|
+
event_date: invitation.event_date,
|
|
1438
|
+
location: text(invitation.event_location),
|
|
1439
|
+
})),
|
|
1440
|
+
].sort((left, right) => new Date(left.event_date).getTime() - new Date(right.event_date).getTime());
|
|
1441
|
+
const initialMonth = calendarMonthKey(content.preview_month, events[0]?.event_date);
|
|
1442
|
+
const initialDate = events.find((event) => calendarDateKey(event.event_date).startsWith(`${initialMonth}-`));
|
|
1443
|
+
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
|
+
),
|
|
1454
|
+
),
|
|
1455
|
+
h('div', { className: 'kumpul-calendar-stats', 'aria-label': 'Ringkasan kalender' },
|
|
1456
|
+
...[
|
|
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
|
+
),
|
|
1465
|
+
),
|
|
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.',
|
|
1469
|
+
)
|
|
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
|
+
),
|
|
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': '' }, '›'),
|
|
1516
|
+
),
|
|
1517
|
+
),
|
|
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),
|
|
1524
|
+
),
|
|
1525
|
+
),
|
|
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}` : ''}`),
|
|
1558
|
+
),
|
|
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.'),
|
|
1565
|
+
),
|
|
1566
|
+
),
|
|
1567
|
+
),
|
|
1568
|
+
),
|
|
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' },
|
|
1577
|
+
...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
|
+
}),
|
|
1588
|
+
),
|
|
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}`,
|
|
1605
|
+
),
|
|
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'),
|
|
1611
|
+
)),
|
|
1612
|
+
h('p', {
|
|
1613
|
+
className: 'kumpul-calendar-empty',
|
|
1614
|
+
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
|
+
),
|
|
1621
|
+
),
|
|
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, '—')}`,
|
|
1644
|
+
),
|
|
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
|
+
),
|
|
1650
|
+
)),
|
|
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
|
+
),
|
|
1657
|
+
);
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1660
|
+
function GatheringCard({ product, index, props, catalogPage = false }) {
|
|
1661
|
+
const href = tenantPath(props, `/products/${encodeURIComponent(text(product.slug, product.id || ''))}`);
|
|
1662
|
+
const image = text(product.image, text(product.images?.[0]?.url));
|
|
1663
|
+
const gathering = product.gatheringMeta || {};
|
|
1664
|
+
const eventDate = formatGatheringDate(gathering.eventDate);
|
|
1665
|
+
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]),
|
|
1678
|
+
),
|
|
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'),
|
|
1695
|
+
),
|
|
1696
|
+
),
|
|
1697
|
+
);
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
function GatheringCategories({ categories, products }) {
|
|
1701
|
+
const counts = new Map();
|
|
1702
|
+
for (const product of products) {
|
|
1703
|
+
const key = slug(product.category);
|
|
1704
|
+
if (key) counts.set(key, (counts.get(key) || 0) + 1);
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1707
|
+
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'),
|
|
1711
|
+
...availableCategories.map((category) => {
|
|
1712
|
+
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
|
+
}),
|
|
1726
|
+
);
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1729
|
+
function GatheringsSection({ props, section, catalogPage = false }) {
|
|
1730
|
+
const content = section?.content || {};
|
|
1731
|
+
const products = gatheringProducts(props);
|
|
1732
|
+
const categories = list(props.categories);
|
|
1733
|
+
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
|
+
),
|
|
1757
|
+
)
|
|
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
|
+
),
|
|
1768
|
+
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' : ''}`,
|
|
1775
|
+
},
|
|
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,
|
|
1799
|
+
);
|
|
1800
|
+
}
|
|
1801
|
+
|
|
1802
|
+
function TestimonialsSection(section) {
|
|
1803
|
+
const content = section?.content || {};
|
|
1804
|
+
const items = list(content.items).slice(0, 3);
|
|
1805
|
+
|
|
1806
|
+
if (!items.length) return null;
|
|
1807
|
+
|
|
1808
|
+
return h('section', { className: 'kumpul-section kumpul-testimonials', id: section?.id || 'cerita-komunitas' },
|
|
1809
|
+
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.'),
|
|
1813
|
+
}),
|
|
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
|
+
),
|
|
1827
|
+
);
|
|
1828
|
+
}
|
|
1829
|
+
|
|
1830
|
+
function LocationsSection({ props, section }) {
|
|
1831
|
+
const content = section?.content || {};
|
|
1832
|
+
const locations = list(props.locations).slice(0, 4);
|
|
1833
|
+
if (!locations.length) return null;
|
|
1834
|
+
|
|
1835
|
+
return h('section', { className: 'kumpul-section kumpul-locations', id: section?.id || 'lokasi' },
|
|
1836
|
+
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.'),
|
|
1840
|
+
}),
|
|
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
|
+
),
|
|
1847
|
+
);
|
|
1848
|
+
}
|
|
1849
|
+
|
|
1850
|
+
function CallToAction({ props, section }) {
|
|
1851
|
+
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, '');
|
|
1857
|
+
if (phone) {
|
|
1858
|
+
const message = text(content.button_message);
|
|
1859
|
+
href = `https://wa.me/${phone}${message ? `?text=${encodeURIComponent(message)}` : ''}`;
|
|
1860
|
+
}
|
|
1861
|
+
} else if (action === 'phone') {
|
|
1862
|
+
const phone = text(content.button_phone, props.profile?.phone).replace(/[^\d+(). -]/g, '');
|
|
1863
|
+
if (phone) href = `tel:${phone}`;
|
|
1864
|
+
} else if (action === 'email') {
|
|
1865
|
+
const email = text(content.button_email);
|
|
1866
|
+
if (/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) href = `mailto:${email}`;
|
|
1867
|
+
} else if (action === 'link') {
|
|
1868
|
+
const target = text(content.button_url);
|
|
1869
|
+
if (target.startsWith('/') && !target.startsWith('//')) {
|
|
1870
|
+
href = tenantPath(props, target);
|
|
1871
|
+
} else {
|
|
1872
|
+
try {
|
|
1873
|
+
const url = new URL(target);
|
|
1874
|
+
if (url.protocol === 'https:' || url.protocol === 'http:') href = url.href;
|
|
1875
|
+
} catch {
|
|
1876
|
+
href = tenantPath(props, '/gathering');
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
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
|
+
),
|
|
1891
|
+
),
|
|
1892
|
+
);
|
|
1893
|
+
}
|
|
1894
|
+
|
|
1895
|
+
function MobileDock(props) {
|
|
1896
|
+
const auth = props.auth || {};
|
|
1897
|
+
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
|
+
|
|
1906
|
+
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
|
+
)),
|
|
1920
|
+
);
|
|
1921
|
+
}
|
|
1922
|
+
|
|
1923
|
+
function styles(colors) {
|
|
1924
|
+
return `
|
|
1925
|
+
.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}
|
|
1926
|
+
.kumpul-cart.is-empty .kumpul-cart-select-all,.kumpul-cart.is-empty .kumpul-cart-summary{display:none}.kumpul-cart.is-empty .kumpul-cart-layout{grid-template-columns:1fr}
|
|
1927
|
+
@media(max-width:760px){.kumpul-cart-layout{grid-template-columns:1fr;gap:15px}.kumpul-cart-item{grid-template-columns:20px 52px minmax(0,1fr);gap:10px;padding:12px}.kumpul-cart-art{width:52px;height:52px;border-radius:12px;font-size:23px}.kumpul-cart-copy h2{font-size:11px}.kumpul-cart-item-controls{grid-column:3;min-width:0;width:100%;display:flex;align-items:center;justify-content:space-between;gap:8px}.kumpul-cart-price{margin-right:auto;font-size:12px}.kumpul-cart-summary{position:static}.kumpul-cart-heading h1{font-size:32px}}
|
|
1928
|
+
.kumpul-transactions{max-width:980px;margin:0 auto}.kumpul-transactions-heading{display:flex;align-items:flex-end;justify-content:space-between;gap:24px}.kumpul-transactions-heading h1{margin:0;color:var(--kt-text);font-size:clamp(30px,4vw,42px);line-height:1.15;letter-spacing:-.04em}.kumpul-transactions-heading>div:first-child>p:last-child{margin:9px 0 0;color:var(--kt-muted);font-size:13px}.kumpul-transactions-total{padding:13px 16px;display:grid;gap:2px;border:1px solid var(--kt-border);border-radius:15px;background:var(--kt-surface)}.kumpul-transactions-total strong{font-size:21px;line-height:1.1}.kumpul-transactions-total span{color:var(--kt-muted);font-size:10px}.kumpul-transactions-preview-note{margin:20px 0 0;padding:11px 14px;border:1px solid var(--kt-border);border-radius:12px;background:var(--kt-surface);color:var(--kt-muted);font-size:11px}.kumpul-transactions-filters{margin:25px 0 22px;padding-bottom:7px;display:flex;gap:8px;overflow-x:auto;border-bottom:1px solid var(--kt-border);scrollbar-width:thin}.kumpul-transactions-filters button{padding:9px 12px;display:inline-flex;align-items:center;gap:8px;border:1px solid transparent;border-radius:11px 11px 0 0;background:transparent;color:var(--kt-muted);font:inherit;font-size:11px;font-weight:700;white-space:nowrap;cursor:pointer}.kumpul-transactions-filters button[aria-pressed=true]{border-color:var(--kt-border);border-bottom-color:var(--kt-surface);background:var(--kt-surface);color:var(--kt-accent)}.kumpul-transactions-filters button span{min-width:20px;height:20px;padding:2px 6px;display:grid;place-items:center;border-radius:99px;background:var(--kt-bg);color:var(--kt-muted);font-size:9px}.kumpul-transactions-list{display:grid;gap:12px}.kumpul-transaction-card{overflow:hidden;border:1px solid var(--kt-border);border-radius:16px;background:var(--kt-surface)}.kumpul-transaction-top{padding:13px 18px;display:flex;align-items:center;justify-content:space-between;gap:12px;border-bottom:1px solid #e8f0f2}.kumpul-transaction-top>div{display:flex;align-items:center;gap:8px;color:var(--kt-muted);font-size:10px}.kumpul-transaction-ref{color:var(--kt-text);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-weight:750}.kumpul-transaction-status{padding:6px 9px;flex:none;border-radius:99px;font-size:9px;font-weight:800}.kumpul-transaction-status-warning{background:#fff4da;color:#a15c00}.kumpul-transaction-status-info{background:#e8f2ff;color:#2563eb}.kumpul-transaction-status-success{background:#e5f7ef;color:#08734f}.kumpul-transaction-status-danger{background:#ffeded;color:#b91c1c}.kumpul-transaction-status-muted{background:#eef1f4;color:#64748b}.kumpul-transaction-body{padding:16px 18px;display:flex;align-items:center;justify-content:space-between;gap:20px}.kumpul-transaction-item{min-width:0;display:flex;align-items:center;gap:13px}.kumpul-transaction-art{width:58px;height:58px;flex:none;display:grid;place-items:center;border:1px solid var(--kt-border);border-radius:14px;background:var(--kt-bg);color:var(--kt-accent);font-size:26px}.kumpul-transaction-item>div{min-width:0}.kumpul-transaction-item h2{margin:0;font-size:13px}.kumpul-transaction-item p{margin:5px 0 0;color:var(--kt-muted);font-size:10px}.kumpul-transaction-total{flex:none;text-align:right}.kumpul-transaction-total span{display:block;color:var(--kt-muted);font-size:10px}.kumpul-transaction-total strong{display:block;margin-top:3px;font-size:16px}.kumpul-transaction-actions{padding:0 18px 15px;display:flex;justify-content:flex-end;gap:8px}.kumpul-transaction-actions button{min-height:34px;padding:7px 11px;border:1px solid var(--kt-border);border-radius:10px;background:var(--kt-surface);color:var(--kt-text);font:inherit;font-size:9px;font-weight:750;opacity:.62;cursor:not-allowed}.kumpul-transaction-actions button:disabled{opacity:.62}.kumpul-transactions-empty{margin:0;padding:32px 18px;border:1px dashed var(--kt-border);border-radius:15px;color:var(--kt-muted);font-size:12px;text-align:center}
|
|
1929
|
+
@media(max-width:700px){.kumpul-transactions-heading{align-items:flex-start;flex-direction:column;gap:16px}.kumpul-transactions-total{width:100%;padding:11px 13px}.kumpul-transactions-total strong{font-size:18px}.kumpul-transactions-filters{margin-top:20px}.kumpul-transaction-top{align-items:flex-start;padding:12px 14px}.kumpul-transaction-top>div{flex-wrap:wrap;gap:5px;font-size:9px}.kumpul-transaction-status{max-width:120px;white-space:normal;text-align:center}.kumpul-transaction-body{align-items:flex-start;padding:14px;gap:10px}.kumpul-transaction-art{width:44px;height:44px;border-radius:12px;font-size:20px}.kumpul-transaction-item{gap:9px}.kumpul-transaction-item h2{font-size:11px}.kumpul-transaction-total strong{font-size:13px}.kumpul-transaction-actions{padding:0 14px 13px;flex-wrap:wrap}.kumpul-transaction-actions button{flex:1;padding:7px 8px;font-size:8px}}
|
|
1930
|
+
.kumpul-billing{max-width:980px;margin:0 auto}.kumpul-billing-heading{display:flex;align-items:flex-end;justify-content:space-between;gap:24px}.kumpul-billing-heading h1{margin:0;color:var(--kt-text);font-size:clamp(30px,4vw,42px);line-height:1.15;letter-spacing:-.04em}.kumpul-billing-description{margin:9px 0 0;color:var(--kt-muted);font-size:13px}.kumpul-billing-summary{display:flex;gap:10px}.kumpul-billing-summary-card{min-width:132px;padding:13px 16px;display:grid;gap:2px;border:1px solid var(--kt-border);border-radius:15px;background:var(--kt-surface)}.kumpul-billing-summary-card strong{font-size:21px;line-height:1.1}.kumpul-billing-summary-card span{color:var(--kt-muted);font-size:10px}.kumpul-billing-preview-note{margin:20px 0 0;padding:11px 14px;border:1px solid var(--kt-border);border-radius:12px;background:var(--kt-surface);color:var(--kt-muted);font-size:11px}.kumpul-billing-filters{margin:25px 0 22px;padding-bottom:7px;display:flex;gap:8px;overflow-x:auto;border-bottom:1px solid var(--kt-border);scrollbar-width:thin}.kumpul-billing-filters button{padding:9px 12px;display:inline-flex;align-items:center;gap:8px;border:1px solid transparent;border-radius:11px 11px 0 0;background:transparent;color:var(--kt-muted);font:inherit;font-size:11px;font-weight:700;white-space:nowrap;cursor:pointer}.kumpul-billing-filters button[aria-pressed=true]{border-color:var(--kt-border);border-bottom-color:var(--kt-surface);background:var(--kt-surface);color:var(--kt-accent)}.kumpul-billing-filters button span{min-width:20px;height:20px;padding:2px 6px;display:grid;place-items:center;border-radius:99px;background:var(--kt-bg);color:var(--kt-muted);font-size:9px}.kumpul-billing-results-heading{margin-bottom:12px;display:flex;align-items:baseline;justify-content:space-between;gap:12px}.kumpul-billing-results-heading h2{margin:0;font-size:16px}.kumpul-billing-results-heading span{color:var(--kt-muted);font-size:11px}.kumpul-billing-list{display:grid;gap:12px}.kumpul-billing-card{overflow:hidden;border:1px solid var(--kt-border);border-radius:16px;background:var(--kt-surface)}.kumpul-billing-card-top{padding:17px 19px;display:flex;align-items:flex-start;justify-content:space-between;gap:16px;border-bottom:1px solid #e8f0f2}.kumpul-billing-kind{color:var(--kt-accent);font-size:9px;font-weight:800;letter-spacing:.1em;text-transform:uppercase}.kumpul-billing-card h3{margin:4px 0 0;font-size:14px}.kumpul-billing-card-top p{margin:5px 0 0;color:var(--kt-muted);font-size:10px}.kumpul-billing-status{padding:6px 9px;flex:none;border-radius:99px;font-size:9px;font-weight:800}.kumpul-billing-status-warning{background:#fff4da;color:#a15c00}.kumpul-billing-status-success{background:#e5f7ef;color:#08734f}.kumpul-billing-status-muted{background:#eef1f4;color:#64748b}.kumpul-billing-card-bottom{padding:14px 19px;display:flex;align-items:center;justify-content:space-between;gap:16px}.kumpul-billing-card-bottom strong{font-size:17px;color:var(--kt-accent)}.kumpul-billing-card-bottom p{margin:4px 0 0;color:var(--kt-muted);font-size:10px}.kumpul-billing-action{min-height:36px;padding:8px 13px;border:0;border-radius:10px;background:var(--kt-accent);color:#fff;font:inherit;font-size:10px;font-weight:750;opacity:.62;cursor:not-allowed}.kumpul-billing-empty{margin:0;padding:32px 18px;border:1px dashed var(--kt-border);border-radius:15px;color:var(--kt-muted);font-size:12px;text-align:center}
|
|
1931
|
+
@media(max-width:700px){.kumpul-billing-heading{align-items:flex-start;flex-direction:column;gap:16px}.kumpul-billing-summary{width:100%}.kumpul-billing-summary-card{min-width:0;flex:1;padding:11px 13px}.kumpul-billing-summary-card strong{font-size:18px}.kumpul-billing-filters{margin-top:20px}.kumpul-billing-card-top{padding:15px;gap:10px}.kumpul-billing-card h3{font-size:13px}.kumpul-billing-status{max-width:120px;white-space:normal;text-align:center}.kumpul-billing-card-bottom{padding:13px 15px}.kumpul-billing-card-bottom strong{font-size:15px}}
|
|
1932
|
+
.kumpul-calendar-agenda:not([open]){display:none}.kumpul-calendar-agenda[open]{position:fixed;inset:50% auto auto 50%;z-index:10;width:min(560px,calc(100vw - 32px));max-height:calc(100dvh - 48px);margin:0;padding:0;display:flex;flex-direction:column;transform:translate(-50%,-50%);overflow:hidden;border:1px solid var(--kt-border);border-radius:22px;background:var(--kt-bg);color:var(--kt-text);box-shadow:0 24px 80px #0f172a45}.kumpul-calendar-agenda::backdrop{background:rgb(15 23 42 / 45%);backdrop-filter:blur(2px)}.kumpul-calendar-agenda-handle{display:none}.kumpul-calendar-agenda-heading{padding:22px 24px 16px;display:flex;align-items:flex-start;justify-content:space-between;gap:16px;border-bottom:1px solid var(--kt-border)}.kumpul-calendar-agenda-heading .kumpul-eyebrow{margin:0 0 4px}.kumpul-calendar-agenda-heading h2{margin:0;font-size:20px;text-transform:capitalize}.kumpul-calendar-agenda-close{width:36px;height:36px;flex:none;border:1px solid var(--kt-border);border-radius:50%;background:var(--kt-surface);color:var(--kt-text);font:inherit;font-size:22px;line-height:1;cursor:pointer}.kumpul-calendar-agenda-content{min-height:0;padding:18px 24px 24px;overflow:auto;overscroll-behavior:contain}.kumpul-calendar-agenda-list{display:grid;gap:10px}.kumpul-calendar-empty{margin:0;padding:18px;border:1px dashed var(--kt-border);border-radius:14px;color:var(--kt-muted);font-size:13px;text-align:center}
|
|
1933
|
+
@media(max-width:620px){.kumpul-calendar-agenda[open]{inset:auto 0 0;width:100%;max-width:none;max-height:min(84dvh,720px);padding-bottom:env(safe-area-inset-bottom);transform:none;border-right:0;border-bottom:0;border-left:0;border-radius:22px 22px 0 0}.kumpul-calendar-agenda-handle{width:38px;height:4px;margin:10px auto 0;display:block;border-radius:99px;background:#cbd5e1}.kumpul-calendar-agenda-heading{padding:14px 20px 14px}.kumpul-calendar-agenda-content{padding:16px 20px 22px}.kumpul-calendar-agenda-close{width:34px;height:34px}}
|
|
1934
|
+
.kumpul-calendar-month-toolbar{margin:22px 0 14px;padding:17px 19px;display:flex;align-items:center;justify-content:space-between;gap:16px;border:1px solid var(--kt-border);border-radius:17px;background:var(--kt-surface)}.kumpul-calendar-month-title h2{margin:0;font-size:20px;line-height:1.2;text-transform:capitalize}.kumpul-calendar-month-title p{margin:5px 0 0;color:var(--kt-muted);font-size:11px}.kumpul-calendar-month-actions{display:flex;align-items:center;gap:7px}.kumpul-calendar-month-actions button{min-width:38px;height:38px;padding:7px 11px;border:1px solid var(--kt-border);border-radius:11px;background:var(--kt-surface);color:var(--kt-text);font:inherit;font-size:12px;font-weight:700;cursor:pointer}.kumpul-calendar-month-actions button[data-calendar-previous],.kumpul-calendar-month-actions button[data-calendar-next]{font-size:22px;line-height:1}.kumpul-calendar-month-view{overflow:hidden;border:1px solid var(--kt-border);border-radius:17px;background:var(--kt-surface)}.kumpul-calendar-weekdays,.kumpul-calendar-grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr))}.kumpul-calendar-weekdays{border-bottom:1px solid var(--kt-border);background:#f8fbfc}.kumpul-calendar-weekdays span{padding:10px 6px;color:var(--kt-muted);font-size:10px;font-weight:750;text-align:center}.kumpul-calendar-day{position:relative;min-width:0;min-height:77px;padding:9px;display:flex;align-items:flex-start;justify-content:space-between;gap:4px;border:0;border-right:1px solid #e8f0f2;border-bottom:1px solid #e8f0f2;background:var(--kt-surface);color:var(--kt-text);font:inherit;text-align:left;cursor:pointer}.kumpul-calendar-day:nth-child(7n){border-right:0}.kumpul-calendar-day:nth-last-child(-n+7){border-bottom:0}.kumpul-calendar-day:hover{background:#f4fafb}.kumpul-calendar-day[aria-pressed=true]{background:#e6f4f6;box-shadow:inset 0 0 0 2px var(--kt-accent)}.kumpul-calendar-day[data-outside-month=true]{color:#a7b3bd;background:#fbfcfd}.kumpul-calendar-day>span{font-size:11px;font-weight:700}.kumpul-calendar-day small{min-width:19px;height:19px;padding:2px 5px;display:grid;place-items:center;border-radius:999px;background:var(--kt-accent);color:#fff;font-size:9px;font-weight:800}.kumpul-calendar-day:focus-visible,.kumpul-calendar-month-actions button:focus-visible{position:relative;z-index:1;outline:3px solid var(--kt-success);outline-offset:-3px}.kumpul-calendar-agenda{margin-top:24px}.kumpul-calendar-agenda>h3{margin:0 0 12px;font-size:16px;text-transform:capitalize}.kumpul-calendar-event{padding:14px 16px;display:grid;grid-template-columns:76px 1fr;align-items:start;gap:14px;border:1px solid var(--kt-border);border-left:4px solid var(--kt-accent);border-radius:14px;background:var(--kt-surface)}.kumpul-calendar-event[hidden]{display:none}.kumpul-calendar-event-invitation{border-left-color:var(--kt-success)}.kumpul-calendar-event-time{padding-top:2px;color:var(--kt-accent);font-size:11px;font-weight:800}.kumpul-calendar-event-copy{min-width:0}.kumpul-calendar-event-kind{color:var(--kt-muted);font-size:9px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.kumpul-calendar-event-copy h4{margin:3px 0 0;font-size:13px}.kumpul-calendar-event-copy p{margin:4px 0 0;color:var(--kt-muted);font-size:10px}
|
|
1935
|
+
@media(max-width:620px){.kumpul-calendar-month-toolbar{padding:13px;align-items:flex-start}.kumpul-calendar-month-title h2{font-size:17px}.kumpul-calendar-month-title p{max-width:170px;font-size:9px}.kumpul-calendar-month-actions{gap:4px}.kumpul-calendar-month-actions button{min-width:33px;height:34px;padding:5px 8px;font-size:10px}.kumpul-calendar-weekdays span{padding:8px 2px;font-size:9px}.kumpul-calendar-day{min-height:55px;padding:6px 5px}.kumpul-calendar-day>span{font-size:10px}.kumpul-calendar-day small{min-width:16px;height:16px;padding:1px 4px;font-size:8px}.kumpul-calendar-event{grid-template-columns:52px 1fr;gap:9px;padding:12px}.kumpul-calendar-event-time{font-size:10px}}
|
|
1936
|
+
@media(max-width:620px){.kumpul-calendar-tabs{overflow-x:auto}.kumpul-calendar-tabs button{flex:none;white-space:nowrap}}
|
|
1937
|
+
.kumpul-template{--kt-bg:${colors.background};--kt-surface:${colors.surface};--kt-text:${colors.text};--kt-muted:${colors.textMuted};--kt-accent:${colors.accent};--kt-hover:${colors.accentHover};--kt-border:${colors.border};--kt-success:${colors.success};--kt-warning:${colors.warning};min-height:100vh;background:var(--kt-bg);color:var(--kt-text);font:400 15px/1.55 Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}
|
|
1938
|
+
.kumpul-template *{box-sizing:border-box}.kumpul-template [hidden]{display:none!important}.kumpul-template a{color:inherit;text-decoration:none}.kumpul-template a:focus-visible{outline:3px solid var(--kt-success);outline-offset:3px}
|
|
1939
|
+
.kumpul-icon{width:20px;height:20px;flex:none}.kumpul-header{position:sticky;top:0;z-index:10;background:var(--kt-surface);border-bottom:1px solid var(--kt-border)}
|
|
1940
|
+
.kumpul-header-main{min-height:72px;max-width:1280px;margin:auto;padding:12px 28px;display:flex;align-items:center;justify-content:space-between;gap:24px}
|
|
1941
|
+
.kumpul-brand{display:flex;align-items:center;gap:12px;min-width:0}.kumpul-logo,.kumpul-logo-mark{width:44px;height:44px;flex:none;border-radius:15px}.kumpul-logo{object-fit:cover}.kumpul-logo-mark{display:grid;place-items:center;background:var(--kt-accent);color:#fff;font-size:17px;font-weight:800;letter-spacing:-.04em}
|
|
1942
|
+
.kumpul-brand-copy{display:grid;line-height:1.2}.kumpul-brand-copy strong{font-size:17px;letter-spacing:-.02em}.kumpul-brand-copy small{margin-top:5px;color:var(--kt-muted);font-size:10px;font-weight:750;letter-spacing:.13em;text-transform:uppercase}
|
|
1943
|
+
.kumpul-utilities{display:flex;align-items:center;justify-content:flex-end;gap:7px}.kumpul-utilities>a{display:flex;align-items:center;gap:7px;padding:8px 10px;border-radius:999px;color:var(--kt-muted);font-size:12px;font-weight:650;transition:background .16s,color .16s}.kumpul-utilities>a:hover,.kumpul-utilities>a[aria-current=page]{background:var(--kt-bg);color:var(--kt-accent)}.kumpul-utilities .kumpul-login{background:var(--kt-accent);color:#fff}
|
|
1944
|
+
.kumpul-page-nav{min-height:52px;padding:7px 24px;display:flex;align-items:center;justify-content:center;gap:8px;border-top:1px solid #eef2f4}.kumpul-page-nav a{padding:8px 16px;border:1px solid transparent;border-radius:999px;color:var(--kt-muted);font-size:13px;font-weight:650;white-space:nowrap}.kumpul-page-nav a:hover{border-color:var(--kt-border);color:var(--kt-accent)}.kumpul-page-nav a[aria-current=page]{background:var(--kt-text);color:#fff}
|
|
1945
|
+
.kumpul-main{max-width:1280px;margin:0 auto;padding:32px 28px 80px}.kumpul-hero{display:grid;grid-template-columns:1.08fr .92fr;min-height:430px;overflow:hidden;border:1px solid var(--kt-border);border-radius:28px;background:var(--kt-surface);box-shadow:0 12px 40px #0f172a0b}
|
|
1946
|
+
.kumpul-hero-copy{align-self:center;padding:clamp(28px,5vw,64px)}.kumpul-pill{display:inline-flex;align-items:center;gap:8px;padding:7px 12px;border:1px solid var(--kt-border);border-radius:999px;background:var(--kt-bg);color:var(--kt-accent);font-size:11px;font-weight:750;letter-spacing:.045em}
|
|
1947
|
+
.kumpul-community-pill{margin-bottom:20px}.kumpul-status-dot{width:8px;height:8px;border-radius:50%;background:var(--kt-success);box-shadow:0 0 0 4px #0e9f6e1d}.kumpul-hero h1{max-width:620px;margin:0;font-size:clamp(42px,6.1vw,76px);line-height:.98;font-weight:850;letter-spacing:-.065em}.kumpul-hero-description{max-width:540px;margin:20px 0 0;color:var(--kt-muted);font-size:15px;line-height:1.75}
|
|
1948
|
+
.kumpul-hero-actions{display:flex;flex-wrap:wrap;gap:10px;margin-top:24px}.kumpul-button{min-height:44px;padding:11px 17px;display:inline-flex;align-items:center;justify-content:center;gap:10px;border:1px solid transparent;border-radius:999px;font-size:13px;font-weight:750;transition:background .16s,transform .16s}.kumpul-button:hover{transform:translateY(-1px)}.kumpul-button .kumpul-icon{width:17px;height:17px}.kumpul-button-primary{background:var(--kt-accent);color:#fff!important}.kumpul-button-primary:hover{background:var(--kt-hover)}.kumpul-button-secondary{border-color:var(--kt-border);background:var(--kt-bg);color:var(--kt-text)}
|
|
1949
|
+
.kumpul-stats{display:flex;gap:clamp(20px,4vw,48px);margin-top:28px}.kumpul-stat{display:grid;gap:2px}.kumpul-stat strong{font-size:22px;line-height:1.2;letter-spacing:-.04em}.kumpul-stat span{color:var(--kt-muted);font-size:11px}
|
|
1950
|
+
.kumpul-feature-card{position:relative;min-height:360px;padding:24px;display:flex;flex-direction:column;justify-content:space-between;overflow:hidden;background:radial-gradient(ellipse at 68% 30%,#58a3b8 0,#006699 53%,#00557a 100%);color:#fff}
|
|
1951
|
+
.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
|
+
.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
|
+
.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}
|
|
1955
|
+
.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
|
+
.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
|
+
.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}
|
|
1958
|
+
.kumpul-section{margin-top:76px}.kumpul-section-heading{max-width:680px}.kumpul-eyebrow{margin:0 0 10px;color:var(--kt-accent);font-size:10px;font-weight:800;letter-spacing:.16em;text-transform:uppercase} .kumpul-section-heading .kumpul-section-title,.kumpul-cta h2{margin:0;font-size:clamp(26px,3.8vw,42px);line-height:1.08;font-weight:800;letter-spacing:-.05em}.kumpul-section-description{margin:12px 0 0;color:var(--kt-muted);font-size:13px}
|
|
1959
|
+
.kumpul-calendar{margin:10px auto 0;max-width:1120px}.kumpul-calendar-heading{display:flex;align-items:flex-end;justify-content:space-between;gap:24px}.kumpul-calendar-title{margin:0;font-size:clamp(32px,4vw,48px);line-height:1.05;font-weight:850;letter-spacing:-.055em}.kumpul-calendar-description{margin:12px 0 0;color:var(--kt-muted);font-size:14px}.kumpul-calendar-stats{display:flex;flex-wrap:wrap;gap:10px}.kumpul-calendar-stat{min-width:105px;padding:12px 15px;display:grid;gap:2px;border:1px solid var(--kt-border);border-radius:14px;background:var(--kt-surface)}.kumpul-calendar-stat strong{font-size:18px;line-height:1.2}.kumpul-calendar-stat span{color:var(--kt-muted);font-size:10px}.kumpul-calendar-preview-note{margin:22px 0 0;padding:12px 15px;border:1px solid var(--kt-border);border-radius:13px;background:#e6f4f6;color:#28576a;font-size:12px}.kumpul-calendar-tabs{margin-top:25px;display:flex;gap:8px;border-bottom:1px solid var(--kt-border)}.kumpul-calendar-tabs button{min-height:44px;padding:9px 14px;display:inline-flex;align-items:center;gap:8px;border:1px solid transparent;border-bottom:2px solid transparent;background:transparent;color:var(--kt-muted);font:inherit;font-size:13px;font-weight:700;cursor:pointer}.kumpul-calendar-tabs button[aria-selected=true]{border-bottom-color:var(--kt-accent);color:var(--kt-text)}.kumpul-calendar-tabs button>span,.kumpul-calendar-tabs button>b,.kumpul-calendar-filters button>span{padding:2px 7px;border-radius:999px;background:var(--kt-bg);color:var(--kt-muted);font-size:10px}.kumpul-calendar-tabs button>b{background:var(--kt-accent);color:#fff}.kumpul-calendar-filters{margin:20px 0;display:flex;gap:8px;overflow-x:auto;padding-bottom:3px}.kumpul-calendar-filters button{flex:none;padding:8px 11px;display:inline-flex;align-items:center;gap:7px;border:1px solid var(--kt-border);border-radius:999px;background:var(--kt-surface);color:var(--kt-muted);font:inherit;font-size:11px;font-weight:650;cursor:pointer}.kumpul-calendar-filters button[aria-pressed=true]{border-color:var(--kt-accent);background:#e6f4f6;color:var(--kt-accent)}.kumpul-calendar-list{display:grid;gap:12px}.kumpul-calendar-card{padding:18px 20px;display:flex;align-items:center;justify-content:space-between;gap:18px;border:1px solid var(--kt-border);border-radius:17px;background:var(--kt-surface);box-shadow:0 7px 20px #0f172a08}.kumpul-calendar-card-copy{min-width:0}.kumpul-calendar-card-title{display:flex;align-items:center;flex-wrap:wrap;gap:9px}.kumpul-calendar-card-title h2{margin:0;font-size:15px;line-height:1.35}.kumpul-calendar-status,.kumpul-calendar-new{padding:4px 8px;border:1px solid var(--kt-border);border-radius:999px;color:var(--kt-muted);font-size:9px;font-weight:750}.kumpul-calendar-new{border-color:transparent;background:var(--kt-accent);color:#fff}.kumpul-calendar-meta{margin:6px 0 0;color:var(--kt-muted);font-size:11px}.kumpul-calendar-action{flex:none;min-height:38px;padding:8px 13px;border:1px solid var(--kt-border);border-radius:999px;background:var(--kt-bg);color:var(--kt-muted);font:inherit;font-size:10px;font-weight:700}.kumpul-calendar-action:disabled{opacity:.72}.kumpul-calendar-invitation-action{display:grid;justify-items:end;gap:7px}.kumpul-calendar-invitation-action>span{color:var(--kt-muted);font-size:10px}.kumpul-calendar-empty{margin:0;padding:28px 20px;border:1px dashed var(--kt-border);border-radius:15px;background:var(--kt-surface);color:var(--kt-muted);font-size:12px;text-align:center}.kumpul-calendar [hidden]{display:none!important}
|
|
1960
|
+
.kumpul-flow-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-flow-step{position:relative;min-height:150px;padding:22px 18px;display:flex;flex-direction:column;align-items:flex-start;gap:8px}.kumpul-flow-step+.kumpul-flow-step{border-left:1px solid var(--kt-border)}.kumpul-flow-number{width:31px;height:31px;display:grid;place-items:center;border-radius:11px;background:var(--kt-bg);color:var(--kt-accent);font-size:12px;font-weight:800}.kumpul-flow-step strong{margin-top:4px;font-size:13px}.kumpul-flow-step>span:last-child{color:var(--kt-muted);font-size:11px}
|
|
1961
|
+
.kumpul-section-topline{display:flex;align-items:flex-end;justify-content:space-between;gap:18px}.kumpul-text-link{flex:none;display:inline-flex;align-items:center;gap:8px;color:var(--kt-accent);font-size:12px;font-weight:750}.kumpul-text-link .kumpul-icon{width:16px;height:16px}.kumpul-gathering-grid{margin-top:25px;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px}
|
|
1962
|
+
.kumpul-catalog-heading{display:flex;align-items:flex-end;justify-content:space-between;gap:28px}.kumpul-catalog-search{width:min(100%,360px);min-height:48px;padding:0 15px;display:flex;align-items:center;gap:10px;border:1px solid var(--kt-border);border-radius:14px;background:var(--kt-surface);color:var(--kt-muted)}.kumpul-catalog-search .kumpul-icon{width:18px;height:18px}.kumpul-catalog-search input{width:100%;border:0;outline:0;background:transparent;color:var(--kt-text);font:inherit;font-size:13px}.kumpul-catalog-search input::placeholder{color:var(--kt-muted)} .kumpul-category-filters{margin-top:24px;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}.kumpul-category-filter{min-width:0;padding:13px;display:flex;align-items:center;gap:11px;border:1px solid var(--kt-border);border-radius:16px;background:var(--kt-surface);color:var(--kt-text);text-align:left;cursor:pointer}.kumpul-category-filter[aria-pressed=true]{border-color:var(--kt-accent);background:#e6f4f6}.kumpul-category-icon{width:39px;height:39px;flex:none;display:grid;place-items:center;border-radius:12px;background:var(--kt-bg);color:var(--kt-accent);font-size:15px;font-weight:800}.kumpul-category-filter>span:last-child{min-width:0;display:grid}.kumpul-category-filter strong{font-size:12px}.kumpul-category-filter small{overflow:hidden;color:var(--kt-muted);font-size:9px;text-overflow:ellipsis;white-space:nowrap}.kumpul-catalog-results{margin:20px 0 -12px;color:var(--kt-muted);font-size:12px}.kumpul-no-results{margin:20px 0;padding:28px;border:1px dashed var(--kt-border);border-radius:16px;background:var(--kt-surface);color:var(--kt-muted);text-align:center}.kumpul-pagination{margin-top:26px;display:flex;align-items:center;justify-content:center;gap:16px}.kumpul-pagination button{min-height:40px;padding:8px 14px;border:1px solid var(--kt-border);border-radius:999px;background:var(--kt-surface);color:var(--kt-accent);font:inherit;font-size:12px;font-weight:700;cursor:pointer}.kumpul-pagination button:disabled{opacity:.45;cursor:not-allowed}.kumpul-pagination span{min-width:110px;color:var(--kt-muted);font-size:11px;text-align:center}.kumpul-catalog-grid{margin-top:20px}.kumpul-card-location{margin:8px 0;color:var(--kt-muted);display:flex;align-items:center;gap:6px;font-size:10px}.kumpul-card-location .kumpul-icon{width:14px;height:14px}.kumpul-card-bottom span{color:var(--kt-muted);font-size:10px}
|
|
1963
|
+
.kumpul-gathering-card{overflow:hidden;border:1px solid var(--kt-border);border-radius:19px;background:var(--kt-surface);transition:transform .18s,box-shadow .18s}.kumpul-gathering-card:hover{transform:translateY(-3px);box-shadow:0 14px 28px #0f172a12} .kumpul-gathering-art{position:relative;min-height:160px;display:grid;place-items:center;overflow:hidden;background:linear-gradient(135deg,#d9eff0,#91c4c9)}.kumpul-gathering-art>span:first-child{font-size:52px;filter:drop-shadow(0 10px 12px #163c3b25)}.kumpul-gathering-art>img{width:100%;height:100%;position:absolute;inset:0;object-fit:cover}.kumpul-art-1{background:linear-gradient(135deg,#eee7db,#d4bd9f)}.kumpul-art-2{background:linear-gradient(135deg,#d9e8d9,#9dbba0)}.kumpul-art-3{background:linear-gradient(135deg,#e1e8ed,#b1c8d6)}
|
|
1964
|
+
.kumpul-card-content{padding:16px}.kumpul-card-meta{display:flex;justify-content:space-between;gap:10px;color:var(--kt-muted);font-size:10px}.kumpul-card-content h3{margin:10px 0 8px;font-size:16px;line-height:1.3;letter-spacing:-.025em}.kumpul-card-content h3 a:hover{color:var(--kt-accent)}.kumpul-card-description{margin:0;color:var(--kt-muted);font-size:11px;line-height:1.55}.kumpul-card-bottom{margin-top:14px;padding-top:12px;display:flex;align-items:center;justify-content:space-between;gap:8px;border-top:1px solid #edf1f3}.kumpul-card-bottom strong{font-size:12px}.kumpul-card-bottom a{color:var(--kt-accent);font-size:11px;font-weight:750}
|
|
1965
|
+
.kumpul-empty-state{margin-top:24px;padding:44px 20px;text-align:center;border:1px dashed var(--kt-border);border-radius:20px;background:#ffffff80}.kumpul-empty-icon{width:42px;height:42px;margin:0 auto 12px;display:grid;place-items:center;border-radius:14px;background:#e6f4f6;color:var(--kt-accent);font-size:22px}.kumpul-empty-state h3{margin:0;font-size:17px}.kumpul-empty-state p{margin:8px auto 0;max-width:420px;color:var(--kt-muted);font-size:12px}
|
|
1966
|
+
.kumpul-testimonial-grid{margin-top:24px;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px}.kumpul-testimonial{margin:0;padding:21px;border:1px solid var(--kt-border);border-radius:18px;background:var(--kt-surface)}.kumpul-rating{color:var(--kt-warning);font-size:13px;letter-spacing:.12em}.kumpul-testimonial blockquote{margin:13px 0 18px;font-size:13px;line-height:1.65}.kumpul-testimonial figcaption{display:flex;align-items:center;gap:10px}.kumpul-testimonial figcaption>span:last-child{display:grid}.kumpul-testimonial figcaption strong{font-size:11px}.kumpul-testimonial figcaption small{color:var(--kt-muted);font-size:10px}
|
|
1967
|
+
.kumpul-location-list{margin-top:22px;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}.kumpul-location{min-width:0;padding:14px;display:flex;align-items:center;gap:10px;border:1px solid var(--kt-border);border-radius:15px;background:var(--kt-surface)}.kumpul-location-icon{font-size:21px}.kumpul-location>span:nth-child(2){min-width:0;display:grid}.kumpul-location strong{overflow:hidden;font-size:11px;text-overflow:ellipsis;white-space:nowrap}.kumpul-location small{overflow:hidden;color:var(--kt-muted);font-size:9px;text-overflow:ellipsis;white-space:nowrap}.kumpul-location-count{margin-left:auto;color:var(--kt-accent);font-size:9px;font-weight:750;white-space:nowrap}
|
|
1968
|
+
.kumpul-cta{margin-top:76px;padding:34px 38px;display:flex;align-items:center;justify-content:space-between;gap:24px;border-radius:23px;background:var(--kt-accent);color:#fff}.kumpul-cta .kumpul-eyebrow{color:#c8eaf1}.kumpul-cta h2{font-size:clamp(24px,3.3vw,36px)}.kumpul-cta>div:first-child>p:last-child{margin:10px 0 0;color:#d9edf2;font-size:12px}.kumpul-cta-actions{display:flex;flex-wrap:wrap;gap:9px}.kumpul-button-light{background:#fff;color:var(--kt-accent)!important}.kumpul-button-outline{border-color:#ffffff75;color:#fff!important}
|
|
1969
|
+
.kumpul-footer{padding:26px 28px;display:flex;justify-content:space-between;gap:14px;border-top:1px solid var(--kt-border);color:var(--kt-muted);font-size:11px}.kumpul-footer strong{color:var(--kt-text)}.kumpul-mobile-dock{display:none}
|
|
1970
|
+
.kumpul-detail-page{max-width:980px;margin:0 auto}.kumpul-detail-back{display:inline-block;margin-bottom:20px;color:var(--kt-accent);font-size:11px;font-weight:750}.kumpul-detail-heading{display:flex;align-items:center;justify-content:space-between;gap:16px}.kumpul-detail-heading h1{margin:0;color:var(--kt-text);font-size:clamp(28px,4vw,40px);line-height:1.15;letter-spacing:-.04em}.kumpul-detail-heading .kumpul-eyebrow{margin-bottom:8px}.kumpul-detail-heading>div>p:last-child{margin:8px 0 0;color:var(--kt-muted);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px}.kumpul-detail-preview-note{margin:18px 0 0;padding:11px 14px;border:1px solid var(--kt-border);border-radius:12px;background:var(--kt-surface);color:var(--kt-muted);font-size:10px}.kumpul-detail-layout{margin-top:22px;display:grid;grid-template-columns:minmax(0,1fr) 310px;align-items:start;gap:18px}.kumpul-detail-main{display:grid;gap:14px}.kumpul-detail-card{min-width:0;padding:20px;border:1px solid var(--kt-border);border-radius:17px;background:var(--kt-surface)}.kumpul-detail-card h2{margin:0 0 16px;font-size:14px}.kumpul-detail-fields{margin:0;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:15px}.kumpul-detail-fields>div{min-width:0}.kumpul-detail-fields dt,.kumpul-detail-totals dt{color:var(--kt-muted);font-size:9px}.kumpul-detail-fields dd,.kumpul-detail-totals dd{margin:4px 0 0;font-size:11px;font-weight:700;overflow-wrap:anywhere}.kumpul-detail-total{margin-top:20px;padding-top:16px;display:flex;align-items:baseline;justify-content:space-between;gap:12px;border-top:1px solid var(--kt-border);color:var(--kt-muted);font-size:11px}.kumpul-detail-total strong{color:var(--kt-accent);font-size:22px}.kumpul-detail-aside{position:sticky;top:20px}.kumpul-detail-aside>p{margin:13px 0 0;color:var(--kt-muted);font-size:10px;line-height:1.6}.kumpul-detail-aside>button{width:100%;min-height:42px;margin-top:16px;padding:10px;border:0;border-radius:11px;background:var(--kt-accent);color:#fff;font:inherit;font-size:11px;font-weight:800;opacity:.55;cursor:not-allowed}.kumpul-detail-login-info{margin-top:15px;padding:13px;border-left:3px solid var(--kt-accent);background:var(--kt-bg)}.kumpul-detail-login-info h3{margin:0;font-size:11px}.kumpul-detail-login-info p{margin:7px 0 0;color:var(--kt-muted);font-size:10px;line-height:1.6}.kumpul-detail-items{display:grid}.kumpul-detail-item{padding:13px 0;display:grid;grid-template-columns:48px minmax(0,1fr) auto;align-items:center;gap:12px;border-top:1px solid var(--kt-border)}.kumpul-detail-item-art{width:48px;height:48px;display:grid;place-items:center;border:1px solid var(--kt-border);border-radius:13px;background:var(--kt-bg);color:var(--kt-accent);font-size:20px;font-weight:800}.kumpul-detail-item-copy{min-width:0}.kumpul-detail-item h3{margin:0;font-size:11px}.kumpul-detail-item p{margin:5px 0 0;color:var(--kt-muted);font-size:9px}.kumpul-detail-item>strong{font-size:10px;white-space:nowrap}.kumpul-detail-escrow-note{display:block;margin-top:5px;color:var(--kt-accent);font-size:8px;line-height:1.5}.kumpul-detail-address{margin:0;color:var(--kt-muted);font-size:11px;line-height:1.6}.kumpul-detail-totals{margin:0;display:grid;gap:12px}.kumpul-detail-totals>div{display:flex;justify-content:space-between;gap:12px}.kumpul-detail-totals dd{margin:0;text-align:right}.kumpul-detail-grand-total{padding-top:13px;border-top:1px solid var(--kt-border)}.kumpul-detail-grand-total dt{color:var(--kt-text);font-weight:800}.kumpul-detail-grand-total dd{color:var(--kt-accent);font-size:16px}.kumpul-detail-payment-fields{margin-top:17px;padding-top:14px;border-top:1px solid var(--kt-border)}.kumpul-detail-fields .kumpul-detail-mono{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:9px}.kumpul-detail-payment-note{padding:10px 12px;border:1px solid var(--kt-border);border-radius:11px;background:var(--kt-bg)}
|
|
1971
|
+
.kumpul-plan-detail{max-width:980px;margin:0 auto}.kumpul-plan-heading{display:flex;align-items:flex-start;justify-content:space-between;gap:18px}.kumpul-plan-heading h1{margin:0;color:var(--kt-text);font-size:clamp(28px,4vw,40px);line-height:1.15;letter-spacing:-.04em}.kumpul-plan-heading .kumpul-eyebrow{margin-bottom:8px}.kumpul-plan-number{margin:9px 0 0;color:var(--kt-muted);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:10px}.kumpul-plan-workflow{margin-top:20px;padding:17px;border:1px solid var(--kt-border);border-radius:16px;background:var(--kt-surface)}.kumpul-plan-current-step{margin:0 0 14px;color:var(--kt-muted);font-size:10px}.kumpul-plan-current-step strong{color:var(--kt-text)}.kumpul-plan-workflow ol{margin:0;padding:0;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));list-style:none}.kumpul-plan-workflow li{min-width:0;padding:12px 9px 0;display:flex;align-items:center;gap:7px;border-top:2px solid var(--kt-border);color:var(--kt-muted);font-size:9px;font-weight:700}.kumpul-plan-workflow li.is-complete,.kumpul-plan-workflow li.is-current{border-color:var(--kt-accent);color:var(--kt-text)}.kumpul-plan-step-marker{width:21px;height:21px;flex:none;display:grid;place-items:center;border:1px solid var(--kt-border);border-radius:50%;font-size:9px}.kumpul-plan-workflow li.is-complete .kumpul-plan-step-marker,.kumpul-plan-workflow li.is-current .kumpul-plan-step-marker{border-color:var(--kt-accent);background:var(--kt-accent);color:#fff}.kumpul-plan-readonly{margin:12px 0 0;color:var(--kt-muted);font-size:9px;line-height:1.5}.kumpul-plan-layout{margin-top:16px;display:grid;grid-template-columns:minmax(0,1fr) 300px;align-items:start;gap:16px}.kumpul-plan-main{display:grid;gap:14px}.kumpul-plan-options{margin:0;padding:0;display:grid;list-style:none}.kumpul-plan-options li{padding:13px 0;border-top:1px solid var(--kt-border)}.kumpul-plan-option-heading{display:flex;align-items:center;justify-content:space-between;gap:12px}.kumpul-plan-option-group{color:var(--kt-muted);font-size:8px;font-weight:750;letter-spacing:.08em;text-transform:uppercase}.kumpul-plan-option-heading h3{margin:3px 0 0;font-size:11px}.kumpul-plan-options li>p{margin:6px 0 0;color:var(--kt-muted);font-size:9px;line-height:1.5}.kumpul-plan-final-option{padding:5px 8px;border:1px solid var(--kt-accent);border-radius:99px;color:var(--kt-accent);font-size:8px;font-weight:800;white-space:nowrap}.kumpul-plan-votes{display:inline-block;margin-top:8px;color:var(--kt-accent);font-size:9px;font-weight:750}.kumpul-plan-empty-options{margin:0;color:var(--kt-muted);font-size:10px}.kumpul-plan-aside>p{margin:13px 0 0;color:var(--kt-muted);font-size:10px;line-height:1.6}.kumpul-plan-order-ref{overflow-wrap:anywhere;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:8px!important}.kumpul-plan-account-link{margin-top:16px;padding:10px 12px;display:block;border:1px solid var(--kt-border);border-radius:10px;color:var(--kt-accent);font-size:10px;font-weight:800;text-align:center}
|
|
1972
|
+
.kumpul-plan-simulator{margin-top:18px;padding:20px;border:1px solid var(--kt-border);border-radius:18px;background:var(--kt-surface);box-shadow:0 8px 26px #0f172a0a}.kumpul-plan-simulator-heading{display:flex;align-items:flex-start;justify-content:space-between;gap:16px}.kumpul-plan-simulator-heading h2{margin:0;font-size:19px;letter-spacing:-.025em}.kumpul-plan-simulator-heading .kumpul-eyebrow{margin-bottom:7px}.kumpul-plan-simulator-heading>div>p:last-child{margin:7px 0 0;color:var(--kt-muted);font-size:10px;line-height:1.55}.kumpul-plan-simulation-badge{padding:6px 9px;flex:none;border-radius:99px;background:#e6f4f6;color:var(--kt-accent);font-size:8px;font-weight:800}.kumpul-plan-simulation-note{margin:15px 0;padding:10px 12px;border:1px solid var(--kt-border);border-radius:10px;background:var(--kt-bg);color:var(--kt-muted);font-size:9px;line-height:1.55}.kumpul-plan-sim-steps{margin:17px 0 0;padding:0;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));list-style:none}.kumpul-plan-sim-steps li{min-width:0;border-top:2px solid var(--kt-border)}.kumpul-plan-sim-steps li.is-current,.kumpul-plan-sim-steps li.is-complete{border-color:var(--kt-accent)}.kumpul-plan-sim-steps button{width:100%;padding:10px 5px 4px;display:flex;align-items:center;gap:6px;border:0;background:none;color:var(--kt-muted);font:inherit;font-size:8px;font-weight:750;text-align:left}.kumpul-plan-sim-steps li.is-current button,.kumpul-plan-sim-steps li.is-complete button{color:var(--kt-text)}.kumpul-plan-sim-steps button:disabled{cursor:not-allowed;opacity:.65}.kumpul-plan-sim-steps button:not(:disabled){cursor:pointer}.kumpul-plan-sim-steps button>span:first-child{width:20px;height:20px;flex:none;display:grid;place-items:center;border:1px solid var(--kt-border);border-radius:50%;font-size:8px}.kumpul-plan-sim-steps li.is-current button>span:first-child,.kumpul-plan-sim-steps li.is-complete button>span:first-child{border-color:var(--kt-accent);background:var(--kt-accent);color:#fff}.kumpul-plan-sim-panel{margin-top:17px}.kumpul-plan-sim-panel[hidden],.kumpul-plan-sim-complete[hidden]{display:none}.kumpul-plan-sim-panel h3,.kumpul-plan-sim-complete h3{margin:0;font-size:15px}.kumpul-plan-sim-help{margin:6px 0 14px;color:var(--kt-muted);font-size:9px;line-height:1.5}.kumpul-plan-sim-form{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:11px}.kumpul-plan-sim-form label,.kumpul-plan-sim-invite-form label,.kumpul-plan-sim-person>label{min-width:0;display:grid;gap:5px;color:var(--kt-muted);font-size:9px;font-weight:700}.kumpul-plan-sim-form input,.kumpul-plan-sim-form select,.kumpul-plan-sim-invite-form input,.kumpul-plan-sim-invitees input,.kumpul-plan-sim-person select{width:100%;min-width:0;min-height:37px;padding:8px 9px;border:1px solid var(--kt-border);border-radius:9px;background:#fff;color:var(--kt-text);font:inherit;font-size:10px}.kumpul-plan-sim-options{min-width:0;margin:15px 0 0;padding:11px;border:1px solid var(--kt-border);border-radius:11px}.kumpul-plan-sim-options legend{padding:0 5px;color:var(--kt-text);font-size:10px;font-weight:800}.kumpul-plan-sim-option{margin:5px 10px 5px 0;display:inline-flex;align-items:center;gap:6px;color:var(--kt-muted);font-size:9px}.kumpul-plan-sim-option input{accent-color:var(--kt-accent)}.kumpul-plan-sim-actions{margin-top:15px;display:flex;justify-content:flex-end;gap:8px}.kumpul-plan-sim-actions button,.kumpul-plan-sim-invite-form button,.kumpul-plan-sim-invitees button,.kumpul-plan-sim-payment button,.kumpul-plan-sim-complete button{min-height:36px;padding:8px 12px;border:1px solid var(--kt-border);border-radius:9px;background:#fff;color:var(--kt-text);font:inherit;font-size:9px;font-weight:800;cursor:pointer}.kumpul-plan-sim-actions .kumpul-plan-sim-primary{border-color:var(--kt-accent);background:var(--kt-accent);color:#fff}.kumpul-plan-sim-actions .kumpul-plan-sim-secondary{color:var(--kt-accent)}.kumpul-plan-sim-error{margin:12px 0 0;color:#b91c1c;font-size:9px;font-weight:700}.kumpul-plan-sim-invite-form{display:grid;grid-template-columns:1fr 1fr auto;align-items:end;gap:9px}.kumpul-plan-sim-invitees{margin:12px 0 0;padding:0;display:grid;gap:7px;list-style:none}.kumpul-plan-sim-invitees li{display:flex;align-items:center;gap:8px}.kumpul-plan-sim-invitees li>div{flex:1;display:grid;grid-template-columns:1fr 1fr;gap:8px}.kumpul-plan-sim-invitees button,.kumpul-plan-sim-payment button{min-height:33px;padding:7px 9px;color:var(--kt-accent)}.kumpul-plan-sim-participants,.kumpul-plan-sim-payments{display:grid;gap:9px}.kumpul-plan-sim-person{padding:12px;display:grid;grid-template-columns:minmax(0,1fr) 170px;align-items:center;gap:11px;border:1px solid var(--kt-border);border-radius:12px;background:var(--kt-bg)}.kumpul-plan-sim-person-heading{min-width:0;display:grid;gap:3px}.kumpul-plan-sim-person-heading strong{font-size:10px}.kumpul-plan-sim-person-heading span{overflow-wrap:anywhere;color:var(--kt-muted);font-size:8px}.kumpul-plan-sim-person-options{grid-column:1/-1;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:9px}.kumpul-plan-sim-payment{grid-template-columns:minmax(0,1fr) auto}.kumpul-plan-sim-payment[data-sim-paid=true]{border-color:var(--kt-success);background:#effaf5}.kumpul-plan-sim-final-group{margin:7px 0 0;padding:8px;border:1px solid var(--kt-border);border-radius:9px}.kumpul-plan-sim-final-group legend{padding:0 4px;font-size:9px;font-weight:800}.kumpul-plan-sim-final-group label{margin:5px 10px 5px 0;display:inline-flex;align-items:center;gap:6px;color:var(--kt-muted);font-size:9px}.kumpul-plan-sim-final-group input{accent-color:var(--kt-accent)}.kumpul-plan-sim-complete{margin-top:18px;padding:22px;border:1px solid #8bd1ae;border-radius:13px;background:#effaf5;text-align:center}.kumpul-plan-sim-complete>span{width:34px;height:34px;margin:0 auto 9px;display:grid;place-items:center;border-radius:50%;background:var(--kt-success);color:#fff;font-weight:900}.kumpul-plan-sim-complete p{margin:7px 0 13px;color:var(--kt-muted);font-size:9px;line-height:1.5}
|
|
1973
|
+
@media(max-width:760px){.kumpul-plan-heading{flex-direction:column;gap:12px}.kumpul-plan-workflow{padding:14px}.kumpul-plan-workflow ol{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.kumpul-plan-workflow li{padding:9px 5px 0;font-size:8px}.kumpul-plan-layout{grid-template-columns:1fr;gap:13px}.kumpul-plan-aside{position:static}.kumpul-plan-simulator{padding:15px}.kumpul-plan-simulator-heading{flex-direction:column;gap:10px}.kumpul-plan-sim-form{grid-template-columns:1fr}.kumpul-plan-sim-invite-form{grid-template-columns:1fr}.kumpul-plan-sim-invite-form button{width:100%}.kumpul-plan-sim-invitees li{align-items:flex-start;flex-direction:column}.kumpul-plan-sim-invitees li>div{width:100%;grid-template-columns:1fr}.kumpul-plan-sim-invitees button{align-self:flex-end}.kumpul-plan-sim-person{grid-template-columns:1fr}.kumpul-plan-sim-person-options{grid-template-columns:1fr}.kumpul-plan-sim-payment{grid-template-columns:1fr}.kumpul-plan-sim-payment button{width:100%}.kumpul-plan-sim-steps button{align-items:flex-start;flex-direction:column;font-size:7px}.kumpul-plan-sim-actions{flex-wrap:wrap}.kumpul-plan-sim-actions button{flex:1}}
|
|
1974
|
+
@media(max-width:760px){.kumpul-detail-heading{align-items:flex-start;flex-direction:column}.kumpul-detail-layout{grid-template-columns:1fr;gap:13px}.kumpul-detail-aside{position:static}.kumpul-detail-card{padding:16px}.kumpul-detail-fields{gap:13px}.kumpul-detail-total strong{font-size:19px}.kumpul-detail-item{grid-template-columns:40px minmax(0,1fr);gap:10px}.kumpul-detail-item-art{width:40px;height:40px}.kumpul-detail-item>strong{grid-column:2}.kumpul-detail-page .kumpul-detail-preview-note{font-size:9px}}
|
|
1975
|
+
@media(max-width:900px){.kumpul-header-main{padding:12px 20px}.kumpul-utilities>a span{display:none}.kumpul-utilities>a{padding:9px}.kumpul-main{padding:24px 20px 60px}.kumpul-hero{grid-template-columns:1fr}.kumpul-hero-copy{padding:38px}.kumpul-feature-card{min-height:310px}.kumpul-about-section{grid-template-columns:1fr .8fr;gap:24px}.kumpul-about-art,.kumpul-about-image{min-height:230px}.kumpul-process-list{grid-template-columns:repeat(2,minmax(0,1fr))}.kumpul-process-step+.kumpul-process-step{border-left:0}.kumpul-process-step:nth-child(even){border-left:1px solid var(--kt-border)}.kumpul-process-step:nth-child(n+3){border-top:1px solid var(--kt-border)}.kumpul-gathering-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.kumpul-location-list{grid-template-columns:repeat(2,minmax(0,1fr))}.kumpul-category-filters{grid-template-columns:repeat(2,minmax(0,1fr))}.kumpul-calendar-heading{align-items:flex-start;flex-direction:column}.kumpul-calendar-stats{width:100%}.kumpul-cta{align-items:flex-start;flex-direction:column}}
|
|
1976
|
+
@media(max-width:620px){.kumpul-header-main{min-height:64px;padding:9px 16px}.kumpul-logo,.kumpul-logo-mark{width:40px;height:40px;border-radius:13px}.kumpul-brand-copy strong{font-size:15px}.kumpul-brand-copy small{font-size:8px}.kumpul-utilities{display:none}.kumpul-page-nav{min-height:47px;justify-content:flex-start;overflow-x:auto;padding:5px 12px}.kumpul-page-nav a{padding:7px 12px;font-size:11px}.kumpul-main{padding:16px 14px 98px}.kumpul-hero{border-radius:21px}.kumpul-hero-copy{padding:27px 22px}.kumpul-community-pill{margin-bottom:17px;font-size:9px}.kumpul-hero h1{font-size:clamp(39px,12vw,58px)}.kumpul-hero-description{margin-top:15px;font-size:13px}.kumpul-hero-actions{gap:8px;margin-top:19px}.kumpul-button{min-height:42px;padding:10px 13px;font-size:11px}.kumpul-stats{gap:20px;margin-top:22px}.kumpul-stat strong{font-size:18px}.kumpul-stat span{font-size:9px}.kumpul-feature-card{min-height:250px;padding:16px}.kumpul-feature-art>span{width:86px;height:86px;font-size:42px}.kumpul-about-section{margin-top:0;padding:22px;grid-template-columns:1fr;border-radius:21px}.kumpul-about-copy h1{font-size:clamp(34px,10vw,48px)}.kumpul-about-body{font-size:13px}.kumpul-about-art,.kumpul-about-image{min-height:230px}.kumpul-gallery-grid{grid-template-columns:repeat(2,minmax(0,1fr));grid-auto-rows:135px;gap:9px}.kumpul-gallery-item:nth-child(3n+2){grid-row:span 1}.kumpul-gallery-item:nth-child(4n+1){grid-row:span 2}.kumpul-gallery-item>span{font-size:38px}.kumpul-process-list{grid-template-columns:1fr}.kumpul-process-step{padding:14px;display:grid;grid-template-columns:34px 1fr;column-gap:12px}.kumpul-process-step+.kumpul-process-step,.kumpul-process-step:nth-child(even),.kumpul-process-step:nth-child(n+3){border-top:1px solid var(--kt-border);border-left:0}.kumpul-process-step .kumpul-flow-number{grid-row:span 2}.kumpul-process-step small{grid-column:2}.kumpul-section{margin-top:48px}.kumpul-section-heading .kumpul-section-title,.kumpul-cta h2{font-size:29px}.kumpul-section-description{font-size:12px}.kumpul-flow-list{grid-template-columns:1fr;border-radius:16px}.kumpul-flow-step{min-height:0;padding:13px 15px;display:grid;grid-template-columns:34px 1fr;column-gap:11px}.kumpul-flow-step+.kumpul-flow-step{border-top:1px solid var(--kt-border);border-left:0}.kumpul-flow-number{grid-row:span 2}.kumpul-flow-step strong{margin:0}.kumpul-flow-step>span:last-child{font-size:10px}.kumpul-section-topline{align-items:flex-start}.kumpul-text-link{margin-top:5px;font-size:10px}.kumpul-catalog-heading{align-items:stretch;flex-direction:column;gap:16px}.kumpul-catalog-search{width:100%;min-height:44px}.kumpul-category-filters{grid-template-columns:1fr 1fr;gap:8px}.kumpul-category-filter{padding:9px;gap:8px}.kumpul-category-icon{width:32px;height:32px}.kumpul-category-filter strong{font-size:10px}.kumpul-category-filter small{font-size:8px}.kumpul-gathering-grid{grid-template-columns:1fr;gap:12px}.kumpul-gathering-card{display:grid;grid-template-columns:112px 1fr}.kumpul-gathering-art{min-height:100%;}.kumpul-gathering-art>span:first-child{font-size:36px}.kumpul-card-content{min-width:0;padding:12px}.kumpul-card-content h3{font-size:13px}.kumpul-card-meta{font-size:9px}.kumpul-card-bottom{margin-top:9px;padding-top:8px}.kumpul-card-bottom strong{font-size:10px}.kumpul-card-bottom span{font-size:9px}.kumpul-calendar{margin-top:0}.kumpul-calendar-title{font-size:34px}.kumpul-calendar-description{font-size:12px}.kumpul-calendar-stats{gap:7px}.kumpul-calendar-stat{min-width:0;flex:1;padding:10px}.kumpul-calendar-stat strong{font-size:16px}.kumpul-calendar-stat span{font-size:9px}.kumpul-calendar-card{align-items:flex-start;flex-direction:column;padding:15px}.kumpul-calendar-invitation-action{width:100%;justify-items:start}.kumpul-calendar-action{min-height:36px}.kumpul-section-topline{align-items:flex-start}.kumpul-text-link{margin-top:5px;font-size:10px}.kumpul-testimonial-grid{grid-template-columns:1fr}.kumpul-location-list{grid-template-columns:1fr}.kumpul-cta{margin-top:48px;padding:25px 20px;border-radius:19px}.kumpul-cta-actions{width:100%}.kumpul-cta-actions .kumpul-button{flex:1}.kumpul-footer{padding:20px 15px 95px;flex-direction:column}.kumpul-mobile-dock{position:fixed;z-index:5;right:0;bottom:0;left:0;padding:9px 5px max(9px,env(safe-area-inset-bottom));display:flex;justify-content:space-around;border-top:1px solid var(--kt-border);background:#fffffff2;backdrop-filter:blur(14px)}.kumpul-mobile-dock a{min-width:0;display:grid;justify-items:center;gap:3px;color:var(--kt-muted);font-size:8px}.kumpul-mobile-dock .kumpul-icon{width:19px;height:19px}}
|
|
1977
|
+
@media(prefers-reduced-motion:reduce){.kumpul-template *{scroll-behavior:auto!important;transition:none!important}}
|
|
1978
|
+
`;
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1981
|
+
function render(props = {}) {
|
|
1982
|
+
const colors = themeColors(props);
|
|
1983
|
+
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');
|
|
2003
|
+
const profile = props.profile || {};
|
|
2004
|
+
|
|
2005
|
+
return h('div', { className: 'kumpul-template' },
|
|
2006
|
+
h('style', { dangerouslySetInnerHTML: { __html: styles(colors) } }),
|
|
2007
|
+
h(Header, { ...props, activePageSlug }),
|
|
2008
|
+
h('main', { className: 'kumpul-main' },
|
|
2009
|
+
hero ? h(Hero, { ...props, section: hero }) : null,
|
|
2010
|
+
sections.filter((section) => section?.type === 'about').map((section) => h(AboutSection, { ...section, key: section.id || 'about' })),
|
|
2011
|
+
features ? h(FeaturesSection, features) : null,
|
|
2012
|
+
sections.filter((section) => section?.type === 'gallery').map((section) => h(GallerySection, { ...section, key: section.id || 'gallery' })),
|
|
2013
|
+
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' })),
|
|
2017
|
+
billingPage ? h(BillingSection, { props }) : null,
|
|
2018
|
+
transactionsPage ? h(TransactionsSection, { props }) : null,
|
|
2019
|
+
cartPage ? h(CartSection, { props }) : null,
|
|
2020
|
+
invoiceDetailPage ? h(InvoiceDetailSection, { props }) : null,
|
|
2021
|
+
transactionDetailPage ? h(TransactionDetailSection, { props, section: orderDetailSection }) : null,
|
|
2022
|
+
gatheringPlanDetailPage ? h(GatheringPlanDetailSection, { props, section: orderDetailSection }) : null,
|
|
2023
|
+
testimonials ? h(TestimonialsSection, testimonials) : null,
|
|
2024
|
+
locations ? h(LocationsSection, { props, section: locations }) : null,
|
|
2025
|
+
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,
|
|
2032
|
+
),
|
|
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.')),
|
|
2036
|
+
),
|
|
2037
|
+
h(MobileDock, { ...props, activePageSlug }),
|
|
2038
|
+
);
|
|
2039
|
+
}
|
|
2040
|
+
|
|
2041
|
+
module.exports = { render };
|