includio-cms 0.36.9 → 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.
Files changed (243) hide show
  1. package/API.md +178 -3
  2. package/CHANGELOG.md +54 -0
  3. package/DOCS.md +28 -3
  4. package/ROADMAP.md +18 -0
  5. package/dist/admin/client/booking/booking-dashboard.svelte +40 -0
  6. package/dist/admin/client/booking/booking-dashboard.svelte.d.ts +3 -0
  7. package/dist/admin/client/booking/customer-panel.svelte +102 -0
  8. package/dist/admin/client/booking/customer-panel.svelte.d.ts +11 -0
  9. package/dist/admin/client/booking/customer-view.d.ts +52 -0
  10. package/dist/admin/client/booking/customer-view.js +134 -0
  11. package/dist/admin/client/booking/participant-data-panel.svelte +330 -0
  12. package/dist/admin/client/booking/participant-data-panel.svelte.d.ts +22 -0
  13. package/dist/admin/client/booking/reservation-detail-page.svelte +637 -0
  14. package/dist/admin/client/booking/reservation-detail-page.svelte.d.ts +3 -0
  15. package/dist/admin/client/booking/reservations-page.svelte +221 -0
  16. package/dist/admin/client/booking/reservations-page.svelte.d.ts +3 -0
  17. package/dist/admin/client/collection/collection-entries.svelte +1 -1
  18. package/dist/admin/client/collection/entry-link.svelte +6 -4
  19. package/dist/admin/client/collection/entry-link.svelte.d.ts +3 -1
  20. package/dist/admin/client/collection/status-badge.svelte +39 -3
  21. package/dist/admin/client/collection/status-badge.svelte.d.ts +5 -3
  22. package/dist/admin/client/entry/entry.svelte +26 -9
  23. package/dist/admin/client/entry/hybrid/hybrid-preview.svelte +73 -10
  24. package/dist/admin/client/entry/hybrid/hybrid-preview.svelte.d.ts +6 -5
  25. package/dist/admin/client/entry/preview-views-context.svelte.d.ts +22 -0
  26. package/dist/admin/client/entry/preview-views-context.svelte.js +58 -0
  27. package/dist/admin/client/entry/preview-views.d.ts +27 -0
  28. package/dist/admin/client/entry/preview-views.js +33 -0
  29. package/dist/admin/client/index.d.ts +3 -0
  30. package/dist/admin/client/index.js +3 -0
  31. package/dist/admin/client/modules/dashboard-registry.d.ts +7 -0
  32. package/dist/admin/client/modules/dashboard-registry.js +11 -0
  33. package/dist/admin/client/modules/module-dashboard-page.svelte +26 -0
  34. package/dist/admin/client/modules/module-dashboard-page.svelte.d.ts +6 -0
  35. package/dist/admin/client/modules/stat-card.svelte +22 -0
  36. package/dist/admin/client/modules/stat-card.svelte.d.ts +10 -0
  37. package/dist/admin/client/shop/shop-dashboard.svelte +29 -0
  38. package/dist/admin/client/shop/shop-dashboard.svelte.d.ts +3 -0
  39. package/dist/admin/components/fields/relation-field.svelte +11 -2
  40. package/dist/admin/components/icons/icon-map.js +8 -0
  41. package/dist/admin/components/layout/app-sidebar.svelte +45 -14
  42. package/dist/admin/components/layout/context-switcher.svelte +90 -0
  43. package/dist/admin/components/layout/context-switcher.svelte.d.ts +3 -0
  44. package/dist/admin/components/layout/lang.d.ts +4 -0
  45. package/dist/admin/components/layout/lang.js +8 -0
  46. package/dist/admin/components/layout/layout-renderer.svelte +2 -1
  47. package/dist/admin/components/layout/layout-tabs.svelte +14 -0
  48. package/dist/admin/components/layout/layout-tabs.svelte.d.ts +2 -0
  49. package/dist/admin/components/layout/nav-collections.svelte +16 -9
  50. package/dist/admin/components/layout/nav-collections.svelte.d.ts +5 -1
  51. package/dist/admin/components/layout/nav-global.svelte +45 -0
  52. package/dist/admin/components/layout/nav-global.svelte.d.ts +3 -0
  53. package/dist/admin/components/layout/nav-main.svelte +8 -32
  54. package/dist/admin/components/layout/nav-main.svelte.d.ts +6 -1
  55. package/dist/admin/components/layout/nav-module.svelte +57 -0
  56. package/dist/admin/components/layout/nav-module.svelte.d.ts +7 -0
  57. package/dist/admin/components/layout/nav-section.svelte +1 -1
  58. package/dist/admin/components/layout/nav-section.svelte.d.ts +1 -1
  59. package/dist/admin/components/layout/nav-singletons.svelte +14 -7
  60. package/dist/admin/components/layout/nav-singletons.svelte.d.ts +5 -1
  61. package/dist/admin/remote/booking.remote.d.ts +244 -0
  62. package/dist/admin/remote/booking.remote.js +283 -0
  63. package/dist/admin/remote/index.d.ts +2 -0
  64. package/dist/admin/remote/index.js +2 -0
  65. package/dist/admin/remote/modules.remote.d.ts +10 -0
  66. package/dist/admin/remote/modules.remote.js +14 -0
  67. package/dist/admin/state/active-context-resolve.d.ts +37 -0
  68. package/dist/admin/state/active-context-resolve.js +66 -0
  69. package/dist/admin/state/active-context.svelte.d.ts +8 -0
  70. package/dist/admin/state/active-context.svelte.js +27 -0
  71. package/dist/booking/adjustments.d.ts +33 -0
  72. package/dist/booking/adjustments.js +26 -0
  73. package/dist/booking/capacity.d.ts +12 -0
  74. package/dist/booking/capacity.js +10 -0
  75. package/dist/booking/client/index.d.ts +39 -0
  76. package/dist/booking/client/index.js +44 -0
  77. package/dist/booking/client/use-booking.svelte.d.ts +25 -0
  78. package/dist/booking/client/use-booking.svelte.js +56 -0
  79. package/dist/booking/config.d.ts +156 -0
  80. package/dist/booking/config.js +36 -0
  81. package/dist/booking/draft.d.ts +77 -0
  82. package/dist/booking/draft.js +67 -0
  83. package/dist/booking/expiry-logic.d.ts +30 -0
  84. package/dist/booking/expiry-logic.js +33 -0
  85. package/dist/booking/index.d.ts +18 -0
  86. package/dist/booking/index.js +52 -0
  87. package/dist/booking/ledger.d.ts +46 -0
  88. package/dist/booking/ledger.js +60 -0
  89. package/dist/booking/number.d.ts +2 -0
  90. package/dist/booking/number.js +11 -0
  91. package/dist/booking/participant-fields/access.d.ts +10 -0
  92. package/dist/booking/participant-fields/access.js +14 -0
  93. package/dist/booking/participant-fields/age.d.ts +12 -0
  94. package/dist/booking/participant-fields/age.js +28 -0
  95. package/dist/booking/participant-fields/completeness.d.ts +8 -0
  96. package/dist/booking/participant-fields/completeness.js +13 -0
  97. package/dist/booking/participant-fields/group.d.ts +6 -0
  98. package/dist/booking/participant-fields/group.js +15 -0
  99. package/dist/booking/participant-fields/index.d.ts +6 -0
  100. package/dist/booking/participant-fields/index.js +6 -0
  101. package/dist/booking/participant-fields/types.d.ts +50 -0
  102. package/dist/booking/participant-fields/types.js +5 -0
  103. package/dist/booking/participant-fields/validate.d.ts +7 -0
  104. package/dist/booking/participant-fields/validate.js +44 -0
  105. package/dist/booking/participant-pricing.d.ts +93 -0
  106. package/dist/booking/participant-pricing.js +91 -0
  107. package/dist/booking/participants-view.d.ts +32 -0
  108. package/dist/booking/participants-view.js +22 -0
  109. package/dist/booking/payment-context.d.ts +19 -0
  110. package/dist/booking/payment-context.js +29 -0
  111. package/dist/booking/pricing-inputs.d.ts +28 -0
  112. package/dist/booking/pricing-inputs.js +35 -0
  113. package/dist/booking/pricing.d.ts +86 -0
  114. package/dist/booking/pricing.js +125 -0
  115. package/dist/booking/recompute.d.ts +22 -0
  116. package/dist/booking/recompute.js +31 -0
  117. package/dist/booking/reminders-schedule.d.ts +11 -0
  118. package/dist/booking/reminders-schedule.js +28 -0
  119. package/dist/booking/server/adjustments.d.ts +27 -0
  120. package/dist/booking/server/adjustments.js +136 -0
  121. package/dist/booking/server/bookings.d.ts +45 -0
  122. package/dist/booking/server/bookings.js +288 -0
  123. package/dist/booking/server/catalog.d.ts +9 -0
  124. package/dist/booking/server/catalog.js +20 -0
  125. package/dist/booking/server/db.d.ts +7 -0
  126. package/dist/booking/server/db.js +18 -0
  127. package/dist/booking/server/email.d.ts +23 -0
  128. package/dist/booking/server/email.js +59 -0
  129. package/dist/booking/server/emailTemplateRegistry.d.ts +29 -0
  130. package/dist/booking/server/emailTemplateRegistry.js +125 -0
  131. package/dist/booking/server/http/create-handler.d.ts +5 -0
  132. package/dist/booking/server/http/create-handler.js +68 -0
  133. package/dist/booking/server/http/index.d.ts +4 -0
  134. package/dist/booking/server/http/index.js +4 -0
  135. package/dist/booking/server/http/maintenance-handler.d.ts +9 -0
  136. package/dist/booking/server/http/maintenance-handler.js +36 -0
  137. package/dist/booking/server/http/portal-handler.d.ts +13 -0
  138. package/dist/booking/server/http/portal-handler.js +99 -0
  139. package/dist/booking/server/http/webhook-handler.d.ts +9 -0
  140. package/dist/booking/server/http/webhook-handler.js +39 -0
  141. package/dist/booking/server/index.d.ts +12 -0
  142. package/dist/booking/server/index.js +14 -0
  143. package/dist/booking/server/maintenance.d.ts +28 -0
  144. package/dist/booking/server/maintenance.js +134 -0
  145. package/dist/booking/server/participants.d.ts +26 -0
  146. package/dist/booking/server/participants.js +92 -0
  147. package/dist/booking/server/payments.d.ts +34 -0
  148. package/dist/booking/server/payments.js +207 -0
  149. package/dist/booking/server/portal-session.d.ts +16 -0
  150. package/dist/booking/server/portal-session.js +42 -0
  151. package/dist/booking/server/portal.d.ts +207 -0
  152. package/dist/booking/server/portal.js +234 -0
  153. package/dist/booking/server/refunds.d.ts +7 -0
  154. package/dist/booking/server/refunds.js +58 -0
  155. package/dist/booking/server/reminders.d.ts +9 -0
  156. package/dist/booking/server/reminders.js +24 -0
  157. package/dist/booking/server/validation.d.ts +17 -0
  158. package/dist/booking/server/validation.js +55 -0
  159. package/dist/booking/state-machine.d.ts +41 -0
  160. package/dist/booking/state-machine.js +73 -0
  161. package/dist/booking/templates/_partials/footer.en.html +4 -0
  162. package/dist/booking/templates/_partials/footer.pl.html +4 -0
  163. package/dist/booking/templates/_partials/header.en.html +4 -0
  164. package/dist/booking/templates/_partials/header.pl.html +4 -0
  165. package/dist/booking/templates/balance-due.en.html +10 -0
  166. package/dist/booking/templates/balance-due.pl.html +10 -0
  167. package/dist/booking/templates/balance-overdue-cancelled.en.html +5 -0
  168. package/dist/booking/templates/balance-overdue-cancelled.pl.html +5 -0
  169. package/dist/booking/templates/booking-received.en.html +9 -0
  170. package/dist/booking/templates/booking-received.pl.html +9 -0
  171. package/dist/booking/templates/deposit-paid.en.html +6 -0
  172. package/dist/booking/templates/deposit-paid.pl.html +6 -0
  173. package/dist/booking/templates/payment-link.en.html +5 -0
  174. package/dist/booking/templates/payment-link.pl.html +5 -0
  175. package/dist/booking/templates/payment-received.en.html +10 -0
  176. package/dist/booking/templates/payment-received.pl.html +10 -0
  177. package/dist/booking/totals.d.ts +38 -0
  178. package/dist/booking/totals.js +61 -0
  179. package/dist/booking/webhook-logic.d.ts +28 -0
  180. package/dist/booking/webhook-logic.js +50 -0
  181. package/dist/cli/create-user.d.ts +7 -1
  182. package/dist/cli/create-user.js +23 -15
  183. package/dist/cli/index.js +55 -7
  184. package/dist/cli/scaffold/admin.d.ts +6 -0
  185. package/dist/cli/scaffold/admin.js +5 -3
  186. package/dist/cli/scaffold/booking.d.ts +12 -0
  187. package/dist/cli/scaffold/booking.js +103 -0
  188. package/dist/core/cms.d.ts +24 -9
  189. package/dist/core/cms.js +72 -34
  190. package/dist/core/config/validatePreviews.d.ts +12 -0
  191. package/dist/core/config/validatePreviews.js +90 -0
  192. package/dist/core/fields/slugPath.d.ts +9 -1
  193. package/dist/core/fields/slugPath.js +16 -2
  194. package/dist/core/server/fields/resolveRelationFields.d.ts +11 -2
  195. package/dist/core/server/fields/resolveRelationFields.js +12 -3
  196. package/dist/core/server/generator/generator.js +7 -2
  197. package/dist/db-postgres/schema/booking/bookingAdjustments.d.ts +186 -0
  198. package/dist/db-postgres/schema/booking/bookingAdjustments.js +22 -0
  199. package/dist/db-postgres/schema/booking/bookingItemPersons.d.ts +117 -0
  200. package/dist/db-postgres/schema/booking/bookingItemPersons.js +22 -0
  201. package/dist/db-postgres/schema/booking/bookingItems.d.ts +181 -0
  202. package/dist/db-postgres/schema/booking/bookingItems.js +22 -0
  203. package/dist/db-postgres/schema/booking/bookingPayments.d.ts +204 -0
  204. package/dist/db-postgres/schema/booking/bookingPayments.js +25 -0
  205. package/dist/db-postgres/schema/booking/bookingPersons.d.ts +99 -0
  206. package/dist/db-postgres/schema/booking/bookingPersons.js +17 -0
  207. package/dist/db-postgres/schema/booking/bookingReminders.d.ts +131 -0
  208. package/dist/db-postgres/schema/booking/bookingReminders.js +18 -0
  209. package/dist/db-postgres/schema/booking/bookings.d.ts +307 -0
  210. package/dist/db-postgres/schema/booking/bookings.js +40 -0
  211. package/dist/db-postgres/schema/booking/index.d.ts +7 -0
  212. package/dist/db-postgres/schema/booking/index.js +7 -0
  213. package/dist/db-postgres/schema/index.d.ts +1 -0
  214. package/dist/db-postgres/schema/index.js +1 -0
  215. package/dist/db-postgres/schema-booking.d.ts +1 -0
  216. package/dist/db-postgres/schema-booking.js +1 -0
  217. package/dist/server/security/rate-limit-handler.d.ts +19 -0
  218. package/dist/server/security/rate-limit-handler.js +34 -0
  219. package/dist/shop/adapters/payu/client.js +3 -1
  220. package/dist/shop/adapters/payu/index.js +37 -17
  221. package/dist/shop/adapters/payu/payload.d.ts +6 -0
  222. package/dist/shop/adapters/payu/payload.js +1 -1
  223. package/dist/shop/adapters/stripe/index.js +36 -21
  224. package/dist/shop/index.d.ts +11 -2
  225. package/dist/shop/index.js +43 -1
  226. package/dist/shop/rate-limit.d.ts +1 -9
  227. package/dist/shop/rate-limit.js +3 -28
  228. package/dist/shop/types.d.ts +19 -0
  229. package/dist/sveltekit/config.d.ts +4 -0
  230. package/dist/sveltekit/config.js +6 -0
  231. package/dist/types/cms.d.ts +15 -1
  232. package/dist/types/cms.schema.d.ts +96 -2
  233. package/dist/types/cms.schema.js +84 -1
  234. package/dist/types/config.d.ts +33 -0
  235. package/dist/types/layout.d.ts +6 -0
  236. package/dist/types/modules.d.ts +133 -0
  237. package/dist/types/modules.js +27 -0
  238. package/dist/updates/0.37.0/index.d.ts +2 -0
  239. package/dist/updates/0.37.0/index.js +52 -0
  240. package/dist/updates/index.js +3 -1
  241. package/package.json +19 -1
  242. package/dist/admin/components/layout/nav-shop.svelte +0 -33
  243. package/dist/admin/components/layout/nav-shop.svelte.d.ts +0 -3
@@ -1,10 +1,43 @@
1
1
  import type { Field } from './fields.js';
2
2
  import type { IconName } from '../admin/components/icons/icon-map.js';
3
3
  import type { Layout } from './layout.js';
4
+ import type { Localized } from './languages.js';
5
+ /**
6
+ * A named preview target. The same entry is often rendered in more than one way
7
+ * on the front end — a full page and a teaser card in a listing — and each way
8
+ * is a view.
9
+ *
10
+ * The admin loads `{url}?preview={entryId}&view={name}` in the preview iframe,
11
+ * so a project may expose one route per view, or a single route that branches
12
+ * on the `view` query param. Views do not change what is fetched from the
13
+ * database — the entry always arrives whole.
14
+ *
15
+ * @public
16
+ * @example
17
+ * ```ts
18
+ * previews: [
19
+ * { name: 'full', label: { pl: 'Pełny wpis' }, url: '/preview/blog-post' },
20
+ * { name: 'teaser', label: { pl: 'Zajawka' }, url: '/preview/blog-post/teaser' }
21
+ * ]
22
+ * ```
23
+ */
24
+ export interface PreviewView {
25
+ /** Stable identifier, referenced by `TabNode.preview`. */
26
+ name: string;
27
+ /** Switcher label. Defaults to `name`. */
28
+ label?: Localized;
29
+ /** Preview route, e.g. '/preview/blog-post/teaser'. */
30
+ url: string;
31
+ /** Start view. Defaults to the first entry of the array. */
32
+ default?: boolean;
33
+ }
4
34
  export interface ConfigBase {
5
35
  sidebarIcon?: IconName;
6
36
  slug: string;
37
+ /** Shorthand for a single preview view. Mutually exclusive with `previews`. */
7
38
  previewUrl?: string;
39
+ /** Named preview views. Mutually exclusive with `previewUrl`. */
40
+ previews?: PreviewView[];
8
41
  fields: Field[];
9
42
  layout?: Layout;
10
43
  slugField?: string;
@@ -81,6 +81,12 @@ export interface TabsNode extends LayoutNodeBase {
81
81
  export interface TabNode extends LayoutNodeBase {
82
82
  type: 'tab';
83
83
  label: Localized;
84
+ /**
85
+ * Name of a view from `previews[]`. Entering this tab switches the preview to
86
+ * that view, unless the user manually picked another view while on this tab.
87
+ * A tab without `preview` leaves the current view alone.
88
+ */
89
+ preview?: string;
84
90
  fields?: string[];
85
91
  children?: LayoutNode[];
86
92
  }
@@ -0,0 +1,133 @@
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
+ /** A label that is either a plain string or a `{ lang: text }` map. */
15
+ export type LocalizedText = string | Record<string, string>;
16
+ /**
17
+ * One sidebar entry contributed by a module's context. Icons are referenced
18
+ * by **name** (resolved client-side via the admin icon-map), never as a
19
+ * component, so the descriptor stays serializable and userland never needs an
20
+ * icon library as a dependency.
21
+ *
22
+ * @public
23
+ */
24
+ export interface ModuleNavSection {
25
+ /** Stable key for keyed rendering and active-state checks. */
26
+ key: string;
27
+ /** Display title. */
28
+ title: LocalizedText;
29
+ /** Target route, e.g. `/admin/shop/orders`. */
30
+ url: string;
31
+ /** Icon name from the admin icon-map, e.g. `shopping-cart`. */
32
+ icon: string;
33
+ /**
34
+ * Optional remote-query name returning a `number`, rendered as a badge and
35
+ * resolved reactively on the client (same pattern as collection entry
36
+ * counts). Omit for sections without a count.
37
+ */
38
+ countSource?: string;
39
+ }
40
+ /**
41
+ * The curated workspace a module contributes: a landing (dashboard) target,
42
+ * its own nav sections, and optional **surfaced** core collections/singles
43
+ * pulled into the module's context (e.g. shop surfaces the `products`
44
+ * collection as "Products").
45
+ *
46
+ * @public
47
+ */
48
+ export interface ModuleContext {
49
+ /** Switcher label for this context. Defaults to the module's `label`. */
50
+ contextLabel?: LocalizedText;
51
+ /** Where selecting this context navigates, e.g. `/admin/shop`. */
52
+ landingUrl: string;
53
+ /** Static nav sections owned by the module. */
54
+ sections: ModuleNavSection[];
55
+ /** Slugs of core collections surfaced inside this context. */
56
+ surfacedCollections?: string[];
57
+ /** Slugs of core singles surfaced inside this context. */
58
+ surfacedSingles?: string[];
59
+ }
60
+ /** Context passed to a module's `serverHooks.init`. */
61
+ export interface ModuleInitContext {
62
+ /** Raw drizzle handle (`databaseAdapter._drizzle`), or `undefined`. */
63
+ drizzle: unknown;
64
+ /** The module's own resolved config (same reference as `CMSModule.config`). */
65
+ config: unknown;
66
+ /** The CMS default language code (first configured language). */
67
+ defaultLanguage: string;
68
+ }
69
+ /**
70
+ * Server-only module hooks. NEVER serialized or sent to the admin client —
71
+ * stripped from the descriptor returned by `getModules()`.
72
+ *
73
+ * @public
74
+ */
75
+ export interface ModuleServerHooks {
76
+ /**
77
+ * Idempotent boot-time init run by `initCMS` (e.g. create indexes,
78
+ * smoke-test templates). Non-blocking: errors are logged, not thrown.
79
+ *
80
+ * Define this ONLY in a server-only module. A module whose factory (e.g.
81
+ * `defineBooking`) is re-exported from a client-safe barrel MUST NOT inline a
82
+ * server import here — bundlers create a chunk for it and break browser builds.
83
+ * Use {@link initModule} instead.
84
+ */
85
+ init?: (ctx: ModuleInitContext) => Promise<void> | void;
86
+ /**
87
+ * Bare package specifier of a SERVER-ONLY module exporting `serverInit(ctx)`,
88
+ * run by `initCMS` at boot. Prefer this over {@link init} when the module's
89
+ * factory lives in a client-safe barrel: it is a plain string (no import), so
90
+ * the client bundle stays free of server code. `initCMS` (server-only) resolves
91
+ * and imports it at runtime from node_modules. Ignored if {@link init} is set.
92
+ */
93
+ initModule?: string;
94
+ }
95
+ /**
96
+ * A CMS module ("overlay"): shop, booking, etc. Register via
97
+ * `defineConfig({ modules: [defineShop(...), defineBooking(...)] })`.
98
+ *
99
+ * @public
100
+ */
101
+ export interface CMSModule {
102
+ /** Unique slug, e.g. `shop` | `booking`. */
103
+ id: string;
104
+ /** Display label (switcher + sidebar group label). */
105
+ label: LocalizedText;
106
+ /** Icon name from the admin icon-map, e.g. `building-store`. */
107
+ icon: string;
108
+ /** The curated workspace this module contributes. */
109
+ context: ModuleContext;
110
+ /** The module's typed resolved config — opaque to the framework. */
111
+ config?: unknown;
112
+ /** Server-only hooks (not part of the serialized descriptor). */
113
+ serverHooks?: ModuleServerHooks;
114
+ }
115
+ /**
116
+ * The serializable subset of a {@link CMSModule} sent to the admin client.
117
+ * Excludes `config` (may hold adapter functions) and `serverHooks`.
118
+ *
119
+ * @public
120
+ */
121
+ export interface CMSModuleDescriptor {
122
+ id: string;
123
+ label: LocalizedText;
124
+ icon: string;
125
+ context: ModuleContext;
126
+ }
127
+ /**
128
+ * Strips a {@link CMSModule} down to its serializable {@link CMSModuleDescriptor}
129
+ * for transport to the admin client. Drops `config` and `serverHooks`.
130
+ *
131
+ * @public
132
+ */
133
+ export declare function toModuleDescriptor(module: CMSModule): CMSModuleDescriptor;
@@ -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,2 @@
1
+ import type { CmsUpdate } from '../index.js';
2
+ export declare const update: CmsUpdate;
@@ -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
+ };
@@ -75,6 +75,7 @@ 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
77
  import { update as update0369 } from './0.36.9/index.js';
78
+ import { update as update0370 } from './0.37.0/index.js';
78
79
  export const updates = [
79
80
  update0065,
80
81
  update0066,
@@ -152,7 +153,8 @@ export const updates = [
152
153
  update0365,
153
154
  update0367,
154
155
  update0368,
155
- update0369
156
+ update0369,
157
+ update0370
156
158
  ];
157
159
  export const getUpdatesFrom = (fromVersion) => {
158
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.36.9",
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}
@@ -1,3 +0,0 @@
1
- declare const NavShop: import("svelte").Component<Record<string, never>, {}, "">;
2
- type NavShop = ReturnType<typeof NavShop>;
3
- export default NavShop;