@bagdja/kumpul 1.0.2 → 1.1.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 CHANGED
@@ -15,10 +15,38 @@ direction and notes about the prototype's sample data and host-managed pages.
15
15
  ## Contract
16
16
 
17
17
  - Package: `@bagdja/kumpul`
18
- - Version: `1.0.2`
18
+ - Version: `1.1.0`
19
19
  - Template slug: `kumpul`
20
- - `rendererApiVersion`: `1`
21
- - Entry point: `dist/server.cjs`
20
+ - `manifestVersion`: `1`, `rendererApiVersion`: `1`
21
+ - Entry point: `dist/server.cjs` (wajib) dan `dist/client.js` (JavaScript browser), dinyatakan di `manifest.entry`
22
+ - Halaman contoh untuk website baru: `manifest.defaultPages` (Beranda, Katalog Gathering, Cara Kerja, Tentang)
23
+ - Halaman sistem milik template (`manifest.pageOverrides`): header, keranjang, transaksi, detail transaksi, tagihan, invoice, kalender, rencana gathering
24
+
25
+ ## Halaman sistem (`props.page`)
26
+
27
+ Sejak `1.1.0`, data halaman sistem dibaca dari `props.page` sesuai kontrak
28
+ Bagdja (`bagdja-website-template-runtime/contract/page-contract.d.ts`), bukan
29
+ lagi dari `props.preview*`. `src/page-adapter.cjs` adalah satu-satunya tempat
30
+ yang mengenal bentuk kontrak itu dan menerjemahkannya ke model internal
31
+ renderer. Data yang sama dipakai di preview lokal, preview platform, dan
32
+ website seller; `isPreview` hanya mengatur catatan "Preview desainer" dan
33
+ simulator rencana gathering.
34
+
35
+ - Tanggal: ISO 8601 dengan offset timezone; uang: bilangan bulat rupiah.
36
+ - Template tidak menerima email/token/ID internal. Identitas aksi = `key` opaque.
37
+ - Aksi memakai atribut bridge host Bagdja — bootstrap di iframe menangani
38
+ klik, template tidak memanggil API:
39
+ `data-bagdja-intent` (`cart.set_quantity` / `cart.remove` / `cart.checkout` /
40
+ `invoice.pay` / `gathering.respond`) + `data-bagdja-key`,
41
+ `data-bagdja-quantity` (jumlah tujuan), `data-bagdja-selectable` pada checkbox
42
+ item yang ikut checkout, dan `data-bagdja-action="order.retry_payment"` untuk
43
+ aksi transaksi. Tombol baru aktif bila host menyediakan bridge
44
+ (`props.bridgeVersion`); setelah aksi berhasil host memuat ulang halaman atau
45
+ mengarahkan ke pembayaran.
46
+ - `props.headerOnly === true` → hanya header Kumpul (halaman yang isinya masih
47
+ dikelola Bagdja, mis. chat dan checkout).
48
+ - Fixture halaman sistem di `fixtures/` memakai data yang sama dengan fixture
49
+ standar Bagdja, dengan identitas Kumpul.
22
50
  - Export: `render(props)`, returning a React element
23
51
  - React: supplied by the Bagdja runtime
24
52
 
@@ -93,9 +121,9 @@ from it, then replace the renderer and fixtures while preserving the package
93
121
  and manifest contract. The local preview is a development aid, not a substitute
94
122
  for Bagdja Studio/reviewer preview or the isolated production runtime.
95
123
 
96
- The runtime's optional `client_bundle` capability is approval-gated. Review
97
- and approve the exact package version before enabling its browser bundle in
98
- Bagdja; the local fixture preview is not that approval.
124
+ `dist/client.js` dibaca reviewer Bagdja sebelum versi disetujui; setelah
125
+ terbit, JavaScript ini berjalan di semua halaman website seller di dalam iframe
126
+ sandbox. Preview fixture lokal bukan persetujuan tersebut.
99
127
 
100
128
  `npm run build` builds the package; `npm test` checks the renderer, and
101
129
  `npm pack --dry-run` previews the contents to be uploaded to npm without
package/dist/server.cjs CHANGED
@@ -1,5 +1,275 @@
1
+ var __getOwnPropNames = Object.getOwnPropertyNames;
2
+ var __commonJS = (cb, mod) => function __require() {
3
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
4
+ };
5
+
6
+ // src/page-adapter.cjs
7
+ var require_page_adapter = __commonJS({
8
+ "src/page-adapter.cjs"(exports2, module2) {
9
+ var PAGE_SLUGS = {
10
+ cart: "cart",
11
+ orders: "orders",
12
+ order_detail: "transaction-detail",
13
+ tagihan: "tagihan",
14
+ invoice_detail: "invoice-detail",
15
+ calendar: "calendar",
16
+ gathering_plan: "plan-detail"
17
+ };
18
+ function list2(value) {
19
+ return Array.isArray(value) ? value : [];
20
+ }
21
+ function gatheringPaymentStatus(status) {
22
+ if (status === "PAID") return "PAID";
23
+ if (status === "REFUNDED") return "REFUNDED";
24
+ return "PENDING_PAYMENT";
25
+ }
26
+ function adaptCart(page) {
27
+ return list2(page.items).map((item) => ({
28
+ id: item.key,
29
+ key: item.key,
30
+ kind: item.kind,
31
+ name: item.name,
32
+ category: item.category,
33
+ subtitle: item.subtitle,
34
+ variant: item.variant,
35
+ emoji: item.emoji,
36
+ imageUrl: item.imageUrl,
37
+ price: item.unitPrice,
38
+ quantity: item.quantity,
39
+ quantity_editable: item.quantityEditable !== false,
40
+ max_quantity: item.maxQuantity,
41
+ can_checkout: item.checkoutable !== false,
42
+ blocked_reason: item.blockedReason,
43
+ detail_href: item.detailHref
44
+ }));
45
+ }
46
+ function adaptTransactions(page) {
47
+ return list2(page.transactions).map((transaction) => ({
48
+ id: transaction.key,
49
+ key: transaction.key,
50
+ ref_number: transaction.reference,
51
+ status: transaction.status,
52
+ status_label: transaction.statusLabel,
53
+ created_at: transaction.createdAt,
54
+ total_amount: transaction.totalAmount,
55
+ item_count: transaction.itemCount,
56
+ has_outstanding_invoice: Boolean(transaction.outstanding),
57
+ outstanding_label: transaction.outstanding ? transaction.outstanding.label : void 0,
58
+ items: list2(transaction.itemNames).map((name) => ({ product_name: name })),
59
+ detail_href: transaction.detailHref
60
+ }));
61
+ }
62
+ function adaptTransaction(page) {
63
+ const transaction = page.transaction || {};
64
+ const shipping = transaction.shipping || {};
65
+ return {
66
+ id: transaction.key,
67
+ key: transaction.key,
68
+ ref_number: transaction.reference,
69
+ status: transaction.status,
70
+ status_label: transaction.statusLabel,
71
+ status_message: transaction.statusMessage,
72
+ created_at: transaction.createdAt,
73
+ total_amount: transaction.totalAmount,
74
+ subtotal_amount: transaction.subtotalAmount,
75
+ payment_mode: transaction.paymentMode,
76
+ payment_mode_label: transaction.paymentModeLabel,
77
+ shipping_cost: transaction.shippingAmount,
78
+ recipient_name: shipping.recipient,
79
+ phone: shipping.phone,
80
+ address: shipping.address,
81
+ metadata: {
82
+ shipping: {
83
+ courier_service_name: shipping.courierLabel || transaction.courierLabel,
84
+ destination_area_name: shipping.areaLabel
85
+ }
86
+ },
87
+ items: list2(transaction.items).map((item) => ({
88
+ id: item.key,
89
+ key: item.key,
90
+ quantity: item.quantity,
91
+ unit_price: item.unitPrice,
92
+ total_amount: item.totalAmount,
93
+ product_name: item.name,
94
+ emoji: item.emoji,
95
+ detail_href: item.detailHref
96
+ }))
97
+ };
98
+ }
99
+ function adaptInvoices(page) {
100
+ return list2(page.invoices).map((invoice) => {
101
+ if (invoice.kind === "gathering") {
102
+ return {
103
+ id: invoice.key,
104
+ key: invoice.key,
105
+ kind: "gathering",
106
+ invoice_id: invoice.label,
107
+ gathering_title: invoice.title,
108
+ amount: invoice.amount,
109
+ invoice_issued_at: invoice.status === "SCHEDULED" ? null : invoice.createdAt,
110
+ invoice_status: invoice.status === "SCHEDULED" ? "SCHEDULED" : "ISSUED",
111
+ payment_status: gatheringPaymentStatus(invoice.status),
112
+ payment_deadline: invoice.dueAt,
113
+ can_pay: invoice.canPay === true,
114
+ detail_href: invoice.detailHref,
115
+ transaction_href: invoice.transactionHref
116
+ };
117
+ }
118
+ return {
119
+ id: invoice.key,
120
+ key: invoice.key,
121
+ kind: "termin",
122
+ sequence: invoice.sequence,
123
+ productName: invoice.title,
124
+ label: invoice.label,
125
+ amount: invoice.amount,
126
+ status: invoice.status,
127
+ anchorStepName: invoice.stepLabel,
128
+ createdAt: invoice.createdAt,
129
+ dueDate: invoice.dueAt,
130
+ can_pay: invoice.canPay === true,
131
+ detail_href: invoice.detailHref,
132
+ transaction_href: invoice.transactionHref
133
+ };
134
+ });
135
+ }
136
+ function adaptInvoice(page) {
137
+ const invoice = page.invoice || {};
138
+ return {
139
+ key: invoice.key,
140
+ invoice_id: invoice.number,
141
+ plan_number: invoice.planNumber,
142
+ gathering_title: invoice.title,
143
+ attendee_name: invoice.attendeeName,
144
+ initiator_name: invoice.initiatorName,
145
+ amount: invoice.amount,
146
+ currency: page.currency,
147
+ payment_status: invoice.status === "PAID" || invoice.status === "REFUNDED" ? invoice.status : "UNPAID",
148
+ payment_open: page.canPay === true,
149
+ login_required: page.loginRequired === true,
150
+ payment_deadline: invoice.dueAt,
151
+ event_date: invoice.eventAt
152
+ };
153
+ }
154
+ function adaptPlan(page) {
155
+ const plan = page.plan || {};
156
+ const occurrence = plan.occurrence || {};
157
+ const options = list2(occurrence.options);
158
+ return {
159
+ id: plan.key,
160
+ key: plan.key,
161
+ plan_number: plan.planNumber,
162
+ title: plan.title,
163
+ status: plan.status,
164
+ status_label: plan.statusLabel,
165
+ workflow_step: plan.workflowStep,
166
+ workflow_step_label: plan.workflowStepLabel,
167
+ invite_policy: plan.invitePolicy,
168
+ occurrence: {
169
+ status: occurrence.status,
170
+ status_label: occurrence.statusLabel,
171
+ price_per_seat: occurrence.seatPrice,
172
+ currency: page.currency,
173
+ deposit_amount_per_seat: occurrence.depositPerSeatAmount,
174
+ min_attendees: occurrence.minAttendees,
175
+ max_attendees: occurrence.maxAttendees,
176
+ rsvp_close_at: occurrence.rsvpCloseAt,
177
+ payment_deadline: occurrence.paymentDueAt,
178
+ final_schedule: occurrence.scheduledAt,
179
+ final_location: occurrence.location,
180
+ option_groups_snapshot: options.map((option) => ({
181
+ product_option_id: option.key,
182
+ option_group_key: option.group,
183
+ option_key: option.key,
184
+ label: option.label,
185
+ description: option.description,
186
+ venue_location: option.venue,
187
+ is_final_selection: option.isFinal === true
188
+ })),
189
+ opened_option_ids_snapshot: options.filter((option) => option.isOpen).map((option) => option.key),
190
+ voting_results: Object.fromEntries(
191
+ options.filter((option) => typeof option.votes === "number").map((option) => [option.key, option.votes])
192
+ )
193
+ }
194
+ };
195
+ }
196
+ function adaptCalendar(page) {
197
+ return {
198
+ title: "Kalender Acara",
199
+ month: page.initialMonth,
200
+ plans: list2(page.plans).map((plan) => ({
201
+ id: plan.key,
202
+ key: plan.key,
203
+ title: plan.title,
204
+ plan_number: plan.planNumber,
205
+ status: plan.status,
206
+ workflow_step_label: plan.stepLabel,
207
+ event_date: plan.eventAt,
208
+ payment_deadline: plan.paymentDueAt,
209
+ min_attendees: plan.minAttendees,
210
+ max_attendees: plan.maxAttendees,
211
+ detail_href: plan.detailHref
212
+ })),
213
+ invitations: list2(page.invitations).map((invitation) => ({
214
+ id: invitation.key,
215
+ key: invitation.key,
216
+ gathering_title: invitation.title,
217
+ plan_number: invitation.planNumber,
218
+ initiator_name: invitation.initiatorName,
219
+ event_date: invitation.eventAt,
220
+ event_location: invitation.location,
221
+ is_new: invitation.isNew === true,
222
+ needs_action: invitation.needsAction === true,
223
+ response: invitation.response,
224
+ action_label: invitation.responseLabel,
225
+ detail_href: invitation.detailHref
226
+ }))
227
+ };
228
+ }
229
+ function adaptPage2(page) {
230
+ if (!page || typeof page !== "object" || !PAGE_SLUGS[page.type]) return null;
231
+ const base = {
232
+ type: page.type,
233
+ activePageSlug: PAGE_SLUGS[page.type],
234
+ actions: list2(page.actions),
235
+ timezone: typeof page.timezone === "string" ? page.timezone : "Asia/Jakarta"
236
+ };
237
+ switch (page.type) {
238
+ case "cart":
239
+ return { ...base, cart: adaptCart(page) };
240
+ case "orders":
241
+ return { ...base, transactions: adaptTransactions(page) };
242
+ case "order_detail":
243
+ return { ...base, transaction: adaptTransaction(page) };
244
+ case "tagihan":
245
+ return { ...base, invoices: adaptInvoices(page) };
246
+ case "invoice_detail":
247
+ return { ...base, invoice: adaptInvoice(page) };
248
+ case "calendar":
249
+ return { ...base, calendar: adaptCalendar(page) };
250
+ case "gathering_plan":
251
+ return {
252
+ ...base,
253
+ plan: adaptPlan(page),
254
+ // Keputusan E3: tanpa email/kontak peserta.
255
+ invitees: list2(page.invitees).map((invitee) => ({
256
+ name: invitee.name,
257
+ rsvp_status: invitee.rsvpStatus,
258
+ rsvp_label: invitee.rsvpLabel
259
+ })),
260
+ viewerRole: page.viewerRole
261
+ };
262
+ default:
263
+ return null;
264
+ }
265
+ }
266
+ module2.exports = { adaptPage: adaptPage2, PAGE_SLUGS };
267
+ }
268
+ });
269
+
1
270
  // src/server.cjs
2
271
  var React = require("react");
272
+ var { adaptPage } = require_page_adapter();
3
273
  var h = React.createElement;
4
274
  var defaultColors = {
5
275
  background: "#F0F7F8",
@@ -15,6 +285,12 @@ var defaultColors = {
15
285
  function text(value, fallback = "") {
16
286
  return typeof value === "string" && value.trim() ? value : fallback;
17
287
  }
288
+ function intentEnabled(props, action) {
289
+ return Boolean(props.bridgeVersion) && list(props.kumpulPage && props.kumpulPage.actions).includes(action);
290
+ }
291
+ function intentAttributes(action, key, extra = {}) {
292
+ return { "data-bagdja-intent": action, ...key ? { "data-bagdja-key": key } : {}, ...extra };
293
+ }
18
294
  function list(value) {
19
295
  return Array.isArray(value) ? value : [];
20
296
  }
@@ -47,7 +323,9 @@ function billingStatus(invoice) {
47
323
  return {
48
324
  SCHEDULED: "scheduled",
49
325
  ISSUED: "issued",
326
+ OVERDUE: "issued",
50
327
  PAID: "paid",
328
+ REFUNDED: "refunded",
51
329
  CANCELLED: "cancelled"
52
330
  }[invoice.status] || "scheduled";
53
331
  }
@@ -84,7 +362,7 @@ var transactionFilters = [
84
362
  ["cancelled", "Dibatalkan"]
85
363
  ];
86
364
  function CartSection({ props }) {
87
- const cartItems = props.isPreview === true ? list(props.previewCart) : [];
365
+ const cartItems = list(props.kumpulPage && props.kumpulPage.cart);
88
366
  const displayCount = cartItems.filter((item) => item.kind !== "gathering_plan").reduce((count, item) => count + (Number(item.quantity) || 1), 0);
89
367
  const selectableCount = cartItems.filter((item) => item.can_checkout !== false && item.kind !== "gathering_plan").length;
90
368
  return h(
@@ -149,6 +427,7 @@ function CartSection({ props }) {
149
427
  defaultChecked: canCheckout,
150
428
  disabled: !canCheckout,
151
429
  "data-cart-select": "",
430
+ ...canCheckout && item.key ? { "data-bagdja-selectable": "", "data-bagdja-key": item.key } : {},
152
431
  "aria-label": canCheckout ? `Pilih ${text(item.name, "item keranjang")}` : `${text(item.name, "Item")} belum bisa checkout`
153
432
  })
154
433
  ),
@@ -173,19 +452,23 @@ function CartSection({ props }) {
173
452
  type: "button",
174
453
  "aria-label": `Kurangi jumlah ${text(item.name, "item")}`,
175
454
  "data-cart-quantity-decrease": "",
176
- disabled: quantity <= 1
455
+ disabled: quantity <= 1 || item.quantity_editable === false,
456
+ ...item.key && quantity > 1 ? intentAttributes("cart.set_quantity", item.key, { "data-bagdja-quantity": String(quantity - 1) }) : {}
177
457
  }, "\u2212"),
178
458
  h("span", { "data-cart-quantity": "" }, String(quantity)),
179
459
  h("button", {
180
460
  type: "button",
181
461
  "aria-label": `Tambah jumlah ${text(item.name, "item")}`,
182
- "data-cart-quantity-increase": ""
462
+ "data-cart-quantity-increase": "",
463
+ disabled: item.quantity_editable === false || Number(item.max_quantity) > 0 && quantity >= Number(item.max_quantity),
464
+ ...item.key ? intentAttributes("cart.set_quantity", item.key, { "data-bagdja-quantity": String(quantity + 1) }) : {}
183
465
  }, "+")
184
466
  ) : null,
185
467
  h("button", {
186
468
  type: "button",
187
469
  className: "kumpul-cart-remove",
188
470
  "data-cart-remove": "",
471
+ ...item.key ? intentAttributes("cart.remove", item.key) : {},
189
472
  "aria-label": `Hapus ${text(item.name, "item")}`
190
473
  }, "Hapus")
191
474
  )
@@ -209,7 +492,7 @@ function CartSection({ props }) {
209
492
  h("span", null, "Total sementara"),
210
493
  h("strong", { "data-cart-selected-total": "" }, "Rp 0")
211
494
  ),
212
- h("button", { type: "button", className: "kumpul-cart-checkout", disabled: true }, "Lanjut ke Checkout"),
495
+ h("button", { type: "button", className: "kumpul-cart-checkout", disabled: !intentEnabled(props, "cart.checkout"), ...intentAttributes("cart.checkout") }, "Lanjut ke Checkout"),
213
496
  h("p", null, "Item yang belum dapat dibayar akan tetap tersimpan di keranjang.")
214
497
  )
215
498
  ),
@@ -243,7 +526,7 @@ function transactionStatus(transaction) {
243
526
  };
244
527
  }
245
528
  function TransactionsSection({ props }) {
246
- const transactions = props.isPreview === true ? list(props.previewTransactions) : [];
529
+ const transactions = list(props.kumpulPage && props.kumpulPage.transactions);
247
530
  const counts = Object.fromEntries(transactionFilters.map(([key]) => [
248
531
  key,
249
532
  key === "all" ? transactions.length : transactions.filter((transaction) => transactionStatus(transaction).filter === key).length
@@ -343,9 +626,9 @@ function TransactionsSection({ props }) {
343
626
  h(
344
627
  "div",
345
628
  { className: "kumpul-transaction-actions" },
346
- transaction.status === "PENDING_PAYMENT" ? h("button", { type: "button", disabled: true }, "Lanjutkan Pembayaran") : null,
347
- h("button", { type: "button", disabled: true }, "Detail Transaksi"),
348
- h("button", { type: "button", disabled: true }, "Chat Order")
629
+ transaction.status === "PENDING_PAYMENT" && transaction.detail_href ? h("a", { className: "kumpul-transaction-action-link", href: transaction.detail_href }, "Lanjutkan Pembayaran") : null,
630
+ transaction.detail_href ? h("a", { className: "kumpul-transaction-action-link", href: transaction.detail_href }, "Detail Transaksi") : h("button", { type: "button", disabled: true }, "Detail Transaksi"),
631
+ props.auth && props.auth.chatHref ? h("a", { className: "kumpul-transaction-action-link", href: props.auth.chatHref }, "Chat Order") : h("button", { type: "button", disabled: true }, "Chat Order")
349
632
  )
350
633
  );
351
634
  }),
@@ -372,7 +655,8 @@ function invoiceDetailStatus(invoice) {
372
655
  };
373
656
  }
374
657
  function InvoiceDetailSection({ props }) {
375
- if (props.isPreview !== true) {
658
+ const invoice = props.kumpulPage && props.kumpulPage.invoice;
659
+ if (!invoice) {
376
660
  return h(
377
661
  "section",
378
662
  { className: "kumpul-detail-page", "data-invoice-detail": "" },
@@ -380,7 +664,6 @@ function InvoiceDetailSection({ props }) {
380
664
  h("p", null, "Data tagihan dan status pembayaran dikelola oleh host Bagdja.")
381
665
  );
382
666
  }
383
- const invoice = props.isPreview === true ? props.previewInvoice || {} : {};
384
667
  const status = invoiceDetailStatus(invoice);
385
668
  const amount = new Intl.NumberFormat("id-ID", {
386
669
  style: "currency",
@@ -454,17 +737,21 @@ function InvoiceDetailSection({ props }) {
454
737
  h("h3", null, "Mengapa perlu login untuk membayar?"),
455
738
  h("p", null, "Akun Bagdja menghubungkan pembayaran escrow dengan peserta. Gunakan email yang sama dengan email saat RSVP. Initiator juga dapat membayar beberapa tagihan dari halaman gathering.")
456
739
  ) : null,
457
- !isPaid ? h(
740
+ !isPaid && paymentOpen && invoice.login_required && props.auth && props.auth.loginHref ? h("a", { className: "kumpul-detail-pay-link", href: props.auth.loginHref }, "Login untuk membayar") : !isPaid ? h(
458
741
  "button",
459
- { type: "button", disabled: props.isPreview === true || !paymentOpen },
460
- paymentOpen ? isPending ? "Lanjutkan pembayaran" : "Login untuk membayar" : "Pembayaran belum dibuka"
742
+ {
743
+ type: "button",
744
+ disabled: !paymentOpen || !intentEnabled(props, "invoice.pay"),
745
+ ...intentAttributes("invoice.pay", invoice.key)
746
+ },
747
+ paymentOpen ? isPending ? "Lanjutkan pembayaran" : "Bayar sekarang" : "Pembayaran belum dibuka"
461
748
  ) : null
462
749
  )
463
750
  )
464
751
  );
465
752
  }
466
753
  function TransactionDetailSection({ props, section }) {
467
- const transaction = props.isPreview === true ? props.previewTransaction || {} : section?.content?.transaction || {};
754
+ const transaction = props.kumpulPage && props.kumpulPage.transaction || section && section.content && section.content.transaction || {};
468
755
  const items = list(transaction.items);
469
756
  const status = transactionStatus(transaction);
470
757
  const subtotal = items.reduce((sum, item) => sum + (Number(item.total_amount) || 0), 0);
@@ -574,7 +861,8 @@ function TransactionDetailSection({ props, section }) {
574
861
  transaction.status === "PENDING_PAYMENT" || transaction.status === "PENDING" ? h(
575
862
  React.Fragment,
576
863
  null,
577
- h("button", { type: "button", disabled: true }, "Lanjutkan Pembayaran"),
864
+ // order.* memakai jalur aksi transaksi host yang sudah ada (data-bagdja-action).
865
+ h("button", { type: "button", disabled: !intentEnabled(props, "order.retry_payment"), "data-bagdja-action": "order.retry_payment" }, "Lanjutkan Pembayaran"),
578
866
  transaction.payment_mode === "ESCROW" ? h("p", { className: "kumpul-detail-payment-note" }, "Dana escrow disimpan sampai proses konfirmasi pesanan selesai.") : null
579
867
  ) : h(
580
868
  "p",
@@ -605,7 +893,7 @@ function GatheringPlanSimulator({ plan, props }) {
605
893
  const occurrence = plan.occurrence || {};
606
894
  const options = list(occurrence.option_groups_snapshot);
607
895
  const openedIds = new Set(list(occurrence.opened_option_ids_snapshot));
608
- const invitees = list(props.previewPlanInvitees);
896
+ const invitees = list(props.kumpulPage && props.kumpulPage.invitees);
609
897
  const localDatePart = (value) => typeof value === "string" ? value.slice(0, 10) : "";
610
898
  const localTimePart = (value) => typeof value === "string" ? value.slice(11, 16) : "";
611
899
  return h(
@@ -888,8 +1176,8 @@ function GatheringPlanSimulator({ plan, props }) {
888
1176
  }
889
1177
  function GatheringPlanDetailSection({ props, section }) {
890
1178
  const sectionContent = section?.content || {};
891
- const plan = props.isPreview === true ? props.previewGatheringPlan || {} : sectionContent.gatheringPlan || {};
892
- const order = props.isPreview === true ? props.previewGatheringOrder || {} : sectionContent.order || {};
1179
+ const plan = props.kumpulPage && props.kumpulPage.plan || sectionContent.gatheringPlan || {};
1180
+ const order = sectionContent.order || {};
893
1181
  const occurrence = plan.occurrence || {};
894
1182
  const openedIds = new Set(list(occurrence.opened_option_ids_snapshot));
895
1183
  const openedOptions = list(occurrence.option_groups_snapshot).filter((option) => openedIds.has(option.product_option_id));
@@ -1032,7 +1320,7 @@ function GatheringPlanDetailSection({ props, section }) {
1032
1320
  );
1033
1321
  }
1034
1322
  function BillingSection({ props }) {
1035
- const previewInvoices = props.isPreview === true ? list(props.previewInvoices) : [];
1323
+ const previewInvoices = list(props.kumpulPage && props.kumpulPage.invoices);
1036
1324
  const outstandingCount = previewInvoices.filter((invoice) => billingStatus(invoice) === "issued").length;
1037
1325
  const counts = Object.fromEntries(billingFilters.map(([key]) => [
1038
1326
  key,
@@ -1136,7 +1424,12 @@ function BillingSection({ props }) {
1136
1424
  h("strong", null, formatCurrency(invoice.amount)),
1137
1425
  dueDate ? h("p", null, `Batas pembayaran \xB7 ${formatCalendarDate(dueDate)}`) : null
1138
1426
  ),
1139
- status === "issued" ? h("button", { type: "button", className: "kumpul-billing-action", disabled: true }, isGathering ? "Lihat detail tagihan" : "Bayar") : null
1427
+ status === "issued" && isGathering && invoice.detail_href ? h("a", { className: "kumpul-billing-action", href: invoice.detail_href }, "Lihat detail tagihan") : status === "issued" ? h("button", {
1428
+ type: "button",
1429
+ className: "kumpul-billing-action",
1430
+ disabled: !invoice.can_pay || !intentEnabled(props, "invoice.pay"),
1431
+ ...intentAttributes("invoice.pay", invoice.key)
1432
+ }, isGathering ? "Lihat detail tagihan" : "Bayar") : null
1140
1433
  )
1141
1434
  );
1142
1435
  }),
@@ -1594,8 +1887,8 @@ function calendarMonthCells(monthKey, events, selectedDate) {
1594
1887
  function CalendarSection({ props, section }) {
1595
1888
  const content = section?.content || {};
1596
1889
  const isPreview = props.isPreview === true;
1597
- const plans = isPreview ? list(content.preview_plans) : [];
1598
- const invitations = isPreview ? list(content.preview_invitations) : [];
1890
+ const plans = list(content.plans);
1891
+ const invitations = list(content.invitations);
1599
1892
  const attentionCount = invitations.filter((invitation) => invitation.needs_action === true).length;
1600
1893
  const events = [
1601
1894
  ...plans.filter((plan) => calendarDateKey(plan.event_date)).map((plan) => ({
@@ -1617,7 +1910,7 @@ function CalendarSection({ props, section }) {
1617
1910
  location: text(invitation.event_location)
1618
1911
  }))
1619
1912
  ].sort((left, right) => new Date(left.event_date).getTime() - new Date(right.event_date).getTime());
1620
- const initialMonth = calendarMonthKey(content.preview_month, events[0]?.event_date);
1913
+ const initialMonth = calendarMonthKey(content.month, events[0]?.event_date);
1621
1914
  const initialDate = events.find((event) => calendarDateKey(event.event_date).startsWith(`${initialMonth}-`));
1622
1915
  const selectedDate = initialDate ? calendarDateKey(initialDate.event_date) : `${initialMonth}-01`;
1623
1916
  const monthLabel = formatCalendarDate(`${initialMonth}-01`, { month: "long", year: "numeric" });
@@ -1841,7 +2134,7 @@ function CalendarSection({ props, section }) {
1841
2134
  ),
1842
2135
  plan.payment_deadline ? h("p", { className: "kumpul-calendar-meta" }, `Batas pembayaran: ${formatCalendarDate(plan.payment_deadline)}`) : null
1843
2136
  ),
1844
- h("button", { type: "button", className: "kumpul-calendar-action", disabled: true }, "Lanjutkan rencana")
2137
+ plan.detail_href ? h("a", { className: "kumpul-calendar-action", href: plan.detail_href }, "Lanjutkan rencana") : h("button", { type: "button", className: "kumpul-calendar-action", disabled: true }, "Lanjutkan rencana")
1845
2138
  )),
1846
2139
  h("p", {
1847
2140
  className: "kumpul-calendar-empty",
@@ -1893,7 +2186,12 @@ function CalendarSection({ props, section }) {
1893
2186
  "div",
1894
2187
  { className: "kumpul-calendar-invitation-action" },
1895
2188
  invitation.action_label ? h("span", null, invitation.action_label) : null,
1896
- h("button", { type: "button", className: "kumpul-calendar-action", disabled: true }, "Lihat undangan")
2189
+ invitation.detail_href ? h("a", { className: "kumpul-calendar-action", href: invitation.detail_href }, "Lihat undangan") : h("button", {
2190
+ type: "button",
2191
+ className: "kumpul-calendar-action",
2192
+ disabled: !invitation.key || !intentEnabled(props, "gathering.respond"),
2193
+ ...invitation.key ? intentAttributes("gathering.respond", invitation.key) : {}
2194
+ }, "Lihat undangan")
1897
2195
  )
1898
2196
  )),
1899
2197
  h("p", {
@@ -2201,7 +2499,7 @@ function styles(colors) {
2201
2499
  .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}
2202
2500
  @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}}
2203
2501
  .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}
2204
- @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}}
2502
+ @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,.kumpul-transaction-actions .kumpul-transaction-action-link{flex:1;padding:7px 8px;font-size:8px}}
2205
2503
  .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}
2206
2504
  @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}}
2207
2505
  .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}
@@ -2247,16 +2545,34 @@ function styles(colors) {
2247
2545
  .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}
2248
2546
  @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}}
2249
2547
  @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}}
2548
+ .kumpul-transaction-actions .kumpul-transaction-action-link{display:inline-flex;min-height:34px;align-items:center;justify-content:center;padding:7px 11px;border:1px solid var(--kt-border);border-radius:10px;background:var(--kt-surface);color:var(--kt-text);font-size:9px;font-weight:750;text-decoration:none}
2549
+ .kumpul-transaction-actions .kumpul-transaction-action-link:hover{border-color:var(--kt-accent);color:var(--kt-accent)}
2550
+ a.kumpul-billing-action{display:inline-flex;align-items:center;text-decoration:none;opacity:1;cursor:pointer}
2551
+ .kumpul-billing-action:not(:disabled),.kumpul-detail-aside>button:not(:disabled),.kumpul-cart-checkout:not(:disabled){opacity:1;cursor:pointer}
2552
+ .kumpul-detail-aside>.kumpul-detail-pay-link{display:flex;width:100%;min-height:42px;margin-top:16px;align-items:center;justify-content:center;border-radius:11px;background:var(--kt-accent);color:#fff;font-size:11px;font-weight:800;text-decoration:none}
2553
+ .kumpul-header-only .kumpul-header{position:static}
2554
+ a.kumpul-calendar-action{display:inline-flex;align-items:center;justify-content:center;text-decoration:none;opacity:1;cursor:pointer}
2250
2555
  @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}}
2251
2556
  @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}}
2252
2557
  @media(prefers-reduced-motion:reduce){.kumpul-template *{scroll-behavior:auto!important;transition:none!important}}
2253
2558
  `;
2254
2559
  }
2255
- function render(props = {}) {
2560
+ function render(inputProps = {}) {
2561
+ const kumpulPage = adaptPage(inputProps.page);
2562
+ const props = kumpulPage ? { ...inputProps, kumpulPage } : inputProps;
2256
2563
  const colors = themeColors(props);
2257
2564
  const sections = list(props.sections);
2565
+ if (props.headerOnly === true) {
2566
+ return h(
2567
+ "div",
2568
+ { className: "kumpul-template kumpul-header-only" },
2569
+ h("style", { dangerouslySetInnerHTML: { __html: styles(colors) } }),
2570
+ h(Header, { ...props, activePageSlug: "" })
2571
+ );
2572
+ }
2258
2573
  const orderDetailSection = sections.find((section) => section?.type === "order_detail");
2259
- const activePageSlug = orderDetailSection ? orderDetailSection.content?.gatheringPlan ? "plan-detail" : "transaction-detail" : ["cart", "orders", "tagihan", "invoice-detail", "transaction-detail", "plan-detail"].includes(props.activePageSlug) ? props.activePageSlug : pageSlugForSections(sections);
2574
+ const activePageSlug = kumpulPage ? kumpulPage.activePageSlug : orderDetailSection ? orderDetailSection.content?.gatheringPlan ? "plan-detail" : "transaction-detail" : ["cart", "orders", "tagihan", "invoice-detail", "transaction-detail", "plan-detail"].includes(props.activePageSlug) ? props.activePageSlug : pageSlugForSections(sections);
2575
+ const calendarPageSection = kumpulPage && kumpulPage.calendar ? { id: "kalender-acara", type: "gathering_calendar", content: kumpulPage.calendar } : null;
2260
2576
  const catalogPage = activePageSlug === "gathering";
2261
2577
  const billingPage = activePageSlug === "tagihan";
2262
2578
  const transactionsPage = activePageSlug === "orders";
@@ -2286,7 +2602,7 @@ function render(props = {}) {
2286
2602
  gatherings ? h(GatheringsSection, { props, section: gatherings, catalogPage }) : null,
2287
2603
  sections.filter((section) => section?.type === "service_process_section").map((section) => h(ProcessSection, { ...section, key: section.id || "process" })),
2288
2604
  sections.filter((section) => section?.type === "faq_list").map((section) => h(FaqSection, { props, section, key: section.id || "faq" })),
2289
- sections.filter((section) => section?.type === "gathering_calendar").map((section) => h(CalendarSection, { props, section, key: section.id || "calendar" })),
2605
+ calendarPageSection ? h(CalendarSection, { props, section: calendarPageSection, key: "calendar" }) : null,
2290
2606
  billingPage ? h(BillingSection, { props }) : null,
2291
2607
  transactionsPage ? h(TransactionsSection, { props }) : null,
2292
2608
  cartPage ? h(CartSection, { props }) : null,
package/manifest.json CHANGED
@@ -1,15 +1,21 @@
1
1
  {
2
+ "manifestVersion": 1,
2
3
  "slug": "kumpul",
3
4
  "name": "Kumpul",
4
- "version": "1.0.2",
5
+ "version": "1.1.0",
5
6
  "rendererApiVersion": 1,
6
- "isBuiltin": false,
7
7
  "businessProfiles": [
8
8
  "gathering"
9
9
  ],
10
10
  "capabilities": [
11
11
  "catalog",
12
- "gathering"
12
+ "cart",
13
+ "orders",
14
+ "faq",
15
+ "locations",
16
+ "gathering",
17
+ "buyer_auth",
18
+ "chat"
13
19
  ],
14
20
  "sections": [
15
21
  "hero",
@@ -22,5 +28,284 @@
22
28
  "testimonial",
23
29
  "locations_list",
24
30
  "cta"
31
+ ],
32
+ "pageOverrides": [
33
+ "header",
34
+ "cart",
35
+ "orders",
36
+ "order_detail",
37
+ "tagihan",
38
+ "invoice_detail",
39
+ "calendar",
40
+ "gathering_plan"
41
+ ],
42
+ "entry": {
43
+ "server": "dist/server.cjs",
44
+ "client": "dist/client.js"
45
+ },
46
+ "defaultPages": [
47
+ {
48
+ "slug": "home",
49
+ "title": "Beranda",
50
+ "isHome": true,
51
+ "sections": [
52
+ {
53
+ "type": "hero",
54
+ "content": {
55
+ "subtitle": "Komunitas aktif • saatnya berkumpul",
56
+ "headline": "Kumpul bareng jadi lebih mudah.",
57
+ "lede": "Platform gathering untuk keluarga, workshop, dan komunitas. Dari perencanaan hingga hari acara, semua dalam satu alur.",
58
+ "stats": [
59
+ {
60
+ "value": "1.2K+",
61
+ "label": "Peserta komunitas"
62
+ },
63
+ {
64
+ "value": "48",
65
+ "label": "Event aktif"
66
+ },
67
+ {
68
+ "value": "4.9/5",
69
+ "label": "Rating komunitas"
70
+ }
71
+ ]
72
+ }
73
+ },
74
+ {
75
+ "type": "features_grid",
76
+ "content": {
77
+ "title": "Dari ide sampai absensi, rapi.",
78
+ "subtitle": "Alur acara yang jelas dari persiapan sampai hari berkumpul.",
79
+ "features": [
80
+ {
81
+ "icon": "1",
82
+ "title": "Perencanaan",
83
+ "desc": "Tentukan tema & lokasi"
84
+ },
85
+ {
86
+ "icon": "2",
87
+ "title": "Buka pendaftaran",
88
+ "desc": "Form dibuka untuk umum"
89
+ },
90
+ {
91
+ "icon": "3",
92
+ "title": "Buka pembayaran",
93
+ "desc": "Termin & tagihan otomatis"
94
+ },
95
+ {
96
+ "icon": "4",
97
+ "title": "Konfirmasi",
98
+ "desc": "Verifikasi peserta"
99
+ },
100
+ {
101
+ "icon": "5",
102
+ "title": "Absensi",
103
+ "desc": "Check-in QR saat gathering"
104
+ }
105
+ ]
106
+ }
107
+ },
108
+ {
109
+ "type": "products_grid",
110
+ "content": {
111
+ "title": "Gathering Terdekat",
112
+ "subtitle": "Pilih pengalaman berikutnya bersama keluarga dan komunitas.",
113
+ "filter_type": "gathering"
114
+ }
115
+ },
116
+ {
117
+ "type": "testimonial",
118
+ "content": {
119
+ "title": "Komunitas yang balik lagi.",
120
+ "subtitle": "Cerita peserta dari acara yang mereka ikuti.",
121
+ "items": [
122
+ {
123
+ "quote": "Anak-anak happy, panitia rapi banget. Pembayaran termin sangat membantu.",
124
+ "context": "Family Camp Lembang",
125
+ "location": "Rini & Keluarga"
126
+ },
127
+ {
128
+ "quote": "Flow-nya jelas. Dari daftar sampai check-in semuanya terasa mudah.",
129
+ "context": "Trail Run Sentul",
130
+ "location": "Dimas Pratama"
131
+ },
132
+ {
133
+ "quote": "Tempatnya nyaman dan materinya menarik. Suka pengingat lewat kalender.",
134
+ "context": "Workshop Keramik",
135
+ "location": "Sasha"
136
+ }
137
+ ]
138
+ }
139
+ },
140
+ {
141
+ "type": "locations_list",
142
+ "content": {
143
+ "title": "Lokasi Kumpul",
144
+ "subtitle": "Tempat pilihan komunitas untuk bertemu dan berbagi cerita."
145
+ }
146
+ },
147
+ {
148
+ "type": "cta",
149
+ "content": {
150
+ "title": "Siap bikin gathering pertamamu?",
151
+ "subtitle": "Rencanakan acara, undang komunitas, dan nikmati momen bersama.",
152
+ "button_text": "Jelajahi gathering",
153
+ "button_action": "link",
154
+ "button_url": "/gathering"
155
+ }
156
+ }
157
+ ]
158
+ },
159
+ {
160
+ "slug": "gathering",
161
+ "title": "Katalog Gathering",
162
+ "sections": [
163
+ {
164
+ "type": "products_grid",
165
+ "content": {
166
+ "eyebrow": "Temukan acara berikutnya",
167
+ "title": "Katalog Gathering",
168
+ "subtitle": "Pilih pengalaman berikutnya bersama keluarga dan komunitas.",
169
+ "filter_type": "gathering"
170
+ }
171
+ }
172
+ ]
173
+ },
174
+ {
175
+ "slug": "how-it-works",
176
+ "title": "Cara Kerja",
177
+ "sections": [
178
+ {
179
+ "type": "service_process_section",
180
+ "content": {
181
+ "title": "5 langkah, gathering jalan. Tanpa drama WA.",
182
+ "subtitle": "Alur yang jelas membantu panitia dan peserta menikmati setiap momen.",
183
+ "flow_id": "gathering-flow",
184
+ "flow_steps": [
185
+ {
186
+ "sequence": 1,
187
+ "status_name": "Perencanaan",
188
+ "description": "Tentukan tema, jadwal, lokasi, dan kebutuhan acara.",
189
+ "process_day": 1
190
+ },
191
+ {
192
+ "sequence": 2,
193
+ "status_name": "Buka pendaftaran",
194
+ "description": "Bagikan informasi acara dan kumpulkan data peserta.",
195
+ "process_day": 1
196
+ },
197
+ {
198
+ "sequence": 3,
199
+ "status_name": "Pembayaran",
200
+ "description": "Peserta melihat tagihan dan informasi pembayaran acara.",
201
+ "process_day": 2
202
+ },
203
+ {
204
+ "sequence": 4,
205
+ "status_name": "Konfirmasi",
206
+ "description": "Panitia memantau data dan kesiapan peserta.",
207
+ "process_day": 3
208
+ },
209
+ {
210
+ "sequence": 5,
211
+ "status_name": "Hari gathering",
212
+ "description": "Gunakan daftar peserta untuk membantu proses check-in.",
213
+ "process_day": 7
214
+ }
215
+ ]
216
+ }
217
+ },
218
+ {
219
+ "type": "faq_list",
220
+ "content": {
221
+ "title": "Pertanyaan tentang gathering",
222
+ "source": "faqs"
223
+ }
224
+ }
225
+ ]
226
+ },
227
+ {
228
+ "slug": "about",
229
+ "title": "Tentang",
230
+ "sections": [
231
+ {
232
+ "type": "about",
233
+ "content": {
234
+ "eyebrow": "Tentang Kumpul",
235
+ "title": "Kumpul bukan sekadar datang, tapi bertumbuh bareng.",
236
+ "body": "Bagdja Kumpul lahir dari keresahan: bikin gathering itu ribet — daftar peserta tercecer, tagihan manual, dan koordinasi berantakan. Kami membantu mengurus alurnya, supaya penyelenggara bisa fokus pada orang-orang dan momen kebersamaan."
237
+ }
238
+ },
239
+ {
240
+ "type": "features_grid",
241
+ "content": {
242
+ "eyebrow": "Kenapa pilih kami",
243
+ "title": "Lebih rapi untuk panitia, lebih nyaman untuk peserta.",
244
+ "features": [
245
+ {
246
+ "icon": "✍️",
247
+ "title": "Pendaftaran praktis",
248
+ "desc": "Form pendaftaran membantu mengumpulkan kebutuhan peserta dalam satu alur."
249
+ },
250
+ {
251
+ "icon": "🧾",
252
+ "title": "Tagihan teratur",
253
+ "desc": "Informasi pembayaran dan tagihan peserta tersaji lebih jelas."
254
+ },
255
+ {
256
+ "icon": "👥",
257
+ "title": "Kelola kapasitas",
258
+ "desc": "Data peserta membantu panitia menyiapkan acara sesuai kapasitas."
259
+ },
260
+ {
261
+ "icon": "📅",
262
+ "title": "Komunitas terhubung",
263
+ "desc": "Informasi acara, kalender, dan komunikasi peserta lebih mudah ditemukan."
264
+ }
265
+ ]
266
+ }
267
+ },
268
+ {
269
+ "type": "gallery",
270
+ "content": {
271
+ "eyebrow": "Momen kebersamaan",
272
+ "title": "Cerita dari setiap pertemuan",
273
+ "layout": "grid",
274
+ "images": [
275
+ {
276
+ "url": "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 260'%3E%3Crect width='400' height='260' fill='%23006699'/%3E%3Ccircle cx='200' cy='130' r='64' fill='%23e6f4f6'/%3C/svg%3E",
277
+ "alt": "Ilustrasi camping keluarga",
278
+ "caption": "Camping bersama keluarga"
279
+ },
280
+ {
281
+ "url": "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 260'%3E%3Crect width='400' height='260' fill='%230e7490'/%3E%3Ccircle cx='200' cy='130' r='64' fill='%23d9eff0'/%3C/svg%3E",
282
+ "alt": "Ilustrasi workshop komunitas",
283
+ "caption": "Workshop komunitas"
284
+ },
285
+ {
286
+ "url": "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 260'%3E%3Crect width='400' height='260' fill='%231f766e'/%3E%3Ccircle cx='200' cy='130' r='64' fill='%23d9e8d9'/%3C/svg%3E",
287
+ "alt": "Ilustrasi olahraga luar ruang",
288
+ "caption": "Olahraga di alam terbuka"
289
+ },
290
+ {
291
+ "url": "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 260'%3E%3Crect width='400' height='260' fill='%235b6b8a'/%3E%3Ccircle cx='200' cy='130' r='64' fill='%23e1e8ed'/%3C/svg%3E",
292
+ "alt": "Ilustrasi komunitas berdiskusi",
293
+ "caption": "Berbagi cerita dan ide"
294
+ },
295
+ {
296
+ "url": "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 260'%3E%3Crect width='400' height='260' fill='%237a6547'/%3E%3Ccircle cx='200' cy='130' r='64' fill='%23eee7db'/%3C/svg%3E",
297
+ "alt": "Ilustrasi belajar bersama",
298
+ "caption": "Belajar hal baru bersama"
299
+ },
300
+ {
301
+ "url": "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 260'%3E%3Crect width='400' height='260' fill='%233a6b55'/%3E%3Ccircle cx='200' cy='130' r='64' fill='%23d9e8d9'/%3E%3C/svg%3E",
302
+ "alt": "Ilustrasi kegiatan luar ruang",
303
+ "caption": "Menikmati waktu di luar ruang"
304
+ }
305
+ ]
306
+ }
307
+ }
308
+ ]
309
+ }
25
310
  ]
26
311
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bagdja/kumpul",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "description": "Kumpul website template for Bagdja",
5
5
  "license": "UNLICENSED",
6
6
  "type": "commonjs",