includio-cms 0.25.0 → 0.26.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 (349) hide show
  1. package/API.md +57 -4
  2. package/CHANGELOG.md +53 -0
  3. package/DOCS.md +1 -1
  4. package/README.md +2 -0
  5. package/ROADMAP.md +6 -0
  6. package/dist/admin/client/account/lang.d.ts +1 -0
  7. package/dist/admin/client/account/lang.js +4 -2
  8. package/dist/admin/client/account/profile-section.svelte +2 -2
  9. package/dist/admin/client/account/security-section.svelte +27 -4
  10. package/dist/admin/client/account/sessions-section.svelte +1 -1
  11. package/dist/admin/client/admin/admin-after-login-layout-content.svelte +1 -1
  12. package/dist/admin/client/admin/dashboard-page.svelte +34 -10
  13. package/dist/admin/client/collection/bulk-actions-bar.svelte +86 -44
  14. package/dist/admin/client/collection/bulk-actions-bar.svelte.d.ts +3 -1
  15. package/dist/admin/client/collection/collection-entries.svelte +52 -36
  16. package/dist/admin/client/collection/collection-entries.svelte.d.ts +3 -0
  17. package/dist/admin/client/collection/collection.svelte +28 -14
  18. package/dist/admin/client/collection/collection.svelte.d.ts +3 -0
  19. package/dist/admin/client/collection/data-table.svelte +279 -130
  20. package/dist/admin/client/collection/data-table.svelte.d.ts +11 -0
  21. package/dist/admin/client/collection/date-cell.svelte +4 -4
  22. package/dist/admin/client/collection/row-actions.svelte +2 -1
  23. package/dist/admin/client/collection/sortable-header.svelte +33 -9
  24. package/dist/admin/client/collection/state-display.svelte +102 -0
  25. package/dist/admin/client/collection/state-display.svelte.d.ts +12 -0
  26. package/dist/admin/client/collection/status-badge.svelte +99 -11
  27. package/dist/admin/client/collection/status-badge.svelte.d.ts +15 -1
  28. package/dist/admin/client/collection/table-pagination.svelte +21 -6
  29. package/dist/admin/client/collection/table-toolbar.svelte +105 -80
  30. package/dist/admin/client/collection/table-toolbar.svelte.d.ts +11 -8
  31. package/dist/admin/client/entry/entry-form.svelte +36 -11
  32. package/dist/admin/client/entry/entry-form.svelte.d.ts +1 -0
  33. package/dist/admin/client/entry/entry-header.svelte +22 -15
  34. package/dist/admin/client/entry/entry-header.svelte.d.ts +1 -0
  35. package/dist/admin/client/entry/entry.svelte +269 -165
  36. package/dist/admin/client/entry/header/a11y-header-badge.svelte +47 -0
  37. package/dist/admin/client/entry/header/a11y-header-badge.svelte.d.ts +8 -0
  38. package/dist/admin/client/entry/header/publish-panel.svelte +69 -13
  39. package/dist/admin/client/entry/header/save-indicator.svelte +57 -28
  40. package/dist/admin/client/entry/header/save-indicator.svelte.d.ts +1 -0
  41. package/dist/admin/client/entry/header/status-badge.svelte +60 -15
  42. package/dist/admin/client/entry/header/status-badge.svelte.d.ts +1 -2
  43. package/dist/admin/client/entry/header/version-history-sheet.svelte +1 -1
  44. package/dist/admin/client/entry/hybrid/hybrid-layout.svelte +74 -23
  45. package/dist/admin/client/entry/hybrid/hybrid-preview.svelte +1 -1
  46. package/dist/admin/client/entry/utils.d.ts +14 -0
  47. package/dist/admin/client/entry/utils.js +28 -0
  48. package/dist/admin/client/form/form-submission/form-submission.svelte +2 -2
  49. package/dist/admin/client/form/form-submissions.svelte +143 -194
  50. package/dist/admin/client/form/form-submissions.svelte.d.ts +2 -0
  51. package/dist/admin/client/login/lang.d.ts +3 -0
  52. package/dist/admin/client/login/lang.js +10 -4
  53. package/dist/admin/client/login/login-form.svelte +8 -1
  54. package/dist/admin/client/login/reset-password-page.svelte +24 -3
  55. package/dist/admin/client/login/schema.d.ts +14 -2
  56. package/dist/admin/client/login/schema.js +19 -8
  57. package/dist/admin/client/maintenance/maintenance-page.svelte +16 -17
  58. package/dist/admin/client/media/media-page.svelte +1 -1
  59. package/dist/admin/client/shop/coupon-edit-page.svelte +117 -13
  60. package/dist/admin/client/shop/coupon-form.svelte +282 -138
  61. package/dist/admin/client/shop/coupon-form.svelte.d.ts +1 -9
  62. package/dist/admin/client/shop/coupon-new-page.svelte +40 -10
  63. package/dist/admin/client/shop/coupon-new-page.svelte.d.ts +2 -17
  64. package/dist/admin/client/shop/coupon-schema.d.ts +28 -0
  65. package/dist/admin/client/shop/coupon-schema.js +53 -0
  66. package/dist/admin/client/shop/coupons-list-page.svelte +262 -118
  67. package/dist/admin/client/shop/coupons-list-page.svelte.d.ts +16 -1
  68. package/dist/admin/client/shop/shipping-method-edit-page.svelte +108 -59
  69. package/dist/admin/client/shop/shipping-method-form.svelte +36 -9
  70. package/dist/admin/client/shop/shipping-method-new-page.svelte +44 -13
  71. package/dist/admin/client/shop/shipping-methods-list-page.svelte +101 -59
  72. package/dist/admin/client/shop/shop-order-detail-page.svelte +113 -84
  73. package/dist/admin/client/shop/shop-orders-list-page.svelte +302 -152
  74. package/dist/admin/client/shop/shop-orders-list-page.svelte.d.ts +18 -1
  75. package/dist/admin/client/shop/shop-products-list-page.svelte +355 -118
  76. package/dist/admin/client/shop/shop-products-list-page.svelte.d.ts +19 -1
  77. package/dist/admin/client/users/accept-invite-page.svelte +24 -3
  78. package/dist/admin/client/users/create-user-dialog.svelte +3 -8
  79. package/dist/admin/client/users/lang.d.ts +2 -0
  80. package/dist/admin/client/users/lang.js +4 -0
  81. package/dist/admin/client/users/pending-invitations.svelte +2 -9
  82. package/dist/admin/client/users/user-name-cell.svelte +20 -0
  83. package/dist/admin/client/users/user-name-cell.svelte.d.ts +9 -0
  84. package/dist/admin/client/users/user-role-badge.svelte +16 -0
  85. package/dist/admin/client/users/user-role-badge.svelte.d.ts +7 -0
  86. package/dist/admin/client/users/user-row-actions.svelte +72 -0
  87. package/dist/admin/client/users/user-row-actions.svelte.d.ts +20 -0
  88. package/dist/admin/client/users/user-sessions-sheet.svelte +2 -11
  89. package/dist/admin/client/users/users-page.svelte +283 -497
  90. package/dist/admin/client/users/users-page.svelte.d.ts +12 -1
  91. package/dist/admin/components/dashboard/form-submissions-widget.svelte +59 -74
  92. package/dist/admin/components/dashboard/recent-activity.svelte +17 -5
  93. package/dist/admin/components/dashboard/recent-entries.svelte +19 -7
  94. package/dist/admin/components/dialogs/confirmation-dialog.svelte +105 -0
  95. package/dist/admin/components/dialogs/confirmation-dialog.svelte.d.ts +13 -0
  96. package/dist/admin/components/fields/block-picker-modal.svelte +6 -0
  97. package/dist/admin/components/fields/blocks-field.svelte +46 -1
  98. package/dist/admin/components/fields/boolean-field.svelte +1 -1
  99. package/dist/admin/components/fields/field-renderer.svelte +23 -21
  100. package/dist/admin/components/fields/file-field.svelte +344 -30
  101. package/dist/admin/components/fields/media-field.svelte +16 -2
  102. package/dist/admin/components/fields/radio-field.svelte +22 -0
  103. package/dist/admin/components/fields/relation-field.svelte +123 -97
  104. package/dist/admin/components/fields/relation-picker-dialog.svelte +2 -2
  105. package/dist/admin/components/fields/seo-field.svelte +60 -30
  106. package/dist/admin/components/fields/shop-field.svelte +9 -4
  107. package/dist/admin/components/fields/simple-array-field.svelte +321 -151
  108. package/dist/admin/components/fields/simple-array-field.svelte.d.ts +3 -0
  109. package/dist/admin/components/fields/slug-field.svelte +146 -21
  110. package/dist/admin/components/fields/text-field-wrapper.svelte +37 -20
  111. package/dist/admin/components/fields/text-field.svelte +7 -2
  112. package/dist/admin/components/fields/url-field-wrapper.svelte +10 -0
  113. package/dist/admin/components/fields/url-field.svelte +36 -23
  114. package/dist/admin/components/forms/form-error-summary.svelte +143 -0
  115. package/dist/admin/components/forms/form-error-summary.svelte.d.ts +27 -0
  116. package/dist/admin/components/layout/app-sidebar.svelte +7 -2
  117. package/dist/admin/components/layout/detail-page-shell.svelte +71 -0
  118. package/dist/admin/components/layout/detail-page-shell.svelte.d.ts +24 -0
  119. package/dist/admin/components/layout/lang.d.ts +5 -0
  120. package/dist/admin/components/layout/lang.js +10 -0
  121. package/dist/admin/components/layout/layout-renderer.svelte +71 -2
  122. package/dist/admin/components/layout/layout-renderer.svelte.d.ts +1 -0
  123. package/dist/admin/components/layout/layout-tabs.svelte +172 -0
  124. package/dist/admin/components/layout/layout-tabs.svelte.d.ts +24 -0
  125. package/dist/admin/components/layout/nav-breadcrumbs.svelte +25 -7
  126. package/dist/admin/components/layout/nav-collections.svelte +23 -36
  127. package/dist/admin/components/layout/nav-forms.svelte +19 -35
  128. package/dist/admin/components/layout/nav-main.svelte +3 -28
  129. package/dist/admin/components/layout/nav-search.svelte +70 -2
  130. package/dist/admin/components/layout/nav-section.svelte +77 -0
  131. package/dist/admin/components/layout/nav-section.svelte.d.ts +22 -0
  132. package/dist/admin/components/layout/nav-shop.svelte +3 -27
  133. package/dist/admin/components/layout/nav-singletons.svelte +16 -28
  134. package/dist/admin/components/layout/page-header.stories.svelte +93 -0
  135. package/dist/admin/components/layout/page-header.stories.svelte.d.ts +27 -0
  136. package/dist/admin/components/layout/page-header.svelte +68 -0
  137. package/dist/admin/components/layout/page-header.svelte.d.ts +17 -0
  138. package/dist/admin/components/layout/site-header.svelte +9 -0
  139. package/dist/admin/components/layout/site-header.svelte.d.ts +2 -17
  140. package/dist/admin/components/media/file/file-name-input.svelte +6 -2
  141. package/dist/admin/components/media/file/file-preview.svelte +130 -17
  142. package/dist/admin/components/media/file-upload.svelte +16 -7
  143. package/dist/admin/components/media/file-upload.svelte.d.ts +1 -0
  144. package/dist/admin/components/media/files-list.svelte +153 -53
  145. package/dist/admin/components/media/files-list.svelte.d.ts +1 -0
  146. package/dist/admin/components/media/media-library.svelte +577 -198
  147. package/dist/admin/components/media/media-library.svelte.d.ts +4 -0
  148. package/dist/admin/components/media/media-selector.svelte +4 -2
  149. package/dist/admin/components/media/media-selector.svelte.d.ts +1 -0
  150. package/dist/admin/components/media/tag-sidebar.svelte +4 -4
  151. package/dist/admin/components/tiptap/FigureNodeView.svelte +10 -0
  152. package/dist/admin/components/tiptap/bubble-menu.svelte +104 -0
  153. package/dist/admin/components/tiptap/bubble-menu.svelte.d.ts +19 -0
  154. package/dist/admin/components/tiptap/content-editor.svelte +28 -24
  155. package/dist/admin/components/tiptap/editor-toolbar.svelte +7 -7
  156. package/dist/admin/components/tiptap/extensions.js +5 -1
  157. package/dist/admin/components/tiptap/image-dialog.svelte +5 -1
  158. package/dist/admin/components/tiptap/link-dialog.svelte +2 -0
  159. package/dist/admin/components/tiptap/tiptap-editor.svelte +18 -20
  160. package/dist/admin/components/tiptap/video-dialog.svelte +1 -1
  161. package/dist/admin/i18n/errors.d.ts +140 -0
  162. package/dist/admin/i18n/errors.js +151 -0
  163. package/dist/admin/remote/entry.remote.d.ts +59 -4
  164. package/dist/admin/remote/entry.remote.js +239 -62
  165. package/dist/admin/remote/shop.remote.d.ts +37 -32
  166. package/dist/admin/remote/shop.remote.js +9 -2
  167. package/dist/admin/shared/password-generate.d.ts +6 -0
  168. package/dist/admin/shared/password-generate.js +40 -0
  169. package/dist/admin/shared/password-schema.d.ts +6 -0
  170. package/dist/admin/shared/password-schema.js +10 -3
  171. package/dist/admin/styles/admin.css +23 -6
  172. package/dist/admin/styles/tokens.md +244 -0
  173. package/dist/admin/utils/accordionActivation.d.ts +13 -0
  174. package/dist/admin/utils/accordionActivation.js +35 -0
  175. package/dist/admin/utils/entryLabel.d.ts +23 -0
  176. package/dist/admin/utils/entryLabel.js +51 -12
  177. package/dist/admin/utils/field-a11y.d.ts +29 -0
  178. package/dist/admin/utils/field-a11y.js +23 -0
  179. package/dist/admin/utils/fieldPathElement.d.ts +9 -0
  180. package/dist/admin/utils/fieldPathElement.js +18 -0
  181. package/dist/admin/utils/fileDisplay.d.ts +10 -0
  182. package/dist/admin/utils/fileDisplay.js +26 -0
  183. package/dist/admin/utils/flattenFormErrors.d.ts +19 -0
  184. package/dist/admin/utils/flattenFormErrors.js +102 -0
  185. package/dist/admin/utils/formatters.d.ts +12 -0
  186. package/dist/admin/utils/{formatDate.js → formatters.js} +23 -2
  187. package/dist/admin/utils/scrollWithin.d.ts +9 -0
  188. package/dist/admin/utils/scrollWithin.js +32 -0
  189. package/dist/admin/utils/tabActivation.d.ts +12 -0
  190. package/dist/admin/utils/tabActivation.js +24 -0
  191. package/dist/cms/runtime/schema.d.ts +1 -0
  192. package/dist/cms/runtime/schema.js +1 -0
  193. package/dist/cms/runtime/types.d.ts +80 -7
  194. package/dist/components/ui/accordion/accordion-content.svelte +17 -3
  195. package/dist/components/ui/accordion/accordion.stories.svelte +21 -1
  196. package/dist/components/ui/alert/alert.stories.svelte +14 -0
  197. package/dist/components/ui/alert-dialog/alert-dialog.stories.svelte +45 -0
  198. package/dist/components/ui/alert-dialog/alert-dialog.stories.svelte.d.ts +27 -0
  199. package/dist/components/ui/avatar/avatar.stories.svelte +27 -0
  200. package/dist/components/ui/badge/badge.stories.svelte +15 -0
  201. package/dist/components/ui/breadcrumb/breadcrumb.stories.svelte +47 -0
  202. package/dist/components/ui/breadcrumb/breadcrumb.svelte +1 -1
  203. package/dist/components/ui/button/button.stories.svelte +53 -6
  204. package/dist/components/ui/button/button.svelte +39 -5
  205. package/dist/components/ui/button/button.svelte.d.ts +4 -0
  206. package/dist/components/ui/button-group/button-group.stories.svelte +44 -0
  207. package/dist/components/ui/button-group/button-group.stories.svelte.d.ts +27 -0
  208. package/dist/components/ui/calendar/calendar.stories.svelte +36 -0
  209. package/dist/components/ui/calendar/calendar.stories.svelte.d.ts +27 -0
  210. package/dist/components/ui/card/card.stories.svelte +7 -0
  211. package/dist/components/ui/carousel/carousel.stories.svelte +43 -0
  212. package/dist/components/ui/carousel/carousel.stories.svelte.d.ts +27 -0
  213. package/dist/components/ui/checkbox/checkbox.stories.svelte +67 -0
  214. package/dist/components/ui/checkbox/checkbox.stories.svelte.d.ts +27 -0
  215. package/dist/components/ui/checkbox/checkbox.svelte +3 -3
  216. package/dist/components/ui/command/command.stories.svelte +18 -0
  217. package/dist/components/ui/data-table/data-table.stories.svelte +61 -0
  218. package/dist/components/ui/data-table/data-table.stories.svelte.d.ts +18 -0
  219. package/dist/components/ui/dialog/dialog-content.svelte +5 -0
  220. package/dist/components/ui/dialog/dialog-content.svelte.d.ts +2 -0
  221. package/dist/components/ui/dialog/dialog.stories.svelte +35 -0
  222. package/dist/components/ui/dropdown-menu/dropdown-menu.stories.svelte +74 -0
  223. package/dist/components/ui/dropdown-menu/dropdown-menu.stories.svelte.d.ts +27 -0
  224. package/dist/components/ui/field/field-context.svelte.d.ts +22 -0
  225. package/dist/components/ui/field/field-context.svelte.js +9 -0
  226. package/dist/components/ui/field/field-control.svelte +18 -0
  227. package/dist/components/ui/field/field-control.svelte.d.ts +8 -0
  228. package/dist/components/ui/field/field-description.svelte +12 -0
  229. package/dist/components/ui/field/field-error.svelte +14 -6
  230. package/dist/components/ui/field/field-label.svelte +10 -0
  231. package/dist/components/ui/field/field.stories.svelte +95 -9
  232. package/dist/components/ui/field/field.svelte +57 -0
  233. package/dist/components/ui/field/field.svelte.d.ts +2 -0
  234. package/dist/components/ui/field/index.d.ts +3 -1
  235. package/dist/components/ui/field/index.js +4 -2
  236. package/dist/components/ui/form/form-field-errors.svelte +1 -1
  237. package/dist/components/ui/form/form.stories.svelte +25 -0
  238. package/dist/components/ui/form/form.stories.svelte.d.ts +26 -0
  239. package/dist/components/ui/input/input.stories.svelte +26 -0
  240. package/dist/components/ui/input-group/input-group-input.svelte.d.ts +1 -1
  241. package/dist/components/ui/input-group/input-group.stories.svelte +43 -0
  242. package/dist/components/ui/input-group/input-group.stories.svelte.d.ts +27 -0
  243. package/dist/components/ui/item/item.stories.svelte +61 -0
  244. package/dist/components/ui/item/item.stories.svelte.d.ts +27 -0
  245. package/dist/components/ui/label/label.stories.svelte +7 -0
  246. package/dist/components/ui/live-region/index.d.ts +1 -0
  247. package/dist/components/ui/live-region/index.js +1 -0
  248. package/dist/components/ui/live-region/live-region-demo.svelte +32 -0
  249. package/dist/components/ui/live-region/live-region-demo.svelte.d.ts +7 -0
  250. package/dist/components/ui/live-region/live-region.stories.svelte +23 -0
  251. package/dist/components/ui/live-region/live-region.stories.svelte.d.ts +26 -0
  252. package/dist/components/ui/live-region/live-region.svelte +12 -0
  253. package/dist/components/ui/live-region/live-region.svelte.d.ts +8 -0
  254. package/dist/components/ui/popover/popover.stories.svelte +34 -0
  255. package/dist/components/ui/radio-group/radio-group.stories.svelte +58 -0
  256. package/dist/components/ui/radio-group/radio-group.stories.svelte.d.ts +27 -0
  257. package/dist/components/ui/resizable/resizable.stories.svelte +56 -0
  258. package/dist/components/ui/resizable/resizable.stories.svelte.d.ts +27 -0
  259. package/dist/components/ui/select/select.stories.svelte +49 -0
  260. package/dist/components/ui/separator/separator.stories.svelte +18 -0
  261. package/dist/components/ui/sheet/sheet.stories.svelte +34 -0
  262. package/dist/components/ui/sidebar/sidebar-input.svelte.d.ts +1 -1
  263. package/dist/components/ui/sidebar/sidebar-menu-button.svelte +1 -0
  264. package/dist/components/ui/sidebar/sidebar-trigger.svelte +1 -1
  265. package/dist/components/ui/sidebar/sidebar.stories.svelte +72 -0
  266. package/dist/components/ui/sidebar/sidebar.stories.svelte.d.ts +27 -0
  267. package/dist/components/ui/skeleton/skeleton.stories.svelte +39 -0
  268. package/dist/components/ui/skeleton/skeleton.stories.svelte.d.ts +27 -0
  269. package/dist/components/ui/skeleton/skeleton.svelte +6 -0
  270. package/dist/components/ui/sonner/index.d.ts +1 -1
  271. package/dist/components/ui/sonner/index.js +1 -1
  272. package/dist/components/ui/sonner/sonner.stories.svelte +7 -0
  273. package/dist/components/ui/sonner/sonner.svelte +17 -1
  274. package/dist/components/ui/sonner/sonner.svelte.d.ts +6 -0
  275. package/dist/components/ui/spinner/spinner.stories.svelte +30 -0
  276. package/dist/components/ui/spinner/spinner.stories.svelte.d.ts +27 -0
  277. package/dist/components/ui/switch/switch.stories.svelte +56 -0
  278. package/dist/components/ui/switch/switch.stories.svelte.d.ts +27 -0
  279. package/dist/components/ui/table/table-cell.svelte +1 -1
  280. package/dist/components/ui/table/table-head.svelte +1 -1
  281. package/dist/components/ui/table/table.stories.svelte +68 -0
  282. package/dist/components/ui/table/table.stories.svelte.d.ts +27 -0
  283. package/dist/components/ui/table/table.svelte +1 -1
  284. package/dist/components/ui/tabs/tabs.stories.svelte +48 -0
  285. package/dist/components/ui/tabs/tabs.stories.svelte.d.ts +27 -0
  286. package/dist/components/ui/textarea/textarea.stories.svelte +21 -0
  287. package/dist/components/ui/toggle/toggle.stories.svelte +23 -0
  288. package/dist/components/ui/toggle-group/toggle-group.stories.svelte +43 -0
  289. package/dist/components/ui/tooltip/tooltip.stories.svelte +46 -6
  290. package/dist/core/fields/fieldSchemaToTs.d.ts +7 -0
  291. package/dist/core/fields/fieldSchemaToTs.js +234 -90
  292. package/dist/core/fields/layoutUtils.d.ts +4 -1
  293. package/dist/core/fields/layoutUtils.js +41 -4
  294. package/dist/core/fields/resolveSeo.d.ts +70 -0
  295. package/dist/core/fields/resolveSeo.js +88 -0
  296. package/dist/core/fields/seoFieldDescriptor.d.ts +43 -0
  297. package/dist/core/fields/seoFieldDescriptor.js +74 -0
  298. package/dist/core/fields/slugPath.d.ts +13 -0
  299. package/dist/core/fields/slugPath.js +32 -0
  300. package/dist/core/fields/urlUtils.d.ts +8 -0
  301. package/dist/core/fields/urlUtils.js +27 -0
  302. package/dist/core/index.d.ts +1 -0
  303. package/dist/core/index.js +1 -0
  304. package/dist/core/server/entries/operations/create.js +13 -0
  305. package/dist/core/server/entries/operations/get.d.ts +7 -0
  306. package/dist/core/server/entries/operations/get.js +10 -6
  307. package/dist/core/server/entries/operations/slugUniqueness.d.ts +37 -0
  308. package/dist/core/server/entries/operations/slugUniqueness.js +116 -0
  309. package/dist/core/server/entries/operations/update.d.ts +6 -1
  310. package/dist/core/server/entries/operations/update.js +24 -1
  311. package/dist/core/server/fields/slugResolver.d.ts +3 -13
  312. package/dist/core/server/fields/slugResolver.js +8 -37
  313. package/dist/core/server/generator/fields.js +10 -17
  314. package/dist/core/server/generator/formFields.js +2 -1
  315. package/dist/core/server/generator/generator.js +4 -4
  316. package/dist/core/server/generator/utils.d.ts +1 -0
  317. package/dist/core/server/generator/utils.js +4 -0
  318. package/dist/paraglide/messages/_index.d.ts +3 -36
  319. package/dist/paraglide/messages/_index.js +3 -71
  320. package/dist/paraglide/messages/hello_world.d.ts +5 -0
  321. package/dist/paraglide/messages/hello_world.js +33 -0
  322. package/dist/paraglide/messages/login_hello.d.ts +16 -0
  323. package/dist/paraglide/messages/login_hello.js +34 -0
  324. package/dist/paraglide/messages/login_please_login.d.ts +16 -0
  325. package/dist/paraglide/messages/login_please_login.js +34 -0
  326. package/dist/shop/server/orders.d.ts +1 -0
  327. package/dist/shop/server/orders.js +14 -0
  328. package/dist/shop/server/shop-data.d.ts +2 -0
  329. package/dist/shop/server/shop-data.js +20 -5
  330. package/dist/sveltekit/server/handle.js +17 -0
  331. package/dist/types/cms.schema.js +4 -2
  332. package/dist/types/fields.d.ts +35 -0
  333. package/dist/types/index.d.ts +1 -1
  334. package/dist/types/layout.d.ts +35 -2
  335. package/dist/updates/0.26.0/index.d.ts +2 -0
  336. package/dist/updates/0.26.0/index.js +51 -0
  337. package/dist/updates/index.js +3 -1
  338. package/package.json +29 -7
  339. package/dist/admin/client/collection/empty-state.svelte +0 -28
  340. package/dist/admin/client/collection/empty-state.svelte.d.ts +0 -9
  341. package/dist/admin/client/form/submission-status-badge.svelte +0 -41
  342. package/dist/admin/client/form/submission-status-badge.svelte.d.ts +0 -7
  343. package/dist/admin/components/media/file-preview.svelte +0 -51
  344. package/dist/admin/components/media/file-preview.svelte.d.ts +0 -6
  345. package/dist/admin/utils/formatDate.d.ts +0 -5
  346. package/dist/paraglide/messages/en.d.ts +0 -5
  347. package/dist/paraglide/messages/en.js +0 -14
  348. package/dist/paraglide/messages/pl.d.ts +0 -5
  349. package/dist/paraglide/messages/pl.js +0 -14
@@ -1,17 +1,16 @@
1
1
  <script lang="ts">
2
+ import { defaults, superForm } from 'sveltekit-superforms';
3
+ import { zod4, zod4Client } from 'sveltekit-superforms/adapters';
4
+ import * as Form from '../../../components/ui/form/index.js';
2
5
  import { Input } from '../../../components/ui/input/index.js';
3
6
  import { Button } from '../../../components/ui/button/index.js';
4
- import Label from '../../../components/ui/label/label.svelte';
5
-
6
- type CouponInput = {
7
- code: string;
8
- type: 'percent' | 'fixed';
9
- value: number;
10
- minOrderAmount: number | null;
11
- maxUses: number | null;
12
- expiresAt: string | null;
13
- isActive: boolean;
14
- };
7
+ import { Switch } from '../../../components/ui/switch/index.js';
8
+ import FormErrorSummary, {
9
+ type FormErrorEntry
10
+ } from '../../components/forms/form-error-summary.svelte';
11
+ import { createCouponSchema, defaultCoupon, type CouponInput } from './coupon-schema.js';
12
+ import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
13
+ import type { InterfaceLanguage } from '../../../types/languages.js';
15
14
 
16
15
  type Props = {
17
16
  initial?: Partial<CouponInput>;
@@ -20,150 +19,295 @@
20
19
  onCancel?: () => void;
21
20
  };
22
21
 
23
- let { initial, submitLabel = 'Zapisz', onSubmit, onCancel }: Props = $props();
22
+ let { initial, submitLabel, onSubmit, onCancel }: Props = $props();
24
23
 
25
- let code = $state(initial?.code ?? '');
26
- let type = $state<'percent' | 'fixed'>(initial?.type ?? 'percent');
27
- let value = $state(initial?.value != null ? String(initial.value) : '');
28
- let minOrderAmountPln = $state(
29
- initial?.minOrderAmount != null ? (initial.minOrderAmount / 100).toFixed(2) : ''
30
- );
31
- let maxUses = $state(initial?.maxUses != null ? String(initial.maxUses) : '');
32
- let expiresAt = $state(initial?.expiresAt ? initial.expiresAt.slice(0, 10) : '');
33
- let isActive = $state(initial?.isActive ?? true);
34
-
35
- let submitting = $state(false);
36
- let error = $state<string | null>(null);
37
-
38
- async function handleSubmit(e: Event) {
39
- e.preventDefault();
40
- error = null;
41
- const numValue = Number(value.replace(',', '.'));
42
- if (!Number.isFinite(numValue) || numValue <= 0) {
43
- error = 'Podaj wartość większą od zera.';
44
- return;
45
- }
46
- if (type === 'percent' && numValue > 100) {
47
- error = 'Procent nie może przekraczać 100.';
48
- return;
24
+ const interfaceLanguage = useInterfaceLanguage();
25
+
26
+ const lang: Record<
27
+ InterfaceLanguage,
28
+ {
29
+ code: string;
30
+ codeHint: string;
31
+ codePlaceholder: string;
32
+ discountType: string;
33
+ discountTypePercent: string;
34
+ discountTypeFixed: string;
35
+ value: string;
36
+ valuePercent: string;
37
+ valueFixed: string;
38
+ valuePercentPlaceholder: string;
39
+ valueFixedPlaceholder: string;
40
+ conditionsSection: string;
41
+ minOrder: string;
42
+ minOrderHint: string;
43
+ minOrderPlaceholder: string;
44
+ maxUses: string;
45
+ maxUsesPlaceholder: string;
46
+ expiresAt: string;
47
+ expiresHint: string;
48
+ statusSection: string;
49
+ isActive: string;
50
+ isActiveHint: string;
51
+ save: string;
52
+ saving: string;
53
+ cancel: string;
49
54
  }
50
- const minOrderCents = minOrderAmountPln
51
- ? Math.round(Number(minOrderAmountPln.replace(',', '.')) * 100)
52
- : null;
53
- if (minOrderCents != null && (!Number.isFinite(minOrderCents) || minOrderCents < 0)) {
54
- error = 'Minimalna wartość zamówienia musi być nieujemna.';
55
- return;
55
+ > = {
56
+ pl: {
57
+ code: 'Kod',
58
+ codeHint: 'Litery, cyfry, „_”, „-”. Wielkość liter zostanie ujednolicona do dużych.',
59
+ codePlaceholder: 'np. ARIA10',
60
+ discountType: 'Typ rabatu',
61
+ discountTypePercent: 'Procent (% od kwoty netto)',
62
+ discountTypeFixed: 'Kwota stała (PLN)',
63
+ value: 'Wartość',
64
+ valuePercent: 'Procent (0–100)',
65
+ valueFixed: 'Kwota (PLN)',
66
+ valuePercentPlaceholder: 'np. 10',
67
+ valueFixedPlaceholder: 'np. 50,00',
68
+ conditionsSection: 'Warunki',
69
+ minOrder: 'Min. wartość zamówienia (PLN)',
70
+ minOrderHint: 'Zostaw puste, jeśli rabat nie ma minimum.',
71
+ minOrderPlaceholder: 'opcjonalnie',
72
+ maxUses: 'Maks. liczba użyć',
73
+ maxUsesPlaceholder: 'bez limitu',
74
+ expiresAt: 'Data wygaśnięcia',
75
+ expiresHint: 'Zostaw puste, jeśli kod nie ma terminu.',
76
+ statusSection: 'Status',
77
+ isActive: 'Aktywny',
78
+ isActiveHint: 'Tylko aktywne kody działają w koszyku.',
79
+ save: 'Zapisz',
80
+ saving: 'Zapisuję…',
81
+ cancel: 'Anuluj'
82
+ },
83
+ en: {
84
+ code: 'Code',
85
+ codeHint: 'Letters, digits, "_", "-". Case will be normalized to uppercase.',
86
+ codePlaceholder: 'e.g. ARIA10',
87
+ discountType: 'Discount type',
88
+ discountTypePercent: 'Percent (% off net amount)',
89
+ discountTypeFixed: 'Fixed amount (PLN)',
90
+ value: 'Value',
91
+ valuePercent: 'Percent (0–100)',
92
+ valueFixed: 'Amount (PLN)',
93
+ valuePercentPlaceholder: 'e.g. 10',
94
+ valueFixedPlaceholder: 'e.g. 50.00',
95
+ conditionsSection: 'Conditions',
96
+ minOrder: 'Min. order amount (PLN)',
97
+ minOrderHint: 'Leave empty if there is no minimum.',
98
+ minOrderPlaceholder: 'optional',
99
+ maxUses: 'Max uses',
100
+ maxUsesPlaceholder: 'no limit',
101
+ expiresAt: 'Expiry date',
102
+ expiresHint: 'Leave empty if the code does not expire.',
103
+ statusSection: 'Status',
104
+ isActive: 'Active',
105
+ isActiveHint: 'Only active codes work at checkout.',
106
+ save: 'Save',
107
+ saving: 'Saving…',
108
+ cancel: 'Cancel'
56
109
  }
57
- const maxUsesNum = maxUses ? Number(maxUses) : null;
58
- if (maxUsesNum != null && (!Number.isInteger(maxUsesNum) || maxUsesNum <= 0)) {
59
- error = 'Maksymalna liczba użyć musi być dodatnią liczbą całkowitą.';
60
- return;
110
+ };
111
+
112
+ const t = $derived(lang[interfaceLanguage.current]);
113
+
114
+ const initialData: CouponInput = {
115
+ ...defaultCoupon,
116
+ ...initial
117
+ };
118
+
119
+ const schema = createCouponSchema(interfaceLanguage.current);
120
+
121
+ const form = superForm(defaults(initialData, zod4(schema)), {
122
+ validators: zod4Client(schema),
123
+ SPA: true,
124
+ resetForm: false,
125
+ onUpdate: async ({ form }) => {
126
+ if (form.valid) {
127
+ await onSubmit({
128
+ ...form.data,
129
+ code: form.data.code.trim().toUpperCase()
130
+ });
131
+ }
61
132
  }
133
+ });
62
134
 
63
- submitting = true;
64
- try {
65
- await onSubmit({
66
- code: code.trim().toUpperCase(),
67
- type,
68
- value: numValue,
69
- minOrderAmount: minOrderCents,
70
- maxUses: maxUsesNum,
71
- expiresAt: expiresAt ? new Date(expiresAt).toISOString() : null,
72
- isActive
73
- });
74
- } catch (err) {
75
- error = err instanceof Error ? err.message : 'Nie udało się zapisać.';
76
- submitting = false;
135
+ const { form: formData, errors, enhance, submitting } = form;
136
+
137
+ const summaryErrors = $derived.by<FormErrorEntry[]>(() => {
138
+ const list: FormErrorEntry[] = [];
139
+ const e = $errors as Record<string, string[] | undefined>;
140
+ const labels: Record<string, string> = {
141
+ code: t.code,
142
+ type: t.discountType,
143
+ value: t.value,
144
+ minOrderAmount: t.minOrder,
145
+ maxUses: t.maxUses,
146
+ expiresAt: t.expiresAt,
147
+ isActive: t.isActive
148
+ };
149
+ for (const [key, msgs] of Object.entries(e)) {
150
+ if (!msgs || !Array.isArray(msgs)) continue;
151
+ for (const message of msgs) {
152
+ list.push({ path: key, label: labels[key] ?? key, message });
153
+ }
77
154
  }
78
- }
155
+ return list;
156
+ });
157
+
158
+ let valueInput = $state(initialData.value === 0 ? '' : String(initialData.value));
159
+ let minOrderPlnInput = $state(
160
+ initialData.minOrderAmount != null ? (initialData.minOrderAmount / 100).toFixed(2) : ''
161
+ );
162
+ let maxUsesInput = $state(initialData.maxUses != null ? String(initialData.maxUses) : '');
163
+ let expiresInput = $state(initialData.expiresAt ? initialData.expiresAt.slice(0, 10) : '');
164
+
165
+ $effect(() => {
166
+ const num = Number(valueInput.replace(',', '.'));
167
+ $formData.value = Number.isFinite(num) ? num : 0;
168
+ });
169
+
170
+ $effect(() => {
171
+ const num = minOrderPlnInput ? Number(minOrderPlnInput.replace(',', '.')) : null;
172
+ $formData.minOrderAmount = num != null && Number.isFinite(num) ? Math.round(num * 100) : null;
173
+ });
174
+
175
+ $effect(() => {
176
+ const num = maxUsesInput ? Number(maxUsesInput) : null;
177
+ $formData.maxUses = num != null && Number.isInteger(num) ? num : null;
178
+ });
179
+
180
+ $effect(() => {
181
+ $formData.expiresAt = expiresInput ? new Date(expiresInput).toISOString() : null;
182
+ });
79
183
  </script>
80
184
 
81
- <form onsubmit={handleSubmit} class="space-y-5">
82
- <div class="space-y-2">
83
- <Label for="coupon-code">Kod</Label>
84
- <Input
85
- id="coupon-code"
86
- bind:value={code}
87
- placeholder="np. ARIA10"
88
- required
89
- pattern="[A-Za-z0-9_-]+"
90
- maxlength={64}
91
- aria-describedby="coupon-code-hint"
92
- />
93
- <p id="coupon-code-hint" class="text-muted-foreground text-xs">
94
- Wielkość liter zostanie ujednolicona do dużych liter. Tylko litery, cyfry, „_”, „-”.
95
- </p>
96
- </div>
185
+ {#snippet sectionHeader(title: string)}
186
+ <h2 class="text-lg font-bold">{title}</h2>
187
+ {/snippet}
97
188
 
98
- <fieldset class="space-y-2">
99
- <legend class="mb-1 text-sm font-semibold">Typ rabatu</legend>
100
- <label class="flex items-center gap-2 text-sm">
101
- <input type="radio" name="coupon-type" value="percent" bind:group={type} />
102
- <span>Procent (% od kwoty netto)</span>
103
- </label>
104
- <label class="flex items-center gap-2 text-sm">
105
- <input type="radio" name="coupon-type" value="fixed" bind:group={type} />
106
- <span>Kwota stała (PLN)</span>
107
- </label>
108
- </fieldset>
109
-
110
- <div class="space-y-2">
111
- <Label for="coupon-value">{type === 'percent' ? 'Procent (0–100)' : 'Kwota (PLN)'}</Label>
112
- <Input
113
- id="coupon-value"
114
- type="text"
115
- inputmode="decimal"
116
- bind:value
117
- placeholder={type === 'percent' ? 'np. 10' : 'np. 50,00'}
118
- required
119
- />
120
- </div>
189
+ <form method="POST" use:enhance class="space-y-6">
190
+ <FormErrorSummary errors={summaryErrors} />
121
191
 
122
- <div class="grid grid-cols-2 gap-4">
123
- <div class="space-y-2">
124
- <Label for="coupon-min-order">Min. wartość zamówienia (PLN)</Label>
125
- <Input
126
- id="coupon-min-order"
127
- type="text"
128
- inputmode="decimal"
129
- bind:value={minOrderAmountPln}
130
- placeholder="opcjonalnie"
131
- />
132
- </div>
133
- <div class="space-y-2">
134
- <Label for="coupon-max-uses">Maks. liczba użyć</Label>
135
- <Input
136
- id="coupon-max-uses"
137
- type="number"
138
- min="1"
139
- step="1"
140
- bind:value={maxUses}
141
- placeholder="bez limitu"
142
- />
143
- </div>
144
- </div>
192
+ <section class="border-border bg-card space-y-4 rounded-xl border p-6">
193
+ {@render sectionHeader(t.code)}
194
+ <Form.Field name="code" {form}>
195
+ <Form.Control>
196
+ {#snippet children({ props })}
197
+ <Input
198
+ {...props}
199
+ bind:value={$formData.code}
200
+ placeholder={t.codePlaceholder}
201
+ maxlength={64}
202
+ />
203
+ {/snippet}
204
+ </Form.Control>
205
+ <Form.Description>{t.codeHint}</Form.Description>
206
+ <Form.FieldErrors />
207
+ </Form.Field>
208
+ </section>
145
209
 
146
- <div class="space-y-2">
147
- <Label for="coupon-expires-at">Data wygaśnięcia</Label>
148
- <Input id="coupon-expires-at" type="date" bind:value={expiresAt} />
149
- </div>
210
+ <section class="border-border bg-card space-y-4 rounded-xl border p-6">
211
+ {@render sectionHeader(t.discountType)}
212
+ <Form.Fieldset {form} name="type" class="space-y-2">
213
+ <label class="flex items-center gap-2 text-sm">
214
+ <input type="radio" name="coupon-type" value="percent" bind:group={$formData.type} />
215
+ <span>{t.discountTypePercent}</span>
216
+ </label>
217
+ <label class="flex items-center gap-2 text-sm">
218
+ <input type="radio" name="coupon-type" value="fixed" bind:group={$formData.type} />
219
+ <span>{t.discountTypeFixed}</span>
220
+ </label>
221
+ <Form.FieldErrors />
222
+ </Form.Fieldset>
150
223
 
151
- <label class="flex items-center gap-2 text-sm">
152
- <input type="checkbox" bind:checked={isActive} />
153
- <span>Aktywny (dostępny przy checkoucie)</span>
154
- </label>
224
+ <Form.ElementField name="value" {form}>
225
+ <Form.Control>
226
+ {#snippet children({ props })}
227
+ <Form.Label>
228
+ {$formData.type === 'percent' ? t.valuePercent : t.valueFixed}
229
+ </Form.Label>
230
+ <Input
231
+ {...props}
232
+ type="text"
233
+ inputmode="decimal"
234
+ bind:value={valueInput}
235
+ placeholder={$formData.type === 'percent'
236
+ ? t.valuePercentPlaceholder
237
+ : t.valueFixedPlaceholder}
238
+ />
239
+ {/snippet}
240
+ </Form.Control>
241
+ <Form.FieldErrors />
242
+ </Form.ElementField>
243
+ </section>
155
244
 
156
- {#if error}
157
- <p class="text-destructive text-sm" role="alert">{error}</p>
158
- {/if}
245
+ <section class="border-border bg-card space-y-4 rounded-xl border p-6">
246
+ {@render sectionHeader(t.conditionsSection)}
247
+ <div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
248
+ <Form.ElementField name="minOrderAmount" {form}>
249
+ <Form.Control>
250
+ {#snippet children({ props })}
251
+ <Form.Label>{t.minOrder}</Form.Label>
252
+ <Input
253
+ {...props}
254
+ type="text"
255
+ inputmode="decimal"
256
+ bind:value={minOrderPlnInput}
257
+ placeholder={t.minOrderPlaceholder}
258
+ />
259
+ {/snippet}
260
+ </Form.Control>
261
+ <Form.Description>{t.minOrderHint}</Form.Description>
262
+ <Form.FieldErrors />
263
+ </Form.ElementField>
264
+
265
+ <Form.ElementField name="maxUses" {form}>
266
+ <Form.Control>
267
+ {#snippet children({ props })}
268
+ <Form.Label>{t.maxUses}</Form.Label>
269
+ <Input
270
+ {...props}
271
+ type="number"
272
+ min="1"
273
+ step="1"
274
+ bind:value={maxUsesInput}
275
+ placeholder={t.maxUsesPlaceholder}
276
+ />
277
+ {/snippet}
278
+ </Form.Control>
279
+ <Form.FieldErrors />
280
+ </Form.ElementField>
281
+ </div>
282
+
283
+ <Form.ElementField name="expiresAt" {form}>
284
+ <Form.Control>
285
+ {#snippet children({ props })}
286
+ <Form.Label>{t.expiresAt}</Form.Label>
287
+ <Input {...props} type="date" bind:value={expiresInput} />
288
+ {/snippet}
289
+ </Form.Control>
290
+ <Form.Description>{t.expiresHint}</Form.Description>
291
+ <Form.FieldErrors />
292
+ </Form.ElementField>
293
+ </section>
294
+
295
+ <section class="border-border bg-card space-y-4 rounded-xl border p-6">
296
+ {@render sectionHeader(t.statusSection)}
297
+ <label class="flex items-center gap-2">
298
+ <Switch bind:checked={$formData.isActive} />
299
+ <span class="text-sm">{t.isActive}</span>
300
+ </label>
301
+ <p class="text-muted-foreground text-sm">{t.isActiveHint}</p>
302
+ </section>
159
303
 
160
304
  <div class="flex gap-2">
161
- <Button type="submit" disabled={submitting}>
162
- {submitting ? 'Zapisywanie…' : submitLabel}
305
+ <Button type="submit" disabled={$submitting}>
306
+ {$submitting ? t.saving : (submitLabel ?? t.save)}
163
307
  </Button>
164
308
  {#if onCancel}
165
- <Button type="button" variant="outline" onclick={onCancel} disabled={submitting}>
166
- Anuluj
309
+ <Button type="button" variant="outline" onclick={onCancel} disabled={$submitting}>
310
+ {t.cancel}
167
311
  </Button>
168
312
  {/if}
169
313
  </div>
@@ -1,12 +1,4 @@
1
- type CouponInput = {
2
- code: string;
3
- type: 'percent' | 'fixed';
4
- value: number;
5
- minOrderAmount: number | null;
6
- maxUses: number | null;
7
- expiresAt: string | null;
8
- isActive: boolean;
9
- };
1
+ import { type CouponInput } from './coupon-schema.js';
10
2
  type Props = {
11
3
  initial?: Partial<CouponInput>;
12
4
  submitLabel?: string;
@@ -1,25 +1,55 @@
1
1
  <script lang="ts">
2
2
  import { goto } from '$app/navigation';
3
3
  import { getRemotes } from '../../../sveltekit/index.js';
4
+ import { toast } from 'svelte-sonner';
4
5
  import CouponForm from './coupon-form.svelte';
6
+ import DetailPageShell from '../../components/layout/detail-page-shell.svelte';
7
+ import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
8
+ import { getBreadcrumbs } from '../../state/breadcrumbs.svelte.js';
9
+ import { sidebarLang } from '../../components/layout/lang.js';
10
+ import type { InterfaceLanguage } from '../../../types/languages.js';
5
11
 
6
12
  const remotes = getRemotes();
7
- </script>
13
+ const interfaceLanguage = useInterfaceLanguage();
14
+ const breadcrumbs = getBreadcrumbs();
15
+
16
+ const lang: Record<
17
+ InterfaceLanguage,
18
+ { title: string; description: string; submitLabel: string; createdToast: string }
19
+ > = {
20
+ pl: {
21
+ title: 'Nowy kod rabatowy',
22
+ description: 'Skonfiguruj rabat — procent lub kwotę stałą.',
23
+ submitLabel: 'Utwórz kod',
24
+ createdToast: 'Kod utworzony.'
25
+ },
26
+ en: {
27
+ title: 'New coupon',
28
+ description: 'Configure the discount — percentage or fixed amount.',
29
+ submitLabel: 'Create coupon',
30
+ createdToast: 'Coupon created.'
31
+ }
32
+ };
33
+ const t = $derived(lang[interfaceLanguage.current]);
8
34
 
9
- <div class="mx-auto max-w-2xl space-y-6 p-6">
10
- <header>
11
- <h1 class="text-2xl font-extrabold tracking-tight">Nowy kod rabatowy</h1>
12
- <p class="text-muted-foreground text-sm">
13
- <a href="/admin/shop/coupons" class="hover:underline">← Wróć do listy</a>
14
- </p>
15
- </header>
35
+ $effect(() => {
36
+ const s = sidebarLang[interfaceLanguage.current].shop;
37
+ breadcrumbs.state = [
38
+ { label: s.title },
39
+ { label: s.coupons, href: '/admin/shop/coupons' },
40
+ { label: t.title }
41
+ ];
42
+ });
43
+ </script>
16
44
 
45
+ <DetailPageShell title={t.title} description={t.description}>
17
46
  <CouponForm
18
- submitLabel="Utwórz kod"
47
+ submitLabel={t.submitLabel}
19
48
  onSubmit={async (input) => {
20
49
  await remotes.createCouponCmd(input);
50
+ toast.success(t.createdToast);
21
51
  await goto('/admin/shop/coupons');
22
52
  }}
23
53
  onCancel={() => goto('/admin/shop/coupons')}
24
54
  />
25
- </div>
55
+ </DetailPageShell>
@@ -1,18 +1,3 @@
1
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
- $$bindings?: Bindings;
4
- } & Exports;
5
- (internal: unknown, props: {
6
- $$events?: Events;
7
- $$slots?: Slots;
8
- }): Exports & {
9
- $set?: any;
10
- $on?: any;
11
- };
12
- z_$$bindings?: Bindings;
13
- }
14
- declare const CouponNewPage: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
- [evt: string]: CustomEvent<any>;
16
- }, {}, {}, string>;
17
- type CouponNewPage = InstanceType<typeof CouponNewPage>;
1
+ declare const CouponNewPage: import("svelte").Component<Record<string, never>, {}, "">;
2
+ type CouponNewPage = ReturnType<typeof CouponNewPage>;
18
3
  export default CouponNewPage;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @internal
3
+ * Zod schema for coupon edit form (superForm + formsnap, S8).
4
+ */
5
+ import { z } from 'zod';
6
+ import type { InterfaceLanguage } from '../../../types/languages.js';
7
+ export type CouponInput = {
8
+ code: string;
9
+ type: 'percent' | 'fixed';
10
+ value: number;
11
+ minOrderAmount: number | null;
12
+ maxUses: number | null;
13
+ expiresAt: string | null;
14
+ isActive: boolean;
15
+ };
16
+ export declare function createCouponSchema(lang?: InterfaceLanguage): z.ZodObject<{
17
+ code: z.ZodString;
18
+ type: z.ZodEnum<{
19
+ fixed: "fixed";
20
+ percent: "percent";
21
+ }>;
22
+ value: z.ZodNumber;
23
+ minOrderAmount: z.ZodNullable<z.ZodNumber>;
24
+ maxUses: z.ZodNullable<z.ZodNumber>;
25
+ expiresAt: z.ZodNullable<z.ZodString>;
26
+ isActive: z.ZodBoolean;
27
+ }, z.core.$strip>;
28
+ export declare const defaultCoupon: CouponInput;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @internal
3
+ * Zod schema for coupon edit form (superForm + formsnap, S8).
4
+ */
5
+ import { z } from 'zod';
6
+ const messages = {
7
+ pl: {
8
+ codeRequired: 'Wpisz kod, np. ARIA10.',
9
+ codeFormat: 'Kod może zawierać litery, cyfry, „_” i „-”.',
10
+ valuePositive: 'Podaj wartość większą od zera.',
11
+ percentRange: 'Procent nie może przekraczać 100.',
12
+ minOrderNonneg: 'Minimalna wartość zamówienia musi być nieujemna.',
13
+ maxUsesPositive: 'Maksymalna liczba użyć musi być dodatnia.'
14
+ },
15
+ en: {
16
+ codeRequired: 'Enter a code, e.g. ARIA10.',
17
+ codeFormat: 'Use letters, digits, "_" or "-" only.',
18
+ valuePositive: 'Enter a value greater than zero.',
19
+ percentRange: 'Percent cannot exceed 100.',
20
+ minOrderNonneg: 'Minimum order amount must be non-negative.',
21
+ maxUsesPositive: 'Maximum uses must be positive.'
22
+ }
23
+ };
24
+ export function createCouponSchema(lang = 'pl') {
25
+ const m = messages[lang];
26
+ return z
27
+ .object({
28
+ code: z
29
+ .string()
30
+ .min(1, m.codeRequired)
31
+ .max(64)
32
+ .regex(/^[A-Za-z0-9_-]+$/, m.codeFormat),
33
+ type: z.enum(['percent', 'fixed']),
34
+ value: z.number().positive(m.valuePositive),
35
+ minOrderAmount: z.number().int().nonnegative(m.minOrderNonneg).nullable(),
36
+ maxUses: z.number().int().positive(m.maxUsesPositive).nullable(),
37
+ expiresAt: z.string().nullable(),
38
+ isActive: z.boolean()
39
+ })
40
+ .refine((d) => !(d.type === 'percent' && d.value > 100), {
41
+ message: m.percentRange,
42
+ path: ['value']
43
+ });
44
+ }
45
+ export const defaultCoupon = {
46
+ code: '',
47
+ type: 'percent',
48
+ value: 10,
49
+ minOrderAmount: null,
50
+ maxUses: null,
51
+ expiresAt: null,
52
+ isActive: true
53
+ };