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
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Module system — shop, booking, and future "overlays" on the CMS core.
|
|
3
|
+
*
|
|
4
|
+
* A module is registered via `defineConfig({ modules: [...] })`. It is split
|
|
5
|
+
* into a **serializable descriptor** (id/label/icon/context — safe to send to
|
|
6
|
+
* the admin client via a remote query) and **server-only `serverHooks`**
|
|
7
|
+
* (init logic that must never cross the wire). The module's dashboard
|
|
8
|
+
* component lives in a separate client-side registry keyed by `id`, never in
|
|
9
|
+
* the config — Svelte components are not serializable and the config is also
|
|
10
|
+
* validated server-side with Zod.
|
|
11
|
+
*
|
|
12
|
+
* @see {@link CMSModule}
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Strips a {@link CMSModule} down to its serializable {@link CMSModuleDescriptor}
|
|
16
|
+
* for transport to the admin client. Drops `config` and `serverHooks`.
|
|
17
|
+
*
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
export function toModuleDescriptor(module) {
|
|
21
|
+
return {
|
|
22
|
+
id: module.id,
|
|
23
|
+
label: module.label,
|
|
24
|
+
icon: module.icon,
|
|
25
|
+
context: module.context
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const update = {
|
|
2
|
+
version: '0.36.9',
|
|
3
|
+
date: '2026-07-02',
|
|
4
|
+
description: '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`.',
|
|
5
|
+
features: [
|
|
6
|
+
'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.'
|
|
7
|
+
],
|
|
8
|
+
fixes: [
|
|
9
|
+
'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.'
|
|
10
|
+
],
|
|
11
|
+
breakingChanges: []
|
|
12
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export const update = {
|
|
2
|
+
version: '0.37.0',
|
|
3
|
+
date: '2026-06-17',
|
|
4
|
+
description: '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`.',
|
|
5
|
+
features: [
|
|
6
|
+
'`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.',
|
|
7
|
+
'`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).',
|
|
8
|
+
'`moduleSchema` w `cms.schema.ts` — walidacja Zod modułów (unikalny `id`, wymagane icon/sections, `surfacedCollections`/`surfacedSingles` muszą referować zadeklarowane kolekcje/single).',
|
|
9
|
+
'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).',
|
|
10
|
+
'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`.',
|
|
11
|
+
'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).',
|
|
12
|
+
'`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).',
|
|
13
|
+
'`defineBooking(config): CMSModule` (`includio-cms/booking`, `@public`) — moduł rezerwacji. Config: `currency`, `catalogCollection` (surfaced), `depositAmount`, `pricing` (rabaty), `payment`, `adminEmail`.',
|
|
14
|
+
'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.',
|
|
15
|
+
'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.',
|
|
16
|
+
'`includio-cms/booking` + `includio-cms/db-postgres/schema-booking` — nowe entry points w `package.json` exports.',
|
|
17
|
+
'Admin: lista Rezerwacje (`/admin/booking/reservations`) + remote `listBookings`/`getBookingEnabled`.',
|
|
18
|
+
'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`).',
|
|
19
|
+
'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.',
|
|
20
|
+
'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).',
|
|
21
|
+
'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.',
|
|
22
|
+
'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`).',
|
|
23
|
+
'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.',
|
|
24
|
+
'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`).',
|
|
25
|
+
'`includio-cms/booking/client` (SDK + `useBooking`) i `includio-cms/booking/server` (serwisy + HTTP handlery, node-only — kod serwerowy poza bundlem klienta) — nowe entry points.',
|
|
26
|
+
'`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`.',
|
|
27
|
+
'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).',
|
|
28
|
+
'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`.',
|
|
29
|
+
'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).',
|
|
30
|
+
'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`.',
|
|
31
|
+
'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).',
|
|
32
|
+
'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`.',
|
|
33
|
+
'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`.',
|
|
34
|
+
'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.',
|
|
35
|
+
'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.',
|
|
36
|
+
'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.',
|
|
37
|
+
'`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.',
|
|
38
|
+
'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.',
|
|
39
|
+
'`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.',
|
|
40
|
+
'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.'
|
|
41
|
+
],
|
|
42
|
+
fixes: [
|
|
43
|
+
'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.',
|
|
44
|
+
'Ś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`.'
|
|
45
|
+
],
|
|
46
|
+
breakingChanges: [
|
|
47
|
+
'`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.',
|
|
48
|
+
'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.',
|
|
49
|
+
'`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: [...] } })`.'
|
|
50
|
+
],
|
|
51
|
+
notes: '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.'
|
|
52
|
+
};
|
package/dist/updates/index.js
CHANGED
|
@@ -74,6 +74,8 @@ import { update as update0364 } from './0.36.4/index.js';
|
|
|
74
74
|
import { update as update0365 } from './0.36.5/index.js';
|
|
75
75
|
import { update as update0367 } from './0.36.7/index.js';
|
|
76
76
|
import { update as update0368 } from './0.36.8/index.js';
|
|
77
|
+
import { update as update0369 } from './0.36.9/index.js';
|
|
78
|
+
import { update as update0370 } from './0.37.0/index.js';
|
|
77
79
|
export const updates = [
|
|
78
80
|
update0065,
|
|
79
81
|
update0066,
|
|
@@ -150,7 +152,9 @@ export const updates = [
|
|
|
150
152
|
update0364,
|
|
151
153
|
update0365,
|
|
152
154
|
update0367,
|
|
153
|
-
update0368
|
|
155
|
+
update0368,
|
|
156
|
+
update0369,
|
|
157
|
+
update0370
|
|
154
158
|
];
|
|
155
159
|
export const getUpdatesFrom = (fromVersion) => {
|
|
156
160
|
const fromParts = fromVersion.split('.').map(Number);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "includio-cms",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.37.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev": "vite dev",
|
|
6
6
|
"build": "vite build && npm run prepack",
|
|
@@ -111,6 +111,10 @@
|
|
|
111
111
|
"types": "./dist/db-postgres/schema-shop.d.ts",
|
|
112
112
|
"node": "./dist/db-postgres/schema-shop.js"
|
|
113
113
|
},
|
|
114
|
+
"./db-postgres/schema-booking": {
|
|
115
|
+
"types": "./dist/db-postgres/schema-booking.d.ts",
|
|
116
|
+
"node": "./dist/db-postgres/schema-booking.js"
|
|
117
|
+
},
|
|
114
118
|
"./auth-schema": {
|
|
115
119
|
"types": "./dist/server/db/schema/auth-schema.d.ts",
|
|
116
120
|
"node": "./dist/server/db/schema/auth-schema.js"
|
|
@@ -129,6 +133,20 @@
|
|
|
129
133
|
"types": "./dist/shop/http/index.d.ts",
|
|
130
134
|
"node": "./dist/shop/http/index.js"
|
|
131
135
|
},
|
|
136
|
+
"./booking": {
|
|
137
|
+
"types": "./dist/booking/index.d.ts",
|
|
138
|
+
"svelte": "./dist/booking/index.js",
|
|
139
|
+
"node": "./dist/booking/index.js"
|
|
140
|
+
},
|
|
141
|
+
"./booking/client": {
|
|
142
|
+
"types": "./dist/booking/client/index.d.ts",
|
|
143
|
+
"svelte": "./dist/booking/client/index.js",
|
|
144
|
+
"node": "./dist/booking/client/index.js"
|
|
145
|
+
},
|
|
146
|
+
"./booking/server": {
|
|
147
|
+
"types": "./dist/booking/server/index.d.ts",
|
|
148
|
+
"node": "./dist/booking/server/index.js"
|
|
149
|
+
},
|
|
132
150
|
"./files-local": {
|
|
133
151
|
"types": "./dist/files-local/index.d.ts",
|
|
134
152
|
"node": "./dist/files-local/index.js"
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
|
|
3
|
-
import { sidebarLang } from './lang.js';
|
|
4
|
-
import { getRemotes } from '../../../sveltekit/index.js';
|
|
5
|
-
import PackageIcon from '@tabler/icons-svelte/icons/package';
|
|
6
|
-
import ShoppingCartIcon from '@tabler/icons-svelte/icons/shopping-cart';
|
|
7
|
-
import TruckIcon from '@tabler/icons-svelte/icons/truck';
|
|
8
|
-
import TicketIcon from '@tabler/icons-svelte/icons/ticket';
|
|
9
|
-
import BuildingStoreIcon from '@tabler/icons-svelte/icons/building-store';
|
|
10
|
-
import { page } from '$app/state';
|
|
11
|
-
import NavSection, { type NavSectionItem } from './nav-section.svelte';
|
|
12
|
-
|
|
13
|
-
const interfaceLanguage = useInterfaceLanguage();
|
|
14
|
-
const lang = $derived(sidebarLang[interfaceLanguage.current].shop);
|
|
15
|
-
const remotes = getRemotes();
|
|
16
|
-
const enabledQuery = $derived(remotes.getShopEnabled());
|
|
17
|
-
|
|
18
|
-
function isActive(url: string) {
|
|
19
|
-
const pathname = page.url.pathname;
|
|
20
|
-
return pathname === url || pathname.startsWith(url + '/');
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const items: NavSectionItem[] = $derived([
|
|
24
|
-
{ title: lang.products, url: '/admin/shop/products', icon: PackageIcon },
|
|
25
|
-
{ title: lang.orders, url: '/admin/shop/orders', icon: ShoppingCartIcon },
|
|
26
|
-
{ title: lang.shipping, url: '/admin/shop/shipping-methods', icon: TruckIcon },
|
|
27
|
-
{ title: lang.coupons, url: '/admin/shop/coupons', icon: TicketIcon }
|
|
28
|
-
]);
|
|
29
|
-
</script>
|
|
30
|
-
|
|
31
|
-
{#if enabledQuery.ready && enabledQuery.current}
|
|
32
|
-
<NavSection {items} label={lang.title} labelIcon={BuildingStoreIcon} {isActive} withTopBorder />
|
|
33
|
-
{/if}
|