includio-cms 0.36.8 → 0.37.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/API.md +179 -3
- package/CHANGELOG.md +64 -0
- package/DOCS.md +28 -3
- package/ROADMAP.md +18 -0
- package/dist/admin/client/booking/booking-dashboard.svelte +40 -0
- package/dist/admin/client/booking/booking-dashboard.svelte.d.ts +3 -0
- package/dist/admin/client/booking/customer-panel.svelte +102 -0
- package/dist/admin/client/booking/customer-panel.svelte.d.ts +11 -0
- package/dist/admin/client/booking/customer-view.d.ts +52 -0
- package/dist/admin/client/booking/customer-view.js +134 -0
- package/dist/admin/client/booking/participant-data-panel.svelte +330 -0
- package/dist/admin/client/booking/participant-data-panel.svelte.d.ts +22 -0
- package/dist/admin/client/booking/reservation-detail-page.svelte +637 -0
- package/dist/admin/client/booking/reservation-detail-page.svelte.d.ts +3 -0
- package/dist/admin/client/booking/reservations-page.svelte +221 -0
- package/dist/admin/client/booking/reservations-page.svelte.d.ts +3 -0
- package/dist/admin/client/collection/collection-entries.svelte +21 -2
- package/dist/admin/client/collection/entry-link.svelte +6 -4
- package/dist/admin/client/collection/entry-link.svelte.d.ts +3 -1
- package/dist/admin/client/collection/row-actions.svelte +12 -4
- package/dist/admin/client/collection/row-actions.svelte.d.ts +1 -0
- package/dist/admin/client/collection/status-badge.svelte +39 -3
- package/dist/admin/client/collection/status-badge.svelte.d.ts +5 -3
- package/dist/admin/client/entry/entry.svelte +26 -9
- package/dist/admin/client/entry/hybrid/hybrid-preview.svelte +73 -10
- package/dist/admin/client/entry/hybrid/hybrid-preview.svelte.d.ts +6 -5
- package/dist/admin/client/entry/preview-views-context.svelte.d.ts +22 -0
- package/dist/admin/client/entry/preview-views-context.svelte.js +58 -0
- package/dist/admin/client/entry/preview-views.d.ts +27 -0
- package/dist/admin/client/entry/preview-views.js +33 -0
- package/dist/admin/client/index.d.ts +3 -0
- package/dist/admin/client/index.js +3 -0
- package/dist/admin/client/modules/dashboard-registry.d.ts +7 -0
- package/dist/admin/client/modules/dashboard-registry.js +11 -0
- package/dist/admin/client/modules/module-dashboard-page.svelte +26 -0
- package/dist/admin/client/modules/module-dashboard-page.svelte.d.ts +6 -0
- package/dist/admin/client/modules/stat-card.svelte +22 -0
- package/dist/admin/client/modules/stat-card.svelte.d.ts +10 -0
- package/dist/admin/client/shop/shop-dashboard.svelte +29 -0
- package/dist/admin/client/shop/shop-dashboard.svelte.d.ts +3 -0
- package/dist/admin/components/fields/relation-field.svelte +11 -2
- package/dist/admin/components/icons/icon-map.js +8 -0
- package/dist/admin/components/layout/app-sidebar.svelte +45 -14
- package/dist/admin/components/layout/context-switcher.svelte +90 -0
- package/dist/admin/components/layout/context-switcher.svelte.d.ts +3 -0
- package/dist/admin/components/layout/lang.d.ts +4 -0
- package/dist/admin/components/layout/lang.js +8 -0
- package/dist/admin/components/layout/layout-renderer.svelte +2 -1
- package/dist/admin/components/layout/layout-tabs.svelte +14 -0
- package/dist/admin/components/layout/layout-tabs.svelte.d.ts +2 -0
- package/dist/admin/components/layout/nav-collections.svelte +16 -9
- package/dist/admin/components/layout/nav-collections.svelte.d.ts +5 -1
- package/dist/admin/components/layout/nav-global.svelte +45 -0
- package/dist/admin/components/layout/nav-global.svelte.d.ts +3 -0
- package/dist/admin/components/layout/nav-main.svelte +8 -32
- package/dist/admin/components/layout/nav-main.svelte.d.ts +6 -1
- package/dist/admin/components/layout/nav-module.svelte +57 -0
- package/dist/admin/components/layout/nav-module.svelte.d.ts +7 -0
- package/dist/admin/components/layout/nav-section.svelte +1 -1
- package/dist/admin/components/layout/nav-section.svelte.d.ts +1 -1
- package/dist/admin/components/layout/nav-singletons.svelte +14 -7
- package/dist/admin/components/layout/nav-singletons.svelte.d.ts +5 -1
- package/dist/admin/remote/booking.remote.d.ts +244 -0
- package/dist/admin/remote/booking.remote.js +283 -0
- package/dist/admin/remote/entry.remote.d.ts +3 -0
- package/dist/admin/remote/entry.remote.js +14 -3
- package/dist/admin/remote/index.d.ts +2 -0
- package/dist/admin/remote/index.js +2 -0
- package/dist/admin/remote/modules.remote.d.ts +10 -0
- package/dist/admin/remote/modules.remote.js +14 -0
- package/dist/admin/state/active-context-resolve.d.ts +37 -0
- package/dist/admin/state/active-context-resolve.js +66 -0
- package/dist/admin/state/active-context.svelte.d.ts +8 -0
- package/dist/admin/state/active-context.svelte.js +27 -0
- package/dist/booking/adjustments.d.ts +33 -0
- package/dist/booking/adjustments.js +26 -0
- package/dist/booking/capacity.d.ts +12 -0
- package/dist/booking/capacity.js +10 -0
- package/dist/booking/client/index.d.ts +39 -0
- package/dist/booking/client/index.js +44 -0
- package/dist/booking/client/use-booking.svelte.d.ts +25 -0
- package/dist/booking/client/use-booking.svelte.js +56 -0
- package/dist/booking/config.d.ts +156 -0
- package/dist/booking/config.js +36 -0
- package/dist/booking/draft.d.ts +77 -0
- package/dist/booking/draft.js +67 -0
- package/dist/booking/expiry-logic.d.ts +30 -0
- package/dist/booking/expiry-logic.js +33 -0
- package/dist/booking/index.d.ts +18 -0
- package/dist/booking/index.js +52 -0
- package/dist/booking/ledger.d.ts +46 -0
- package/dist/booking/ledger.js +60 -0
- package/dist/booking/number.d.ts +2 -0
- package/dist/booking/number.js +11 -0
- package/dist/booking/participant-fields/access.d.ts +10 -0
- package/dist/booking/participant-fields/access.js +14 -0
- package/dist/booking/participant-fields/age.d.ts +12 -0
- package/dist/booking/participant-fields/age.js +28 -0
- package/dist/booking/participant-fields/completeness.d.ts +8 -0
- package/dist/booking/participant-fields/completeness.js +13 -0
- package/dist/booking/participant-fields/group.d.ts +6 -0
- package/dist/booking/participant-fields/group.js +15 -0
- package/dist/booking/participant-fields/index.d.ts +6 -0
- package/dist/booking/participant-fields/index.js +6 -0
- package/dist/booking/participant-fields/types.d.ts +50 -0
- package/dist/booking/participant-fields/types.js +5 -0
- package/dist/booking/participant-fields/validate.d.ts +7 -0
- package/dist/booking/participant-fields/validate.js +44 -0
- package/dist/booking/participant-pricing.d.ts +93 -0
- package/dist/booking/participant-pricing.js +91 -0
- package/dist/booking/participants-view.d.ts +32 -0
- package/dist/booking/participants-view.js +22 -0
- package/dist/booking/payment-context.d.ts +19 -0
- package/dist/booking/payment-context.js +29 -0
- package/dist/booking/pricing-inputs.d.ts +28 -0
- package/dist/booking/pricing-inputs.js +35 -0
- package/dist/booking/pricing.d.ts +86 -0
- package/dist/booking/pricing.js +125 -0
- package/dist/booking/recompute.d.ts +22 -0
- package/dist/booking/recompute.js +31 -0
- package/dist/booking/reminders-schedule.d.ts +11 -0
- package/dist/booking/reminders-schedule.js +28 -0
- package/dist/booking/server/adjustments.d.ts +27 -0
- package/dist/booking/server/adjustments.js +136 -0
- package/dist/booking/server/bookings.d.ts +45 -0
- package/dist/booking/server/bookings.js +288 -0
- package/dist/booking/server/catalog.d.ts +9 -0
- package/dist/booking/server/catalog.js +20 -0
- package/dist/booking/server/db.d.ts +7 -0
- package/dist/booking/server/db.js +18 -0
- package/dist/booking/server/email.d.ts +23 -0
- package/dist/booking/server/email.js +59 -0
- package/dist/booking/server/emailTemplateRegistry.d.ts +29 -0
- package/dist/booking/server/emailTemplateRegistry.js +125 -0
- package/dist/booking/server/http/create-handler.d.ts +5 -0
- package/dist/booking/server/http/create-handler.js +68 -0
- package/dist/booking/server/http/index.d.ts +4 -0
- package/dist/booking/server/http/index.js +4 -0
- package/dist/booking/server/http/maintenance-handler.d.ts +9 -0
- package/dist/booking/server/http/maintenance-handler.js +36 -0
- package/dist/booking/server/http/portal-handler.d.ts +13 -0
- package/dist/booking/server/http/portal-handler.js +99 -0
- package/dist/booking/server/http/webhook-handler.d.ts +9 -0
- package/dist/booking/server/http/webhook-handler.js +39 -0
- package/dist/booking/server/index.d.ts +12 -0
- package/dist/booking/server/index.js +14 -0
- package/dist/booking/server/maintenance.d.ts +28 -0
- package/dist/booking/server/maintenance.js +134 -0
- package/dist/booking/server/participants.d.ts +26 -0
- package/dist/booking/server/participants.js +92 -0
- package/dist/booking/server/payments.d.ts +34 -0
- package/dist/booking/server/payments.js +207 -0
- package/dist/booking/server/portal-session.d.ts +16 -0
- package/dist/booking/server/portal-session.js +42 -0
- package/dist/booking/server/portal.d.ts +207 -0
- package/dist/booking/server/portal.js +234 -0
- package/dist/booking/server/refunds.d.ts +7 -0
- package/dist/booking/server/refunds.js +58 -0
- package/dist/booking/server/reminders.d.ts +9 -0
- package/dist/booking/server/reminders.js +24 -0
- package/dist/booking/server/validation.d.ts +17 -0
- package/dist/booking/server/validation.js +55 -0
- package/dist/booking/state-machine.d.ts +41 -0
- package/dist/booking/state-machine.js +73 -0
- package/dist/booking/templates/_partials/footer.en.html +4 -0
- package/dist/booking/templates/_partials/footer.pl.html +4 -0
- package/dist/booking/templates/_partials/header.en.html +4 -0
- package/dist/booking/templates/_partials/header.pl.html +4 -0
- package/dist/booking/templates/balance-due.en.html +10 -0
- package/dist/booking/templates/balance-due.pl.html +10 -0
- package/dist/booking/templates/balance-overdue-cancelled.en.html +5 -0
- package/dist/booking/templates/balance-overdue-cancelled.pl.html +5 -0
- package/dist/booking/templates/booking-received.en.html +9 -0
- package/dist/booking/templates/booking-received.pl.html +9 -0
- package/dist/booking/templates/deposit-paid.en.html +6 -0
- package/dist/booking/templates/deposit-paid.pl.html +6 -0
- package/dist/booking/templates/payment-link.en.html +5 -0
- package/dist/booking/templates/payment-link.pl.html +5 -0
- package/dist/booking/templates/payment-received.en.html +10 -0
- package/dist/booking/templates/payment-received.pl.html +10 -0
- package/dist/booking/totals.d.ts +38 -0
- package/dist/booking/totals.js +61 -0
- package/dist/booking/webhook-logic.d.ts +28 -0
- package/dist/booking/webhook-logic.js +50 -0
- package/dist/cli/create-user.d.ts +7 -1
- package/dist/cli/create-user.js +23 -15
- package/dist/cli/index.js +55 -7
- package/dist/cli/scaffold/admin.d.ts +6 -0
- package/dist/cli/scaffold/admin.js +5 -3
- package/dist/cli/scaffold/booking.d.ts +12 -0
- package/dist/cli/scaffold/booking.js +103 -0
- package/dist/core/cms.d.ts +24 -9
- package/dist/core/cms.js +72 -34
- package/dist/core/config/validatePreviews.d.ts +12 -0
- package/dist/core/config/validatePreviews.js +90 -0
- package/dist/core/fields/dotPath.d.ts +4 -0
- package/dist/core/fields/dotPath.js +18 -0
- package/dist/core/fields/slugPath.d.ts +9 -1
- package/dist/core/fields/slugPath.js +16 -2
- package/dist/core/fields/slugify.d.ts +3 -0
- package/dist/core/fields/slugify.js +4 -0
- package/dist/core/server/entries/operations/duplicate.d.ts +10 -0
- package/dist/core/server/entries/operations/duplicate.js +73 -0
- package/dist/core/server/entries/operations/slugNormalize.d.ts +8 -0
- package/dist/core/server/entries/operations/slugNormalize.js +20 -0
- package/dist/core/server/entries/operations/slugUniqueness.d.ts +17 -0
- package/dist/core/server/entries/operations/slugUniqueness.js +39 -0
- package/dist/core/server/fields/resolveRelationFields.d.ts +11 -2
- package/dist/core/server/fields/resolveRelationFields.js +12 -3
- package/dist/core/server/generator/generator.js +7 -2
- package/dist/db-postgres/schema/booking/bookingAdjustments.d.ts +186 -0
- package/dist/db-postgres/schema/booking/bookingAdjustments.js +22 -0
- package/dist/db-postgres/schema/booking/bookingItemPersons.d.ts +117 -0
- package/dist/db-postgres/schema/booking/bookingItemPersons.js +22 -0
- package/dist/db-postgres/schema/booking/bookingItems.d.ts +181 -0
- package/dist/db-postgres/schema/booking/bookingItems.js +22 -0
- package/dist/db-postgres/schema/booking/bookingPayments.d.ts +204 -0
- package/dist/db-postgres/schema/booking/bookingPayments.js +25 -0
- package/dist/db-postgres/schema/booking/bookingPersons.d.ts +99 -0
- package/dist/db-postgres/schema/booking/bookingPersons.js +17 -0
- package/dist/db-postgres/schema/booking/bookingReminders.d.ts +131 -0
- package/dist/db-postgres/schema/booking/bookingReminders.js +18 -0
- package/dist/db-postgres/schema/booking/bookings.d.ts +307 -0
- package/dist/db-postgres/schema/booking/bookings.js +40 -0
- package/dist/db-postgres/schema/booking/index.d.ts +7 -0
- package/dist/db-postgres/schema/booking/index.js +7 -0
- package/dist/db-postgres/schema/index.d.ts +1 -0
- package/dist/db-postgres/schema/index.js +1 -0
- package/dist/db-postgres/schema-booking.d.ts +1 -0
- package/dist/db-postgres/schema-booking.js +1 -0
- package/dist/server/security/rate-limit-handler.d.ts +19 -0
- package/dist/server/security/rate-limit-handler.js +34 -0
- package/dist/shop/adapters/payu/client.js +3 -1
- package/dist/shop/adapters/payu/index.js +37 -17
- package/dist/shop/adapters/payu/payload.d.ts +6 -0
- package/dist/shop/adapters/payu/payload.js +1 -1
- package/dist/shop/adapters/stripe/index.js +36 -21
- package/dist/shop/index.d.ts +11 -2
- package/dist/shop/index.js +43 -1
- package/dist/shop/rate-limit.d.ts +1 -9
- package/dist/shop/rate-limit.js +3 -28
- package/dist/shop/types.d.ts +19 -0
- package/dist/sveltekit/config.d.ts +4 -0
- package/dist/sveltekit/config.js +6 -0
- package/dist/types/cms.d.ts +15 -1
- package/dist/types/cms.schema.d.ts +96 -2
- package/dist/types/cms.schema.js +84 -1
- package/dist/types/config.d.ts +33 -0
- package/dist/types/layout.d.ts +6 -0
- package/dist/types/modules.d.ts +133 -0
- package/dist/types/modules.js +27 -0
- package/dist/updates/0.36.9/index.d.ts +2 -0
- package/dist/updates/0.36.9/index.js +12 -0
- package/dist/updates/0.37.0/index.d.ts +2 -0
- package/dist/updates/0.37.0/index.js +52 -0
- package/dist/updates/index.js +5 -1
- package/package.json +19 -1
- package/dist/admin/components/layout/nav-shop.svelte +0 -33
- package/dist/admin/components/layout/nav-shop.svelte.d.ts +0 -3
package/API.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# includio-cms — Public API v0.
|
|
1
|
+
# includio-cms — Public API v0.37.0
|
|
2
2
|
|
|
3
3
|
> Auto-generated by `scripts/generate-api-md.ts`. Do not edit by hand.
|
|
4
4
|
|
|
5
|
-
Entry points: **
|
|
5
|
+
Entry points: **23** · Stable: **665** · Experimental: **4**
|
|
6
6
|
|
|
7
7
|
Tags:
|
|
8
8
|
- `@public` — frozen for v1.0; semver-protected.
|
|
@@ -148,6 +148,8 @@ Tags:
|
|
|
148
148
|
- `const AdminLayout: LegacyComponentType`
|
|
149
149
|
- `interface AdminNavItem` — One additional sidebar entry rendered below built-in nav sections
|
|
150
150
|
- `const Badge: LegacyComponentType`
|
|
151
|
+
- `const BookingReservationDetailPage: LegacyComponentType`
|
|
152
|
+
- `const BookingReservationsPage: LegacyComponentType`
|
|
151
153
|
- `interface Breadcrumb`
|
|
152
154
|
- `class Breadcrumbs`
|
|
153
155
|
- `buildCsv(opts: { headers: string[]; rows: (string | number | null ...): string` — Build a CSV string from `headers` and `rows`. Values are escaped per
|
|
@@ -177,6 +179,7 @@ Tags:
|
|
|
177
179
|
- `const MaintenancePage: LegacyComponentType`
|
|
178
180
|
- `const MediaPage: LegacyComponentType`
|
|
179
181
|
- `const MediaSelector: LegacyComponentType`
|
|
182
|
+
- `const ModuleDashboardPage: LegacyComponentType`
|
|
180
183
|
- `const PageHeader: LegacyComponentType`
|
|
181
184
|
- `interface PaginationState`
|
|
182
185
|
- `const ResetPasswordPage: LegacyComponentType`
|
|
@@ -205,11 +208,16 @@ Tags:
|
|
|
205
208
|
|
|
206
209
|
### `includio-cms/admin/remote`
|
|
207
210
|
|
|
211
|
+
- `const addAdjustment: <inferred>`
|
|
212
|
+
- `const addPaymentLink: <inferred>`
|
|
208
213
|
- `const archiveEntryCommand: <inferred>`
|
|
209
214
|
- `const bulkDeleteMediaFiles: <inferred>`
|
|
210
215
|
- `const bulkSetMediaFileTags: <inferred>`
|
|
216
|
+
- `const cancelBooking: <inferred>`
|
|
211
217
|
- `const cancelShipmentForOrderCmd: <inferred>`
|
|
218
|
+
- `const changeBookingStatus: <inferred>`
|
|
212
219
|
- `const countMediaFiles: <inferred>`
|
|
220
|
+
- `const createBookingStaff: <inferred>`
|
|
213
221
|
- `const createCouponCmd: <inferred>`
|
|
214
222
|
- `const createEntry: <inferred>`
|
|
215
223
|
- `const createMediaTag: <inferred>`
|
|
@@ -224,6 +232,8 @@ Tags:
|
|
|
224
232
|
- `const deleteOrderCmd: <inferred>`
|
|
225
233
|
- `const deleteShippingMethodCmd: <inferred>`
|
|
226
234
|
- `const deleteShopDataForEntry: <inferred>`
|
|
235
|
+
- `const duplicateEntryCommand: <inferred>`
|
|
236
|
+
- `const editBookingStaff: <inferred>`
|
|
227
237
|
- `const exportFormSubmissions: <inferred>`
|
|
228
238
|
- `const exportOrdersCsv: <inferred>`
|
|
229
239
|
- `const findMediaReferences: <inferred>`
|
|
@@ -231,6 +241,9 @@ Tags:
|
|
|
231
241
|
- `const generateBalanceLinkForOrder: <inferred>`
|
|
232
242
|
- `const getAdminExtraNavItems: <inferred>`
|
|
233
243
|
- `const getAltOverview: <inferred>`
|
|
244
|
+
- `const getBooking: <inferred>`
|
|
245
|
+
- `const getBookingEnabled: <inferred>`
|
|
246
|
+
- `const getBookingStats: <inferred>`
|
|
234
247
|
- `const getCollection: <inferred>`
|
|
235
248
|
- `const getCollections: <inferred>`
|
|
236
249
|
- `const getCouponAdmin: <inferred>`
|
|
@@ -250,6 +263,7 @@ Tags:
|
|
|
250
263
|
- `const getMediaFiles: <inferred>`
|
|
251
264
|
- `const getMediaTags: <inferred>`
|
|
252
265
|
- `const getMediaTagsWithCounts: <inferred>`
|
|
266
|
+
- `const getModules: <inferred>`
|
|
253
267
|
- `const getOrderForAdmin: <inferred>`
|
|
254
268
|
- `const getOrderInvoiceAdmin: <inferred>`
|
|
255
269
|
- `const getOrderRefundsAdmin: <inferred>`
|
|
@@ -266,12 +280,16 @@ Tags:
|
|
|
266
280
|
- `const getSubmissionsOverview: <inferred>`
|
|
267
281
|
- `const isAIAvailable: <inferred>`
|
|
268
282
|
- `const issueInvoiceCmd: <inferred>`
|
|
283
|
+
- `const listBookingCatalog: <inferred>`
|
|
284
|
+
- `const listBookings: <inferred>`
|
|
269
285
|
- `const listCouponsAdmin: <inferred>`
|
|
270
286
|
- `const listOrdersAdmin: <inferred>`
|
|
271
287
|
- `const listShippingMethodsAdmin: <inferred>`
|
|
272
288
|
- `const listShopableCollections: <inferred>`
|
|
273
289
|
- `const listShopProductEntries: <inferred>`
|
|
274
290
|
- `const populatePreviewData: <inferred>`
|
|
291
|
+
- `const recordCashPayment: <inferred>`
|
|
292
|
+
- `const refundBookingPayment: <inferred>`
|
|
275
293
|
- `const refundOrderCmd: <inferred>`
|
|
276
294
|
- `const regenerateVideoPoster: <inferred>`
|
|
277
295
|
- `const renameMediaFile: <inferred>`
|
|
@@ -281,6 +299,7 @@ Tags:
|
|
|
281
299
|
- `const restoreOrderCmd: <inferred>`
|
|
282
300
|
- `const searchEntries: <inferred>`
|
|
283
301
|
- `const searchLinkableEntries: <inferred>`
|
|
302
|
+
- `const sendBookingEmailCmd: <inferred>`
|
|
284
303
|
- `const setFocalPoint: <inferred>`
|
|
285
304
|
- `const setMediaFileAlt: <inferred>`
|
|
286
305
|
- `const setMediaFileTags: <inferred>`
|
|
@@ -292,8 +311,10 @@ Tags:
|
|
|
292
311
|
- `const updateMediaAccessibility: <inferred>`
|
|
293
312
|
- `const updateMediaTag: <inferred>`
|
|
294
313
|
- `const updateOrderStatusCmd: <inferred>`
|
|
314
|
+
- `const updateParticipantData: <inferred>`
|
|
295
315
|
- `const updateShippingMethodCmd: <inferred>`
|
|
296
316
|
- `const upsertShopDataForEntry: <inferred>`
|
|
317
|
+
- `const voidAdjustment: <inferred>`
|
|
297
318
|
|
|
298
319
|
### `includio-cms/sveltekit`
|
|
299
320
|
|
|
@@ -350,6 +371,14 @@ Tags:
|
|
|
350
371
|
|
|
351
372
|
- `const account: <inferred>`
|
|
352
373
|
- `const accountRelations: <inferred>`
|
|
374
|
+
- `const bookingAdjustmentsTable: <inferred>`
|
|
375
|
+
- `const bookingItemPersonsTable: <inferred>`
|
|
376
|
+
- `const bookingItemsTable: <inferred>`
|
|
377
|
+
- `const bookingPaymentsTable: <inferred>`
|
|
378
|
+
- `const bookingPersonsTable: <inferred>`
|
|
379
|
+
- `const bookingRemindersTable: <inferred>`
|
|
380
|
+
- `const bookingsTable: <inferred>`
|
|
381
|
+
- `interface BookingTotals` — Computed money snapshot kept on the booking for fast list/detail reads.
|
|
353
382
|
- `const consentLogsTable: <inferred>`
|
|
354
383
|
- `type DatabaseAdapterWithDrizzle = DatabaseAdapter & { _drizzle: ReturnType<typeof drizzle<typeof schema>>; }`
|
|
355
384
|
- `const entriesTable: <inferred>`
|
|
@@ -432,6 +461,17 @@ Tags:
|
|
|
432
461
|
- `const shopStockReservationsTable: <inferred>`
|
|
433
462
|
- `const shopWebhookEventsTable: <inferred>`
|
|
434
463
|
|
|
464
|
+
### `includio-cms/db-postgres/schema-booking`
|
|
465
|
+
|
|
466
|
+
- `const bookingAdjustmentsTable: <inferred>`
|
|
467
|
+
- `const bookingItemPersonsTable: <inferred>`
|
|
468
|
+
- `const bookingItemsTable: <inferred>`
|
|
469
|
+
- `const bookingPaymentsTable: <inferred>`
|
|
470
|
+
- `const bookingPersonsTable: <inferred>`
|
|
471
|
+
- `const bookingRemindersTable: <inferred>`
|
|
472
|
+
- `const bookingsTable: <inferred>`
|
|
473
|
+
- `interface BookingTotals` — Computed money snapshot kept on the booking for fast list/detail reads.
|
|
474
|
+
|
|
435
475
|
### `includio-cms/auth-schema`
|
|
436
476
|
|
|
437
477
|
- `const account: <inferred>`
|
|
@@ -450,7 +490,7 @@ Tags:
|
|
|
450
490
|
- `interface ConsentConfig`
|
|
451
491
|
- `interface CouponRef`
|
|
452
492
|
- `type Currency = 'PLN'`
|
|
453
|
-
- `defineShop(config: ShopConfig):
|
|
493
|
+
- `defineShop(config: ShopConfig): CMSModule` — Defines the shop module. Returns a {@link CMSModule} for
|
|
454
494
|
- `type DepositAmount = { type: 'percent'; value: number } | { type: 'amount'; value: number }` — Deposit amount specifier. `percent` charges `floor(base * value / 100)` of
|
|
455
495
|
- `interface EmailContext` — Context passed to a {@link SubjectPlaceholderResolver}. Currently carries
|
|
456
496
|
- `fakturowniaAdapter(opts: FakturowniaAdapterOptions): InvoicingAdapter` — Invoicing adapter backed by Fakturownia (fakturownia.pl). Issues a paid VAT
|
|
@@ -551,6 +591,142 @@ Tags:
|
|
|
551
591
|
- `createShipmentLabelHandler(): { GET: RequestHandler }` — Admin-only PDF proxy that streams the carrier label without exposing the
|
|
552
592
|
- `createShippingMethodsHandler(): { GET: RequestHandler }`
|
|
553
593
|
|
|
594
|
+
### `includio-cms/booking`
|
|
595
|
+
|
|
596
|
+
- `type AdjustmentKind = 'manual_surcharge' | 'manual_discount'` — Manual booking adjustments — staff-entered surcharges (e.g. e-bike +200) and
|
|
597
|
+
- `interface AdjustmentSums`
|
|
598
|
+
- `ageAt(dob: string, anchor: Date): number | null` — Pełne lata między `dob` a `anchor`. `null` gdy data niepoprawna.
|
|
599
|
+
- `interface AgeBand` — A global age band: participants aged [minAge, maxAge] pay `pct`% of adult price.
|
|
600
|
+
- `interface AgeFlagConfig` — Generyczna flaga wieku: oznacza uczestnika, którego wiek (liczony z pola roli
|
|
601
|
+
- `interface AppliedRule`
|
|
602
|
+
- `assertAdjustmentMagnitude(magnitude: number): void` — Reject a zero/negative magnitude at the write boundary.
|
|
603
|
+
- `assertGrossNotBelowPaid(newGross: number, payments: PaymentEntry[]): void` — Asserts an edit's new gross does not drop below the already-paid total.
|
|
604
|
+
- `assertTransition(from: BookingStatus, to: BookingStatus): void` — Asserts a legal transition, throwing {@link BookingStateError} otherwise.
|
|
605
|
+
- `balance(gross: number, payments: PaymentEntry[]): number` — Outstanding balance: `gross − paid` (never below 0).
|
|
606
|
+
- `bandPctFor(age: number | null, bands: AgeBand[]): number` — Resolve the age-band percent for an age; 100 when null/unmatched (full price).
|
|
607
|
+
- `const BOOKING_STATUSES: readonly BookingStatus[]`
|
|
608
|
+
- `interface BookingAdjustment`
|
|
609
|
+
- `interface BookingConfig` — User-facing booking configuration. Passed to `defineBooking` and registered
|
|
610
|
+
- `class BookingStateError` — Thrown when an illegal status transition is attempted.
|
|
611
|
+
- `type BookingStatus = | 'draft' | 'reserved' | 'partially_paid' | 'paid' | 'completed' | 'cancelled'` — Booking state machine — pure, deterministic. Two concerns:
|
|
612
|
+
- `interface BookingValidationContext` — Context handed to the client-supplied {@link BookingValidator} seam.
|
|
613
|
+
- `type BookingValidator = (ctx: BookingValidationContext) => void | Promise<void>` — Client-specific validation seam (e.g. weekly-model term conflicts). Throws to
|
|
614
|
+
- `buildPricingInputs(persons: PersonRow[], items: ItemRow[], assignments: ItemPersonRow[], identityFields: FieldDef[]): PricingInputs`
|
|
615
|
+
- `canFill(field: FieldDef, audience: 'customer' | 'staff'): boolean` — Whether a given audience may fill/edit a field. Default `whoFills` is `'both'`.
|
|
616
|
+
- `canReduceGrossTo(newGross: number, payments: PaymentEntry[]): boolean` — Whether the gross may be reduced to `newGross` without going below paid.
|
|
617
|
+
- `canTransition(from: BookingStatus, to: BookingStatus): boolean` — Whether `from → to` is a legal transition (self-transitions are allowed).
|
|
618
|
+
- `completeness(data: Record<string, unknown>, fields: FieldDef[]): Completeness`
|
|
619
|
+
- `interface Completeness`
|
|
620
|
+
- `type Condition = | { kind: 'minTripCount'; value: number } // distinct trip refs >= value | { kind: 'minParticipan...` — Booking discount rules engine — a pure, deterministic, module-agnostic
|
|
621
|
+
- `daysUntil(departureDate: Date, now: Date): number` — Whole days from `now` until `departureDate` (negative if departure is past).
|
|
622
|
+
- `defineBooking(config: BookingConfig): CMSModule` — Defines the booking module — a long-lived, mutable reservation system with a
|
|
623
|
+
- `deriveAgeFlag(data: Record<string, unknown>, fields: FieldDef[], config: AgeFlagConfig | null, anchorDate: Date | null): { flagged: boolean; age: number | null }` — Generyczna flaga wieku — bez magicznego klucza. Bierze pole z rolą `birthDate`,
|
|
624
|
+
- `deriveStatus(input: DeriveStatusInput): BookingStatus` — Derives the payment-progress status from the ledger.
|
|
625
|
+
- `interface DiscountRule` — A serializable discount rule.
|
|
626
|
+
- `interface EarlyBird` — Early-bird: `percent`% off a full-price participant's gross when booked early.
|
|
627
|
+
- `type Effect = | { kind: 'percentOff'; value: number } // % off gross (0–100) | { kind: 'amountOff'; value: numb...` — An effect applied when a rule wins its group.
|
|
628
|
+
- `const FIELD_TYPES: <inferred>`
|
|
629
|
+
- `interface FieldDef` — Serializowalna definicja pojedynczego pola uczestnika.
|
|
630
|
+
- `interface FieldError`
|
|
631
|
+
- `interface FieldGroup`
|
|
632
|
+
- `type FieldRole = 'name' | 'birthDate'` — Generyczna „rola" pola — opcjonalna wskazówka semantyczna, którą UI/logika
|
|
633
|
+
- `type FieldType = (typeof FIELD_TYPES)[number]`
|
|
634
|
+
- `groupBySection(fields: FieldDef[]): FieldGroup[]`
|
|
635
|
+
- `isFieldType(v: unknown): v is FieldType`
|
|
636
|
+
- `isFullyPaid(gross: number, payments: PaymentEntry[]): boolean` — Whether the booking is fully settled (`gross > 0` and balance reached 0).
|
|
637
|
+
- `interface ItemPersonRow` — Assignment (junction) row.
|
|
638
|
+
- `interface ItemRow` — Trip-line row (subset needed for pricing). `unitPrice` = adult price (minor units).
|
|
639
|
+
- `interface LadderTier` — One ladder tier: from `minTrips` trips, the cheapest trip gets `percent`% off.
|
|
640
|
+
- `ladderTierFor(tripCount: number, ladder: LadderTier[]): LadderTier | null` — Highest ladder tier whose `minTrips` ≤ tripCount; null when none qualifies.
|
|
641
|
+
- `class LedgerError` — Thrown when an edit would push the gross below what has already been paid.
|
|
642
|
+
- `ledgerSummary(gross: number, payments: PaymentEntry[]): LedgerSummary` — Full ledger snapshot for a given gross.
|
|
643
|
+
- `interface LedgerSummary`
|
|
644
|
+
- `const NO_ADJUSTMENTS: AdjustmentSums`
|
|
645
|
+
- `interface ParticipantBreakdown`
|
|
646
|
+
- `interface ParticipantLine`
|
|
647
|
+
- `interface ParticipantPriceResult`
|
|
648
|
+
- `interface ParticipantPricingConfig` — Serializable per-participant pricing config (sourced from client globalSettings).
|
|
649
|
+
- `interface PaymentEntry`
|
|
650
|
+
- `type PaymentKind = 'deposit' | 'installment' | 'cash' | 'online'` — Booking payment ledger — pure helpers over a list of payment entries. The
|
|
651
|
+
- `type PaymentStatus = 'pending' | 'paid' | 'failed' | 'refunded'`
|
|
652
|
+
- `interface Perk`
|
|
653
|
+
- `interface PersonRow` — Person row (subset needed for pricing).
|
|
654
|
+
- `price(lines: PricingLine[], now: Date, config: PricingConfig): PriceResult`
|
|
655
|
+
- `priceByParticipant(participants: PricingParticipant[], trips: PricedTrip[], anchor: Date | null, now: Date, config: ParticipantPricingCo...): ParticipantPriceResult`
|
|
656
|
+
- `interface PricedTrip` — A trip available in the booking, with its full (adult) price (minor units).
|
|
657
|
+
- `interface PriceResult`
|
|
658
|
+
- `interface PricingConfig`
|
|
659
|
+
- `interface PricingInputs`
|
|
660
|
+
- `interface PricingLine` — A single priced line that retains trip identity (for cheapest/distinct-count).
|
|
661
|
+
- `interface PricingParticipant` — A participant and the trips they take.
|
|
662
|
+
- `interface ReminderRule` — One scheduled reminder rule, relative to the earliest departure date.
|
|
663
|
+
- `interface ResolvedBookingConfig` — Fully-defaulted booking config, carried on `CMSModule.config`.
|
|
664
|
+
- `signedAmount(kind: AdjustmentKind, magnitude: number): number` — Convert a UI-entered positive magnitude + kind into a signed stored amount.
|
|
665
|
+
- `sumAdjustments(rows: Pick<BookingAdjustment, 'amount' | 'voidedAt'>[]): AdjustmentSums` — Fold active (non-voided) adjustments into totals contributions. By sign.
|
|
666
|
+
- `totalPaid(payments: PaymentEntry[]): number` — Sum of entries currently in `paid` state.
|
|
667
|
+
- `totalPending(payments: PaymentEntry[]): number` — Sum of entries still pending (links generated, not yet settled).
|
|
668
|
+
- `totalRefunded(payments: PaymentEntry[]): number` — Sum of entries that were refunded.
|
|
669
|
+
- `validateAgainstSchema(data: Record<string, unknown>, fields: FieldDef[]): FieldError[]`
|
|
670
|
+
- `type WhoFills = 'customer' | 'staff' | 'both'` — Kto wypełnia pole. Default 'both'.
|
|
671
|
+
|
|
672
|
+
### `includio-cms/booking/client`
|
|
673
|
+
|
|
674
|
+
- `class BookingClientError` — Error thrown on a non-2xx response; `code` carries the server's error code.
|
|
675
|
+
- `interface BookingClientOptions` — Browser SDK for the booking storefront + self-service portal. Thin fetch
|
|
676
|
+
- `createBookingClient(opts: BookingClientOptions = {}): <inferred>` — Create a booking API client bound to a base URL + fetch.
|
|
677
|
+
- `useBooking(token: string, opts: BookingClientOptions = {}): <inferred>` — Reactive self-service portal state for a booking access token. Loads the view
|
|
678
|
+
|
|
679
|
+
### `includio-cms/booking/server`
|
|
680
|
+
|
|
681
|
+
- `interface AddAdjustmentInput`
|
|
682
|
+
- `addBookingAdjustment(bookingId: string, input: AddAdjustmentInput, opts: { actor: string; now?: Date }): Promise<BookingAdjustment>` — Add a manual adjustment (surcharge/discount) and recompute the booking totals
|
|
683
|
+
- `applyWebhookPayment(event: PaymentEvent): Promise<{ applied: boolean; bookingId: string | null; kind: PaymentKind | nul...` — Apply a provider webhook event to the ledger, idempotently. Locks the payment
|
|
684
|
+
- `interface BookingEditChanges` — Edit payload: replace people + items (+assignments) and/or customer details.
|
|
685
|
+
- `type BookingEmailKind = | 'booking-received' | 'deposit-paid' | 'payment-received' | 'payment-link' | 'balance-due' | 'ba...` — The transactional emails the booking module can send.
|
|
686
|
+
- `interface BookingStatus`
|
|
687
|
+
- `bookingStatusByToken(token: string): Promise<BookingStatus | null>`
|
|
688
|
+
- `interface BookingStatusItem`
|
|
689
|
+
- `type BookingTx = Parameters<Parameters<ReturnType<typeof getBookingDb>['transaction']>[0]>[0]` — Exact drizzle transaction handle, derived from the booking db's `transaction`.
|
|
690
|
+
- `class BookingValidationError` — Thrown when a booking fails capacity (core) or the client `validateBooking` seam.
|
|
691
|
+
- `createBooking(input: CreateBookingInput, opts: { now?: Date } = {}): Promise<{ booking: typeof bookingsTable.$inferSelect; accessToken: string }>` — Create a booking (public self-serve or staff). Validates catalog capacity +
|
|
692
|
+
- `createBookingHandler(): { POST: RequestHandler }` — Public self-serve booking creation. Mount at `POST /api/booking`.
|
|
693
|
+
- `createDepositPayment(bookingId: string): Promise<{ redirectUrl: string | null; status: 'redirect' | 'manual' | 'error'...` — Create the deposit payment for a freshly-created booking: ask the first
|
|
694
|
+
- `createInstallmentPayment(bookingId: string, amount: number): Promise<{ paymentLink: string | null }>` — Generate an installment/balance payment link for an arbitrary amount (staff or
|
|
695
|
+
- `createMaintenanceHandler(): { POST: RequestHandler }` — Secured external trigger for booking maintenance — the swap-in for the
|
|
696
|
+
- `createPortalHandler(): { GET: RequestHandler; POST: RequestHandler }` — Self-service portal. Mount at `GET|POST /api/booking/portal/[token]`.
|
|
697
|
+
- `createWebhookHandler(): { POST: RequestHandler }` — Payment-provider webhook. Mount at `POST /api/booking/webhook/[provider]`.
|
|
698
|
+
- `editBooking(bookingId: string, changes: BookingEditChanges, opts: { actor: 'staff' | 'portal'; now?: Date }): Promise<typeof bookingsTable.$inferSelect>` — Edit a booking (staff or portal). Recomputes totals per-participant + derived
|
|
699
|
+
- `getBookingDb(): <inferred>` — Returns the Drizzle handle, asserting the postgres adapter is in use.
|
|
700
|
+
- `getBookingMaintenanceStatus(): { running: boolean; lastRun: Date | null }`
|
|
701
|
+
- `listBookingAdjustments(bookingId: string): Promise<BookingAdjustment[]>` — List all adjustments (active + voided) for a booking, newest first.
|
|
702
|
+
- `pickEmailTemplate(kind: BookingEmailKind): string` — Template file name for a kind (1:1 — kept as a function for future indirection).
|
|
703
|
+
- `portalAddTrips(token: string, additions: Array<{ tripRef: string; unitPrice: number; as...): <inferred>` — Self-service dobieranie wycieczki: doczytaj obecny stan, scal z `additions`
|
|
704
|
+
- `portalEdit(token: string, changes: BookingEditChanges): <inferred>` — Portal self-service edit (actor:'portal' guards). Throws → handler maps to 409/400.
|
|
705
|
+
- `portalPay(token: string, amount: number): <inferred>` — Portal: create an installment/balance payment link.
|
|
706
|
+
- `portalUpdateParticipant(token: string, assignmentId: string, data: Record<string, unknown>): <inferred>` — Portal self-service: customer fills their own participant data. Verifies the
|
|
707
|
+
- `portalView(token: string): <inferred>` — Portal view: booking + items + participants + ledger (no staff data).
|
|
708
|
+
- `priceFromExistingRows(tx: BookingTx, bookingId: string, config: ResolvedBookingConfig, now: Date): Promise<ParticipantPriceResult>` — Price a booking from its CURRENTLY persisted people/items/assignments (no
|
|
709
|
+
- `processDueExpirations(now: Date = new Date()): Promise<{ abandoned: number; forfeited: number }>` — Auto-cancel expired bookings: abandoned drafts (deposit hold lapsed) and
|
|
710
|
+
- `processDueReminders(now: Date = new Date()): Promise<number>` — Send all due reminders (unsent, `scheduledFor <= now`) via the email adapter,
|
|
711
|
+
- `readTripCapacity(tripRef: string): Promise<number | null>` — Read a trip's seat capacity from the catalog collection.
|
|
712
|
+
- `recordCash(bookingId: string, amount: number): Promise<void>` — Record a manual cash payment (staff). Settles immediately and recomputes status.
|
|
713
|
+
- `refundPayment(paymentId: string, amount?: number): Promise<void>` — Refund a paid ledger entry via the adapter (staff-only manual action), then
|
|
714
|
+
- `renderBookingEmail(kind: BookingEmailKind, lang: string, context: Record<string, unknown>): Promise<string>` — Render a booking email's HTML body for the given language + context.
|
|
715
|
+
- `requireBookingConfig(): ResolvedBookingConfig` — Returns the resolved booking config, throwing when the module is not registered.
|
|
716
|
+
- `rescheduleReminders(tx: BookingTx, bookingId: string, dates: Array<Date | null>): Promise<void>` — Recompute the reminder schedule for a booking after a departure-date change:
|
|
717
|
+
- `resolveByToken(token: string): Promise<BookingRow | null>` — Resolve a booking by its unguessable portal access token (active only).
|
|
718
|
+
- `runBookingMaintenance(now: Date = new Date()): Promise<void>` — Run one maintenance pass (reminders + expirations), guarded against overlap.
|
|
719
|
+
- `runCapacityCheck(items: Array<{ tripRef: string; participantsCount: number }>, excludeBookingId?: string): Promise<void>` — Generic seat-capacity check (core). Sums requested participants per trip and
|
|
720
|
+
- `runValidateBooking(ctx: BookingValidationContext): Promise<void>` — Invoke the client-supplied validation seam, wrapping failures uniformly.
|
|
721
|
+
- `sendBookingEmail(bookingId: string, kind: BookingEmailKind, extra: Record<string, unknown> = {}): Promise<void>` — Send a transactional booking email to the booker. No-op when no email adapter
|
|
722
|
+
- `serverInit(): void` — Conventional server-init entry run by `initCMS` via `serverHooks.initModule`
|
|
723
|
+
- `startBookingMaintenance(): void` — Start the in-process loop (config-gated). Idempotent. Called from serverHooks.init.
|
|
724
|
+
- `stopBookingMaintenance(): void`
|
|
725
|
+
- `subjectFor(kind: BookingEmailKind, lang: string): string` — Localised subject for a kind, falling back to English.
|
|
726
|
+
- `toPortalView(booking: BookingRow, items: ItemRow[], participants: FlatParticipant[], payments: Array<PaymentEntry & { paidAt?: Dat...): <inferred>` — Pure: shape a portal-safe DTO. Explicitly whitelists fields — `staffNotes`,
|
|
727
|
+
- `verifyPhone(token: string, phone: string): Promise<BookingRow | null>` — Drugi czynnik: zwraca booking gdy podany numer pasuje do `customer.phone`.
|
|
728
|
+
- `voidBookingAdjustment(adjustmentId: string, opts: { actor: string; now?: Date }): Promise<void>` — Soft-void an adjustment (kept for audit) and recompute the booking totals +
|
|
729
|
+
|
|
554
730
|
### `includio-cms/files-local`
|
|
555
731
|
|
|
556
732
|
- `const fullDir: <inferred>`
|
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,70 @@
|
|
|
3
3
|
All notable changes to includio-cms are documented here.
|
|
4
4
|
Generated from `src/lib/updates/` — do not edit manually.
|
|
5
5
|
|
|
6
|
+
## 0.37.0 — 2026-06-17
|
|
7
|
+
|
|
8
|
+
Moduły-nakładki + context switcher: shop i booking jako równorzędne, opcjonalne moduły rozszerzające rdzeń CMS (model „WooCommerce na WordPressie"). Zunifikowany rejestr `config.modules`, przełącznik kontekstu w adminie (Treści / Sklep / Rezerwacje) dla czytelniejszego UI, per-moduł dashboard. Shop przepięty na nowy kontrakt `CMSModule` (dowód generyczności #1), booking dodany jako drugi moduł biblioteki z pełnym rdzeniem domenowym (wycena/state machine/księga płatności) — dowód #2. Booking write-flow + portal self-service domknięte: tworzenie (public+staff), zadatek + webhook idempotentny, pełna edycja self-service (recompute/pojemność/„nie poniżej wpłaconego”), maile + przypomnienia, cron bez-infra (in-process loop + secured endpoint), strefa obsługi w adminie, scaffold `--booking`. Plan: `docs/superpowers/plans/2026-06-18-booking-write-flow-portal.md`, spec: `docs/superpowers/specs/2026-06-18-booking-write-flow-portal-design.md`.
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `CMSModule` (`includio-cms` — `$lib/types/modules.ts`, `@public`) — kontrakt modułu-nakładki w 3 warstwach: serializowalny deskryptor (id/label/icon-string/context z nav sections + surfaced collections), server-only `serverHooks` (init), oraz client-side dashboard rejestrowany po `id`. Nav = dane (ikony jako nazwy z icon-map), nie komponenty.
|
|
12
|
+
- `config.modules: CMSModule[]` — zunifikowany rejestr modułów w `defineConfig`. CMS dostaje `getModule(id)` / `getModuleConfig<T>(id)` / `hasModule(id)` + `modules` Map. `initCMS` odpala `serverHooks.init` każdego modułu (idempotentnie, fire-and-forget).
|
|
13
|
+
- `moduleSchema` w `cms.schema.ts` — walidacja Zod modułów (unikalny `id`, wymagane icon/sections, `surfacedCollections`/`surfacedSingles` muszą referować zadeklarowane kolekcje/single).
|
|
14
|
+
- Context switcher (`context-switcher.svelte` w `site-header`) — przełącznik widoku admina: Treści (rdzeń CMS) / Sklep / Rezerwacje. Renderuje się tylko gdy ≥1 moduł; zero zmian wizualnych dla projektów bez modułów. Aktywny kontekst rozstrzygany przez `resolveActiveContext` (`?ctx` query > PersistedState sticky > ścieżka), ścieżki modułowe i content-core mają pierwszeństwo (poprawny deep-linking).
|
|
15
|
+
- Generyczny sidebar wg kontekstu (`nav-module.svelte`) — kontekst modułu pokazuje jego sekcje + „wciągnięte" kolekcje/single rdzenia (prop `filterSlugs` + `?ctx` w linkach na `nav-collections`/`nav-singletons`). Opcjonalne reaktywne badge przez `countSource`.
|
|
16
|
+
- Per-kontekst dashboard (`ModuleDashboardPage` + `dashboard-registry` po `id`, `@public` przez `includio-cms/admin/client`) — landing `/admin/shop` i `/admin/booking`. `shop-dashboard` (liczba zamówień + skróty), `booking-dashboard` (aktywne rezerwacje / zaległe salda / do potwierdzenia).
|
|
17
|
+
- `defineShop()` zwraca teraz `CMSModule` (id `shop`, ikona `building-store`, sekcje Produkty/Zamówienia/Wysyłka/Kupony). Pełna warstwa server/http/remote shopa nietknięta (363 testy zielone).
|
|
18
|
+
- `defineBooking(config): CMSModule` (`includio-cms/booking`, `@public`) — moduł rezerwacji. Config: `currency`, `catalogCollection` (surfaced), `depositAmount`, `pricing` (rabaty), `payment`, `adminEmail`.
|
|
19
|
+
- Booking rdzeń domenowy (pure, w pełni testowalny): `price()` — silnik wyceny (rabat ilościowy + early-bird, kompozycja largest-wins/sumowanie); `deriveStatus()` + `assertTransition()` — state machine `draft→reserved→partially_paid→paid→completed/cancelled` (status liczony z salda); `ledger` — saldo = gross − Σpaid, guard „nie poniżej wpłaconego". 37 testów.
|
|
20
|
+
- 5 tabel Drizzle bookingu (`bookings`/`booking_items`/`booking_participants`/`booking_payments`/`booking_reminders`) + eksport `includio-cms/db-postgres/schema-booking`. Kwoty w groszach, soft-delete, jsonb totals/customer/participants.
|
|
21
|
+
- `includio-cms/booking` + `includio-cms/db-postgres/schema-booking` — nowe entry points w `package.json` exports.
|
|
22
|
+
- Admin: lista Rezerwacje (`/admin/booking/reservations`) + remote `listBookings`/`getBookingEnabled`.
|
|
23
|
+
- Booking write-flow: `createBooking()` (public self-serve + staff, walidacja pojemności + seam `validateBooking`, snapshot ceny, harmonogram przypomnień), `createDepositPayment()` (link zadatku przez wstrzyknięty adapter), public handler `POST /api/booking`. Status zawsze liczony z księgi (`deriveStatus`).
|
|
24
|
+
- Webhook płatności (`POST /api/booking/webhook/[provider]`) — `applyWebhookPayment()` idempotentny przez row-lock (`SELECT … FOR UPDATE` po `providerRef`), przeliczenie salda + statusu, czyszczenie holdu zadatku, mail `deposit-paid`/`payment-received`. Czysta logika `applyPaymentEvent` testowana jednostkowo.
|
|
25
|
+
- Edycja rezerwacji (`editBooking()`, wspólna dla obsługi i portalu): recompute ceny, guardy wg actora, `portal` blokuje zejście poniżej wpłaconego (`LedgerError` → HTTP 409 „skontaktuj się z obsługą”), reschedule przypomnień przy zmianie wylotu. Refundy = ręczna akcja obsługi przez adapter (`refundPayment`, przeliczenie salda).
|
|
26
|
+
- Portal self-service (`GET|POST /api/booking/portal/[token]`, `?action=edit|pay`) + SDK `createBookingClient` i reaktywny `useBooking` (`includio-cms/booking/client`). `toPortalView` whitelistuje pola (brak `staffNotes`). Strony storefront/portalu buduje repo klienta na SDK.
|
|
27
|
+
- Maile bookingu: lokalny Handlebars registry (override projektem → package default → fallback lang) + 6 szablonów PL/EN (`booking-received`/`deposit-paid`/`payment-received`/`payment-link`/`balance-due`/`balance-overdue-cancelled`).
|
|
28
|
+
- Cron bez-infra: czyste `processDueReminders`/`processDueExpirations` (draft-expiry + balance-due forfeiture z przepadkiem zadatku) napędzane in-process loopem (`serverHooks.init`, interwał z configu, domyślnie 15 min) ORAZ secured endpointem `POST /api/booking/maintenance` (Bearer token) jako trigger wymienny.
|
|
29
|
+
- Strefa obsługi w adminie: detal rezerwacji `/admin/booking/reservations/[id]` (księga, pozycje, uczestnicy, akcje) + remote mutacje (`createBookingStaff`/`editBookingStaff`/`addPaymentLink`/`recordCashPayment`/`refundBookingPayment`/`changeBookingStatus`/`cancelBooking`/`sendBookingEmailCmd`).
|
|
30
|
+
- `includio-cms/booking/client` (SDK + `useBooking`) i `includio-cms/booking/server` (serwisy + HTTP handlery, node-only — kod serwerowy poza bundlem klienta) — nowe entry points.
|
|
31
|
+
- `defineBooking` config rozszerzony: `depositTtlMinutes` (TTL porzuconego draftu, def. 60), `balanceDueDaysBefore` (termin dopłaty), `capacityField` (pojemność z wpisu katalogu), `reminders[]`, `validateBooking(ctx)` (seam client-specific), `maintenance` (autoRun/intervalMinutes), `maintenanceToken`. Kolumny `bookings`: `balanceDueAt`/`holdExpiresAt`/`cancelReason`.
|
|
32
|
+
- Scaffold: `includio scaffold admin` emituje też trasy bookingu (api/booking/*, strony admina, portal `rezerwacja/[token]`) gdy wykryje `defineBooking(` — flagi `--booking`/`--no-booking`. Generyczny helper rate-limit podniesiony do core (`$lib/server/security/rate-limit-handler`, współdzielony shop+booking).
|
|
33
|
+
- Redesign kontekstów (admin context workspaces): context switcher przeniesiony do nagłówka sidebara obok loga (inline pill, w trybie zwiniętym sama ikona kontekstu), nawigacja scoped per kontekst — każdy kontekst pokazuje wyłącznie swoje sekcje + własny „Pulpit" (Treści→`/admin`, moduł→`landingUrl` z ikoną modułu). Globalne narzędzia (Biblioteka mediów + admin: Użytkownicy/Konserwacja) przyklejone do dołu sidebara w każdym kontekście. Trasy neutralne (`/admin/media|users|maintenance|account`) zachowują aktywny kontekst zamiast wracać do Treści. Tożsamość kontekstu przez ikonę, Plum jednolity (`data-context` na korzeniu sidebara jako forward-compat hook pod ewentualne akcenty). Spec: `docs/superpowers/specs/2026-06-18-admin-context-workspaces-design.md`.
|
|
34
|
+
- Silnik reguł rabatowych bookingu (`price()` przepisany, `includio-cms/booking`): rabaty jako serializowalne reguły `when`→`then` z grupami wykluczającymi (w grupie wygrywa największy rabat, między grupami sumują się). Zastępuje `quantityDiscounts`/`earlyBird`/`combine`. Nowe efekty: `percentOffCheapestLine` (100 = najtańsza pozycja gratis) + `grantPerk` (prezent — notka dla obsługi). `PriceResult.perks` + per-linia `appliedDiscounts` (targetRef). Typy: `DiscountRule`/`Condition`/`Effect`/`Perk`/`PricingLine`. Silnik czysty, bez sprzężenia z domeną (gotowy pod współdzielenie z shop).
|
|
35
|
+
- Generyczny seam wyceny per linia: `PricingLine.subtotal?` — gdy podany, jest grossem linii (zamiast `unitPrice×quantity`), używany też przez „najtańsza pozycja gratis" (cheapest wg subtotalu). Snapshot na `booking_items.subtotalSnapshot` (nullable) zapewnia wierny recompute przy edycji. Wstecznie kompatybilne (brak subtotalu = zachowanie bez zmian). Pozwala klientowi naliczać dowolną nie-płaską cenę linii (np. cena wg wieku uczestników, stawki grupowe) bez logiki klienta w rdzeniu — wartości/obliczenia po stronie projektu. Spec: `docs/superpowers/specs/2026-06-18-booking-participants-fields-child-pricing-design.md`.
|
|
36
|
+
- Booking + PayU (i każdy adapter shopu) bez modułu shop: `PaymentCreateContext` zyskuje `continueUrl` (pełny absolutny URL powrotu) + `buyer` ({firstName,lastName,phone}). Adapter PayU `createPayment` preferuje ctx i pomija `requireShopConfig`/`getOrderById` gdy `continueUrl` podane (ścieżka shop bez zmian, wstecznie zgodna). `defineBooking` zyskuje `portalUrlTemplate` (placeholder `{token}` → `accessToken`); `createDepositPayment`/`createInstallmentPayment` budują ctx przez czysty `buildPaymentContext` i przekazują do adaptera. Pozwala wpiąć realny PayU w booking bez shopu. Spec: `docs/superpowers/specs/2026-06-19-booking-payu.md` (repo klienta).
|
|
37
|
+
- Treść maili transakcyjnych bookingu dopracowana (PL/EN, wszystkie 6 rodzajów) we wspólnym layoucie — nowe partials `_partials/{header,footer}` (rejestrowane przed każdym renderem, kolizyjnie-bezpieczne wobec identycznych nazw w module shop), styling AriaCMS + przycisk do panelu rezerwacji (`portalUrl` z `accessToken`+`portalUrlTemplate`). `balance-due` podaje termin dopłaty z datą i przybliżoną liczbą dni oraz ostrzega o przepadku zadatku; nowe helpery Handlebars `date`/`daysUntil`. Link do płatności wysyłany mailem do bookera po akcji obsługi `addPaymentLink`. Nowe pole `defineBooking({ brand })` — nazwa firmy w stopce maila (override per-projekt nadal przez `src/emails/booking/`). Spec/plan: `docs/superpowers/specs/2026-06-19-booking-email-content-design.md`.
|
|
38
|
+
- Widoki podglądu (`previews[]` w kolekcji/singlu, `@public`) — jedno entry może mieć kilka celów podglądu (pełny wpis, zajawka/karta w liście). Przełącznik „Widok" w pasku podglądu (ukryty przy jednym widoku), a `preview: '<nazwa>'` na tabie przełącza widok automatycznie przy wejściu na ten tab; tab bez powiązania nie rusza podglądu, a ręcznie wybrany widok jest zapamiętywany per tab. Podgląd ładuje `{url}?preview={id}&view={name}` — projekt może mieć route per widok albo jeden route rozgałęziający się na `view`. Stary `previewUrl` działa bez zmian (normalizowany do jednego widoku). `defineConfig` waliduje spójność: unikalne nazwy, max jeden `default`, `previewUrl`/`previews` wykluczają się, każde `tab.preview` musi wskazywać istniejący widok (literówka wywala build). Spec: `docs/superpowers/specs/2026-07-13-preview-views-design.md`.
|
|
39
|
+
- Admin bookingu — lista rezerwacji na wspólnym `DataTable`: wyszukiwanie po numerze oraz po danych klienta, filtr statusu, paginacja serwerowa (`listBookings({status, search, limit, offset})` → `{items, total}`; było: `SELECT *` bez limitu, czyli cała baza rezerwacji do przeglądarki). Statystyki pulpitu liczy nowy `getBookingStats()` — agregat SQL, bo sumowanie stronicowanej listy pokazywałoby po cichu liczby z pierwszej strony.
|
|
40
|
+
- Admin bookingu — czytelne statusy (`StatusBadge variant="booking"`): „Czeka na zaliczkę", „Zarezerwowane", „Częściowo opłacone", … zamiast surowych wartości technicznych (`draft`, `partially_paid`) na liście i w detalu.
|
|
41
|
+
- Admin bookingu — pozycje rezerwacji pokazują NAZWĘ wycieczki, nie jej uuid. `getBooking` rozwiązuje wpis katalogu zawsze, gdy katalog jest skonfigurowany (wcześniej tylko gdy `participantFields` było funkcją) i wystawia `tripTitle`; picker pozycji i detal używają jednego helpera `catalogTitle`, więc nazywają wycieczkę tak samo.
|
|
42
|
+
- `defineBooking({ customerFields })` (`@experimental`) — etykiety worka `customer` w panelu admina (`FieldDef[]`: `key`, `label`, opcjonalna `role`). Rdzeń nie zna nazw pól projektu, więc bez tego panel pokazuje uczłowieczone klucze („Referral source"). Klucze zagnieżdżone adresuje się kropką (`people.birthDate`). Wyłącznie prezentacja — nie waliduje i nie zmienia danych.
|
|
43
|
+
- Admin bookingu — data urodzenia uczestnika pokazuje skończone lata w nawiasie („1990-05-05 (36 l.)"). Rozpoznanie po ROLI pola (`role: 'birthDate'`), nie po nazwie — z samej wartości nie odróżnisz daty urodzenia od daty przylotu.
|
|
44
|
+
- `defineBooking({ surfacedCollections })` (`@experimental`) — dodatkowe kolekcje wciągane do kontekstu „Rezerwacje" w adminie obok katalogu (np. kolekcja definiująca typy wypraw i pola uczestnika). Bez tego mieszkają w kontekście „Treści" i wyglądają jak doszyta kolekcja CMS-a, choć obsługują rezerwacje.
|
|
45
|
+
- Admin bookingu — nowa sekcja „Klient" w detalu rezerwacji. Wcześniej dane osoby rezerwującej (imię, e-mail, telefon, okno pobytu, odpowiedzi z formularza) były zapisywane, ale **nigdzie nie pokazywane** — obsługa nie mogła oddzwonić do klienta z panelu. Renderer jest generyczny: rozpoznaje typ po WARTOŚCI (e-mail → `mailto:`, telefon → `tel:`, data ISO → format lokalny), nie po nazwie pola, więc działa dla dowolnego kształtu `customer` bez zmian w rdzeniu; tablice obiektów (np. manifest uczestników) renderują się tabelką. `getBooking` wystawia `arrivalDateField` z konfiguracji.
|
|
46
|
+
|
|
47
|
+
### Fixed
|
|
48
|
+
- Pole `relation` — dwa wpisy o tej samej nazwie przestają się zlewać w jeden. `Command.Item` dostawał `value={label}`, a `value` jest w bits-ui tożsamością pozycji (filtrowanie, nawigacja klawiaturą, podświetlenie), więc identyczne nazwy dawały `aria-selected=true` na obu wierszach naraz. Teraz tożsamość to `id` wpisu, a wyszukiwanie po nazwie zapewnia `keywords` (domyślny scorer skleja `value` + `keywords`). Zaznaczenie (`isSelected`) zawsze szło po `id` — psuło się wyłącznie podświetlenie.
|
|
49
|
+
- Ścieżka wpisu (`_url`, lista kolekcji) zawsze bezwzględna, z dokładnie jednym wiodącym slashem. `applyPathTemplate` zwracało szablon 1:1, więc `pathTemplate: 'blog/{slug}'` dawało `_url: 'blog/x'` — URL **względny** (z podstrony prowadził w złe miejsce), mimo że docs obiecują `/blog/x`. Projekty pisały więc `pathTemplate: '/blog/{slug}'`, a wtedy lista kolekcji w adminie pokazywała `//blog/x`, bo `entry-link` doklejał własny slash. Teraz szablon i slug są składane bez podwojenia (`//` → `/`), obie formy szablonu działają, a URL-e bezwzględne (`https://…`) zostają nietknięte. `EntryLink` przyjmuje `path` (gotowa ścieżka) zamiast `slug`.
|
|
50
|
+
|
|
51
|
+
### Breaking
|
|
52
|
+
- `config.shop` USUNIĘTY. Shop rejestruje się teraz przez `config.modules`: `defineConfig({ modules: [defineShop({...})] })` zamiast `defineConfig({ shop: defineShop({...}) })`. `defineShop()` zwraca `CMSModule` (nie `ResolvedShopConfig`). Wewnętrznie `getCMS().shopConfig` działa nadal (shim → `getModuleConfig('shop')`), więc warstwa server/http/remote shopa pozostaje kompatybilna.
|
|
53
|
+
- Tabela `bookings` ma nowe kolumny (`balance_due_at`, `hold_expires_at`, `cancel_reason`) oraz `booking_items` kolumnę `subtotal_snapshot` (nullable) wymagane przez write-flow. Po aktualizacji uruchom `pnpm db:push` (lub migrację) w projekcie używającym bookingu.
|
|
54
|
+
- `PricingConfig` bookingu przepisany na `{ rules: DiscountRule[] }` — `quantityDiscounts`/`earlyBird`/`combine` USUNIĘTE. `price(lines, now, config)` ma nową sygnaturę (linie z `ref`/`departureDate` zamiast płaskich `{unitPrice,quantity}` + osobnej daty). `BookingTotals` zyskuje `perks`/`appliedRules` (jsonb `totals` — bez migracji DB). Zaktualizuj `defineBooking({ pricing: { rules: [...] } })`.
|
|
55
|
+
|
|
56
|
+
### Notes
|
|
57
|
+
|
|
58
|
+
Pre-1.0: zmiana dozwolona bez okresu deprecacji (jednoosobowy konsument). Migracja: (1) w `cms.config.ts` zamień `shop: defineShop({...})` na `modules: [defineShop({...})]`; (2) jeśli używasz bookingu — `pnpm db:push` (nowe kolumny) i przescaffolduj trasy (`includio scaffold admin` wykryje `defineBooking(`). Provider płatności (Stripe/PayU) konfigurowalny przez `defineBooking({ payment: [...] })` — core adapter-agnostyczny.
|
|
59
|
+
|
|
60
|
+
## 0.36.9 — 2026-07-02
|
|
61
|
+
|
|
62
|
+
Duplikacja wpisu z tabeli kolekcji + serwerowa normalizacja pól slug przy zapisie. Menu wiersza zyskuje „Duplikuj" — tworzy nieopublikowany szkic z tą samą treścią (wszystkie języki), z prefiksem tytułu „Kopia — " i unikalnym slugiem („-kopia"), i przenosi do edytora duplikatu. Media i relacje są współdzielone przez referencje (bez głębokiego klonu). Niezależnie od duplikacji: każde pole typu slug (SlugField oraz slug w polu SEO) jest przy zapisie normalizowane przez slugify — „Singapur"/„Hello World" zapisują się jako „singapur"/„hello-world", transparentnie dla użytkownika. Spec: `docs/superpowers/specs/2026-07-02-duplicate-entry-and-slug-normalization-design.md`, plan: `docs/superpowers/plans/2026-07-02-duplicate-entry-and-slug-normalization.md`.
|
|
63
|
+
|
|
64
|
+
### Added
|
|
65
|
+
- Duplikacja wpisu (`duplicateEntry` + remote `duplicateEntryCommand`, akcja „Duplikuj" w menu wiersza tabeli kolekcji `/admin/collections/[collection]`): kopiuje najświeższą treść per język (draft ?? published ?? scheduled) na nowy wpis jako wersje nieopublikowane (`publishedAt: null`), prefiksuje `entryAdminTitle` przez „Kopia — " i nadaje każdemu polu slug unikalny sufiks („-kopia", „-kopia-2", …) sprawdzany wobec published-or-scheduled slugów kolekcji, po czym przenosi do edytora duplikatu. Media/relacje = współdzielone referencje. Akcja ukryta dla wpisów archiwalnych.
|
|
66
|
+
|
|
67
|
+
### Fixed
|
|
68
|
+
- Normalizacja slug przy zapisie (`normalizeSlugFields` wpięte w `updateEntryVersionCommand`, ścieżka draft i publish): wartości pól typu slug (SlugField oraz slug w polu SEO) są normalizowane przez `slugify({ lower, strict, trim })` przed zapisem i przed kontrolą unikalności. Nietechniczny użytkownik wpisujący np. „Singapur" czy „Hello World" dostaje poprawny „singapur"/„hello-world" bez ręcznej korekty. Puste/nie-string i pola nie-slug pozostają nietknięte.
|
|
69
|
+
|
|
6
70
|
## 0.36.8 — 2026-07-02
|
|
7
71
|
|
|
8
72
|
Optymalizacja obrazów przeniesiona do tła: render nigdy nie odpala sharpa. Warianty generuje in-process worker zasilany trwałą kolejką media_job (concurrency=1, twarde limity sharp, retry/backoff, circuit-breaker). Lżejsza, konfigurowalna matryca (avif+webp, bez pełno-res bazy, cap 2560) tnie ~połowę plików/jobów i eliminuje bombę CPU pełno-res AVIF, która OOM-owała VPS.
|
package/DOCS.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Includio CMS Documentation (v0.
|
|
1
|
+
# Includio CMS Documentation (v0.37.0)
|
|
2
2
|
|
|
3
3
|
> This file is auto-generated from the docs site. For the latest version, update the package.
|
|
4
4
|
|
|
@@ -587,7 +587,8 @@ const posts = defineCollection({
|
|
|
587
587
|
| `labels` | `{ singular?: Localized; plural?: Localized }` | No | Display labels in admin |
|
|
588
588
|
| `entryAdminTitle` | `string` | No | Field slug used as entry title in admin list |
|
|
589
589
|
| `sidebarIcon` | `IconName` | No | Icon for the admin sidebar |
|
|
590
|
-
| `previewUrl` | `string` | No | URL pattern for previewing entries |
|
|
590
|
+
| `previewUrl` | `string` | No | URL pattern for previewing entries (shorthand for one view) |
|
|
591
|
+
| `previews` | `PreviewView[]` | No | Named [preview views](#preview-views) — mutually exclusive with `previewUrl` |
|
|
591
592
|
| `orderable` | `boolean` | No | Enable manual drag-and-drop ordering |
|
|
592
593
|
| `listColumns` | `string[]` | No | Field slugs to display as columns in admin list |
|
|
593
594
|
| `layout` | `Layout` | No | Admin editor [layout](/docs/getting-started/layout) |
|
|
@@ -596,6 +597,29 @@ const posts = defineCollection({
|
|
|
596
597
|
|
|
597
598
|
> **entryAdminTitle:** Set `entryAdminTitle` to a text field slug (like `'title'`) so entries show meaningful names in the admin list instead of IDs.
|
|
598
599
|
|
|
600
|
+
## Preview views
|
|
601
|
+
|
|
602
|
+
One entry is often rendered in more than one way on the front end — a full page, and a teaser card in a listing. Declare each way as a view:
|
|
603
|
+
|
|
604
|
+
```typescript
|
|
605
|
+
previews: [
|
|
606
|
+
{ name: 'full', label: { pl: 'Pełny wpis' }, url: '/preview/blog-post' },
|
|
607
|
+
{ name: 'teaser', label: { pl: 'Zajawka' }, url: '/preview/blog-post/teaser' }
|
|
608
|
+
]
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
The admin loads `{url}?preview={entryId}&view={name}`, so you may expose one route per view, or a single route that branches on the `view` query param. A **Widok / View** switcher appears in the preview toolbar; with a single view it stays hidden. `previewUrl: '/preview/blog-post'` is the shorthand for exactly one view, and keeps working as before.
|
|
612
|
+
|
|
613
|
+
Bind a view to a tab and the preview follows the editor:
|
|
614
|
+
|
|
615
|
+
```typescript
|
|
616
|
+
{ type: 'tab', label: { pl: 'Zajawka' }, preview: 'teaser', fields: ['thumbnail', 'featured'] }
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
A tab **without** `preview` leaves the current view alone, and a view the editor picks by hand is remembered for that tab. Views do not change what is fetched — the entry always arrives whole; they only change how it is rendered in the preview.
|
|
620
|
+
|
|
621
|
+
> **Typos fail the build:** `defineConfig` checks that view names are unique, that at most one is `default`, that `previewUrl` and `previews` are not both set, and that every `tab.preview` points at a declared view.
|
|
622
|
+
|
|
599
623
|
## Usage in Config
|
|
600
624
|
|
|
601
625
|
```typescript
|
|
@@ -674,7 +698,8 @@ const homepage = defineSingle({
|
|
|
674
698
|
| `fields` | `Field[]` | Yes | Array of field definitions |
|
|
675
699
|
| `label` | `Localized` | No | Display label in admin |
|
|
676
700
|
| `sidebarIcon` | `IconName` | No | Icon for admin sidebar |
|
|
677
|
-
| `previewUrl` | `string` | No | URL for previewing |
|
|
701
|
+
| `previewUrl` | `string` | No | URL for previewing (shorthand for one view) |
|
|
702
|
+
| `previews` | `PreviewView[]` | No | Named [preview views](/docs/collections#preview-views) — mutually exclusive with `previewUrl` |
|
|
678
703
|
| `layout` | `Layout` | No | Admin editor [layout](/docs/getting-started/layout) |
|
|
679
704
|
| `slugField` | `string` | No | Dot-path to slug field (default: `'seo.slug'`) |
|
|
680
705
|
| `pathTemplate` | `string` | No | URL path template, e.g. `'about'` |
|
package/ROADMAP.md
CHANGED
|
@@ -19,6 +19,9 @@
|
|
|
19
19
|
- [x] `[chore]` `[P1]` Faza 10 — Documentation Pass (0.23.0): DOCS.md uzupełnione (number/boolean/date edge cases, REST cURL + error codes, Entries error handling + transactions, Admin UI a11y, Adapter Contracts), nowe sekcje (Stability Promise, Security Model), Migration Guide v0.x → v1.0 master cheatsheet (0.16-0.22), ROADMAP cleanup (pre-v1.0 → ROADMAP-ARCHIVE.md) <!-- files: src/routes/docs/{stability-promise,security}/+page.svx, src/routes/docs/migration/+page.svx, src/routes/docs/_config/nav.ts, scripts/compile-docs.ts, ROADMAP-ARCHIVE.md, src/lib/updates/0.23.0/ -->
|
|
20
20
|
- [x] `[chore]` `[P1]` Faza 11 — Performance Pass (0.24.0): N+1 elimination (`getImageStyle` batch IN query, `getRawEntries` batch entry versions), Sharp srcset `Promise.allSettled` (one timeout doesn't kill batch), background maintenance in-process lock verified + tested, bench infra (`pnpm bench` + representative benchmarks), lazy adapter imports verified <!-- files: src/lib/core/server/media/styles/operations/, src/lib/core/server/fields/resolveImageFields.ts, src/lib/core/server/entries/operations/get.ts, src/lib/db-postgres/index.ts, src/lib/core/server/media/operations/backgroundMaintenance.spec.ts, src/lib/updates/0.24.0/ -->
|
|
21
21
|
- [x] `[feature]` `[P0]` Faza 11.5 — Shop polish (0.25.0): Stripe adapter (Checkout Session, sig verify, idempotency), refund infra (full + partial cross-adapter), webhook idempotency table (`shop_webhook_events`), coupons (% / fixed, expiresAt, maxUses, minOrder), low-stock email alert, order export CSV, default email templates (PL/EN), SDK JSDoc + `@public`, pełna dokumentacja shopa <!-- files: src/lib/shop/adapters/stripe/, src/lib/shop/server/{refund,coupons}.ts, src/lib/db-postgres/schema/shop/{refunds,webhookEvents,coupons,couponRedemptions}.ts, src/lib/admin/client/shop/, src/lib/updates/0.25.0/ -->
|
|
22
|
+
- [x] `[feature]` `[breaking]` `[P1]` Moduły-nakładki + context switcher (0.37.0) — zunifikowany `config.modules` (`CMSModule`: deskryptor + serverHooks + client dashboard), przełącznik kontekstu admina (Treści/Sklep/Rezerwacje), per-moduł dashboard; shop przepięty na kontrakt modułu (`config.shop` usunięty, shim `shopConfig`); booking jako 2. moduł biblioteki — rdzeń domenowy (wycena/state-machine/księga, 37 testów) + 5 tabel Drizzle + lista Rezerwacje. Booking write-flow + portal self-service domknięte: create (public+staff), zadatek + webhook idempotentny (row-lock), pełna edycja self-service (recompute/pojemność/„nie poniżej wpłaconego” → 409), maile + przypomnienia, cron bez-infra (in-process loop + secured endpoint), strefa obsługi, SDK `./booking/client` + node-only `./booking/server`, scaffold `--booking`. <!-- files: src/lib/types/modules.ts, src/lib/core/cms.ts, src/lib/admin/state/active-context*, src/lib/admin/components/layout/{context-switcher,nav-module}.svelte, src/lib/booking/, src/lib/db-postgres/schema/booking/, src/lib/admin/remote/booking.remote.ts, src/lib/admin/client/booking/, src/lib/cli/scaffold/booking.ts, docs/superpowers/specs/2026-06-18-booking-write-flow-portal-design.md, docs/superpowers/plans/2026-06-18-booking-write-flow-portal.md -->
|
|
23
|
+
- [x] `[feature]` `[breaking]` `[P1]` Silnik reguł rabatowych bookingu (0.37.0) — `price()` przepisany na data-driven reguły `when`→`then` z grupami wykluczającymi; zastępuje qty/early-bird; `percentOffCheapestLine` + `grantPerk` (prezent); drabinka bundle pod-zwrotnikami jako dane w configu klienta. Spec: `docs/superpowers/specs/2026-06-18-booking-discount-rules-engine-design.md`, plan: `docs/superpowers/plans/2026-06-18-booking-discount-rules-engine.md`. <!-- files: src/lib/booking/pricing.ts, src/lib/booking/{draft,recompute}.ts, src/lib/booking/server/bookings.ts, src/lib/db-postgres/schema/booking/bookings.ts, src/lib/booking/templates/booking-received.*.html, src/lib/admin/client/booking/reservation-detail-page.svelte -->
|
|
24
|
+
- [x] `[feature]` `[P1]` Widoki podglądu (0.37.0) — `previews[]` w kolekcji/singlu (nazwa + label + url, `previewUrl` = skrót na jeden widok), przełącznik „Widok" w pasku podglądu, `tab.preview` przełącza widok przy wejściu na tab (ręczny wybór zapamiętywany per tab), URL podglądu `{url}?preview={id}&view={name}`, walidacja spójności w `defineConfig`. Spec: `docs/superpowers/specs/2026-07-13-preview-views-design.md`, plan: `docs/superpowers/plans/2026-07-13-preview-views.md`. <!-- files: src/lib/types/{config,layout,cms.schema}.ts, src/lib/core/config/validatePreviews.ts, src/lib/admin/client/entry/{preview-views.ts,preview-views-context.svelte.ts,entry.svelte,hybrid/hybrid-preview.svelte}, src/lib/admin/components/layout/{layout-tabs,layout-renderer}.svelte -->
|
|
22
25
|
- [ ] `[fix]` `[P1]` Select field — `defaultValue` propagacja do zod schema (full repro: `ideas/post-v1/select-field-defaultvalue-bug.md`); fix planowany w Fazie 12 (RC)
|
|
23
26
|
- [x] `[chore]` `[P2]` Demo orchestrator — `pnpm demo` startuje czystą instancję na tmpfs DB :5436, seeduje 12 blog postów / 6 projektów / 5 contact submissions / 8 gradient PNG-ów, włącza `demo-site` frontend pod `/demo-site`, każdy start = czysty stan <!-- files: scripts/demo.ts, scripts/seed-demo.ts, src/routes/demo-site/, docker-compose.yml, .env.demo -->
|
|
24
27
|
- [x] `[feature]` `[P1]` Shop platformowy 0.27.0 — schema-driven variants + booking deposit (envet pilot). Plan: 7 faz. <!-- files: docs/superpowers/specs/2026-05-28-shop-platformowy-design.md, /Users/patryk/.claude/plans/implementacja-ariacms-0-27-partitioned-kahn.md -->
|
|
@@ -32,6 +35,19 @@
|
|
|
32
35
|
- [x] `[feature]` `[P1]` Slug first-class + SEO v1.0 freeze (0.26.0) — `resolveSeo` public (`includio-cms/core`), `seoFieldDescriptor` SSOT (Zod+TS drift-guard), admin URL un-hardcode (`slugPath.ts` pure resolver, no `seo`-field requirement), `SlugField`/`SeoField`/`SeoFieldData` `@public` v1.0-frozen <!-- files: src/lib/core/fields/slugPath.ts, src/lib/core/fields/seoFieldDescriptor.ts, src/lib/core/fields/resolveSeo.ts, src/lib/types/fields.ts, src/lib/admin/client/collection/collection-entries.svelte, src/lib/updates/0.26.0/ -->
|
|
33
36
|
- [x] `[feature]` `[P2]` Soft-delete zamówień admin-only (0.34.0) — ukrycie zamówienia z listy bez utraty danych (`deleted_at`/`deleted_by`), kosz + przywracanie, guard `decideOrderDeletion` (safe-statuses + faktura), auto-restore przy płatności, zwolnienie rezerwacji stocku, `requireRole('admin')` <!-- files: src/lib/shop/server/orders.ts, src/lib/db-postgres/schema/shop/order.ts, src/lib/admin/remote/shop.remote.ts, src/lib/admin/client/shop/{shop-order-detail-page,shop-orders-list-page,restore-order-cell}.svelte, src/lib/updates/0.34.0/ -->
|
|
34
37
|
|
|
38
|
+
## 0.38.0 — Moduły: kontrakt vs polityka
|
|
39
|
+
|
|
40
|
+
Spec: `docs/superpowers/specs/2026-07-13-moduly-kontrakt-vs-polityka-design.md`. Kolejność i uzasadnienia tam.
|
|
41
|
+
|
|
42
|
+
- [x] `[feature]` `[P0]` Kawałek 3a — jądro reguł w rdzeniu (`core/rules`) + cennik jako kategorie uczestnika; golden testy parytetu ze starym silnikiem. Branch `feat/pricing-rules-kernel`.
|
|
43
|
+
- [ ] `[feature]` `[P0]` Kawałek 1 — fundament: `module_settings` (polityka w bazie) + system migracji (`aria migrate` + guard) + `AdminRouter` (routes admina jako dane, koniec z plikami w repo klienta) + `PaymentAdapter` wyprowadzony z shopu do rdzenia.
|
|
44
|
+
- [ ] `[feature]` `[P0]` Kawałek 2 — polityka bookingu: strona „Ustawienia rezerwacji", builder reguł (generowany z rejestru, pole `blocks`), symulator ceny, **snapshot polityki na rezerwacji** (dziś dotknięcie starej rezerwacji przelicza early-bird wg dzisiejszej daty i potrafi podnieść cenę klientowi), kasacja `pricing.ts`.
|
|
45
|
+
- [ ] `[feature]` `[P0]` **Typy wypraw / kategorie uczestnika wracają do modułu.** Dziś kolekcja `tripType` (bloki-dane) + adapter `mapTripTypeFields` (dane→`FieldDef`) mieszkają w repo KLIENTA — każdy kolejny klient przepisuje ~100 linii, a kolekcja wyświetla się w kontekście „Treści", bo moduł nie umie wnieść własnej. Wzorzec jest poprawny (Payload form-builder: stała kolekcja + pola jako bloki; zero DDL, odpowiedzi w `booking_persons.data`) — zły jest tylko adres. Moduł ma wnosić to pojęcie sam (dane w ustawieniach modułu), mapować na `FieldDef` w rdzeniu i pokazywać w kontekście „Rezerwacje". Efekt: klient N nie pisze ani linijki. Obejście na 0.37.0: `defineBooking({ surfacedCollections })` (`@experimental`).
|
|
46
|
+
- [ ] `[feature]` `[P1]` **`customer` dostaje prawdziwy schemat**, nie tylko etykiety. Dziś `defineBooking({ customerFields })` (`@experimental`) opisuje worek `customer` WYŁĄCZNIE do prezentacji, a walidacja tego samego worka żyje w repo klienta (`assertManifest`, `validateSurveyAnswers`) — dwie deklaracje jednej rzeczy, gotowy dryf. Docelowo jedna deklaracja napędza walidację, render w adminie i formularz publiczny (jak `participantFields`).
|
|
47
|
+
- [ ] `[feature]` `[P0]` Kawałek 4 — kody rabatowe: wspólna tabela `coupons` + `coupon_redemptions` w rdzeniu; **port kuponu shopu na jądro reguł** (twardy warunek: jądro z jednym konsumentem to generalizacja bez dowodu).
|
|
48
|
+
- [ ] `[feature]` `[P1]` Kawałek 5 — braki domenowe: `weekdays[]` → dodatki (extras) → overrides per data `{date, capacity?, price?, status?}`.
|
|
49
|
+
- [ ] `[chore]` `[P1]` Konsolidacja pól: `booking/FieldDef` → koperta nad core `Field`. Usuwa import `VariantAttribute` z shopu w `core/server/generator/fields.ts` (dziś **rdzeń importuje z modułu** — odwrócona zależność).
|
|
50
|
+
|
|
35
51
|
## v1.x — Post-v1.0 deferred
|
|
36
52
|
|
|
37
53
|
- [ ] `[feature]` `[P1]` SEO module — SERP preview, char limits, global settings, frontend components, sitemap (full plan: `ideas/post-v1/seo-aeo-geo-module.md`)
|
|
@@ -56,6 +72,8 @@
|
|
|
56
72
|
|
|
57
73
|
## Backlog
|
|
58
74
|
|
|
75
|
+
- [ ] `[fix]` `[P1]` Wyciek puli połączeń DB w dev (HMR) — pojedynczy proces `vite dev` konsumenta trzymał **100 połączeń** do Postgresa (cały `max_connections`), po czym baza odbijała wszystko: `FATAL: sorry, too many clients already` (zaobserwowane 2026-07-13 na pod-zwrotnikami). Hipoteza: każde przeładowanie modułu przez HMR tworzy nowy klient `postgres.js` (pula domyślnie 10), a stary nie jest zamykany — 10 przeładowań wyczerpuje limit. Sprawdzić zamykanie klienta w `import.meta.hot.dispose` / singleton na `globalThis` w adapterze. Dotyka każdego, kto dłużej pracuje w dev. <!-- files: src/lib/db-postgres/index.ts -->
|
|
76
|
+
- [ ] `[chore]` `[P1]` CMS doctor — `validateLayout()` jest napisany i przetestowany, ale nie jest wołany z żadnego miejsca produkcyjnego: literówka w nazwie pola w tabie przechodzi po cichu (pole ląduje w orphanach). Podpiąć go do `defineConfig` obok `validatePreviews`, dołożyć `pnpm cms check` w CLI i zestaw reguł zdrowia configu (martwe pola, `pathTemplate` bez `previewUrl`/`previews`, itp.). <!-- files: src/lib/core/fields/layoutUtils.ts, src/lib/sveltekit/config.ts, src/lib/core/config/, src/lib/cli/index.ts -->
|
|
59
77
|
- [ ] `[feature]` `[P2]` Date/datetime field — przebudowa na shadcn-svelte (bits-ui Calendar/DatePicker) zamiast natywnego inputu. Zgłoszone w QA Etap 5a (4/5); funkcjonalnie OK, odłożone jako osobny redesign pola daty. <!-- files: src/lib/admin/components/fields/date-field.svelte, datetime-field.svelte -->
|
|
60
78
|
- [ ] `[feature]` `[P2]` `<Video>` — eksponować ref wewnętrznego `<video>` (np. bindable `element` prop lub forward `bind:this`). Obecnie konsument potrzebujący programowej kontroli (play/pause, scrub, mute toggle) musi owijać w `<div bind:this>` + `querySelector('video')` — boilerplate i kruche. Zgłoszone przy customowym hero-wideo (autoplay + przycisk pauzy). <!-- files: src/lib/sveltekit/components/video.svelte -->
|
|
61
79
|
- [ ] `[feature]` `[P1]` Re-introduce entry autosave with strict draft-only guard (opt-in via `cms.config.ts`, never touch published versions, debounced + visual countdown). Removed in 0.26.0 / S8 because old impl could touch published data ambiguously.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { getRemotes } from '../../../sveltekit/index.js';
|
|
3
|
+
import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
|
|
4
|
+
import StatCard from '../modules/stat-card.svelte';
|
|
5
|
+
import { Button } from '../../../components/ui/button/index.js';
|
|
6
|
+
import { formatCentsPrice } from '../../utils/formatters.js';
|
|
7
|
+
|
|
8
|
+
const remotes = getRemotes();
|
|
9
|
+
const interfaceLanguage = useInterfaceLanguage();
|
|
10
|
+
|
|
11
|
+
// Agregaty liczone w SQL — lista rezerwacji jest stronicowana, więc sumowanie jej wierszy
|
|
12
|
+
// dawałoby po cichu statystyki wyłącznie z pierwszej strony.
|
|
13
|
+
const statsQuery = $derived(remotes.getBookingStats());
|
|
14
|
+
const stats = $derived(statsQuery.current);
|
|
15
|
+
|
|
16
|
+
const active = $derived(stats?.active ?? 0);
|
|
17
|
+
const outstanding = $derived(stats?.outstanding ?? 0);
|
|
18
|
+
const toConfirm = $derived(stats?.toConfirm ?? 0);
|
|
19
|
+
const currency = $derived(stats?.currency ?? 'PLN');
|
|
20
|
+
|
|
21
|
+
const t = $derived(
|
|
22
|
+
interfaceLanguage.current === 'pl'
|
|
23
|
+
? { active: 'Aktywne rezerwacje', outstanding: 'Zaległe salda', toConfirm: 'Do potwierdzenia', manage: 'Rezerwacje' }
|
|
24
|
+
: { active: 'Active bookings', outstanding: 'Outstanding balances', toConfirm: 'To confirm', manage: 'Reservations' }
|
|
25
|
+
);
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<div class="flex flex-col gap-4 px-4 pb-6 sm:px-6">
|
|
29
|
+
<div class="grid grid-cols-2 gap-3 sm:grid-cols-3">
|
|
30
|
+
<StatCard label={t.active} value={statsQuery.ready ? active : '—'} />
|
|
31
|
+
<StatCard
|
|
32
|
+
label={t.outstanding}
|
|
33
|
+
value={statsQuery.ready ? formatCentsPrice(outstanding, currency) : '—'}
|
|
34
|
+
/>
|
|
35
|
+
<StatCard label={t.toConfirm} value={statsQuery.ready ? toConfirm : '—'} />
|
|
36
|
+
</div>
|
|
37
|
+
<div class="flex flex-wrap gap-2">
|
|
38
|
+
<Button href="/admin/booking/reservations" variant="outline" size="sm">{t.manage}</Button>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|