@ketvietlab/ketsuite 0.1.3 → 0.1.6

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 (359) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/deployment.d.ts.map +1 -1
  3. package/dist/deployment.js +3 -0
  4. package/dist/deployment.js.map +1 -1
  5. package/dist/index.d.ts +8 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +7 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/modules/account_staff_channel/channel-routes.d.ts.map +1 -1
  10. package/dist/modules/account_staff_channel/channel-routes.js +1 -12
  11. package/dist/modules/account_staff_channel/channel-routes.js.map +1 -1
  12. package/dist/modules/attendance/channel-routes.d.ts.map +1 -1
  13. package/dist/modules/attendance/channel-routes.js +1 -12
  14. package/dist/modules/attendance/channel-routes.js.map +1 -1
  15. package/dist/modules/backend/design/HANDOFF.md +2 -2
  16. package/dist/modules/backend/design/auth.css +12 -0
  17. package/dist/modules/backend/design/client/table-selection.d.mts +3 -3
  18. package/dist/modules/backend/design/client/table-selection.d.mts.map +1 -1
  19. package/dist/modules/backend/design/client/table-selection.mjs +1 -1
  20. package/dist/modules/backend/design/client/table-selection.mjs.map +4 -4
  21. package/dist/modules/backend/design/content.css +43 -0
  22. package/dist/modules/backend/design/design-system.css +1 -1
  23. package/dist/modules/backend/design/forms.css +84 -1
  24. package/dist/modules/backend/design/lists.css +26 -18
  25. package/dist/modules/backend/design/record.css +5 -2
  26. package/dist/modules/backend/design/responsive.css +5 -6
  27. package/dist/modules/backend/design/user-workflow.css +257 -0
  28. package/dist/modules/backend/forms.d.ts +38 -1
  29. package/dist/modules/backend/forms.d.ts.map +1 -1
  30. package/dist/modules/backend/forms.js +29 -0
  31. package/dist/modules/backend/forms.js.map +1 -1
  32. package/dist/modules/backend/index.d.ts +3 -2
  33. package/dist/modules/backend/index.d.ts.map +1 -1
  34. package/dist/modules/backend/index.js +3 -2
  35. package/dist/modules/backend/index.js.map +1 -1
  36. package/dist/modules/backend/messages.d.ts.map +1 -1
  37. package/dist/modules/backend/messages.js +42 -2
  38. package/dist/modules/backend/messages.js.map +1 -1
  39. package/dist/modules/channel_api/core.d.ts +30 -0
  40. package/dist/modules/channel_api/core.d.ts.map +1 -1
  41. package/dist/modules/channel_api/core.js +28 -0
  42. package/dist/modules/channel_api/core.js.map +1 -1
  43. package/dist/modules/crm/functions.d.ts +5 -0
  44. package/dist/modules/crm/functions.d.ts.map +1 -1
  45. package/dist/modules/crm/functions.js +105 -10
  46. package/dist/modules/crm/functions.js.map +1 -1
  47. package/dist/modules/crm/jobs.d.ts.map +1 -1
  48. package/dist/modules/crm/jobs.js +1 -0
  49. package/dist/modules/crm/jobs.js.map +1 -1
  50. package/dist/modules/crm/operations.d.ts.map +1 -1
  51. package/dist/modules/crm/operations.js +2 -1
  52. package/dist/modules/crm/operations.js.map +1 -1
  53. package/dist/modules/crm_backend/index.d.ts.map +1 -1
  54. package/dist/modules/crm_backend/index.js +5 -2
  55. package/dist/modules/crm_backend/index.js.map +1 -1
  56. package/dist/modules/crm_backend/messages.d.ts +116 -0
  57. package/dist/modules/crm_backend/messages.d.ts.map +1 -1
  58. package/dist/modules/crm_backend/messages.js +122 -6
  59. package/dist/modules/crm_backend/messages.js.map +1 -1
  60. package/dist/modules/crm_backend/routes.d.ts.map +1 -1
  61. package/dist/modules/crm_backend/routes.js +434 -174
  62. package/dist/modules/crm_backend/routes.js.map +1 -1
  63. package/dist/modules/crm_backend/screens/case-create.d.ts +7 -0
  64. package/dist/modules/crm_backend/screens/case-create.d.ts.map +1 -1
  65. package/dist/modules/crm_backend/screens/case-create.js +13 -4
  66. package/dist/modules/crm_backend/screens/case-create.js.map +1 -1
  67. package/dist/modules/crm_backend/screens/case-detail.d.ts +6 -0
  68. package/dist/modules/crm_backend/screens/case-detail.d.ts.map +1 -1
  69. package/dist/modules/crm_backend/screens/case-detail.js +73 -23
  70. package/dist/modules/crm_backend/screens/case-detail.js.map +1 -1
  71. package/dist/modules/crm_backend/screens/configuration.d.ts +21 -3
  72. package/dist/modules/crm_backend/screens/configuration.d.ts.map +1 -1
  73. package/dist/modules/crm_backend/screens/configuration.js +260 -55
  74. package/dist/modules/crm_backend/screens/configuration.js.map +1 -1
  75. package/dist/modules/crm_backend/screens/index.d.ts +3 -3
  76. package/dist/modules/crm_backend/screens/index.d.ts.map +1 -1
  77. package/dist/modules/crm_backend/screens/index.js +2 -2
  78. package/dist/modules/crm_backend/screens/index.js.map +1 -1
  79. package/dist/modules/crm_staff_channel/channel-routes.d.ts.map +1 -1
  80. package/dist/modules/crm_staff_channel/channel-routes.js +1 -12
  81. package/dist/modules/crm_staff_channel/channel-routes.js.map +1 -1
  82. package/dist/modules/flow/membership.d.ts.map +1 -1
  83. package/dist/modules/flow/membership.js +7 -1
  84. package/dist/modules/flow/membership.js.map +1 -1
  85. package/dist/modules/flow/operations.d.ts +10 -4
  86. package/dist/modules/flow/operations.d.ts.map +1 -1
  87. package/dist/modules/flow/operations.js +10 -4
  88. package/dist/modules/flow/operations.js.map +1 -1
  89. package/dist/modules/flow_staff_channel/channel-routes.d.ts.map +1 -1
  90. package/dist/modules/flow_staff_channel/channel-routes.js +1 -20
  91. package/dist/modules/flow_staff_channel/channel-routes.js.map +1 -1
  92. package/dist/modules/hospitality_core/messages.d.ts.map +1 -1
  93. package/dist/modules/hospitality_core/messages.js +44 -0
  94. package/dist/modules/hospitality_core/messages.js.map +1 -1
  95. package/dist/modules/hospitality_core/night-audit.d.ts.map +1 -1
  96. package/dist/modules/hospitality_core/night-audit.js +7 -0
  97. package/dist/modules/hospitality_core/night-audit.js.map +1 -1
  98. package/dist/modules/hospitality_core/operations.d.ts.map +1 -1
  99. package/dist/modules/hospitality_core/operations.js +150 -40
  100. package/dist/modules/hospitality_core/operations.js.map +1 -1
  101. package/dist/modules/hospitality_core/routes.d.ts.map +1 -1
  102. package/dist/modules/hospitality_core/routes.js +24 -2
  103. package/dist/modules/hospitality_core/routes.js.map +1 -1
  104. package/dist/modules/hospitality_core/screens/check-out-prep.d.ts +46 -0
  105. package/dist/modules/hospitality_core/screens/check-out-prep.d.ts.map +1 -0
  106. package/dist/modules/hospitality_core/screens/check-out-prep.js +133 -0
  107. package/dist/modules/hospitality_core/screens/check-out-prep.js.map +1 -0
  108. package/dist/modules/hospitality_core/screens/folio-detail.d.ts.map +1 -1
  109. package/dist/modules/hospitality_core/screens/folio-detail.js +2 -4
  110. package/dist/modules/hospitality_core/screens/folio-detail.js.map +1 -1
  111. package/dist/modules/hospitality_core/screens/index.d.ts +2 -0
  112. package/dist/modules/hospitality_core/screens/index.d.ts.map +1 -1
  113. package/dist/modules/hospitality_core/screens/index.js +1 -0
  114. package/dist/modules/hospitality_core/screens/index.js.map +1 -1
  115. package/dist/modules/hospitality_core/screens/reservation-detail.d.ts.map +1 -1
  116. package/dist/modules/hospitality_core/screens/reservation-detail.js +8 -1
  117. package/dist/modules/hospitality_core/screens/reservation-detail.js.map +1 -1
  118. package/dist/modules/hospitality_core/screens/shared.d.ts +12 -0
  119. package/dist/modules/hospitality_core/screens/shared.d.ts.map +1 -1
  120. package/dist/modules/hospitality_core/screens/shared.js +25 -4
  121. package/dist/modules/hospitality_core/screens/shared.js.map +1 -1
  122. package/dist/modules/hospitality_core/services.d.ts +48 -0
  123. package/dist/modules/hospitality_core/services.d.ts.map +1 -1
  124. package/dist/modules/hospitality_core/services.js +70 -0
  125. package/dist/modules/hospitality_core/services.js.map +1 -1
  126. package/dist/modules/hospitality_staff_channel/channel-routes.d.ts.map +1 -1
  127. package/dist/modules/hospitality_staff_channel/channel-routes.js +1 -12
  128. package/dist/modules/hospitality_staff_channel/channel-routes.js.map +1 -1
  129. package/dist/modules/inventory_staff_channel/channel-routes.d.ts.map +1 -1
  130. package/dist/modules/inventory_staff_channel/channel-routes.js +1 -12
  131. package/dist/modules/inventory_staff_channel/channel-routes.js.map +1 -1
  132. package/dist/modules/loyalty/admin-functions.d.ts +2 -0
  133. package/dist/modules/loyalty/admin-functions.d.ts.map +1 -1
  134. package/dist/modules/loyalty/admin-functions.js +96 -20
  135. package/dist/modules/loyalty/admin-functions.js.map +1 -1
  136. package/dist/modules/loyalty/engine.d.ts +4 -1
  137. package/dist/modules/loyalty/engine.d.ts.map +1 -1
  138. package/dist/modules/loyalty/engine.js +125 -18
  139. package/dist/modules/loyalty/engine.js.map +1 -1
  140. package/dist/modules/loyalty/index.d.ts.map +1 -1
  141. package/dist/modules/loyalty/index.js +4 -3
  142. package/dist/modules/loyalty/index.js.map +1 -1
  143. package/dist/modules/loyalty/jobs.d.ts.map +1 -1
  144. package/dist/modules/loyalty/jobs.js +0 -1
  145. package/dist/modules/loyalty/jobs.js.map +1 -1
  146. package/dist/modules/loyalty/membership-functions.d.ts +5 -0
  147. package/dist/modules/loyalty/membership-functions.d.ts.map +1 -1
  148. package/dist/modules/loyalty/membership-functions.js +37 -23
  149. package/dist/modules/loyalty/membership-functions.js.map +1 -1
  150. package/dist/modules/loyalty/messages.d.ts +14 -0
  151. package/dist/modules/loyalty/messages.d.ts.map +1 -1
  152. package/dist/modules/loyalty/messages.js +14 -0
  153. package/dist/modules/loyalty/messages.js.map +1 -1
  154. package/dist/modules/loyalty/models.d.ts.map +1 -1
  155. package/dist/modules/loyalty/models.js +17 -0
  156. package/dist/modules/loyalty/models.js.map +1 -1
  157. package/dist/modules/loyalty/order-functions.d.ts.map +1 -1
  158. package/dist/modules/loyalty/order-functions.js +70 -17
  159. package/dist/modules/loyalty/order-functions.js.map +1 -1
  160. package/dist/modules/loyalty/program-design.d.ts +11 -0
  161. package/dist/modules/loyalty/program-design.d.ts.map +1 -0
  162. package/dist/modules/loyalty/program-design.js +356 -0
  163. package/dist/modules/loyalty/program-design.js.map +1 -0
  164. package/dist/modules/loyalty/stats.d.ts +0 -13
  165. package/dist/modules/loyalty/stats.d.ts.map +1 -1
  166. package/dist/modules/loyalty/stats.js +11 -6
  167. package/dist/modules/loyalty/stats.js.map +1 -1
  168. package/dist/modules/loyalty/stored-value.d.ts.map +1 -1
  169. package/dist/modules/loyalty/stored-value.js +7 -2
  170. package/dist/modules/loyalty/stored-value.js.map +1 -1
  171. package/dist/modules/loyalty/types.d.ts +1 -1
  172. package/dist/modules/loyalty/types.d.ts.map +1 -1
  173. package/dist/modules/loyalty_backend/design-messages.d.ts +221 -0
  174. package/dist/modules/loyalty_backend/design-messages.d.ts.map +1 -0
  175. package/dist/modules/loyalty_backend/design-messages.js +221 -0
  176. package/dist/modules/loyalty_backend/design-messages.js.map +1 -0
  177. package/dist/modules/loyalty_backend/index.js +224 -412
  178. package/dist/modules/loyalty_backend/index.js.map +1 -1
  179. package/dist/modules/loyalty_backend/messages.d.ts +642 -214
  180. package/dist/modules/loyalty_backend/messages.d.ts.map +1 -1
  181. package/dist/modules/loyalty_backend/messages.js +19 -13
  182. package/dist/modules/loyalty_backend/messages.js.map +1 -1
  183. package/dist/modules/loyalty_backend/program-workspace.d.ts +4 -0
  184. package/dist/modules/loyalty_backend/program-workspace.d.ts.map +1 -0
  185. package/dist/modules/loyalty_backend/program-workspace.js +600 -0
  186. package/dist/modules/loyalty_backend/program-workspace.js.map +1 -0
  187. package/dist/modules/loyalty_backend/screens/index.d.ts +12 -36
  188. package/dist/modules/loyalty_backend/screens/index.d.ts.map +1 -1
  189. package/dist/modules/loyalty_backend/screens/index.js +148 -292
  190. package/dist/modules/loyalty_backend/screens/index.js.map +1 -1
  191. package/dist/modules/loyalty_backend/screens/page-frame.d.ts.map +1 -1
  192. package/dist/modules/loyalty_backend/screens/page-frame.js +2 -2
  193. package/dist/modules/loyalty_backend/screens/page-frame.js.map +1 -1
  194. package/dist/modules/loyalty_pos/functions.d.ts.map +1 -1
  195. package/dist/modules/loyalty_pos/functions.js +1 -0
  196. package/dist/modules/loyalty_pos/functions.js.map +1 -1
  197. package/dist/modules/loyalty_pos/index.js +1 -1
  198. package/dist/modules/loyalty_pos/index.js.map +1 -1
  199. package/dist/modules/loyalty_sale/functions.d.ts +1 -0
  200. package/dist/modules/loyalty_sale/functions.d.ts.map +1 -1
  201. package/dist/modules/loyalty_sale/functions.js +1 -0
  202. package/dist/modules/loyalty_sale/functions.js.map +1 -1
  203. package/dist/modules/partner_backend/client/partner.css +3 -1
  204. package/dist/modules/partner_backend/index.d.ts.map +1 -1
  205. package/dist/modules/partner_backend/index.js +4 -0
  206. package/dist/modules/partner_backend/index.js.map +1 -1
  207. package/dist/modules/partner_backend/routes.d.ts.map +1 -1
  208. package/dist/modules/partner_backend/routes.js +6 -1
  209. package/dist/modules/partner_backend/routes.js.map +1 -1
  210. package/dist/modules/partner_backend/screens/form.d.ts +1 -0
  211. package/dist/modules/partner_backend/screens/form.d.ts.map +1 -1
  212. package/dist/modules/partner_backend/screens/form.js +1 -0
  213. package/dist/modules/partner_backend/screens/form.js.map +1 -1
  214. package/dist/modules/purchase_staff_channel/order-routes.d.ts.map +1 -1
  215. package/dist/modules/purchase_staff_channel/order-routes.js +1 -12
  216. package/dist/modules/purchase_staff_channel/order-routes.js.map +1 -1
  217. package/dist/modules/quality_staff_channel/channel-routes.d.ts.map +1 -1
  218. package/dist/modules/quality_staff_channel/channel-routes.js +1 -12
  219. package/dist/modules/quality_staff_channel/channel-routes.js.map +1 -1
  220. package/dist/modules/sale/functions.d.ts.map +1 -1
  221. package/dist/modules/sale/functions.js +27 -17
  222. package/dist/modules/sale/functions.js.map +1 -1
  223. package/dist/modules/sale_staff_channel/channel-routes.d.ts.map +1 -1
  224. package/dist/modules/sale_staff_channel/channel-routes.js +1 -12
  225. package/dist/modules/sale_staff_channel/channel-routes.js.map +1 -1
  226. package/dist/modules/sale_staff_channel/order-routes.d.ts.map +1 -1
  227. package/dist/modules/sale_staff_channel/order-routes.js +1 -12
  228. package/dist/modules/sale_staff_channel/order-routes.js.map +1 -1
  229. package/dist/modules/stock_staff_channel/operation-routes.d.ts.map +1 -1
  230. package/dist/modules/stock_staff_channel/operation-routes.js +1 -12
  231. package/dist/modules/stock_staff_channel/operation-routes.js.map +1 -1
  232. package/dist/modules/user/authorization.d.ts +64 -1
  233. package/dist/modules/user/authorization.d.ts.map +1 -1
  234. package/dist/modules/user/authorization.js +445 -53
  235. package/dist/modules/user/authorization.js.map +1 -1
  236. package/dist/modules/user/functions.d.ts.map +1 -1
  237. package/dist/modules/user/functions.js +45 -23
  238. package/dist/modules/user/functions.js.map +1 -1
  239. package/dist/modules/user/index.d.ts +2 -1
  240. package/dist/modules/user/index.d.ts.map +1 -1
  241. package/dist/modules/user/index.js +1 -1
  242. package/dist/modules/user/index.js.map +1 -1
  243. package/dist/modules/user/models.d.ts.map +1 -1
  244. package/dist/modules/user/models.js +5 -0
  245. package/dist/modules/user/models.js.map +1 -1
  246. package/dist/modules/user/roles.d.ts.map +1 -1
  247. package/dist/modules/user/roles.js +2 -1
  248. package/dist/modules/user/roles.js.map +1 -1
  249. package/dist/modules/user_backend/access-routes.d.ts +31 -0
  250. package/dist/modules/user_backend/access-routes.d.ts.map +1 -0
  251. package/dist/modules/user_backend/access-routes.js +447 -0
  252. package/dist/modules/user_backend/access-routes.js.map +1 -0
  253. package/dist/modules/user_backend/index.d.ts +1 -0
  254. package/dist/modules/user_backend/index.d.ts.map +1 -1
  255. package/dist/modules/user_backend/index.js +1 -0
  256. package/dist/modules/user_backend/index.js.map +1 -1
  257. package/dist/modules/user_backend/messages.d.ts +4 -0
  258. package/dist/modules/user_backend/messages.d.ts.map +1 -1
  259. package/dist/modules/user_backend/messages.js +4 -0
  260. package/dist/modules/user_backend/messages.js.map +1 -1
  261. package/dist/modules/user_backend/routes.d.ts.map +1 -1
  262. package/dist/modules/user_backend/routes.js +38 -3
  263. package/dist/modules/user_backend/routes.js.map +1 -1
  264. package/dist/modules/user_backend/screens/user-form.d.ts +1 -0
  265. package/dist/modules/user_backend/screens/user-form.d.ts.map +1 -1
  266. package/dist/modules/user_backend/screens/user-form.js +28 -0
  267. package/dist/modules/user_backend/screens/user-form.js.map +1 -1
  268. package/dist/modules/website/cms.d.ts.map +1 -1
  269. package/dist/modules/website/cms.js +283 -6
  270. package/dist/modules/website/cms.js.map +1 -1
  271. package/dist/modules/website/index.d.ts.map +1 -1
  272. package/dist/modules/website/index.js +12 -0
  273. package/dist/modules/website/index.js.map +1 -1
  274. package/dist/modules/website/media-usage.d.ts +38 -0
  275. package/dist/modules/website/media-usage.d.ts.map +1 -0
  276. package/dist/modules/website/media-usage.js +87 -0
  277. package/dist/modules/website/media-usage.js.map +1 -0
  278. package/dist/modules/website/paths.js +1 -1
  279. package/dist/modules/website/paths.js.map +1 -1
  280. package/dist/modules/website/sections.d.ts.map +1 -1
  281. package/dist/modules/website/sections.js +12 -1
  282. package/dist/modules/website/sections.js.map +1 -1
  283. package/dist/modules/website_backend/index.js +138 -0
  284. package/dist/modules/website_backend/index.js.map +1 -1
  285. package/dist/modules/website_backend/menus.d.ts.map +1 -1
  286. package/dist/modules/website_backend/menus.js +11 -0
  287. package/dist/modules/website_backend/menus.js.map +1 -1
  288. package/dist/modules/website_backend/routes.d.ts.map +1 -1
  289. package/dist/modules/website_backend/routes.js +414 -31
  290. package/dist/modules/website_backend/routes.js.map +1 -1
  291. package/dist/modules/website_backend/screens/index.d.ts +98 -6
  292. package/dist/modules/website_backend/screens/index.d.ts.map +1 -1
  293. package/dist/modules/website_backend/screens/index.js +600 -154
  294. package/dist/modules/website_backend/screens/index.js.map +1 -1
  295. package/dist/modules/website_backend/screens/page-frame.d.ts +3 -1
  296. package/dist/modules/website_backend/screens/page-frame.d.ts.map +1 -1
  297. package/dist/modules/website_backend/screens/page-frame.js +1 -1
  298. package/dist/modules/website_backend/screens/page-frame.js.map +1 -1
  299. package/dist/modules/website_menu/functions.d.ts.map +1 -1
  300. package/dist/modules/website_menu/functions.js +51 -0
  301. package/dist/modules/website_menu/functions.js.map +1 -1
  302. package/dist/modules/website_menu/index.js +2 -0
  303. package/dist/modules/website_menu/index.js.map +1 -1
  304. package/dist/modules/website_search/functions.d.ts.map +1 -1
  305. package/dist/modules/website_search/functions.js +10 -120
  306. package/dist/modules/website_search/functions.js.map +1 -1
  307. package/dist/modules/website_search/index.js +2 -0
  308. package/dist/modules/website_search/index.js.map +1 -1
  309. package/dist/modules/website_search/jobs.d.ts +3 -0
  310. package/dist/modules/website_search/jobs.d.ts.map +1 -0
  311. package/dist/modules/website_search/jobs.js +101 -0
  312. package/dist/modules/website_search/jobs.js.map +1 -0
  313. package/dist/modules/website_search/rebuild.d.ts +33 -0
  314. package/dist/modules/website_search/rebuild.d.ts.map +1 -0
  315. package/dist/modules/website_search/rebuild.js +125 -0
  316. package/dist/modules/website_search/rebuild.js.map +1 -0
  317. package/dist/permission-catalogue.d.ts.map +1 -1
  318. package/dist/permission-catalogue.js +21 -1
  319. package/dist/permission-catalogue.js.map +1 -1
  320. package/dist/scaffold/index.js +1 -1
  321. package/dist/ui/chrome.d.ts +8 -0
  322. package/dist/ui/chrome.d.ts.map +1 -1
  323. package/dist/ui/chrome.js +9 -1
  324. package/dist/ui/chrome.js.map +1 -1
  325. package/dist/ui/client/table-selection-view.d.ts.map +1 -1
  326. package/dist/ui/client/table-selection-view.js +161 -5
  327. package/dist/ui/client/table-selection-view.js.map +1 -1
  328. package/dist/ui/client/user-workflow.d.ts +2 -0
  329. package/dist/ui/client/user-workflow.d.ts.map +1 -0
  330. package/dist/ui/client/user-workflow.js +141 -0
  331. package/dist/ui/client/user-workflow.js.map +1 -0
  332. package/dist/ui/form.d.ts +9 -0
  333. package/dist/ui/form.d.ts.map +1 -1
  334. package/dist/ui/form.js +29 -15
  335. package/dist/ui/form.js.map +1 -1
  336. package/dist/ui/icons.d.ts.map +1 -1
  337. package/dist/ui/icons.js +2 -0
  338. package/dist/ui/icons.js.map +1 -1
  339. package/dist/ui/index.d.ts +7 -3
  340. package/dist/ui/index.d.ts.map +1 -1
  341. package/dist/ui/index.js +6 -3
  342. package/dist/ui/index.js.map +1 -1
  343. package/dist/ui/layout.d.ts.map +1 -1
  344. package/dist/ui/layout.js +14 -4
  345. package/dist/ui/layout.js.map +1 -1
  346. package/dist/ui/nav.d.ts.map +1 -1
  347. package/dist/ui/nav.js +2 -1
  348. package/dist/ui/nav.js.map +1 -1
  349. package/dist/ui/state.d.ts +20 -1
  350. package/dist/ui/state.d.ts.map +1 -1
  351. package/dist/ui/state.js +17 -0
  352. package/dist/ui/state.js.map +1 -1
  353. package/dist/ui/table.js +1 -1
  354. package/dist/ui/table.js.map +1 -1
  355. package/dist/ui/user-workflow.d.ts +72 -0
  356. package/dist/ui/user-workflow.d.ts.map +1 -0
  357. package/dist/ui/user-workflow.js +144 -0
  358. package/dist/ui/user-workflow.js.map +1 -0
  359. package/package.json +8 -4
@@ -0,0 +1,600 @@
1
+ import { jsx as _jsx } from "@ketvietlab/ketjs-view/jsx-runtime";
2
+ import { minorText, multiplyToMinor, scaleOf } from '../account/money.js';
3
+ import { randomUUID } from 'node:crypto';
4
+ import { text } from '@ketvietlab/ketjs';
5
+ import { actionGroup as actions, badge, dataTable, formatMoney, inline, linkButton, ModalSheet, modalWorkspace, Notice, RecordForm, RecordPage, Section, shell, stack, Surface, Tabs, } from '../../ui/index.js';
6
+ import { readForm, seeOther } from '../backend/forms.js';
7
+ import { adminPage, inLocale } from '../backend/screen.js';
8
+ import { PROGRAM_TYPES } from '../loyalty/types.js';
9
+ const actionGroup = (items) => actions({ actions: items });
10
+ const base = '/admin/loyalty/programs';
11
+ const bool = (value) => ['1', 'true', 'on'].includes(String(value));
12
+ const value = (row, key, fallback = '') => row[key] ?? fallback;
13
+ const rows = (value) => (Array.isArray(value) ? value : []);
14
+ const t = (_, key) => _(`loyalty_backend.design.${key}`);
15
+ const label = (_, key) => _(`loyalty_backend.field.${key}`);
16
+ const select = (_, name, options, current, group = name) => ({
17
+ name,
18
+ label: label(_, name),
19
+ type: 'select',
20
+ value: String(current ?? options[0]),
21
+ options: options.map((v) => ({ value: v, label: _(`loyalty_backend.${group}.${v}`) })),
22
+ });
23
+ const field = (_, row, key, fallback = '', type = 'text', help) => ({
24
+ name: key,
25
+ label: label(_, key),
26
+ value: value(row, key, fallback),
27
+ type,
28
+ ...(help ? { help } : {}),
29
+ });
30
+ const check = (_, row, key, fallback = true) => field(_, row, key, fallback, 'checkbox');
31
+ const many = (_, key, choices, selected) => ({
32
+ name: key,
33
+ label: label(_, key),
34
+ type: 'checkbox-group',
35
+ span: 'full',
36
+ options: choices.map((row) => ({
37
+ name: `${key}:${String(row.id)}`,
38
+ value: '1',
39
+ label: String(row.name),
40
+ checked: Array.isArray(selected) && selected.includes(row.id),
41
+ })),
42
+ });
43
+ const selected = (form, key) => Object.keys(form)
44
+ .filter((name) => name.startsWith(`${key}:`) && bool(form[name]))
45
+ .map((name) => name.slice(key.length + 1));
46
+ const errorsOf = (_, result) => rows(result.errors).map((error) => _(String(error.code), error.params));
47
+ const navigate = (_, href, key, primary = false) => linkButton({ label: t(_, key), href, variant: primary ? 'primary' : 'secondary' });
48
+ const record = (_, frame, title, body, header = {}) => shell(_, title, _jsx(RecordPage, { variant: "operational", frame: frame, title: title, body: body, status: header.status, actions: header.actions }), {
49
+ ...frame,
50
+ chrome: null,
51
+ topbar: false,
52
+ });
53
+ const note = (_, key) => _jsx(Notice, { title: t(_, key), message: "", tone: "info" });
54
+ const pathFor = (url, path) => inLocale(url, path);
55
+ const safePost = (req) => {
56
+ if (!req.headers.origin)
57
+ return true;
58
+ try {
59
+ return new URL(String(req.headers.origin)).host === String(req.headers.host);
60
+ }
61
+ catch {
62
+ return false;
63
+ }
64
+ };
65
+ const catalog = async (ctx, url, req) => {
66
+ const [templates, pricelists, partners, warehouses] = await Promise.all([
67
+ ctx.call('product.listTemplates', { withVariants: true }, url, req),
68
+ ctx.call('pricing.listPricelists', {}, url, req),
69
+ ctx.call('partner.listPartners', { includeArchived: false }, url, req),
70
+ ctx.call('stock.listWarehouses', {}, url, req),
71
+ ]);
72
+ return {
73
+ products: rows(templates)
74
+ .filter((template) => template.active && template.saleOk)
75
+ .flatMap((template) => rows(template.variants)
76
+ .filter((product) => product.active)
77
+ .map((product) => ({
78
+ ...product,
79
+ name: `${String(template.name)}${product.defaultCode ? ` · ${String(product.defaultCode)}` : ''}`,
80
+ }))),
81
+ warehouses: rows(warehouses),
82
+ pricelists: rows(pricelists),
83
+ partners: rows(partners),
84
+ };
85
+ };
86
+ const programFields = (_, program, data) => [
87
+ { ...field(_, program, 'name'), required: true, span: 'full' },
88
+ field(_, program, 'startDate', String(program.dateFrom ?? '').slice(0, 10), 'date'),
89
+ field(_, program, 'endDate', String(program.dateTo ?? '').slice(0, 10), 'date', t(_, 'calendar')),
90
+ check(_, program, 'availableSale'),
91
+ check(_, program, 'availablePos'),
92
+ many(_, 'pricelistIds', data.pricelists, program.pricelistIds),
93
+ ...(program.programType === 'loyalty'
94
+ ? [
95
+ select(_, 'appliesOn', ['both', 'future'], program.appliesOn ?? 'both'),
96
+ field(_, program, 'pointName', t(_, 'points')),
97
+ ]
98
+ : []),
99
+ ...(program.programType === 'next_order_coupons'
100
+ ? [field(_, program, 'voucherValidityDays', 30, 'number', t(_, 'voucherValidity'))]
101
+ : []),
102
+ {
103
+ name: 'advanced',
104
+ label: t(_, 'advanced'),
105
+ fields: [
106
+ check(_, program, 'limitUsage', false),
107
+ field(_, program, 'maxUsage', '', 'number', t(_, 'usage')),
108
+ check(_, program, 'portalVisible', program.programType === 'loyalty'),
109
+ ],
110
+ },
111
+ ];
112
+ const programValues = (form, program) => ({
113
+ name: form.name ?? '',
114
+ programType: program.programType,
115
+ ...(program.currency ? { currency: program.currency } : {}),
116
+ startDate: form.startDate || null,
117
+ endDate: form.endDate || null,
118
+ availableSale: bool(form.availableSale),
119
+ availablePos: bool(form.availablePos),
120
+ appliesOn: form.appliesOn ?? 'both',
121
+ pointName: form.pointName || undefined,
122
+ limitUsage: bool(form.limitUsage),
123
+ maxUsage: form.maxUsage ? Number(form.maxUsage) : undefined,
124
+ portalVisible: bool(form.portalVisible),
125
+ pricelistIds: selected(form, 'pricelistIds'),
126
+ voucherValidityDays: Number(form.voucherValidityDays || 30),
127
+ });
128
+ const ruleFields = (_, rule, program, data) => [
129
+ {
130
+ name: 'scope',
131
+ label: t(_, 'scope'),
132
+ type: 'select',
133
+ value: value(rule, 'scope', Array.isArray(rule.productIds) && rule.productIds.length ? 'specific' : 'all'),
134
+ options: ['all', 'specific'].map((value) => ({ value, label: t(_, value) })),
135
+ },
136
+ many(_, 'productIds', data.products, rule.productIds),
137
+ field(_, rule, 'minimumQuantity', '1', 'decimal'),
138
+ field(_, rule, 'minimumAmount', '0', 'decimal', t(_, 'threshold')),
139
+ select(_, 'taxMode', ['excl', 'incl'], rule.taxMode),
140
+ ...(program.programType === 'loyalty'
141
+ ? [
142
+ select(_, 'pointMode', ['money', 'order', 'unit'], rule.pointMode ?? 'money'),
143
+ {
144
+ name: 'rate',
145
+ label: t(_, 'rate'),
146
+ type: 'decimal',
147
+ value: value(rule, 'rate', rule.pointMode === 'money' && Number(rule.pointAmount) > 0
148
+ ? 1 / Number(rule.pointAmount)
149
+ : value(rule, 'pointAmount', 10000)),
150
+ help: t(_, 'rateHint'),
151
+ required: true,
152
+ },
153
+ ]
154
+ : []),
155
+ ...(program.programType === 'promo_code' ? [{ ...field(_, rule, 'code'), required: true }] : []),
156
+ ];
157
+ const rewardFields = (_, reward, program, data) => [
158
+ { ...field(_, reward, 'description'), required: true, span: 'full' },
159
+ ...(reward.rewardType === 'discount'
160
+ ? [
161
+ select(_, 'discountMode', program.programType === 'loyalty'
162
+ ? ['percent', 'per_order', 'per_point']
163
+ : ['percent', 'per_order'], reward.discountMode),
164
+ field(_, reward, 'discount', '10', 'decimal', t(_, 'discountUnits')),
165
+ {
166
+ name: 'scope',
167
+ label: t(_, 'scope'),
168
+ type: 'select',
169
+ value: value(reward, 'scope', reward.discountApplicability === 'specific' ? 'specific' : 'all'),
170
+ options: ['all', 'specific'].map((value) => ({ value, label: t(_, value) })),
171
+ },
172
+ many(_, 'productIds', data.products, reward.productIds),
173
+ field(_, reward, 'discountMaximum', '', 'decimal', t(_, 'cap')),
174
+ ]
175
+ : reward.rewardType === 'product'
176
+ ? [
177
+ {
178
+ name: 'rewardProductId',
179
+ label: label(_, 'rewardProductId'),
180
+ type: 'select',
181
+ value: value(reward, 'rewardProductId'),
182
+ options: data.products.map((row) => ({ value: String(row.id), label: String(row.name) })),
183
+ required: true,
184
+ },
185
+ field(_, reward, 'rewardProductQuantity', '1', 'decimal', t(_, 'stock')),
186
+ ]
187
+ : [field(_, reward, 'discountMaximum', '', 'decimal', t(_, 'shipping'))]),
188
+ ...(program.programType === 'loyalty'
189
+ ? [field(_, reward, 'requiredPoints', '10', 'decimal', t(_, 'fixedPoints'))]
190
+ : []),
191
+ ];
192
+ const configure = (ctx, url, req, program, form, entity, values, entityId) => ctx.call('loyalty.program.configure', {
193
+ id: program.id,
194
+ expectedVersion: Number(form.version),
195
+ entity,
196
+ ...(entityId ? { entityId } : {}),
197
+ values,
198
+ }, url, req);
199
+ export const newProgramRoute = (ctx) => async (url, req) => {
200
+ if (!['GET', 'POST'].includes(req.method ?? ''))
201
+ return text('GET or POST', { status: 405 });
202
+ const data = await catalog(ctx, url, req);
203
+ let program = { programType: url.searchParams.get('type') ?? 'loyalty' };
204
+ if (!PROGRAM_TYPES.includes(String(program.programType)))
205
+ return text('Invalid program type', { status: 400 });
206
+ let errors = [];
207
+ if (req.method === 'POST') {
208
+ if (!safePost(req))
209
+ return text('Forbidden', { status: 403 });
210
+ const form = await readForm(req);
211
+ const id = randomUUID();
212
+ const result = await configure(ctx, url, req, { ...program, id }, { ...form, version: '0' }, 'program', programValues(form, program));
213
+ if (result.ok)
214
+ return seeOther(pathFor(url, `${base}/${id}`));
215
+ errors = errorsOf(ctx.translate(ctx.localeOf(url, req)), result);
216
+ program = { ...program, ...programValues(form, program) };
217
+ }
218
+ return adminPage(ctx, url, req, {
219
+ title: 'loyalty_backend.action.createProgram',
220
+ body: (_, frame) => record(_, frame, _('loyalty_backend.action.createProgram'), stack([
221
+ actionGroup(PROGRAM_TYPES.map((type) => linkButton({
222
+ label: _(`loyalty.program.${type}`),
223
+ href: pathFor(url, `${base}/new?type=${type}`),
224
+ variant: type === program.programType ? 'primary' : 'secondary',
225
+ }))),
226
+ note(_, `purpose.${String(program.programType)}`),
227
+ note(_, 'setup'),
228
+ _jsx(Surface, { body: _jsx(RecordForm, { action: url.pathname + url.search, fields: programFields(_, program, data), errors: errors, submit: t(_, 'createSetup'), submitVariant: "primary", cancelHref: pathFor(url, base), cancelLabel: t(_, 'back') }) }),
229
+ ])),
230
+ });
231
+ };
232
+ export const programWorkspaceRoute = (ctx) => async (url, req, params) => {
233
+ if (!['GET', 'POST'].includes(req.method ?? ''))
234
+ return text('GET or POST', { status: 405 });
235
+ const program = (await ctx.call('loyalty.program.inspect', { id: params.id }, url, req));
236
+ if (!program)
237
+ return text('Not found', { status: 404 });
238
+ const data = await catalog(ctx, url, req);
239
+ const canWrite = await ctx.allows('loyalty.program.configure', url, req);
240
+ const canTransition = await ctx.allows('loyalty.program.transition', url, req);
241
+ const path = `${base}/${encodeURIComponent(params.id)}`;
242
+ const href = (query = '') => pathFor(url, path + query);
243
+ const tab = url.searchParams.get('tab') ?? 'overview';
244
+ const modal = url.searchParams.get('modal');
245
+ if (modal && !['rule', 'reward', 'activate', 'archive', 'restore'].includes(modal))
246
+ return text('Not found', { status: 404 });
247
+ const entryId = url.searchParams.get('entry') ?? 'new';
248
+ let entry = {
249
+ rewardType: program.programType === 'buy_x_get_y'
250
+ ? 'product'
251
+ : (url.searchParams.get('rewardType') ?? 'discount'),
252
+ };
253
+ if (modal === 'rule' || modal === 'reward') {
254
+ if (entryId !== 'new') {
255
+ const found = rows(program[modal === 'rule' ? 'rules' : 'rewards']).find((row) => row.id === entryId);
256
+ if (!found)
257
+ return text('Not found', { status: 404 });
258
+ entry = found;
259
+ }
260
+ }
261
+ let errors = [];
262
+ let preview = null;
263
+ let submitted = {};
264
+ if (req.method === 'POST') {
265
+ if (!safePost(req))
266
+ return text('Forbidden', { status: 403 });
267
+ const form = await readForm(req);
268
+ submitted = form;
269
+ let result;
270
+ if (modal === 'activate' || modal === 'archive' || modal === 'restore')
271
+ result = (await ctx.call('loyalty.program.transition', { id: params.id, expectedVersion: Number(form.version), action: modal }, url, req));
272
+ else if (modal === 'rule' || modal === 'reward') {
273
+ const values = form.operation === 'toggle'
274
+ ? { active: !entry.active }
275
+ : modal === 'rule'
276
+ ? {
277
+ ...form,
278
+ productIds: selected(form, 'productIds'),
279
+ pointMode: form.pointMode ?? 'order',
280
+ pointAmount: form.pointMode === 'money'
281
+ ? (1 / Number(form.rate)).toFixed(12).replace(/0+$/, '').replace(/\.$/, '')
282
+ : form.rate || '1',
283
+ taxMode: form.taxMode ?? 'excl',
284
+ }
285
+ : {
286
+ ...form,
287
+ productIds: selected(form, 'productIds'),
288
+ rewardType: entry.rewardType,
289
+ discountApplicability: form.scope === 'specific' ? 'specific' : 'order',
290
+ requiredPoints: form.requiredPoints || '1',
291
+ discountMaximum: form.discountMaximum || undefined,
292
+ };
293
+ result = await configure(ctx, url, req, program, form, modal, values, entryId === 'new' ? randomUUID() : entryId);
294
+ entry = { ...entry, ...values, rate: form.rate };
295
+ }
296
+ else if (tab === 'simulator') {
297
+ const lines = [0, 1, 2, 3, 4]
298
+ .filter((index) => form[`product${index}`])
299
+ .map((index) => ({
300
+ id: String(index),
301
+ productId: form[`product${index}`],
302
+ quantity: Number(form[`quantity${index}`] || 1),
303
+ untaxed: minorText(multiplyToMinor([form[`quantity${index}`] || '1', form[`price${index}`] || '0'], scaleOf(program.currency)), scaleOf(program.currency)),
304
+ total: minorText(multiplyToMinor([form[`quantity${index}`] || '1', form[`total${index}`] || form[`price${index}`] || '0'], scaleOf(program.currency)), scaleOf(program.currency)),
305
+ lineKind: 'product',
306
+ }));
307
+ if (Number(form.shipping) > 0 && lines[0])
308
+ lines.push({
309
+ id: 'shipping',
310
+ productId: lines[0].productId,
311
+ quantity: 1,
312
+ untaxed: form.shipping,
313
+ total: form.shipping,
314
+ lineKind: 'shipping',
315
+ });
316
+ result = (await ctx.call('loyalty.program.preview', {
317
+ id: params.id,
318
+ expectedVersion: Number(form.version),
319
+ ...(form.availablePoints !== '' ? { availablePoints: form.availablePoints } : {}),
320
+ order: {
321
+ orderId: 'preview',
322
+ orderType: form.channel || 'sale',
323
+ date: form.date || new Date().toISOString(),
324
+ currency: program.currency,
325
+ partnerId: form.partnerId || null,
326
+ warehouseId: form.warehouseId || null,
327
+ pricelistId: form.pricelistId || null,
328
+ codes: form.code ? [form.code] : [],
329
+ lines,
330
+ },
331
+ }, url, req));
332
+ preview = result;
333
+ }
334
+ else
335
+ result = await configure(ctx, url, req, program, form, 'program', programValues(form, program));
336
+ if (result.ok && !preview) {
337
+ const target = form.returnTo ? new URL(form.returnTo, url.origin) : null;
338
+ const adminDestination = target?.origin === url.origin &&
339
+ (target.pathname === '/admin' || target.pathname.startsWith('/admin/'));
340
+ return seeOther(adminDestination
341
+ ? target.pathname + target.search
342
+ : href(`?tab=${modal === 'rule' ? 'rules' : modal === 'reward' ? 'rewards' : tab}`));
343
+ }
344
+ errors = errorsOf(ctx.translate(ctx.localeOf(url, req)), result);
345
+ }
346
+ return adminPage(ctx, url, req, {
347
+ title: 'loyalty_backend.program.detail',
348
+ body: (_, frame) => {
349
+ const version = { version: String(program.configVersion ?? 0) };
350
+ const action = url.pathname + url.search;
351
+ const money = ['gift_card', 'ewallet'].includes(String(program.programType));
352
+ const tabs = ['overview', ...(money ? [] : ['rules', 'rewards', 'simulator'])];
353
+ const readiness = rows(program.readiness)
354
+ .map((error) => _(String(error.code)))
355
+ .join(' ');
356
+ const entityTable = (entity) => dataTable(_, {
357
+ rows: rows(program[entity === 'rule' ? 'rules' : 'rewards']),
358
+ id: (row) => String(row.id),
359
+ rowHref: (row) => href(`?tab=${tab}&modal=${entity}&entry=${encodeURIComponent(String(row.id))}`),
360
+ rowLink: false,
361
+ columns: [
362
+ {
363
+ key: 'description',
364
+ label: t(_, entity),
365
+ cell: (row) => entity === 'reward'
366
+ ? String(row.description)
367
+ : stack([
368
+ inline([`${label(_, 'minimumQuantity')}: ${String(row.minimumQuantity)}`]),
369
+ inline([
370
+ `${label(_, 'minimumAmount')}: ${formatMoney(_, row.minimumAmount, program.currency)} · ${_(`loyalty_backend.taxMode.${String(row.taxMode)}`)}`,
371
+ ]),
372
+ ], 'compact'),
373
+ priority: 'primary',
374
+ },
375
+ {
376
+ key: 'scope',
377
+ label: t(_, 'scope'),
378
+ cell: (row) => rows(data.products)
379
+ .filter((product) => (row.productIds ?? []).includes(product.id))
380
+ .map((product) => product.name)
381
+ .join(', ') || t(_, 'all'),
382
+ },
383
+ {
384
+ key: 'active',
385
+ label: label(_, 'state'),
386
+ cell: (row) => badge(t(_, row.active ? 'enabled' : 'disabled'), row.active ? 'positive' : 'neutral'),
387
+ },
388
+ ],
389
+ });
390
+ let body;
391
+ if (tab === 'rules' || tab === 'rewards') {
392
+ const entity = tab === 'rules' ? 'rule' : 'reward';
393
+ body = stack([
394
+ note(_, tab === 'rules' ? (program.earnSource === 'groups' ? 'groups' : 'rulesAdd') : 'oneReward'),
395
+ ...(canWrite
396
+ ? [actionGroup([navigate(_, href(`?tab=${tab}&modal=${entity}`), `add.${entity}`, true)])]
397
+ : []),
398
+ entityTable(entity),
399
+ ]);
400
+ }
401
+ else if (tab === 'simulator') {
402
+ const fields = [
403
+ ...[0, 1, 2, 3, 4].flatMap((index) => [
404
+ {
405
+ name: `product${index}`,
406
+ label: `${t(_, 'line')} ${index + 1}`,
407
+ type: 'select',
408
+ value: submitted[`product${index}`] ?? '',
409
+ options: [
410
+ { value: '', label: t(_, 'noProduct') },
411
+ ...data.products.map((row) => ({ value: String(row.id), label: String(row.name) })),
412
+ ],
413
+ },
414
+ {
415
+ name: `quantity${index}`,
416
+ label: label(_, 'quantity'),
417
+ type: 'decimal',
418
+ value: submitted[`quantity${index}`] ?? '1',
419
+ },
420
+ {
421
+ name: `price${index}`,
422
+ label: t(_, 'untaxedPrice'),
423
+ type: 'decimal',
424
+ value: submitted[`price${index}`] ?? '',
425
+ },
426
+ {
427
+ name: `total${index}`,
428
+ label: t(_, 'taxedPrice'),
429
+ type: 'decimal',
430
+ value: submitted[`total${index}`] ?? '',
431
+ },
432
+ ]),
433
+ {
434
+ name: 'partnerId',
435
+ label: label(_, 'partnerId'),
436
+ type: 'select',
437
+ value: submitted.partnerId ?? '',
438
+ options: [
439
+ { value: '', label: t(_, 'guest') },
440
+ ...data.partners.map((row) => ({ value: String(row.id), label: String(row.name) })),
441
+ ],
442
+ },
443
+ ...(program.programType === 'loyalty'
444
+ ? [field(_, submitted, 'availablePoints', '', 'decimal', t(_, 'balancePreview'))]
445
+ : []),
446
+ field(_, submitted, 'shipping', '', 'decimal'),
447
+ field(_, submitted, 'date', new Date().toISOString().slice(0, 10), 'date'),
448
+ {
449
+ name: 'channel',
450
+ label: label(_, 'channel'),
451
+ type: 'select',
452
+ value: submitted.channel ?? 'sale',
453
+ options: ['sale', 'pos'].map((value) => ({ value, label: value === 'sale' ? 'Sales' : 'POS' })),
454
+ },
455
+ {
456
+ name: 'pricelistId',
457
+ label: label(_, 'pricelistIds'),
458
+ type: 'select',
459
+ value: submitted.pricelistId ?? '',
460
+ options: [
461
+ { value: '', label: t(_, 'none') },
462
+ ...data.pricelists.map((row) => ({ value: String(row.id), label: String(row.name) })),
463
+ ],
464
+ },
465
+ {
466
+ name: 'warehouseId',
467
+ label: label(_, 'warehouseId'),
468
+ type: 'select',
469
+ value: submitted.warehouseId ?? '',
470
+ options: [
471
+ { value: '', label: t(_, 'allWarehouses') },
472
+ ...data.warehouses.map((row) => ({ value: String(row.id), label: String(row.name) })),
473
+ ],
474
+ },
475
+ field(_, submitted, 'code'),
476
+ ];
477
+ body = stack([
478
+ note(_, 'preview'),
479
+ _jsx(Surface, { body: _jsx(RecordForm, { action: action, fields: [
480
+ ...fields.filter((field) => !/^(product|quantity|price|total)[1-4]$/.test(field.name) &&
481
+ !['date', 'channel', 'pricelistId', 'warehouseId', 'code'].includes(field.name)),
482
+ {
483
+ name: 'moreLines',
484
+ label: t(_, 'moreLines'),
485
+ fields: fields.filter((field) => /^(product|quantity|price|total)[1-4]$/.test(field.name)),
486
+ open: [1, 2, 3, 4].some((index) => Boolean(submitted[`product${index}`])),
487
+ },
488
+ {
489
+ name: 'advanced',
490
+ label: t(_, 'advanced'),
491
+ fields: fields.filter((field) => ['date', 'channel', 'pricelistId', 'warehouseId', 'code'].includes(field.name)),
492
+ },
493
+ ], hidden: version, errors: errors, submit: t(_, 'calculate'), submitVariant: "primary" }) }),
494
+ ...(preview
495
+ ? [
496
+ _jsx(Section, { title: t(_, 'result'), body: stack(rows(preview.trace).map((trace) => (_jsx(Notice, { title: t(_, `trace.${String(trace.code)}`), message: [
497
+ trace.description,
498
+ trace.quantity == null
499
+ ? null
500
+ : `${label(_, 'quantity')}: ${String(trace.quantity)}`,
501
+ trace.amount == null
502
+ ? null
503
+ : `${label(_, 'minimumAmount')}: ${String(trace.amount)}`,
504
+ trace.earned == null
505
+ ? null
506
+ : `${t(_, 'earned')}: ${String(trace.earned)}; ${t(_, 'available')}: ${String(trace.available)}`,
507
+ trace.requiredPoints == null
508
+ ? null
509
+ : `${program.programType === 'loyalty' ? `${t(_, 'cost')}: ${String(trace.requiredPoints)}; ` : ''}${t(_, 'discount')}: ${String(trace.discountAmount)} ${String(program.currency)}`,
510
+ ]
511
+ .filter(Boolean)
512
+ .join(' · '), tone: [
513
+ 'ruleFailed',
514
+ 'rewardUnavailable',
515
+ 'schedule',
516
+ 'code',
517
+ 'usage',
518
+ 'stopped',
519
+ ].includes(String(trace.code))
520
+ ? 'warning'
521
+ : 'info' })))) }),
522
+ ]
523
+ : []),
524
+ ]);
525
+ }
526
+ else
527
+ body = stack([
528
+ note(_, 'companyScope'),
529
+ ...(program.active ? [note(_, 'saveActive')] : []),
530
+ _jsx(Surface, { body: _jsx(RecordForm, { saveBeforeNavigation: t(_, 'saveBeforeLeave'), action: href(), submitPlacement: canWrite ? 'inside' : 'external', fields: programFields(_, req.method === 'POST' && !modal
531
+ ? { ...program, ...programValues(submitted, program) }
532
+ : program, data).map((field) => ({ ...field, disabled: !canWrite })), hidden: version, errors: !modal ? errors : [], submit: t(_, 'save'), submitVariant: "primary" }) }),
533
+ ]);
534
+ const workspace = record(_, frame, String(program.name), stack([
535
+ ...(program.phase === 'draft'
536
+ ? [
537
+ _jsx(Notice, { title: t(_, readiness ? 'notReady' : 'ready'), message: readiness || t(_, 'readyHint'), tone: readiness ? 'warning' : 'info' }),
538
+ ]
539
+ : []),
540
+ _jsx(Tabs, { label: String(program.name), items: tabs.map((id) => ({
541
+ id,
542
+ label: t(_, `tab.${id}`),
543
+ href: href(`?tab=${id}`),
544
+ active: tab === id,
545
+ })) }),
546
+ body,
547
+ ]), {
548
+ status: badge(_(`loyalty_backend.state.${String(program.state)}`), program.state === 'running' ? 'positive' : 'neutral'),
549
+ actions: actionGroup([
550
+ navigate(_, pathFor(url, base), 'back'),
551
+ ...(canTransition
552
+ ? [
553
+ navigate(_, href(`?modal=${program.phase === 'draft' ? 'activate' : program.active ? 'archive' : 'restore'}`), program.phase === 'draft' ? 'activate' : program.active ? 'archive' : 'restore'),
554
+ ]
555
+ : []),
556
+ ]),
557
+ });
558
+ if (!modal)
559
+ return workspace;
560
+ if (!canWrite && (modal === 'rule' || modal === 'reward')) {
561
+ return modalWorkspace(workspace, _jsx(ModalSheet, { title: t(_, modal), closeHref: href(`?tab=${tab}`), closeLabel: t(_, 'cancel'), body: _jsx(RecordForm, { action: action, fields: (modal === 'rule'
562
+ ? ruleFields(_, entry, program, data)
563
+ : rewardFields(_, entry, program, data)).map((field) => ({ ...field, disabled: true })), submit: "", submitVariant: "secondary", submitPlacement: "external" }) }));
564
+ }
565
+ let content;
566
+ if (modal === 'rule' || modal === 'reward')
567
+ content = stack([
568
+ ...(modal === 'reward' && entryId === 'new' && program.programType !== 'buy_x_get_y'
569
+ ? [
570
+ actionGroup(['discount', 'product', 'shipping'].map((type) => linkButton({
571
+ label: _(`loyalty.reward.${type}`),
572
+ href: href(`?tab=rewards&modal=reward&rewardType=${type}`),
573
+ variant: entry.rewardType === type ? 'primary' : 'secondary',
574
+ }))),
575
+ ]
576
+ : []),
577
+ _jsx(RecordForm, { action: action, fields: modal === 'rule' ? ruleFields(_, entry, program, data) : rewardFields(_, entry, program, data), hidden: version, errors: errors, submit: t(_, 'save'), submitVariant: "primary" }),
578
+ ...(entryId !== 'new'
579
+ ? [
580
+ note(_, 'toggleHint'),
581
+ _jsx(RecordForm, { action: action, fields: [], hidden: { ...version, operation: 'toggle' }, submit: t(_, entry.active ? 'disable' : 'enable'), submitVariant: "secondary" }),
582
+ ]
583
+ : []),
584
+ ]);
585
+ else
586
+ content = stack([
587
+ note(_, modal === 'activate'
588
+ ? 'activateConfirm'
589
+ : modal === 'archive'
590
+ ? money
591
+ ? 'stopMoney'
592
+ : 'stopPoints'
593
+ : 'restoreConfirm'),
594
+ _jsx(RecordForm, { action: action, fields: [], hidden: version, errors: errors, submit: t(_, modal), submitVariant: "primary" }),
595
+ ]);
596
+ return modalWorkspace(workspace, _jsx(ModalSheet, { title: t(_, modal), closeHref: href(`?tab=${tab}`), closeLabel: t(_, 'cancel'), presentation: "dialog", unsavedPrompt: t(_, 'unsaved'), body: content }));
597
+ },
598
+ });
599
+ };
600
+ //# sourceMappingURL=program-workspace.js.map