@open-mercato/core 0.6.5-develop.4516.1.88e6ab71a9 → 0.6.5-develop.4544.1.71c003c861

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 (726) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/AGENTS.md +5 -0
  3. package/dist/generated/entities/role/index.js +3 -1
  4. package/dist/generated/entities/role/index.js.map +2 -2
  5. package/dist/generated/entities/step_instance/index.js +2 -0
  6. package/dist/generated/entities/step_instance/index.js.map +2 -2
  7. package/dist/generated/entities/user/index.js +3 -1
  8. package/dist/generated/entities/user/index.js.map +2 -2
  9. package/dist/generated/entities/user_task/index.js +2 -0
  10. package/dist/generated/entities/user_task/index.js.map +2 -2
  11. package/dist/generated/entities/workflow_branch_instance/index.js +39 -0
  12. package/dist/generated/entities/workflow_branch_instance/index.js.map +7 -0
  13. package/dist/generated/entities/workflow_event/index.js +2 -0
  14. package/dist/generated/entities/workflow_event/index.js.map +2 -2
  15. package/dist/generated/entities/workflow_instance/index.js +2 -0
  16. package/dist/generated/entities/workflow_instance/index.js.map +2 -2
  17. package/dist/generated/entities.ids.generated.js +1 -0
  18. package/dist/generated/entities.ids.generated.js.map +2 -2
  19. package/dist/generated/entity-fields-registry.js +26 -0
  20. package/dist/generated/entity-fields-registry.js.map +2 -2
  21. package/dist/helpers/integration/optimisticLockUi.js +104 -0
  22. package/dist/helpers/integration/optimisticLockUi.js.map +7 -0
  23. package/dist/helpers/integration/salesFixtures.js +17 -0
  24. package/dist/helpers/integration/salesFixtures.js.map +2 -2
  25. package/dist/modules/api_keys/backend/api-keys/page.js +9 -5
  26. package/dist/modules/api_keys/backend/api-keys/page.js.map +2 -2
  27. package/dist/modules/attachments/components/AttachmentPartitionSettings.js +17 -9
  28. package/dist/modules/attachments/components/AttachmentPartitionSettings.js.map +2 -2
  29. package/dist/modules/auth/api/roles/acl/route.js +32 -13
  30. package/dist/modules/auth/api/roles/acl/route.js.map +2 -2
  31. package/dist/modules/auth/api/roles/route.js +3 -1
  32. package/dist/modules/auth/api/roles/route.js.map +2 -2
  33. package/dist/modules/auth/api/sidebar/preferences/route.js +71 -3
  34. package/dist/modules/auth/api/sidebar/preferences/route.js.map +2 -2
  35. package/dist/modules/auth/api/users/acl/route.js +42 -19
  36. package/dist/modules/auth/api/users/acl/route.js.map +2 -2
  37. package/dist/modules/auth/api/users/route.js +3 -1
  38. package/dist/modules/auth/api/users/route.js.map +2 -2
  39. package/dist/modules/auth/backend/roles/[id]/edit/page.js +24 -4
  40. package/dist/modules/auth/backend/roles/[id]/edit/page.js.map +2 -2
  41. package/dist/modules/auth/backend/roles/page.js +8 -4
  42. package/dist/modules/auth/backend/roles/page.js.map +2 -2
  43. package/dist/modules/auth/backend/users/[id]/edit/page.js +27 -5
  44. package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
  45. package/dist/modules/auth/backend/users/page.js +6 -2
  46. package/dist/modules/auth/backend/users/page.js.map +2 -2
  47. package/dist/modules/auth/components/AclEditor.js +3 -1
  48. package/dist/modules/auth/components/AclEditor.js.map +2 -2
  49. package/dist/modules/auth/data/entities.js +6 -0
  50. package/dist/modules/auth/data/entities.js.map +2 -2
  51. package/dist/modules/auth/services/sidebarPreferencesService.js +32 -4
  52. package/dist/modules/auth/services/sidebarPreferencesService.js.map +2 -2
  53. package/dist/modules/business_rules/api/rules/route.js +28 -0
  54. package/dist/modules/business_rules/api/rules/route.js.map +2 -2
  55. package/dist/modules/business_rules/api/sets/route.js +28 -0
  56. package/dist/modules/business_rules/api/sets/route.js.map +2 -2
  57. package/dist/modules/business_rules/backend/rules/[id]/page.js +11 -4
  58. package/dist/modules/business_rules/backend/rules/[id]/page.js.map +3 -3
  59. package/dist/modules/business_rules/backend/rules/page.js +20 -11
  60. package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
  61. package/dist/modules/business_rules/backend/sets/[id]/page.js +11 -4
  62. package/dist/modules/business_rules/backend/sets/[id]/page.js.map +2 -2
  63. package/dist/modules/business_rules/backend/sets/page.js +20 -11
  64. package/dist/modules/business_rules/backend/sets/page.js.map +2 -2
  65. package/dist/modules/catalog/api/categories/route.js +2 -0
  66. package/dist/modules/catalog/api/categories/route.js.map +2 -2
  67. package/dist/modules/catalog/api/products/route.js +2 -1
  68. package/dist/modules/catalog/api/products/route.js.map +2 -2
  69. package/dist/modules/catalog/backend/catalog/categories/[id]/edit/page.js +2 -0
  70. package/dist/modules/catalog/backend/catalog/categories/[id]/edit/page.js.map +2 -2
  71. package/dist/modules/catalog/backend/catalog/products/[id]/page.js +94 -40
  72. package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
  73. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js +37 -8
  74. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js.map +2 -2
  75. package/dist/modules/catalog/backend/catalog/products/optionSchemaClient.js.map +2 -2
  76. package/dist/modules/catalog/commands/variants.js +32 -31
  77. package/dist/modules/catalog/commands/variants.js.map +2 -2
  78. package/dist/modules/catalog/components/PriceKindSettings.js +12 -5
  79. package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
  80. package/dist/modules/catalog/components/categories/CategoriesDataTable.js.map +2 -2
  81. package/dist/modules/catalog/components/products/ProductMediaManager.js.map +2 -2
  82. package/dist/modules/catalog/components/products/ProductsDataTable.js +5 -3
  83. package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
  84. package/dist/modules/catalog/components/products/productForm.js.map +2 -2
  85. package/dist/modules/catalog/components/products/variantForm.js +2 -1
  86. package/dist/modules/catalog/components/products/variantForm.js.map +2 -2
  87. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js +5 -0
  88. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js.map +2 -2
  89. package/dist/modules/currencies/backend/currencies/[id]/page.js +6 -3
  90. package/dist/modules/currencies/backend/currencies/[id]/page.js.map +2 -2
  91. package/dist/modules/currencies/backend/currencies/page.js +18 -11
  92. package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
  93. package/dist/modules/currencies/backend/exchange-rates/[id]/page.js +1 -0
  94. package/dist/modules/currencies/backend/exchange-rates/[id]/page.js.map +2 -2
  95. package/dist/modules/currencies/backend/exchange-rates/page.js +10 -6
  96. package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
  97. package/dist/modules/currencies/commands/currencies.js +7 -5
  98. package/dist/modules/currencies/commands/currencies.js.map +2 -2
  99. package/dist/modules/currencies/components/CurrencyFetchingConfig.js +26 -19
  100. package/dist/modules/currencies/components/CurrencyFetchingConfig.js.map +2 -2
  101. package/dist/modules/customer_accounts/api/admin/roles/[id].js +28 -5
  102. package/dist/modules/customer_accounts/api/admin/roles/[id].js.map +2 -2
  103. package/dist/modules/customer_accounts/api/admin/roles.js +4 -2
  104. package/dist/modules/customer_accounts/api/admin/roles.js.map +2 -2
  105. package/dist/modules/customer_accounts/api/admin/users/[id].js +28 -5
  106. package/dist/modules/customer_accounts/api/admin/users/[id].js.map +2 -2
  107. package/dist/modules/customer_accounts/api/admin/users.js +2 -0
  108. package/dist/modules/customer_accounts/api/admin/users.js.map +2 -2
  109. package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js +16 -8
  110. package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js.map +2 -2
  111. package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js +8 -4
  112. package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js.map +2 -2
  113. package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/page.js +8 -4
  114. package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/page.js.map +2 -2
  115. package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js +29 -18
  116. package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js.map +2 -2
  117. package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js +18 -11
  118. package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js.map +2 -2
  119. package/dist/modules/customers/api/companies/route.js +13 -2
  120. package/dist/modules/customers/api/companies/route.js.map +2 -2
  121. package/dist/modules/customers/api/deals/route.js +2 -0
  122. package/dist/modules/customers/api/deals/route.js.map +2 -2
  123. package/dist/modules/customers/api/people/route.js +11 -2
  124. package/dist/modules/customers/api/people/route.js.map +2 -2
  125. package/dist/modules/customers/api/todos/route.js +1 -0
  126. package/dist/modules/customers/api/todos/route.js.map +2 -2
  127. package/dist/modules/customers/backend/config/customers/deals/page.js.map +2 -2
  128. package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js +34 -21
  129. package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js.map +2 -2
  130. package/dist/modules/customers/backend/customers/companies/[id]/page.js +45 -27
  131. package/dist/modules/customers/backend/customers/companies/[id]/page.js.map +2 -2
  132. package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
  133. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +22 -5
  134. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
  135. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.js +30 -8
  136. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.js.map +2 -2
  137. package/dist/modules/customers/backend/customers/deals/[id]/page.js +1 -0
  138. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
  139. package/dist/modules/customers/backend/customers/deals/page.js +16 -6
  140. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  141. package/dist/modules/customers/backend/customers/deals/pipeline/page.js +62 -39
  142. package/dist/modules/customers/backend/customers/deals/pipeline/page.js.map +2 -2
  143. package/dist/modules/customers/backend/customers/people/[id]/page.js +41 -26
  144. package/dist/modules/customers/backend/customers/people/[id]/page.js.map +2 -2
  145. package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
  146. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +50 -23
  147. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
  148. package/dist/modules/customers/commands/addresses.js +16 -14
  149. package/dist/modules/customers/commands/addresses.js.map +2 -2
  150. package/dist/modules/customers/commands/companies.js +1 -1
  151. package/dist/modules/customers/commands/companies.js.map +2 -2
  152. package/dist/modules/customers/commands/interactions.js +41 -4
  153. package/dist/modules/customers/commands/interactions.js.map +2 -2
  154. package/dist/modules/customers/commands/people.js +1 -1
  155. package/dist/modules/customers/commands/people.js.map +2 -2
  156. package/dist/modules/customers/commands/personCompanyLinks.js +8 -5
  157. package/dist/modules/customers/commands/personCompanyLinks.js.map +2 -2
  158. package/dist/modules/customers/commands/pipeline-stages.js +13 -11
  159. package/dist/modules/customers/commands/pipeline-stages.js.map +3 -3
  160. package/dist/modules/customers/components/AddressFormatSettings.js.map +2 -2
  161. package/dist/modules/customers/components/DictionarySettings.js +20 -13
  162. package/dist/modules/customers/components/DictionarySettings.js.map +2 -2
  163. package/dist/modules/customers/components/DictionarySortSettings.js +4 -0
  164. package/dist/modules/customers/components/DictionarySortSettings.js.map +2 -2
  165. package/dist/modules/customers/components/PipelineSettings.js +38 -23
  166. package/dist/modules/customers/components/PipelineSettings.js.map +2 -2
  167. package/dist/modules/customers/components/detail/ActivityTimeline.js +1 -1
  168. package/dist/modules/customers/components/detail/ActivityTimeline.js.map +2 -2
  169. package/dist/modules/customers/components/detail/AddressesSection.js +4 -0
  170. package/dist/modules/customers/components/detail/AddressesSection.js.map +2 -2
  171. package/dist/modules/customers/components/detail/CompanyPeopleSection.js +28 -22
  172. package/dist/modules/customers/components/detail/CompanyPeopleSection.js.map +2 -2
  173. package/dist/modules/customers/components/detail/DealsSection.js +36 -24
  174. package/dist/modules/customers/components/detail/DealsSection.js.map +2 -2
  175. package/dist/modules/customers/components/detail/EmailCardActions.js +5 -0
  176. package/dist/modules/customers/components/detail/EmailCardActions.js.map +2 -2
  177. package/dist/modules/customers/components/detail/EntityTagsDialog.js +7 -0
  178. package/dist/modules/customers/components/detail/EntityTagsDialog.js.map +2 -2
  179. package/dist/modules/customers/components/detail/ManageTagsDialog.js +34 -22
  180. package/dist/modules/customers/components/detail/ManageTagsDialog.js.map +2 -2
  181. package/dist/modules/customers/components/detail/PersonCompaniesSection.js +41 -29
  182. package/dist/modules/customers/components/detail/PersonCompaniesSection.js.map +2 -2
  183. package/dist/modules/customers/components/detail/RoleAssignmentRow.js +14 -8
  184. package/dist/modules/customers/components/detail/RoleAssignmentRow.js.map +2 -2
  185. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +14 -6
  186. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
  187. package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js +29 -13
  188. package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js.map +2 -2
  189. package/dist/modules/customers/components/detail/hooks/useInteractions.js +77 -35
  190. package/dist/modules/customers/components/detail/hooks/useInteractions.js.map +2 -2
  191. package/dist/modules/customers/components/detail/hooks/usePersonTasks.js +25 -17
  192. package/dist/modules/customers/components/detail/hooks/usePersonTasks.js.map +2 -2
  193. package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +2 -2
  194. package/dist/modules/customers/components/formConfig.js.map +2 -2
  195. package/dist/modules/customers/data/guards.js +66 -0
  196. package/dist/modules/customers/data/guards.js.map +7 -0
  197. package/dist/modules/customers/di.js +37 -0
  198. package/dist/modules/customers/di.js.map +2 -2
  199. package/dist/modules/customers/lib/todoCompatibility.js +11 -0
  200. package/dist/modules/customers/lib/todoCompatibility.js.map +2 -2
  201. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +2 -2
  202. package/dist/modules/data_sync/api/options.js +4 -4
  203. package/dist/modules/data_sync/api/options.js.map +2 -2
  204. package/dist/modules/data_sync/api/schedules/route.js +9 -1
  205. package/dist/modules/data_sync/api/schedules/route.js.map +2 -2
  206. package/dist/modules/data_sync/backend/data-sync/page.js +17 -8
  207. package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
  208. package/dist/modules/data_sync/components/IntegrationScheduleTab.js +43 -22
  209. package/dist/modules/data_sync/components/IntegrationScheduleTab.js.map +2 -2
  210. package/dist/modules/data_sync/lib/sync-schedule-service.js +9 -0
  211. package/dist/modules/data_sync/lib/sync-schedule-service.js.map +2 -2
  212. package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js +8 -1
  213. package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js.map +2 -2
  214. package/dist/modules/dictionaries/api/[dictionaryId]/route.js +17 -1
  215. package/dist/modules/dictionaries/api/[dictionaryId]/route.js.map +2 -2
  216. package/dist/modules/dictionaries/components/DictionariesManager.js +31 -10
  217. package/dist/modules/dictionaries/components/DictionariesManager.js.map +2 -2
  218. package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js +28 -15
  219. package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js.map +2 -2
  220. package/dist/modules/directory/api/organizations/route.js +3 -0
  221. package/dist/modules/directory/api/organizations/route.js.map +2 -2
  222. package/dist/modules/directory/backend/directory/organizations/[id]/edit/page.js +2 -0
  223. package/dist/modules/directory/backend/directory/organizations/[id]/edit/page.js.map +2 -2
  224. package/dist/modules/directory/backend/directory/organizations/page.js +9 -5
  225. package/dist/modules/directory/backend/directory/organizations/page.js.map +2 -2
  226. package/dist/modules/directory/backend/directory/tenants/[id]/edit/page.js +7 -3
  227. package/dist/modules/directory/backend/directory/tenants/[id]/edit/page.js.map +2 -2
  228. package/dist/modules/directory/backend/directory/tenants/page.js +8 -4
  229. package/dist/modules/directory/backend/directory/tenants/page.js.map +2 -2
  230. package/dist/modules/directory/commands/organizations.js +7 -2
  231. package/dist/modules/directory/commands/organizations.js.map +2 -2
  232. package/dist/modules/entities/api/records.js +66 -0
  233. package/dist/modules/entities/api/records.js.map +2 -2
  234. package/dist/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.js +1 -0
  235. package/dist/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.js.map +2 -2
  236. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +8 -4
  237. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
  238. package/dist/modules/entities/lib/helpers.js +17 -0
  239. package/dist/modules/entities/lib/helpers.js.map +2 -2
  240. package/dist/modules/feature_toggles/api/global/[id]/override/route.js +2 -1
  241. package/dist/modules/feature_toggles/api/global/[id]/override/route.js.map +2 -2
  242. package/dist/modules/feature_toggles/api/overrides/route.js +15 -0
  243. package/dist/modules/feature_toggles/api/overrides/route.js.map +2 -2
  244. package/dist/modules/feature_toggles/backend/feature-toggles/global/[id]/edit/page.js +15 -14
  245. package/dist/modules/feature_toggles/backend/feature-toggles/global/[id]/edit/page.js.map +2 -2
  246. package/dist/modules/feature_toggles/components/FeatureToggleOverrideCard.js +20 -12
  247. package/dist/modules/feature_toggles/components/FeatureToggleOverrideCard.js.map +2 -2
  248. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js +6 -2
  249. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js.map +2 -2
  250. package/dist/modules/feature_toggles/components/formConfig.js +2 -1
  251. package/dist/modules/feature_toggles/components/formConfig.js.map +2 -2
  252. package/dist/modules/feature_toggles/components/overrideFormConfig.js +5 -1
  253. package/dist/modules/feature_toggles/components/overrideFormConfig.js.map +2 -2
  254. package/dist/modules/feature_toggles/data/validators.js +7 -4
  255. package/dist/modules/feature_toggles/data/validators.js.map +2 -2
  256. package/dist/modules/inbox_ops/api/settings/route.js +17 -2
  257. package/dist/modules/inbox_ops/api/settings/route.js.map +2 -2
  258. package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js +13 -8
  259. package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js.map +2 -2
  260. package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js +9 -4
  261. package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js.map +2 -2
  262. package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js +18 -11
  263. package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js.map +2 -2
  264. package/dist/modules/integrations/backend/integrations/page.js +12 -8
  265. package/dist/modules/integrations/backend/integrations/page.js.map +2 -2
  266. package/dist/modules/messages/commands/messages.js +13 -10
  267. package/dist/modules/messages/commands/messages.js.map +2 -2
  268. package/dist/modules/perspectives/api/[tableId]/route.js +39 -30
  269. package/dist/modules/perspectives/api/[tableId]/route.js.map +2 -2
  270. package/dist/modules/perspectives/services/perspectiveService.js +7 -0
  271. package/dist/modules/perspectives/services/perspectiveService.js.map +2 -2
  272. package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js +6 -14
  273. package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js.map +3 -3
  274. package/dist/modules/planner/backend/planner/availability-rulesets/page.js +4 -2
  275. package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
  276. package/dist/modules/planner/components/AvailabilityRuleSetForm.js +2 -0
  277. package/dist/modules/planner/components/AvailabilityRuleSetForm.js.map +2 -2
  278. package/dist/modules/planner/components/AvailabilityRulesEditor.js +36 -11
  279. package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
  280. package/dist/modules/planner/components/AvailabilitySchedule.js +9 -5
  281. package/dist/modules/planner/components/AvailabilitySchedule.js.map +2 -2
  282. package/dist/modules/progress/api/jobs/[id]/route.js +7 -1
  283. package/dist/modules/progress/api/jobs/[id]/route.js.map +2 -2
  284. package/dist/modules/query_index/lib/engine.js +19 -0
  285. package/dist/modules/query_index/lib/engine.js.map +2 -2
  286. package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js +1 -0
  287. package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js.map +2 -2
  288. package/dist/modules/resources/backend/resources/resource-types/page.js +4 -2
  289. package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
  290. package/dist/modules/resources/backend/resources/resources/[id]/page.js +14 -3
  291. package/dist/modules/resources/backend/resources/resources/[id]/page.js.map +2 -2
  292. package/dist/modules/resources/backend/resources/resources/page.js +8 -4
  293. package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
  294. package/dist/modules/resources/components/ResourceCrudForm.js +2 -0
  295. package/dist/modules/resources/components/ResourceCrudForm.js.map +2 -2
  296. package/dist/modules/resources/components/ResourceTypeCrudForm.js +1 -0
  297. package/dist/modules/resources/components/ResourceTypeCrudForm.js.map +2 -2
  298. package/dist/modules/sales/api/documents/factory.js +7 -2
  299. package/dist/modules/sales/api/documents/factory.js.map +2 -2
  300. package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js +3 -1
  301. package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js.map +2 -2
  302. package/dist/modules/sales/backend/sales/channels/offers/page.js +13 -4
  303. package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
  304. package/dist/modules/sales/backend/sales/channels/page.js +16 -4
  305. package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
  306. package/dist/modules/sales/backend/sales/documents/[id]/page.js +68 -22
  307. package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
  308. package/dist/modules/sales/backend/sales/documents/create/page.js.map +2 -2
  309. package/dist/modules/sales/commands/documentAddresses.js +181 -2
  310. package/dist/modules/sales/commands/documentAddresses.js.map +2 -2
  311. package/dist/modules/sales/commands/documents.js +29 -1
  312. package/dist/modules/sales/commands/documents.js.map +2 -2
  313. package/dist/modules/sales/commands/returns.js +12 -2
  314. package/dist/modules/sales/commands/returns.js.map +2 -2
  315. package/dist/modules/sales/commands/shared.js +15 -0
  316. package/dist/modules/sales/commands/shared.js.map +2 -2
  317. package/dist/modules/sales/commands/shipments.js +4 -1
  318. package/dist/modules/sales/commands/shipments.js.map +2 -2
  319. package/dist/modules/sales/components/AdjustmentKindSettings.js +19 -11
  320. package/dist/modules/sales/components/AdjustmentKindSettings.js.map +2 -2
  321. package/dist/modules/sales/components/DocumentNumberSettings.js.map +2 -2
  322. package/dist/modules/sales/components/OrderEditingSettings.js.map +2 -2
  323. package/dist/modules/sales/components/PaymentMethodsSettings.js +12 -4
  324. package/dist/modules/sales/components/PaymentMethodsSettings.js.map +2 -2
  325. package/dist/modules/sales/components/ShippingMethodsSettings.js +12 -4
  326. package/dist/modules/sales/components/ShippingMethodsSettings.js.map +2 -2
  327. package/dist/modules/sales/components/StatusSettings.js +18 -11
  328. package/dist/modules/sales/components/StatusSettings.js.map +2 -2
  329. package/dist/modules/sales/components/TaxRatesSettings.js +12 -4
  330. package/dist/modules/sales/components/TaxRatesSettings.js.map +2 -2
  331. package/dist/modules/sales/components/channels/ChannelOfferForm.js +47 -16
  332. package/dist/modules/sales/components/channels/ChannelOfferForm.js.map +2 -2
  333. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +8 -4
  334. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
  335. package/dist/modules/sales/components/documents/AddressesSection.js +44 -25
  336. package/dist/modules/sales/components/documents/AddressesSection.js.map +2 -2
  337. package/dist/modules/sales/components/documents/AdjustmentsSection.js +43 -23
  338. package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
  339. package/dist/modules/sales/components/documents/ItemsSection.js +22 -13
  340. package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
  341. package/dist/modules/sales/components/documents/LineItemDialog.js +23 -10
  342. package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
  343. package/dist/modules/sales/components/documents/PaymentDialog.js +29 -14
  344. package/dist/modules/sales/components/documents/PaymentDialog.js.map +2 -2
  345. package/dist/modules/sales/components/documents/PaymentsSection.js +20 -10
  346. package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
  347. package/dist/modules/sales/components/documents/ReturnDialog.js +26 -17
  348. package/dist/modules/sales/components/documents/ReturnDialog.js.map +2 -2
  349. package/dist/modules/sales/components/documents/ReturnsSection.js +3 -1
  350. package/dist/modules/sales/components/documents/ReturnsSection.js.map +2 -2
  351. package/dist/modules/sales/components/documents/SalesDocumentsTable.js +10 -5
  352. package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
  353. package/dist/modules/sales/components/documents/ShipmentDialog.js +21 -7
  354. package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
  355. package/dist/modules/sales/components/documents/ShipmentsSection.js +19 -10
  356. package/dist/modules/sales/components/documents/ShipmentsSection.js.map +2 -2
  357. package/dist/modules/sales/components/documents/optimisticLock.js +27 -0
  358. package/dist/modules/sales/components/documents/optimisticLock.js.map +7 -0
  359. package/dist/modules/sales/di.js +18 -0
  360. package/dist/modules/sales/di.js.map +2 -2
  361. package/dist/modules/shipping_carriers/api/cancel/route.js +2 -2
  362. package/dist/modules/shipping_carriers/api/cancel/route.js.map +2 -2
  363. package/dist/modules/shipping_carriers/lib/status-sync.js +8 -1
  364. package/dist/modules/shipping_carriers/lib/status-sync.js.map +2 -2
  365. package/dist/modules/staff/api/job-histories.js +11 -2
  366. package/dist/modules/staff/api/job-histories.js.map +2 -2
  367. package/dist/modules/staff/api/timesheets/time-entries/route.js +11 -4
  368. package/dist/modules/staff/api/timesheets/time-entries/route.js.map +2 -2
  369. package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js +13 -8
  370. package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js.map +2 -2
  371. package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js +2 -1
  372. package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js.map +2 -2
  373. package/dist/modules/staff/backend/staff/team-members/[id]/page.js +7 -4
  374. package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
  375. package/dist/modules/staff/backend/staff/team-members/page.js +4 -2
  376. package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
  377. package/dist/modules/staff/backend/staff/team-roles/[id]/edit/page.js +1 -0
  378. package/dist/modules/staff/backend/staff/team-roles/[id]/edit/page.js.map +2 -2
  379. package/dist/modules/staff/backend/staff/team-roles/page.js +4 -2
  380. package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
  381. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +5 -2
  382. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
  383. package/dist/modules/staff/backend/staff/teams/page.js +12 -3
  384. package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
  385. package/dist/modules/staff/backend/staff/timesheets/page.js +4 -1
  386. package/dist/modules/staff/backend/staff/timesheets/page.js.map +2 -2
  387. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js.map +2 -2
  388. package/dist/modules/staff/backend/staff/timesheets/projects/page.js +12 -3
  389. package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +2 -2
  390. package/dist/modules/staff/commands/job-histories.js +40 -3
  391. package/dist/modules/staff/commands/job-histories.js.map +2 -2
  392. package/dist/modules/staff/components/LeaveRequestForm.js +1 -0
  393. package/dist/modules/staff/components/LeaveRequestForm.js.map +2 -2
  394. package/dist/modules/staff/components/TeamForm.js +1 -0
  395. package/dist/modules/staff/components/TeamForm.js.map +2 -2
  396. package/dist/modules/staff/components/TeamMemberForm.js +1 -0
  397. package/dist/modules/staff/components/TeamMemberForm.js.map +2 -2
  398. package/dist/modules/staff/components/TeamRoleForm.js +1 -0
  399. package/dist/modules/staff/components/TeamRoleForm.js.map +2 -2
  400. package/dist/modules/staff/components/detail/JobHistorySection.js +20 -7
  401. package/dist/modules/staff/components/detail/JobHistorySection.js.map +2 -2
  402. package/dist/modules/staff/data/validators.js +7 -1
  403. package/dist/modules/staff/data/validators.js.map +2 -2
  404. package/dist/modules/staff/lib/leaveRequestHelpers.js +2 -1
  405. package/dist/modules/staff/lib/leaveRequestHelpers.js.map +2 -2
  406. package/dist/modules/translations/components/TranslationManager.js +12 -8
  407. package/dist/modules/translations/components/TranslationManager.js.map +2 -2
  408. package/dist/modules/workflows/api/definitions/[id]/route.js +106 -0
  409. package/dist/modules/workflows/api/definitions/[id]/route.js.map +2 -2
  410. package/dist/modules/workflows/backend/definitions/[id]/page.js +11 -3
  411. package/dist/modules/workflows/backend/definitions/[id]/page.js.map +2 -2
  412. package/dist/modules/workflows/backend/definitions/page.js +19 -8
  413. package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
  414. package/dist/modules/workflows/backend/definitions/visual-editor/page.js +29 -16
  415. package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
  416. package/dist/modules/workflows/components/NodeEditDialog.js +3 -1
  417. package/dist/modules/workflows/components/NodeEditDialog.js.map +2 -2
  418. package/dist/modules/workflows/components/WorkflowGraphImpl.js +4 -2
  419. package/dist/modules/workflows/components/WorkflowGraphImpl.js.map +2 -2
  420. package/dist/modules/workflows/components/formConfig.js +4 -1
  421. package/dist/modules/workflows/components/formConfig.js.map +2 -2
  422. package/dist/modules/workflows/components/nodes/ParallelForkNode.js +49 -0
  423. package/dist/modules/workflows/components/nodes/ParallelForkNode.js.map +7 -0
  424. package/dist/modules/workflows/components/nodes/ParallelJoinNode.js +49 -0
  425. package/dist/modules/workflows/components/nodes/ParallelJoinNode.js.map +7 -0
  426. package/dist/modules/workflows/components/nodes/index.js +4 -0
  427. package/dist/modules/workflows/components/nodes/index.js.map +2 -2
  428. package/dist/modules/workflows/data/entities.js +81 -0
  429. package/dist/modules/workflows/data/entities.js.map +2 -2
  430. package/dist/modules/workflows/data/validators.js +146 -1
  431. package/dist/modules/workflows/data/validators.js.map +2 -2
  432. package/dist/modules/workflows/di.js +12 -0
  433. package/dist/modules/workflows/di.js.map +2 -2
  434. package/dist/modules/workflows/events.js +7 -1
  435. package/dist/modules/workflows/events.js.map +2 -2
  436. package/dist/modules/workflows/lib/activity-executor.js +4 -2
  437. package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
  438. package/dist/modules/workflows/lib/activity-queue-types.js.map +2 -2
  439. package/dist/modules/workflows/lib/event-logger.js +2 -0
  440. package/dist/modules/workflows/lib/event-logger.js.map +2 -2
  441. package/dist/modules/workflows/lib/execution-token.js +98 -0
  442. package/dist/modules/workflows/lib/execution-token.js.map +7 -0
  443. package/dist/modules/workflows/lib/node-type-icons.js +14 -5
  444. package/dist/modules/workflows/lib/node-type-icons.js.map +2 -2
  445. package/dist/modules/workflows/lib/parallel-handler.js +364 -0
  446. package/dist/modules/workflows/lib/parallel-handler.js.map +7 -0
  447. package/dist/modules/workflows/lib/signal-handler.js +63 -1
  448. package/dist/modules/workflows/lib/signal-handler.js.map +2 -2
  449. package/dist/modules/workflows/lib/step-handler.js +74 -30
  450. package/dist/modules/workflows/lib/step-handler.js.map +2 -2
  451. package/dist/modules/workflows/lib/task-handler.js +26 -0
  452. package/dist/modules/workflows/lib/task-handler.js.map +2 -2
  453. package/dist/modules/workflows/lib/timer-handler.js +26 -1
  454. package/dist/modules/workflows/lib/timer-handler.js.map +2 -2
  455. package/dist/modules/workflows/lib/transition-handler.js +33 -21
  456. package/dist/modules/workflows/lib/transition-handler.js.map +2 -2
  457. package/dist/modules/workflows/lib/workflow-executor.js +39 -1
  458. package/dist/modules/workflows/lib/workflow-executor.js.map +2 -2
  459. package/dist/modules/workflows/migrations/Migration20260602120000.js +24 -0
  460. package/dist/modules/workflows/migrations/Migration20260602120000.js.map +7 -0
  461. package/dist/modules/workflows/workers/workflow-activities.worker.js +8 -4
  462. package/dist/modules/workflows/workers/workflow-activities.worker.js.map +2 -2
  463. package/generated/entities/role/index.ts +1 -0
  464. package/generated/entities/step_instance/index.ts +1 -0
  465. package/generated/entities/user/index.ts +1 -0
  466. package/generated/entities/user_task/index.ts +1 -0
  467. package/generated/entities/workflow_branch_instance/index.ts +18 -0
  468. package/generated/entities/workflow_event/index.ts +1 -0
  469. package/generated/entities/workflow_instance/index.ts +1 -0
  470. package/generated/entities.ids.generated.ts +1 -0
  471. package/generated/entity-fields-registry.ts +26 -0
  472. package/jest.setup.ts +17 -0
  473. package/package.json +8 -7
  474. package/src/helpers/integration/optimisticLockUi.ts +172 -0
  475. package/src/helpers/integration/salesFixtures.ts +29 -0
  476. package/src/modules/api_keys/backend/api-keys/page.tsx +10 -5
  477. package/src/modules/attachments/components/AttachmentPartitionSettings.tsx +19 -9
  478. package/src/modules/auth/api/roles/acl/route.ts +37 -11
  479. package/src/modules/auth/api/roles/route.ts +2 -0
  480. package/src/modules/auth/api/sidebar/preferences/route.ts +73 -0
  481. package/src/modules/auth/api/users/acl/route.ts +46 -18
  482. package/src/modules/auth/api/users/route.ts +2 -0
  483. package/src/modules/auth/backend/roles/[id]/edit/page.tsx +29 -4
  484. package/src/modules/auth/backend/roles/page.tsx +9 -4
  485. package/src/modules/auth/backend/users/[id]/edit/page.tsx +37 -4
  486. package/src/modules/auth/backend/users/page.tsx +7 -2
  487. package/src/modules/auth/components/AclEditor.tsx +10 -1
  488. package/src/modules/auth/data/entities.ts +7 -1
  489. package/src/modules/auth/services/sidebarPreferencesService.ts +38 -4
  490. package/src/modules/business_rules/api/rules/route.ts +30 -0
  491. package/src/modules/business_rules/api/sets/route.ts +30 -0
  492. package/src/modules/business_rules/backend/rules/[id]/page.tsx +16 -4
  493. package/src/modules/business_rules/backend/rules/page.tsx +20 -11
  494. package/src/modules/business_rules/backend/sets/[id]/page.tsx +16 -4
  495. package/src/modules/business_rules/backend/sets/page.tsx +20 -11
  496. package/src/modules/catalog/api/categories/route.ts +3 -0
  497. package/src/modules/catalog/api/products/route.ts +4 -0
  498. package/src/modules/catalog/backend/catalog/categories/[id]/edit/page.tsx +5 -0
  499. package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +112 -35
  500. package/src/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.tsx +56 -7
  501. package/src/modules/catalog/backend/catalog/products/optionSchemaClient.ts +2 -0
  502. package/src/modules/catalog/commands/variants.ts +32 -32
  503. package/src/modules/catalog/components/PriceKindSettings.tsx +20 -7
  504. package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +1 -0
  505. package/src/modules/catalog/components/products/ProductMediaManager.tsx +2 -0
  506. package/src/modules/catalog/components/products/ProductsDataTable.tsx +8 -4
  507. package/src/modules/catalog/components/products/productForm.ts +3 -0
  508. package/src/modules/catalog/components/products/variantForm.ts +9 -0
  509. package/src/modules/communication_channels/backend/profile/communication-channels/page.tsx +5 -0
  510. package/src/modules/currencies/backend/currencies/[id]/page.tsx +13 -6
  511. package/src/modules/currencies/backend/currencies/page.tsx +18 -11
  512. package/src/modules/currencies/backend/exchange-rates/[id]/page.tsx +3 -0
  513. package/src/modules/currencies/backend/exchange-rates/page.tsx +10 -6
  514. package/src/modules/currencies/commands/currencies.ts +10 -5
  515. package/src/modules/currencies/components/CurrencyFetchingConfig.tsx +31 -21
  516. package/src/modules/customer_accounts/api/admin/roles/[id].ts +35 -5
  517. package/src/modules/customer_accounts/api/admin/roles.ts +2 -0
  518. package/src/modules/customer_accounts/api/admin/users/[id].ts +38 -5
  519. package/src/modules/customer_accounts/api/admin/users.ts +2 -0
  520. package/src/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.tsx +34 -20
  521. package/src/modules/customer_accounts/backend/customer_accounts/roles/page.tsx +9 -4
  522. package/src/modules/customer_accounts/backend/customer_accounts/settings/domain/page.tsx +11 -4
  523. package/src/modules/customer_accounts/backend/customer_accounts/users/[id]/page.tsx +28 -17
  524. package/src/modules/customer_accounts/backend/customer_accounts/users/page.tsx +19 -11
  525. package/src/modules/customers/AGENTS.md +2 -2
  526. package/src/modules/customers/api/companies/route.ts +14 -1
  527. package/src/modules/customers/api/deals/route.ts +3 -0
  528. package/src/modules/customers/api/people/route.ts +12 -1
  529. package/src/modules/customers/api/todos/route.ts +1 -0
  530. package/src/modules/customers/backend/config/customers/deals/page.tsx +1 -0
  531. package/src/modules/customers/backend/config/customers/pipeline-stages/page.tsx +36 -21
  532. package/src/modules/customers/backend/customers/companies/[id]/page.tsx +52 -27
  533. package/src/modules/customers/backend/customers/companies/page.tsx +2 -0
  534. package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +27 -5
  535. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.ts +39 -7
  536. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +1 -0
  537. package/src/modules/customers/backend/customers/deals/page.tsx +18 -6
  538. package/src/modules/customers/backend/customers/deals/pipeline/page.tsx +64 -39
  539. package/src/modules/customers/backend/customers/people/[id]/page.tsx +46 -26
  540. package/src/modules/customers/backend/customers/people/page.tsx +2 -0
  541. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +84 -24
  542. package/src/modules/customers/commands/addresses.ts +16 -14
  543. package/src/modules/customers/commands/companies.ts +3 -1
  544. package/src/modules/customers/commands/interactions.ts +50 -4
  545. package/src/modules/customers/commands/people.ts +2 -1
  546. package/src/modules/customers/commands/personCompanyLinks.ts +8 -5
  547. package/src/modules/customers/commands/pipeline-stages.ts +16 -16
  548. package/src/modules/customers/components/AddressFormatSettings.tsx +1 -0
  549. package/src/modules/customers/components/DictionarySettings.tsx +18 -13
  550. package/src/modules/customers/components/DictionarySortSettings.tsx +4 -0
  551. package/src/modules/customers/components/PipelineSettings.tsx +42 -21
  552. package/src/modules/customers/components/detail/ActivityTimeline.tsx +3 -3
  553. package/src/modules/customers/components/detail/AddressesSection.tsx +4 -0
  554. package/src/modules/customers/components/detail/CompanyPeopleSection.tsx +2 -0
  555. package/src/modules/customers/components/detail/DealsSection.tsx +4 -0
  556. package/src/modules/customers/components/detail/EmailCardActions.tsx +5 -0
  557. package/src/modules/customers/components/detail/EntityTagsDialog.tsx +7 -0
  558. package/src/modules/customers/components/detail/ManageTagsDialog.tsx +4 -0
  559. package/src/modules/customers/components/detail/PersonCompaniesSection.tsx +4 -0
  560. package/src/modules/customers/components/detail/RoleAssignmentRow.tsx +2 -0
  561. package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +23 -7
  562. package/src/modules/customers/components/detail/hooks/useInteractionMutations.ts +25 -15
  563. package/src/modules/customers/components/detail/hooks/useInteractions.ts +76 -35
  564. package/src/modules/customers/components/detail/hooks/usePersonTasks.ts +30 -17
  565. package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +2 -0
  566. package/src/modules/customers/components/detail/types.ts +1 -0
  567. package/src/modules/customers/components/formConfig.tsx +2 -0
  568. package/src/modules/customers/data/guards.ts +67 -0
  569. package/src/modules/customers/di.ts +66 -0
  570. package/src/modules/customers/i18n/de.json +2 -0
  571. package/src/modules/customers/i18n/en.json +2 -0
  572. package/src/modules/customers/i18n/es.json +2 -0
  573. package/src/modules/customers/i18n/pl.json +2 -0
  574. package/src/modules/customers/lib/todoCompatibility.ts +14 -0
  575. package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +2 -0
  576. package/src/modules/data_sync/api/options.ts +7 -4
  577. package/src/modules/data_sync/api/schedules/route.ts +9 -1
  578. package/src/modules/data_sync/backend/data-sync/page.tsx +18 -5
  579. package/src/modules/data_sync/components/IntegrationScheduleTab.tsx +46 -19
  580. package/src/modules/data_sync/lib/sync-schedule-service.ts +11 -0
  581. package/src/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.ts +8 -1
  582. package/src/modules/dictionaries/api/[dictionaryId]/route.ts +23 -0
  583. package/src/modules/dictionaries/components/DictionariesManager.tsx +32 -9
  584. package/src/modules/dictionaries/components/DictionaryEntriesEditor.tsx +30 -14
  585. package/src/modules/dictionaries/i18n/de.json +1 -0
  586. package/src/modules/dictionaries/i18n/en.json +1 -0
  587. package/src/modules/dictionaries/i18n/es.json +1 -0
  588. package/src/modules/dictionaries/i18n/pl.json +1 -0
  589. package/src/modules/directory/api/organizations/route.ts +3 -0
  590. package/src/modules/directory/backend/directory/organizations/[id]/edit/page.tsx +8 -0
  591. package/src/modules/directory/backend/directory/organizations/page.tsx +10 -5
  592. package/src/modules/directory/backend/directory/tenants/[id]/edit/page.tsx +16 -5
  593. package/src/modules/directory/backend/directory/tenants/page.tsx +8 -4
  594. package/src/modules/directory/commands/organizations.ts +7 -4
  595. package/src/modules/entities/api/records.ts +99 -0
  596. package/src/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.tsx +7 -0
  597. package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +8 -4
  598. package/src/modules/entities/lib/helpers.ts +17 -0
  599. package/src/modules/feature_toggles/api/global/[id]/override/route.ts +1 -0
  600. package/src/modules/feature_toggles/api/overrides/route.ts +19 -0
  601. package/src/modules/feature_toggles/backend/feature-toggles/global/[id]/edit/page.tsx +19 -13
  602. package/src/modules/feature_toggles/components/FeatureToggleOverrideCard.tsx +22 -12
  603. package/src/modules/feature_toggles/components/FeatureTogglesTable.tsx +7 -2
  604. package/src/modules/feature_toggles/components/formConfig.tsx +2 -1
  605. package/src/modules/feature_toggles/components/overrideFormConfig.tsx +10 -1
  606. package/src/modules/feature_toggles/data/validators.ts +11 -3
  607. package/src/modules/inbox_ops/api/settings/route.ts +18 -0
  608. package/src/modules/inbox_ops/backend/inbox-ops/settings/page.tsx +15 -10
  609. package/src/modules/inbox_ops/components/proposals/EditActionDialog.tsx +9 -4
  610. package/src/modules/integrations/backend/integrations/bundle/[id]/page.tsx +20 -11
  611. package/src/modules/integrations/backend/integrations/page.tsx +13 -8
  612. package/src/modules/messages/commands/messages.ts +27 -15
  613. package/src/modules/perspectives/api/[tableId]/route.ts +11 -2
  614. package/src/modules/perspectives/services/perspectiveService.ts +13 -1
  615. package/src/modules/planner/backend/planner/availability-rulesets/[id]/page.tsx +16 -14
  616. package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +6 -3
  617. package/src/modules/planner/components/AvailabilityRuleSetForm.tsx +3 -0
  618. package/src/modules/planner/components/AvailabilityRulesEditor.tsx +58 -15
  619. package/src/modules/planner/components/AvailabilitySchedule.tsx +22 -7
  620. package/src/modules/progress/api/jobs/[id]/route.ts +7 -0
  621. package/src/modules/query_index/lib/engine.ts +34 -0
  622. package/src/modules/resources/backend/resources/resource-types/[id]/edit/page.tsx +7 -1
  623. package/src/modules/resources/backend/resources/resource-types/page.tsx +6 -3
  624. package/src/modules/resources/backend/resources/resources/[id]/page.tsx +23 -3
  625. package/src/modules/resources/backend/resources/resources/page.tsx +15 -4
  626. package/src/modules/resources/components/ResourceCrudForm.tsx +3 -0
  627. package/src/modules/resources/components/ResourceTypeCrudForm.tsx +2 -0
  628. package/src/modules/sales/api/documents/factory.ts +13 -1
  629. package/src/modules/sales/backend/sales/channels/[channelId]/edit/page.tsx +6 -0
  630. package/src/modules/sales/backend/sales/channels/offers/page.tsx +10 -4
  631. package/src/modules/sales/backend/sales/channels/page.tsx +19 -4
  632. package/src/modules/sales/backend/sales/documents/[id]/page.tsx +73 -20
  633. package/src/modules/sales/backend/sales/documents/create/page.tsx +2 -0
  634. package/src/modules/sales/commands/documentAddresses.ts +226 -4
  635. package/src/modules/sales/commands/documents.ts +28 -0
  636. package/src/modules/sales/commands/returns.ts +12 -3
  637. package/src/modules/sales/commands/shared.ts +36 -0
  638. package/src/modules/sales/commands/shipments.ts +17 -1
  639. package/src/modules/sales/components/AdjustmentKindSettings.tsx +20 -11
  640. package/src/modules/sales/components/DocumentNumberSettings.tsx +1 -0
  641. package/src/modules/sales/components/OrderEditingSettings.tsx +1 -0
  642. package/src/modules/sales/components/PaymentMethodsSettings.tsx +12 -4
  643. package/src/modules/sales/components/ShippingMethodsSettings.tsx +12 -4
  644. package/src/modules/sales/components/StatusSettings.tsx +20 -11
  645. package/src/modules/sales/components/TaxRatesSettings.tsx +12 -5
  646. package/src/modules/sales/components/channels/ChannelOfferForm.tsx +67 -14
  647. package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +7 -4
  648. package/src/modules/sales/components/documents/AddressesSection.tsx +35 -25
  649. package/src/modules/sales/components/documents/AdjustmentsSection.tsx +50 -25
  650. package/src/modules/sales/components/documents/ItemsSection.tsx +24 -13
  651. package/src/modules/sales/components/documents/LineItemDialog.tsx +26 -9
  652. package/src/modules/sales/components/documents/PaymentDialog.tsx +33 -14
  653. package/src/modules/sales/components/documents/PaymentsSection.tsx +22 -10
  654. package/src/modules/sales/components/documents/ReturnDialog.tsx +28 -17
  655. package/src/modules/sales/components/documents/ReturnsSection.tsx +4 -1
  656. package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +11 -4
  657. package/src/modules/sales/components/documents/ShipmentDialog.tsx +23 -8
  658. package/src/modules/sales/components/documents/ShipmentsSection.tsx +20 -10
  659. package/src/modules/sales/components/documents/optimisticLock.ts +34 -0
  660. package/src/modules/sales/components/documents/shipmentTypes.ts +1 -0
  661. package/src/modules/sales/di.ts +35 -0
  662. package/src/modules/sales/i18n/de.json +3 -0
  663. package/src/modules/sales/i18n/en.json +3 -0
  664. package/src/modules/sales/i18n/es.json +3 -0
  665. package/src/modules/sales/i18n/pl.json +3 -0
  666. package/src/modules/shipping_carriers/api/cancel/route.ts +2 -2
  667. package/src/modules/shipping_carriers/lib/status-sync.ts +19 -0
  668. package/src/modules/staff/api/job-histories.ts +12 -2
  669. package/src/modules/staff/api/timesheets/time-entries/route.ts +16 -4
  670. package/src/modules/staff/backend/staff/leave-requests/[id]/page.tsx +12 -7
  671. package/src/modules/staff/backend/staff/my-leave-requests/[id]/page.tsx +2 -0
  672. package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +16 -5
  673. package/src/modules/staff/backend/staff/team-members/page.tsx +6 -2
  674. package/src/modules/staff/backend/staff/team-roles/[id]/edit/page.tsx +8 -0
  675. package/src/modules/staff/backend/staff/team-roles/page.tsx +6 -2
  676. package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +13 -3
  677. package/src/modules/staff/backend/staff/teams/page.tsx +9 -3
  678. package/src/modules/staff/backend/staff/timesheets/page.tsx +10 -1
  679. package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.tsx +4 -0
  680. package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +9 -3
  681. package/src/modules/staff/commands/job-histories.ts +42 -3
  682. package/src/modules/staff/components/LeaveRequestForm.tsx +2 -0
  683. package/src/modules/staff/components/TeamForm.tsx +2 -0
  684. package/src/modules/staff/components/TeamMemberForm.tsx +2 -0
  685. package/src/modules/staff/components/TeamRoleForm.tsx +2 -0
  686. package/src/modules/staff/components/detail/JobHistorySection.tsx +28 -6
  687. package/src/modules/staff/data/validators.ts +6 -0
  688. package/src/modules/staff/i18n/de.json +1 -0
  689. package/src/modules/staff/i18n/en.json +1 -0
  690. package/src/modules/staff/i18n/es.json +1 -0
  691. package/src/modules/staff/i18n/pl.json +1 -0
  692. package/src/modules/staff/lib/leaveRequestHelpers.ts +4 -0
  693. package/src/modules/translations/components/TranslationManager.tsx +13 -8
  694. package/src/modules/workflows/api/definitions/[id]/route.ts +112 -0
  695. package/src/modules/workflows/backend/definitions/[id]/page.tsx +20 -4
  696. package/src/modules/workflows/backend/definitions/page.tsx +20 -9
  697. package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +29 -16
  698. package/src/modules/workflows/components/NodeEditDialog.tsx +2 -0
  699. package/src/modules/workflows/components/WorkflowGraphImpl.tsx +3 -1
  700. package/src/modules/workflows/components/formConfig.tsx +5 -0
  701. package/src/modules/workflows/components/nodes/ParallelForkNode.tsx +66 -0
  702. package/src/modules/workflows/components/nodes/ParallelJoinNode.tsx +66 -0
  703. package/src/modules/workflows/components/nodes/index.ts +6 -0
  704. package/src/modules/workflows/data/entities.ts +109 -0
  705. package/src/modules/workflows/data/validators.ts +223 -0
  706. package/src/modules/workflows/di.ts +20 -0
  707. package/src/modules/workflows/events.ts +7 -0
  708. package/src/modules/workflows/i18n/de.json +13 -0
  709. package/src/modules/workflows/i18n/en.json +13 -0
  710. package/src/modules/workflows/i18n/es.json +13 -0
  711. package/src/modules/workflows/i18n/pl.json +13 -0
  712. package/src/modules/workflows/lib/activity-executor.ts +8 -2
  713. package/src/modules/workflows/lib/activity-queue-types.ts +3 -0
  714. package/src/modules/workflows/lib/event-logger.ts +3 -0
  715. package/src/modules/workflows/lib/execution-token.ts +166 -0
  716. package/src/modules/workflows/lib/node-type-icons.ts +11 -2
  717. package/src/modules/workflows/lib/parallel-handler.ts +575 -0
  718. package/src/modules/workflows/lib/signal-handler.ts +72 -1
  719. package/src/modules/workflows/lib/step-handler.ts +94 -34
  720. package/src/modules/workflows/lib/task-handler.ts +32 -0
  721. package/src/modules/workflows/lib/timer-handler.ts +30 -1
  722. package/src/modules/workflows/lib/transition-handler.ts +56 -24
  723. package/src/modules/workflows/lib/workflow-executor.ts +53 -1
  724. package/src/modules/workflows/migrations/.snapshot-open-mercato.json +263 -0
  725. package/src/modules/workflows/migrations/Migration20260602120000.ts +25 -0
  726. package/src/modules/workflows/workers/workflow-activities.worker.ts +9 -4
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/modules/customers/backend/customers/deals/page.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { usePathname, useRouter, useSearchParams } from 'next/navigation'\nimport { useQueryClient } from '@tanstack/react-query'\nimport type { ColumnDef } from '@tanstack/react-table'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable, type DataTableExportFormat, withDataTableNamespaces } from '@open-mercato/ui/backend/DataTable'\nimport type { AdvancedFilterTree } from '@open-mercato/shared/lib/query/advanced-filter-tree'\nimport { createEmptyTree, makeRuleTree, makeMultiRuleTree } from '@open-mercato/shared/lib/query/advanced-filter-tree'\nimport { deserializeTree, deserializeAdvancedFilter, flatToTree, mapDictionaryColorToTone, serializeTree, type FilterFieldDef, type FilterOption as AdvancedFilterOption } from '@open-mercato/shared/lib/query/advanced-filter'\nimport { useCurrentUserId } from '@open-mercato/ui/backend/utils/useCurrentUserId'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildCrudExportUrl, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { groupBulkDeleteFailures, runBulkDelete } from '@open-mercato/ui/backend/utils/bulkDelete'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { coalesceLastOperations } from '@open-mercato/ui/backend/operations/store'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { ViewTabsRow } from './pipeline/components/ViewTabsRow'\nimport { E } from '#generated/entities.ids.generated'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport {\n DictionaryValue,\n type CustomerDictionaryKind,\n type CustomerDictionaryMap,\n} from '../../../lib/dictionaries'\nimport {\n ensureCustomerDictionary,\n invalidateCustomerDictionary,\n} from '../../../components/detail/hooks/useCustomerDictionary'\nimport {\n useCustomFieldDefs,\n} from '@open-mercato/ui/backend/utils/customFieldDefs'\nimport {\n mapCustomFieldKindToFilterType,\n normalizeCustomFieldFilterOptions,\n supportsCustomFieldColumn,\n} from '@open-mercato/ui/backend/utils/customFieldColumns'\nimport { CollectionPreviewCell, normalizeCollectionLabels } from '../../../components/list/CollectionPreviewCell'\nimport { useAutoDiscoveredFields } from '@open-mercato/ui/backend/utils/useAutoDiscoveredFields'\nimport { useAdvancedFilterTree } from '@open-mercato/ui/backend/hooks/useAdvancedFilter'\nimport { AdvancedFilterPanel } from '@open-mercato/ui/backend/filters/AdvancedFilterPanel'\nimport { ActiveFilterChips } from '@open-mercato/ui/backend/filters/ActiveFilterChips'\nimport type { FilterPreset } from '@open-mercato/ui/backend/filters/QuickFilters'\nimport {\n ensureCurrentUserFilterOption,\n fetchAssignableStaffMembers,\n mapAssignableStaffToFilterOptions,\n} from '../../../components/detail/assignableStaff'\n\nfunction makeDealsPresets(): FilterPreset[] {\n return [\n {\n id: 'my-deals',\n labelKey: 'customers.deals.presets.myDeals',\n requiresUser: true,\n build: ({ userId }) => makeRuleTree({ field: 'owner_user_id', operator: 'is', value: userId }),\n },\n {\n id: 'closing-month',\n labelKey: 'customers.deals.presets.closingMonth',\n iconName: 'clock',\n build: ({ now }) => {\n const start = new Date(now.getFullYear(), now.getMonth(), 1).toISOString().slice(0, 10)\n const end = new Date(now.getFullYear(), now.getMonth() + 1, 0).toISOString().slice(0, 10)\n return makeRuleTree({ field: 'expected_close_at', operator: 'between', value: [start, end] })\n },\n },\n // The Deal entity has no dedicated \"at risk\" or health-score field \u2014 `customer_deals`\n // exposes only `status` (open/win/loose/closed/in_progress, dictionary-driven) and\n // `closure_outcome`. Rather than fabricate a mapping, the \"At risk\" preset is omitted\n // until the data model exposes a first-class signal.\n {\n id: 'won-quarter',\n labelKey: 'customers.deals.presets.wonQuarter',\n build: ({ now }) => {\n const quarter = Math.floor(now.getMonth() / 3)\n const start = new Date(now.getFullYear(), quarter * 3, 1).toISOString().slice(0, 10)\n return makeMultiRuleTree([\n { field: 'status', operator: 'is', value: 'win' },\n { field: 'expected_close_at', operator: 'is_after', value: start },\n ], 'and')\n },\n },\n ]\n}\n\ntype DealRow = {\n id: string\n title: string\n status?: string | null\n pipelineStage?: string | null\n pipelineStageId?: string | null\n pipelineId?: string | null\n valueAmount?: number | null\n valueCurrency?: string | null\n probability?: number | null\n expectedCloseAt?: string | null\n updatedAt?: string | null\n ownerUserId?: string | null\n companies: { id: string; label: string }[]\n people: { id: string; label: string }[]\n} & Record<string, unknown>\n\ntype DealsResponse = {\n items?: Array<Record<string, unknown>>\n total?: number\n totalPages?: number\n}\n\ntype FilterOption = { value: string; label: string }\ntype DictionaryOptionWithTone = AdvancedFilterOption & FilterOption\n\ntype DictionaryKey = Extract<CustomerDictionaryKind, 'deal-statuses' | 'pipeline-stages'>\n\nconst PAGE_SIZE = 20\nconst UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i\n\nfunction isUuid(value: string | null | undefined): value is string {\n if (!value) return false\n return UUID_REGEX.test(value.trim())\n}\n\nfunction normalizeIdCandidates(raw: Array<string>): string[] {\n const set = new Set<string>()\n raw.forEach((candidate) => {\n candidate\n .split(',')\n .map((part) => part.trim())\n .filter((part) => part.length > 0)\n .forEach((part) => {\n if (isUuid(part)) set.add(part)\n })\n })\n return Array.from(set)\n}\n\nfunction extractIdsFromParams(params: URLSearchParams | null | undefined, key: string): string[] {\n if (!params) return []\n const values = params.getAll(key)\n return normalizeIdCandidates(values)\n}\n\nfunction formatCurrency(amount: number | null | undefined, currency: string | null | undefined, fallback: string): string {\n if (typeof amount !== 'number' || Number.isNaN(amount)) return fallback\n try {\n if (currency && currency.trim().length) {\n const formatter = new Intl.NumberFormat(undefined, { style: 'currency', currency })\n return formatter.format(amount)\n }\n const formatter = new Intl.NumberFormat(undefined, { style: 'decimal', maximumFractionDigits: 2 })\n return formatter.format(amount)\n } catch {\n return currency ? `${amount} ${currency}` : String(amount)\n }\n}\n\nfunction formatDateValue(value: string | null | undefined, fallback: string): string {\n if (!value) return fallback\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return fallback\n return date.toLocaleDateString()\n}\n\nexport default function CustomersDealsPage() {\n const t = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const router = useRouter()\n const pathname = usePathname()\n const searchParams = useSearchParams()\n const scopeVersion = useOrganizationScopeVersion()\n const queryClient = useQueryClient()\n\n const [rows, setRows] = React.useState<DealRow[]>([])\n const [page, setPage] = React.useState(() => {\n const raw = Number(searchParams?.get('page') ?? '1')\n return Number.isFinite(raw) && raw > 0 ? raw : 1\n })\n const [pageSize, setPageSize] = React.useState(PAGE_SIZE)\n const [sorting, setSorting] = React.useState<import('@tanstack/react-table').SortingState>([])\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [search, setSearch] = React.useState(() => searchParams?.get('search')?.trim() ?? '')\n const [isLoading, setIsLoading] = React.useState(false)\n const [reloadToken, setReloadToken] = React.useState(0)\n const [pendingDeleteId, setPendingDeleteId] = React.useState<string | null>(null)\n // One-shot URL hydration used as the hook's initial value. The hook is the\n // single source of truth from this point on \u2014 the page MUST NOT keep a\n // parallel `useState<AdvancedFilterTree>` (see spec \"Migration & Backward\n // Compatibility\" \u2192 state ownership).\n const initialFilterTree = React.useMemo<AdvancedFilterTree>(() => {\n if (!searchParams) return createEmptyTree()\n const record: Record<string, string> = {}\n searchParams.forEach((value, key) => {\n if (key.startsWith('filter[')) record[key] = value\n })\n const v2 = deserializeTree(record)\n if (v2) return v2\n const flat = deserializeAdvancedFilter(record)\n if (flat) return flatToTree(flat)\n return createEmptyTree()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n // `filterPanel` lives at the top of the component so derived state below\n // (URL params, data fetch, export config) can read `filterPanel.appliedTree`\n // directly. Real `FilterFieldDef[]` arrives later from `useAutoDiscoveredFields`\n // (it depends on columns) and is synced into the hook via a small effect at\n // the bottom of the component. The hook reads fields through a ref at\n // validation time only \u2014 first validation cannot fire before user input, by\n // which point fields have settled, so the empty initial value is safe.\n const [panelFields, setPanelFields] = React.useState<FilterFieldDef[]>([])\n const [filtersOpen, setFiltersOpen] = React.useState(false)\n const filtersTriggerRef = React.useRef<HTMLButtonElement | null>(null)\n const filterPanel = useAdvancedFilterTree({\n initial: initialFilterTree,\n fields: panelFields,\n onApply: () => setPage(1),\n })\n const advancedFilterState = filterPanel.appliedTree\n const handleAdvancedFilterClear = React.useCallback(() => {\n filterPanel.clear()\n setPage(1)\n }, [filterPanel])\n const [cacheStatus, setCacheStatus] = React.useState<'hit' | 'miss' | null>(null)\n\n const initialPersonIds = React.useMemo(\n () => extractIdsFromParams(searchParams, 'personId'),\n [searchParams],\n )\n const initialCompanyIds = React.useMemo(\n () => extractIdsFromParams(searchParams, 'companyId'),\n [searchParams],\n )\n\n const [selectedPersonIds, setSelectedPersonIds] = React.useState<string[]>(initialPersonIds)\n const [selectedCompanyIds, setSelectedCompanyIds] = React.useState<string[]>(initialCompanyIds)\n\n const [dictionaryMaps, setDictionaryMaps] = React.useState<Record<DictionaryKey, CustomerDictionaryMap>>({\n 'deal-statuses': {},\n 'pipeline-stages': {},\n })\n\n const [pipelineNames, setPipelineNames] = React.useState<Record<string, string>>({})\n\n const fetchDictionaryEntries = React.useCallback(\n async (kind: DictionaryKey) => {\n try {\n const data = await ensureCustomerDictionary(queryClient, kind, scopeVersion)\n setDictionaryMaps((prev) => ({ ...prev, [kind]: data.map }))\n } catch {\n setDictionaryMaps((prev) => ({ ...prev, [kind]: {} }))\n }\n },\n [queryClient, scopeVersion],\n )\n\n React.useEffect(() => {\n let cancelled = false\n async function loadDictionaries() {\n if (cancelled) return\n await Promise.all([fetchDictionaryEntries('deal-statuses'), fetchDictionaryEntries('pipeline-stages')])\n }\n loadDictionaries().catch(() => {})\n return () => { cancelled = true }\n }, [fetchDictionaryEntries, reloadToken])\n const dictionaryOptions = React.useMemo(() => {\n const toOptions = (map?: CustomerDictionaryMap | null): DictionaryOptionWithTone[] =>\n Object.values(map ?? {})\n .map((entry) => {\n const tone = mapDictionaryColorToTone(entry.color)\n const option: DictionaryOptionWithTone = { value: entry.value, label: entry.label }\n if (tone) option.tone = tone\n return option\n })\n .sort((a, b) => a.label.localeCompare(b.label, undefined, { sensitivity: 'base' }))\n return {\n dealStatuses: toOptions(dictionaryMaps['deal-statuses']),\n pipelineStages: toOptions(dictionaryMaps['pipeline-stages']),\n }\n }, [dictionaryMaps])\n\n React.useEffect(() => {\n let cancelled = false\n async function loadPipelines() {\n try {\n const call = await apiCall<{ items?: Array<{ id: string; name: string }> }>('/api/customers/pipelines')\n if (cancelled || !call.ok) return\n const items = Array.isArray(call.result?.items) ? call.result.items : []\n const map: Record<string, string> = {}\n items.forEach((p) => { if (p.id && p.name) map[p.id] = p.name })\n setPipelineNames(map)\n } catch (err) {\n console.warn('[customers.deals.list] failed to load pipelines', err)\n }\n }\n loadPipelines().catch((err) => {\n console.warn('[customers.deals.list] loadPipelines threw', err)\n })\n return () => { cancelled = true }\n }, [reloadToken, scopeVersion])\n\n const handleSearchChange = React.useCallback((value: string) => {\n setSearch(value.trim())\n setPage(1)\n }, [])\n\n const queryParams = React.useMemo(() => {\n const params = new URLSearchParams()\n params.set('page', String(page))\n params.set('pageSize', String(pageSize))\n if (sorting.length > 0) {\n params.set('sort', sorting[0].id)\n params.set('order', sorting[0].desc ? 'desc' : 'asc')\n }\n if (search.trim().length) params.set('search', search.trim())\n if (selectedPersonIds.length) params.set('personId', selectedPersonIds.join(','))\n if (selectedCompanyIds.length) params.set('companyId', selectedCompanyIds.join(','))\n const advancedParams = serializeTree(advancedFilterState)\n for (const [key, val] of Object.entries(advancedParams)) {\n params.set(key, val)\n }\n return params.toString()\n }, [advancedFilterState, page, pageSize, search, selectedCompanyIds, selectedPersonIds, sorting])\n\n const currentParams = React.useMemo(\n () => Object.fromEntries(new URLSearchParams(queryParams)),\n [queryParams],\n )\n\n const exportConfig = React.useMemo(() => ({\n view: {\n getUrl: (format: DataTableExportFormat) =>\n buildCrudExportUrl('customers/deals', { ...currentParams, exportScope: 'view' }, format),\n },\n full: {\n getUrl: (format: DataTableExportFormat) =>\n buildCrudExportUrl('customers/deals', { ...currentParams, exportScope: 'full', all: 'true' }, format),\n },\n }), [currentParams])\n\n React.useEffect(() => {\n let cancelled = false\n async function load() {\n setIsLoading(true)\n setCacheStatus(null)\n try {\n const fallback: DealsResponse = { items: [], total: 0, totalPages: 1 }\n const call = await apiCall<DealsResponse>(`/api/customers/deals?${queryParams}`, undefined, { fallback })\n if (!call.ok) {\n const message =\n typeof (call.result as { error?: string } | undefined)?.error === 'string'\n ? (call.result as { error?: string }).error!\n : t('customers.deals.list.error.load')\n flash(message, 'error')\n if (!cancelled) setCacheStatus(null)\n return\n }\n const payload = call.result ?? fallback\n if (cancelled) return\n setCacheStatus(call.cacheStatus ?? null)\n const items = Array.isArray(payload.items) ? payload.items : []\n const mapped = items\n .map((item) => mapDeal(item as Record<string, unknown>))\n .filter((row): row is DealRow => !!row)\n setRows(mapped)\n setTotal(typeof payload.total === 'number' ? payload.total : mapped.length)\n setTotalPages(typeof payload.totalPages === 'number' ? payload.totalPages : 1)\n } catch (err) {\n if (!cancelled) {\n setCacheStatus(null)\n const message = err instanceof Error ? err.message : t('customers.deals.list.error.load')\n flash(message, 'error')\n }\n } finally {\n if (!cancelled) setIsLoading(false)\n }\n }\n load()\n return () => { cancelled = true }\n }, [queryParams, reloadToken, scopeVersion, t])\n\n React.useEffect(() => {\n if (totalPages > 0 && page > totalPages) {\n setPage(totalPages)\n }\n }, [page, totalPages])\n\n const queryRef = React.useRef(searchParams?.toString() ?? '')\n React.useEffect(() => {\n if (!pathname) return\n const params = new URLSearchParams()\n if (search.trim().length) params.set('search', search.trim())\n if (selectedPersonIds.length) selectedPersonIds.forEach((id) => params.append('personId', id))\n if (selectedCompanyIds.length) selectedCompanyIds.forEach((id) => params.append('companyId', id))\n if (page > 1) params.set('page', String(page))\n const advancedParams = serializeTree(advancedFilterState)\n for (const [key, val] of Object.entries(advancedParams)) {\n params.set(key, val)\n }\n const next = params.toString()\n if (queryRef.current === next) return\n queryRef.current = next\n router.replace(next ? `${pathname}?${next}` : pathname, { scroll: false })\n }, [pathname, router, page, search, selectedPersonIds, selectedCompanyIds, advancedFilterState])\n\n const handleRefresh = React.useCallback(() => {\n void Promise.all([\n invalidateCustomerDictionary(queryClient, 'deal-statuses'),\n invalidateCustomerDictionary(queryClient, 'pipeline-stages'),\n ])\n setReloadToken((token) => token + 1)\n }, [queryClient])\n\n const bulkMutationContextId = 'customers-deals-list:bulk-delete'\n const { runMutation: runBulkMutation, retryLastMutation: retryBulkMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: bulkMutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n const singleMutationContextId = 'customers-deals-list:single-delete'\n const { runMutation: runSingleMutation, retryLastMutation: retrySingleMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n resourceId: string\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: singleMutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n\n const handleDeleteDeal = React.useCallback(\n async (dealId: string) => {\n if (pendingDeleteId) return\n const confirmed = await confirm({\n title: t(\n 'customers.deals.list.deleteConfirm',\n 'Delete this deal? This action cannot be undone.',\n ),\n variant: 'destructive',\n })\n if (!confirmed) return\n setPendingDeleteId(dealId)\n try {\n await runSingleMutation({\n operation: async () => {\n await deleteCrud('customers/deals', {\n body: { id: dealId },\n errorMessage: t('customers.deals.list.deleteError', 'Failed to delete deal.'),\n })\n },\n context: {\n formId: singleMutationContextId,\n resourceKind: 'customers.deal',\n resourceId: dealId,\n retryLastMutation: retrySingleMutation,\n },\n })\n flash(t('customers.deals.list.deleteSuccess', 'Deal deleted.'), 'success')\n setRows((prev) => prev.filter((row) => row.id !== dealId))\n setTotal((prev) => Math.max(0, prev - 1))\n handleRefresh()\n } catch (err) {\n const message =\n err instanceof Error && err.message\n ? err.message\n : t('customers.deals.list.deleteError', 'Failed to delete deal.')\n flash(message, 'error')\n } finally {\n setPendingDeleteId(null)\n }\n },\n [confirm, handleRefresh, pendingDeleteId, retrySingleMutation, runSingleMutation, singleMutationContextId, t],\n )\n\n const handlePageSizeChange = React.useCallback((newSize: number) => {\n setPageSize(newSize)\n setPage(1)\n }, [])\n\n const handleBulkDelete = React.useCallback(async (selectedRows: DealRow[]) => {\n const confirmed = await confirm({\n title: t('customers.deals.list.bulkDelete.title', 'Delete {count} deals?', { count: selectedRows.length }),\n description: t('customers.deals.list.bulkDelete.description', 'This action cannot be undone.'),\n variant: 'destructive',\n })\n if (!confirmed) return false\n\n const { succeeded, failures } = await runBulkMutation({\n operation: async () =>\n runBulkDelete(\n selectedRows,\n async (row) => {\n await deleteCrud('customers/deals', {\n body: { id: row.id },\n errorMessage: t('customers.deals.list.deleteError', 'Failed to delete deal.'),\n })\n },\n {\n fallbackErrorMessage: t('customers.deals.list.deleteError', 'Failed to delete deal.'),\n logTag: 'customers.deals.list',\n progress: {\n jobType: 'customers.deals.bulk_delete',\n name: t('customers.deals.list.bulkDelete.progressName', 'Delete selected deals'),\n description: t(\n 'customers.deals.list.bulkDelete.progressDescription',\n '{count} deals selected for deletion',\n { count: selectedRows.length },\n ),\n meta: { source: 'customers.deals.list' },\n },\n },\n ),\n context: {\n formId: bulkMutationContextId,\n resourceKind: 'customers.deal',\n retryLastMutation: retryBulkMutation,\n },\n })\n\n if (succeeded.length > 0) {\n const succeededIds = new Set(succeeded.map((r) => r.id))\n setRows((prev) => prev.filter((r) => !succeededIds.has(r.id)))\n setTotal((prev) => Math.max(0, prev - succeeded.length))\n setReloadToken((prev) => prev + 1)\n if (succeeded.length > 1) {\n coalesceLastOperations(succeeded.length, {\n commandId: 'customers.deals.delete',\n actionLabel: t('customers.deals.list.bulkDelete.operationLabel', 'Delete {count} deals', { count: succeeded.length }),\n resourceKind: 'customers.deal',\n })\n }\n if (failures.length === 0) {\n flash(\n t('customers.deals.list.bulkDelete.success', '{count} deals deleted', { count: succeeded.length }),\n 'success',\n )\n } else {\n flash(\n t('customers.deals.list.bulkDelete.partial', '{deleted} of {total} deals deleted; {failed} failed', {\n deleted: succeeded.length,\n total: selectedRows.length,\n failed: failures.length,\n }),\n 'warning',\n )\n }\n }\n\n for (const group of groupBulkDeleteFailures(failures)) {\n const message = group.count === 1\n ? group.sampleMessage\n : t(\n 'customers.deals.list.bulkDelete.failedGroup',\n '{count} deals could not be deleted: {message}',\n { count: group.count, message: group.sampleMessage },\n )\n flash(message, 'error')\n }\n\n return succeeded.length > 0\n }, [bulkMutationContextId, confirm, retryBulkMutation, runBulkMutation, t])\n\n const { data: customFieldDefs = [] } = useCustomFieldDefs([E.customers.customer_deal], {\n keyExtras: [scopeVersion, reloadToken],\n })\n const currentUserId = useCurrentUserId()\n const [ownerFilterOptions, setOwnerFilterOptions] = React.useState<AdvancedFilterOption[]>([])\n React.useEffect(() => {\n const controller = new AbortController()\n let cancelled = false\n void fetchAssignableStaffMembers('', { pageSize: 100, signal: controller.signal })\n .then((items) => {\n if (!cancelled) setOwnerFilterOptions(mapAssignableStaffToFilterOptions(items))\n })\n .catch(() => {\n if (!cancelled) setOwnerFilterOptions([])\n })\n return () => {\n cancelled = true\n controller.abort()\n }\n }, [scopeVersion])\n const resolvedOwnerFilterOptions = React.useMemo(\n () => ensureCurrentUserFilterOption(\n ownerFilterOptions,\n currentUserId,\n t('customers.filters.currentUser', 'Current user'),\n ),\n [currentUserId, ownerFilterOptions, t],\n )\n const loadOwnerFilterOptions = React.useCallback(async (query?: string): Promise<AdvancedFilterOption[]> => {\n const items = await fetchAssignableStaffMembers(query ?? '', { pageSize: 100 })\n return mapAssignableStaffToFilterOptions(items)\n }, [])\n\n const columns = React.useMemo<ColumnDef<DealRow>[]>(() => {\n const noValue = <span className=\"text-muted-foreground text-sm\">{t('customers.deals.list.noValue')}</span>\n const renderDictionaryCell = (kind: DictionaryKey, value: string | null | undefined) => (\n <DictionaryValue\n value={value}\n map={dictionaryMaps[kind]}\n fallback={value ? <span className=\"text-sm\">{value}</span> : noValue}\n className=\"text-sm\"\n iconWrapperClassName=\"inline-flex h-6 w-6 items-center justify-center rounded border border-border bg-card\"\n iconClassName=\"h-4 w-4\"\n colorClassName=\"h-3 w-3 rounded-full\"\n />\n )\n const renderAssociationSummary = (\n items: { id: string; label: string }[],\n fallbackLabel: string,\n ) => {\n if (!items.length) return noValue\n const labels = normalizeCollectionLabels(\n items.map((entry) => (entry.label && entry.label.trim().length ? entry.label : fallbackLabel)),\n )\n if (!labels.length) return noValue\n return (\n <CollectionPreviewCell labels={labels} maxVisible={1} />\n )\n }\n\n const customColumns = customFieldDefs\n .filter((def) => supportsCustomFieldColumn(def))\n .map<ColumnDef<DealRow>>((def) => ({\n accessorKey: `cf_${def.key}`,\n header: def.label || def.key,\n meta: {\n columnChooserGroup: def.group?.title ?? 'Custom Fields',\n filterGroup: def.group?.title ?? 'Custom Fields',\n filterType: mapCustomFieldKindToFilterType(def.kind),\n filterOptions: normalizeCustomFieldFilterOptions(def.options),\n hidden: def.listVisible === false,\n maxWidth: '220px',\n },\n cell: ({ getValue }) => {\n const value = getValue()\n if (value == null) return noValue\n if (Array.isArray(value)) {\n const normalized = normalizeCollectionLabels(\n value\n .map((item) => {\n if (item == null) return ''\n if (typeof item === 'string') return item\n return String(item)\n }),\n )\n if (!normalized.length) return noValue\n return <CollectionPreviewCell labels={normalized} maxVisible={2} />\n }\n if (typeof value === 'boolean') {\n return (\n <span className=\"text-sm\">\n {value\n ? t('customers.deals.list.booleanYes', 'Yes')\n : t('customers.deals.list.booleanNo', 'No')}\n </span>\n )\n }\n const stringValue = typeof value === 'string' ? value.trim() : String(value)\n if (!stringValue) return noValue\n return <span className=\"text-sm\">{stringValue}</span>\n },\n }))\n\n return [\n {\n accessorKey: 'title',\n header: t('customers.deals.list.columns.title'),\n meta: {\n alwaysVisible: true,\n columnChooserGroup: 'Basic Info',\n filterKey: 'title',\n filterGroup: 'Deal',\n maxWidth: '280px',\n },\n cell: ({ row }) => <span className=\"font-medium text-sm\">{row.original.title}</span>,\n },\n {\n accessorKey: 'status',\n header: t('customers.deals.list.columns.status'),\n meta: {\n filterType: 'select' as const,\n filterOptions: dictionaryOptions.dealStatuses,\n columnChooserGroup: 'Basic Info',\n filterKey: 'status',\n filterGroup: 'Deal',\n },\n cell: ({ row }) => renderDictionaryCell('deal-statuses', row.original.status),\n },\n {\n accessorKey: 'pipelineStage',\n header: t('customers.deals.list.columns.pipelineStage'),\n meta: {\n filterType: 'select' as const,\n filterOptions: dictionaryOptions.pipelineStages,\n columnChooserGroup: 'Pipeline',\n filterKey: 'pipeline_stage',\n filterGroup: 'Deal',\n },\n cell: ({ row }) => renderDictionaryCell('pipeline-stages', row.original.pipelineStage),\n },\n {\n accessorKey: 'pipelineId',\n header: t('customers.deals.list.columns.pipeline', 'Pipeline'),\n meta: {\n columnChooserGroup: 'Pipeline',\n filterKey: 'pipeline_id',\n filterGroup: 'Deal',\n maxWidth: '220px',\n },\n cell: ({ row }) => {\n const name = row.original.pipelineId ? pipelineNames[row.original.pipelineId] : null\n return name ? <span className=\"text-sm\">{name}</span> : noValue\n },\n },\n {\n accessorKey: 'valueAmount',\n header: t('customers.deals.list.columns.value'),\n meta: {\n filterType: 'number' as const,\n columnChooserGroup: 'Financial',\n filterKey: 'value_amount',\n filterGroup: 'Deal',\n },\n cell: ({ row }) => (\n <span className=\"text-sm font-medium\">\n {formatCurrency(row.original.valueAmount ?? null, row.original.valueCurrency ?? null, t('customers.deals.list.noValue'))}\n </span>\n ),\n },\n {\n accessorKey: 'probability',\n header: t('customers.deals.list.columns.probability'),\n meta: {\n filterType: 'number' as const,\n columnChooserGroup: 'Financial',\n filterKey: 'probability',\n filterGroup: 'Deal',\n },\n cell: ({ row }) => {\n const value = row.original.probability\n if (typeof value === 'number' && Number.isFinite(value)) {\n return <span className=\"text-sm\">{`${Math.min(Math.max(value, 0), 100)}%`}</span>\n }\n return noValue\n },\n },\n {\n accessorKey: 'expectedCloseAt',\n header: t('customers.deals.list.columns.expectedClose'),\n meta: {\n columnChooserGroup: 'Dates',\n filterKey: 'expected_close_at',\n filterGroup: 'Activity',\n filterIconName: 'calendar',\n },\n cell: ({ row }) => (\n <span className=\"text-sm\">\n {formatDateValue(row.original.expectedCloseAt ?? null, t('customers.deals.list.noValue'))}\n </span>\n ),\n },\n {\n accessorKey: 'ownerUserId',\n header: t('customers.deals.list.columns.owner', 'Owner'),\n meta: {\n columnChooserGroup: 'CRM',\n filterType: 'select',\n filterOptions: resolvedOwnerFilterOptions,\n filterLoadOptions: loadOwnerFilterOptions,\n filterGroup: 'CRM',\n filterIconName: 'user-round',\n filterKey: 'owner_user_id',\n hidden: true,\n },\n cell: ({ row }) => row.original.ownerUserId ?? null,\n },\n {\n accessorKey: 'companies',\n header: t('customers.deals.list.columns.companies'),\n meta: {\n columnChooserGroup: 'Associations',\n filterable: false,\n filterGroup: 'CRM',\n filterIconName: 'building-2',\n maxWidth: '220px',\n tooltipContent: (row: DealRow) =>\n normalizeCollectionLabels(\n row.companies.map((entry) => (entry.label && entry.label.trim().length ? entry.label : t('customers.deals.list.unnamedCompany'))),\n ).join(', '),\n },\n cell: ({ row }) => renderAssociationSummary(row.original.companies, t('customers.deals.list.unnamedCompany')),\n },\n {\n accessorKey: 'people',\n header: t('customers.deals.list.columns.people'),\n meta: {\n columnChooserGroup: 'Associations',\n filterable: false,\n filterGroup: 'CRM',\n filterIconName: 'user-round',\n maxWidth: '220px',\n tooltipContent: (row: DealRow) =>\n normalizeCollectionLabels(\n row.people.map((entry) => (entry.label && entry.label.trim().length ? entry.label : t('customers.deals.list.unnamedPerson'))),\n ).join(', '),\n },\n cell: ({ row }) => renderAssociationSummary(row.original.people, t('customers.deals.list.unnamedPerson')),\n },\n {\n accessorKey: 'updatedAt',\n header: t('customers.deals.list.columns.updatedAt'),\n meta: {\n columnChooserGroup: 'Dates',\n filterKey: 'updated_at',\n filterGroup: 'Activity',\n filterIconName: 'calendar',\n },\n cell: ({ row }) => (\n <span className=\"text-sm\">\n {formatDateValue(row.original.updatedAt ?? null, t('customers.deals.list.noValue'))}\n </span>\n ),\n },\n ...customColumns,\n ]\n }, [customFieldDefs, dictionaryMaps, dictionaryOptions, loadOwnerFilterOptions, pipelineNames, resolvedOwnerFilterOptions, t])\n\n const { advancedFilterFields } = useAutoDiscoveredFields({ columns, customFieldDefs })\n\n // Sync auto-discovered fields into the `filterPanel` declared at the top of\n // the component. See the comment on the `panelFields` state for why this\n // late-binding is safe. Bail out by content (field-key list) \u2014 every render\n // of `useAutoDiscoveredFields` produces fresh `FilterFieldDef` object refs\n // even when the set of fields hasn't actually changed, so a naive reference\n // setState would loop (\"Maximum update depth exceeded\").\n React.useEffect(() => {\n setPanelFields((prev) => {\n if (prev === advancedFilterFields) return prev\n if (prev.length === advancedFilterFields.length) {\n let same = true\n for (let i = 0; i < prev.length; i++) {\n if (prev[i].key !== advancedFilterFields[i].key) { same = false; break }\n }\n if (same) return prev\n }\n return advancedFilterFields\n })\n }, [advancedFilterFields])\n\n const associationFilterFields = React.useMemo<FilterFieldDef[]>(() => {\n const personLabels = new Map<string, string>()\n const companyLabels = new Map<string, string>()\n for (const row of rows) {\n for (const person of row.people) {\n if (selectedPersonIds.includes(person.id) && person.label.trim().length > 0) {\n personLabels.set(person.id, person.label)\n }\n }\n for (const company of row.companies) {\n if (selectedCompanyIds.includes(company.id) && company.label.trim().length > 0) {\n companyLabels.set(company.id, company.label)\n }\n }\n }\n return [\n {\n key: 'people',\n label: t('customers.deals.list.columns.people', 'People'),\n type: 'select',\n options: selectedPersonIds.map((id) => ({ value: id, label: personLabels.get(id) ?? id })),\n },\n {\n key: 'companies',\n label: t('customers.deals.list.columns.companies', 'Companies'),\n type: 'select',\n options: selectedCompanyIds.map((id) => ({ value: id, label: companyLabels.get(id) ?? id })),\n },\n ]\n }, [rows, selectedCompanyIds, selectedPersonIds, t])\n const associationFilterTree = React.useMemo<AdvancedFilterTree>(() => {\n const rules: Array<{ field: string; operator: 'is_any_of'; value: string[] }> = []\n if (selectedPersonIds.length) rules.push({ field: 'people', operator: 'is_any_of', value: selectedPersonIds })\n if (selectedCompanyIds.length) rules.push({ field: 'companies', operator: 'is_any_of', value: selectedCompanyIds })\n return rules.length ? makeMultiRuleTree(rules) : createEmptyTree()\n }, [selectedCompanyIds, selectedPersonIds])\n const handleAssociationFilterRemove = React.useCallback((nodeId: string) => {\n const node = associationFilterTree.root.children.find((child) => child.id === nodeId)\n if (!node || node.type !== 'rule') return\n if (node.field === 'people') setSelectedPersonIds([])\n if (node.field === 'companies') setSelectedCompanyIds([])\n setPage(1)\n }, [associationFilterTree.root.children])\n\n const dealsPresets = React.useMemo<FilterPreset[]>(() => makeDealsPresets(), [])\n\n return (\n <Page>\n <PageBody>\n <ViewTabsRow active=\"list\" className=\"mb-4\" />\n <DataTable<DealRow>\n stickyFirstColumn\n stickyActionsColumn\n title={t('customers.deals.list.title')}\n actions={(\n <Button asChild>\n <Link href=\"/backend/customers/deals/create\">\n {t('customers.deals.list.actions.new', 'New deal')}\n </Link>\n </Button>\n )}\n columns={columns}\n columnChooser={{ auto: true }}\n data={rows}\n onRowClick={(row) => {\n router.push(`/backend/customers/deals/${row.id}`)\n }}\n rowActions={(row) => {\n const isDeleting = pendingDeleteId === row.id\n return (\n <RowActions\n items={[\n {\n id: 'edit',\n label: t('customers.deals.list.actions.edit', 'Edit'),\n onSelect: () => { router.push(`/backend/customers/deals/${row.id}`) },\n },\n {\n id: 'open-new-tab',\n label: t('customers.deals.list.actions.openInNewTab', 'Open in new tab'),\n onSelect: () => {\n if (typeof window !== 'undefined') {\n window.open(`/backend/customers/deals/${row.id}`, '_blank', 'noopener')\n }\n },\n },\n {\n id: 'delete',\n label: isDeleting\n ? t('customers.deals.list.actions.deleting', 'Deleting\u2026')\n : t('customers.deals.list.actions.delete', 'Delete'),\n destructive: true,\n onSelect: () => handleDeleteDeal(row.id),\n },\n ]}\n />\n )\n }}\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n bulkActions={[\n {\n id: 'delete',\n label: t('customers.deals.list.actions.delete', 'Delete'),\n destructive: true,\n onExecute: handleBulkDelete,\n },\n ]}\n searchValue={search}\n onSearchChange={handleSearchChange}\n searchPlaceholder={t('customers.deals.list.searchPlaceholder')}\n pagination={{\n page,\n pageSize,\n total,\n totalPages,\n onPageChange: (nextPage) => setPage(nextPage),\n pageSizeOptions: [10, 25, 50, 100],\n onPageSizeChange: handlePageSizeChange,\n cacheStatus,\n }}\n isLoading={isLoading}\n refreshButton={{\n label: t('customers.deals.list.refresh'),\n onRefresh: handleRefresh,\n }}\n exporter={exportConfig}\n entityId={E.customers.customer_deal}\n perspective={{ tableId: 'customers.deals.list' }}\n advancedFilter={{\n auto: true,\n value: filterPanel.tree,\n onChange: filterPanel.setTree,\n onApply: () => filterPanel.flush(),\n onClear: handleAdvancedFilterClear,\n triggerRef: filtersTriggerRef,\n externalPopover: true,\n onTriggerClick: () => setFiltersOpen((prev) => !prev),\n onApplyTree: (tree) => {\n filterPanel.replaceTree(tree)\n setPage(1)\n },\n }}\n activeFilterChips={(\n <>\n <ActiveFilterChips\n tree={associationFilterTree}\n fields={associationFilterFields}\n popoverOpen={filtersOpen}\n onRemoveNode={handleAssociationFilterRemove}\n onOpen={() => setFiltersOpen(true)}\n />\n <ActiveFilterChips\n tree={filterPanel.tree}\n fields={advancedFilterFields}\n popoverOpen={filtersOpen}\n onRemoveNode={(id) => filterPanel.dispatch({ type: 'removeNode', nodeId: id })}\n onOpen={() => setFiltersOpen(true)}\n />\n </>\n )}\n filterAwareEmptyState={{\n active: advancedFilterState.root.children.length > 0,\n entityNamePlural: t('customers.deals.entityPlural', 'deals'),\n canRemoveLast: filterPanel.tree.root.children.length > 0,\n onClearAll: handleAdvancedFilterClear,\n onRemoveLast: () => filterPanel.dispatch({ type: 'removeLast' }),\n }}\n virtualized\n />\n <AdvancedFilterPanel\n fields={advancedFilterFields}\n value={filterPanel.tree}\n onChange={filterPanel.setTree}\n onApply={filterPanel.flush}\n onClear={handleAdvancedFilterClear}\n onFlush={filterPanel.flush}\n pendingErrors={filterPanel.pendingErrors}\n userId={currentUserId}\n presets={dealsPresets}\n open={filtersOpen}\n onOpenChange={setFiltersOpen}\n triggerRef={filtersTriggerRef}\n savedFilterStorageKey=\"customers.deals.list\"\n />\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n}\n\nfunction mapDeal(item: Record<string, unknown>): DealRow | null {\n const id = typeof item.id === 'string' ? item.id : null\n if (!id) return null\n const title = typeof item.title === 'string' ? item.title : ''\n const status = typeof item.status === 'string' ? item.status : null\n const pipelineStage = typeof item.pipeline_stage === 'string' ? item.pipeline_stage : null\n const pipelineStageId = typeof item.pipeline_stage_id === 'string' ? item.pipeline_stage_id : null\n const pipelineId = typeof item.pipeline_id === 'string' ? item.pipeline_id : null\n const valueAmountRaw = item.value_amount\n const valueAmount =\n typeof valueAmountRaw === 'number'\n ? valueAmountRaw\n : typeof valueAmountRaw === 'string' && valueAmountRaw.trim()\n ? Number(valueAmountRaw)\n : null\n const valueCurrency =\n typeof item.value_currency === 'string' && item.value_currency.trim().length\n ? item.value_currency.trim().toUpperCase()\n : null\n const probabilityRaw = item.probability\n const probability =\n typeof probabilityRaw === 'number'\n ? probabilityRaw\n : typeof probabilityRaw === 'string' && probabilityRaw.trim().length\n ? Number(probabilityRaw)\n : null\n const expectedCloseAt = typeof item.expected_close_at === 'string' ? item.expected_close_at : null\n const updatedAt = typeof item.updated_at === 'string' ? item.updated_at : null\n const ownerUserId = typeof item.owner_user_id === 'string' ? item.owner_user_id : null\n const peopleRaw = Array.isArray(item.people) ? item.people : []\n const companiesRaw = Array.isArray(item.companies) ? item.companies : []\n const people = peopleRaw\n .map((entry) => {\n if (!entry || typeof entry !== 'object') return null\n const data = entry as Record<string, unknown>\n const pid = typeof data.id === 'string' ? data.id : null\n if (!pid) return null\n const label = typeof data.label === 'string' ? data.label : ''\n return { id: pid, label }\n })\n .filter((entry): entry is { id: string; label: string } => !!entry)\n const companies = companiesRaw\n .map((entry) => {\n if (!entry || typeof entry !== 'object') return null\n const data = entry as Record<string, unknown>\n const cid = typeof data.id === 'string' ? data.id : null\n if (!cid) return null\n const label = typeof data.label === 'string' ? data.label : ''\n return { id: cid, label }\n })\n .filter((entry): entry is { id: string; label: string } => !!entry)\n const customFields: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(item)) {\n if (key.startsWith('cf_')) customFields[key] = value\n }\n return withDataTableNamespaces({\n id,\n title,\n status,\n pipelineStage,\n pipelineStageId,\n pipelineId,\n valueAmount,\n valueCurrency,\n probability,\n expectedCloseAt,\n updatedAt,\n ownerUserId,\n people,\n companies,\n ...customFields,\n }, item)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { usePathname, useRouter, useSearchParams } from 'next/navigation'\nimport { useQueryClient } from '@tanstack/react-query'\nimport type { ColumnDef } from '@tanstack/react-table'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable, type DataTableExportFormat, withDataTableNamespaces } from '@open-mercato/ui/backend/DataTable'\nimport type { AdvancedFilterTree } from '@open-mercato/shared/lib/query/advanced-filter-tree'\nimport { createEmptyTree, makeRuleTree, makeMultiRuleTree } from '@open-mercato/shared/lib/query/advanced-filter-tree'\nimport { deserializeTree, deserializeAdvancedFilter, flatToTree, mapDictionaryColorToTone, serializeTree, type FilterFieldDef, type FilterOption as AdvancedFilterOption } from '@open-mercato/shared/lib/query/advanced-filter'\nimport { useCurrentUserId } from '@open-mercato/ui/backend/utils/useCurrentUserId'\nimport { apiCall, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'\nimport { buildCrudExportUrl, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { groupBulkDeleteFailures, runBulkDelete } from '@open-mercato/ui/backend/utils/bulkDelete'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { coalesceLastOperations } from '@open-mercato/ui/backend/operations/store'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { ViewTabsRow } from './pipeline/components/ViewTabsRow'\nimport { E } from '#generated/entities.ids.generated'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport {\n DictionaryValue,\n type CustomerDictionaryKind,\n type CustomerDictionaryMap,\n} from '../../../lib/dictionaries'\nimport {\n ensureCustomerDictionary,\n invalidateCustomerDictionary,\n} from '../../../components/detail/hooks/useCustomerDictionary'\nimport {\n useCustomFieldDefs,\n} from '@open-mercato/ui/backend/utils/customFieldDefs'\nimport {\n mapCustomFieldKindToFilterType,\n normalizeCustomFieldFilterOptions,\n supportsCustomFieldColumn,\n} from '@open-mercato/ui/backend/utils/customFieldColumns'\nimport { CollectionPreviewCell, normalizeCollectionLabels } from '../../../components/list/CollectionPreviewCell'\nimport { useAutoDiscoveredFields } from '@open-mercato/ui/backend/utils/useAutoDiscoveredFields'\nimport { useAdvancedFilterTree } from '@open-mercato/ui/backend/hooks/useAdvancedFilter'\nimport { AdvancedFilterPanel } from '@open-mercato/ui/backend/filters/AdvancedFilterPanel'\nimport { ActiveFilterChips } from '@open-mercato/ui/backend/filters/ActiveFilterChips'\nimport type { FilterPreset } from '@open-mercato/ui/backend/filters/QuickFilters'\nimport {\n ensureCurrentUserFilterOption,\n fetchAssignableStaffMembers,\n mapAssignableStaffToFilterOptions,\n} from '../../../components/detail/assignableStaff'\n\nfunction makeDealsPresets(): FilterPreset[] {\n return [\n {\n id: 'my-deals',\n labelKey: 'customers.deals.presets.myDeals',\n requiresUser: true,\n build: ({ userId }) => makeRuleTree({ field: 'owner_user_id', operator: 'is', value: userId }),\n },\n {\n id: 'closing-month',\n labelKey: 'customers.deals.presets.closingMonth',\n iconName: 'clock',\n build: ({ now }) => {\n const start = new Date(now.getFullYear(), now.getMonth(), 1).toISOString().slice(0, 10)\n const end = new Date(now.getFullYear(), now.getMonth() + 1, 0).toISOString().slice(0, 10)\n return makeRuleTree({ field: 'expected_close_at', operator: 'between', value: [start, end] })\n },\n },\n // The Deal entity has no dedicated \"at risk\" or health-score field \u2014 `customer_deals`\n // exposes only `status` (open/win/loose/closed/in_progress, dictionary-driven) and\n // `closure_outcome`. Rather than fabricate a mapping, the \"At risk\" preset is omitted\n // until the data model exposes a first-class signal.\n {\n id: 'won-quarter',\n labelKey: 'customers.deals.presets.wonQuarter',\n build: ({ now }) => {\n const quarter = Math.floor(now.getMonth() / 3)\n const start = new Date(now.getFullYear(), quarter * 3, 1).toISOString().slice(0, 10)\n return makeMultiRuleTree([\n { field: 'status', operator: 'is', value: 'win' },\n { field: 'expected_close_at', operator: 'is_after', value: start },\n ], 'and')\n },\n },\n ]\n}\n\ntype DealRow = {\n id: string\n title: string\n status?: string | null\n pipelineStage?: string | null\n pipelineStageId?: string | null\n pipelineId?: string | null\n valueAmount?: number | null\n valueCurrency?: string | null\n probability?: number | null\n expectedCloseAt?: string | null\n updatedAt?: string | null\n ownerUserId?: string | null\n companies: { id: string; label: string }[]\n people: { id: string; label: string }[]\n} & Record<string, unknown>\n\ntype DealsResponse = {\n items?: Array<Record<string, unknown>>\n total?: number\n totalPages?: number\n}\n\ntype FilterOption = { value: string; label: string }\ntype DictionaryOptionWithTone = AdvancedFilterOption & FilterOption\n\ntype DictionaryKey = Extract<CustomerDictionaryKind, 'deal-statuses' | 'pipeline-stages'>\n\nconst PAGE_SIZE = 20\nconst UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i\n\nfunction isUuid(value: string | null | undefined): value is string {\n if (!value) return false\n return UUID_REGEX.test(value.trim())\n}\n\nfunction normalizeIdCandidates(raw: Array<string>): string[] {\n const set = new Set<string>()\n raw.forEach((candidate) => {\n candidate\n .split(',')\n .map((part) => part.trim())\n .filter((part) => part.length > 0)\n .forEach((part) => {\n if (isUuid(part)) set.add(part)\n })\n })\n return Array.from(set)\n}\n\nfunction extractIdsFromParams(params: URLSearchParams | null | undefined, key: string): string[] {\n if (!params) return []\n const values = params.getAll(key)\n return normalizeIdCandidates(values)\n}\n\nfunction formatCurrency(amount: number | null | undefined, currency: string | null | undefined, fallback: string): string {\n if (typeof amount !== 'number' || Number.isNaN(amount)) return fallback\n try {\n if (currency && currency.trim().length) {\n const formatter = new Intl.NumberFormat(undefined, { style: 'currency', currency })\n return formatter.format(amount)\n }\n const formatter = new Intl.NumberFormat(undefined, { style: 'decimal', maximumFractionDigits: 2 })\n return formatter.format(amount)\n } catch {\n return currency ? `${amount} ${currency}` : String(amount)\n }\n}\n\nfunction formatDateValue(value: string | null | undefined, fallback: string): string {\n if (!value) return fallback\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return fallback\n return date.toLocaleDateString()\n}\n\nexport default function CustomersDealsPage() {\n const t = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const router = useRouter()\n const pathname = usePathname()\n const searchParams = useSearchParams()\n const scopeVersion = useOrganizationScopeVersion()\n const queryClient = useQueryClient()\n\n const [rows, setRows] = React.useState<DealRow[]>([])\n const [page, setPage] = React.useState(() => {\n const raw = Number(searchParams?.get('page') ?? '1')\n return Number.isFinite(raw) && raw > 0 ? raw : 1\n })\n const [pageSize, setPageSize] = React.useState(PAGE_SIZE)\n const [sorting, setSorting] = React.useState<import('@tanstack/react-table').SortingState>([])\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [search, setSearch] = React.useState(() => searchParams?.get('search')?.trim() ?? '')\n const [isLoading, setIsLoading] = React.useState(false)\n const [reloadToken, setReloadToken] = React.useState(0)\n const [pendingDeleteId, setPendingDeleteId] = React.useState<string | null>(null)\n // One-shot URL hydration used as the hook's initial value. The hook is the\n // single source of truth from this point on \u2014 the page MUST NOT keep a\n // parallel `useState<AdvancedFilterTree>` (see spec \"Migration & Backward\n // Compatibility\" \u2192 state ownership).\n const initialFilterTree = React.useMemo<AdvancedFilterTree>(() => {\n if (!searchParams) return createEmptyTree()\n const record: Record<string, string> = {}\n searchParams.forEach((value, key) => {\n if (key.startsWith('filter[')) record[key] = value\n })\n const v2 = deserializeTree(record)\n if (v2) return v2\n const flat = deserializeAdvancedFilter(record)\n if (flat) return flatToTree(flat)\n return createEmptyTree()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n // `filterPanel` lives at the top of the component so derived state below\n // (URL params, data fetch, export config) can read `filterPanel.appliedTree`\n // directly. Real `FilterFieldDef[]` arrives later from `useAutoDiscoveredFields`\n // (it depends on columns) and is synced into the hook via a small effect at\n // the bottom of the component. The hook reads fields through a ref at\n // validation time only \u2014 first validation cannot fire before user input, by\n // which point fields have settled, so the empty initial value is safe.\n const [panelFields, setPanelFields] = React.useState<FilterFieldDef[]>([])\n const [filtersOpen, setFiltersOpen] = React.useState(false)\n const filtersTriggerRef = React.useRef<HTMLButtonElement | null>(null)\n const filterPanel = useAdvancedFilterTree({\n initial: initialFilterTree,\n fields: panelFields,\n onApply: () => setPage(1),\n })\n const advancedFilterState = filterPanel.appliedTree\n const handleAdvancedFilterClear = React.useCallback(() => {\n filterPanel.clear()\n setPage(1)\n }, [filterPanel])\n const [cacheStatus, setCacheStatus] = React.useState<'hit' | 'miss' | null>(null)\n\n const initialPersonIds = React.useMemo(\n () => extractIdsFromParams(searchParams, 'personId'),\n [searchParams],\n )\n const initialCompanyIds = React.useMemo(\n () => extractIdsFromParams(searchParams, 'companyId'),\n [searchParams],\n )\n\n const [selectedPersonIds, setSelectedPersonIds] = React.useState<string[]>(initialPersonIds)\n const [selectedCompanyIds, setSelectedCompanyIds] = React.useState<string[]>(initialCompanyIds)\n\n const [dictionaryMaps, setDictionaryMaps] = React.useState<Record<DictionaryKey, CustomerDictionaryMap>>({\n 'deal-statuses': {},\n 'pipeline-stages': {},\n })\n\n const [pipelineNames, setPipelineNames] = React.useState<Record<string, string>>({})\n\n const fetchDictionaryEntries = React.useCallback(\n async (kind: DictionaryKey) => {\n try {\n const data = await ensureCustomerDictionary(queryClient, kind, scopeVersion)\n setDictionaryMaps((prev) => ({ ...prev, [kind]: data.map }))\n } catch {\n setDictionaryMaps((prev) => ({ ...prev, [kind]: {} }))\n }\n },\n [queryClient, scopeVersion],\n )\n\n React.useEffect(() => {\n let cancelled = false\n async function loadDictionaries() {\n if (cancelled) return\n await Promise.all([fetchDictionaryEntries('deal-statuses'), fetchDictionaryEntries('pipeline-stages')])\n }\n loadDictionaries().catch(() => {})\n return () => { cancelled = true }\n }, [fetchDictionaryEntries, reloadToken])\n const dictionaryOptions = React.useMemo(() => {\n const toOptions = (map?: CustomerDictionaryMap | null): DictionaryOptionWithTone[] =>\n Object.values(map ?? {})\n .map((entry) => {\n const tone = mapDictionaryColorToTone(entry.color)\n const option: DictionaryOptionWithTone = { value: entry.value, label: entry.label }\n if (tone) option.tone = tone\n return option\n })\n .sort((a, b) => a.label.localeCompare(b.label, undefined, { sensitivity: 'base' }))\n return {\n dealStatuses: toOptions(dictionaryMaps['deal-statuses']),\n pipelineStages: toOptions(dictionaryMaps['pipeline-stages']),\n }\n }, [dictionaryMaps])\n\n React.useEffect(() => {\n let cancelled = false\n async function loadPipelines() {\n try {\n const call = await apiCall<{ items?: Array<{ id: string; name: string }> }>('/api/customers/pipelines')\n if (cancelled || !call.ok) return\n const items = Array.isArray(call.result?.items) ? call.result.items : []\n const map: Record<string, string> = {}\n items.forEach((p) => { if (p.id && p.name) map[p.id] = p.name })\n setPipelineNames(map)\n } catch (err) {\n console.warn('[customers.deals.list] failed to load pipelines', err)\n }\n }\n loadPipelines().catch((err) => {\n console.warn('[customers.deals.list] loadPipelines threw', err)\n })\n return () => { cancelled = true }\n }, [reloadToken, scopeVersion])\n\n const handleSearchChange = React.useCallback((value: string) => {\n setSearch(value.trim())\n setPage(1)\n }, [])\n\n const queryParams = React.useMemo(() => {\n const params = new URLSearchParams()\n params.set('page', String(page))\n params.set('pageSize', String(pageSize))\n if (sorting.length > 0) {\n params.set('sort', sorting[0].id)\n params.set('order', sorting[0].desc ? 'desc' : 'asc')\n }\n if (search.trim().length) params.set('search', search.trim())\n if (selectedPersonIds.length) params.set('personId', selectedPersonIds.join(','))\n if (selectedCompanyIds.length) params.set('companyId', selectedCompanyIds.join(','))\n const advancedParams = serializeTree(advancedFilterState)\n for (const [key, val] of Object.entries(advancedParams)) {\n params.set(key, val)\n }\n return params.toString()\n }, [advancedFilterState, page, pageSize, search, selectedCompanyIds, selectedPersonIds, sorting])\n\n const currentParams = React.useMemo(\n () => Object.fromEntries(new URLSearchParams(queryParams)),\n [queryParams],\n )\n\n const exportConfig = React.useMemo(() => ({\n view: {\n getUrl: (format: DataTableExportFormat) =>\n buildCrudExportUrl('customers/deals', { ...currentParams, exportScope: 'view' }, format),\n },\n full: {\n getUrl: (format: DataTableExportFormat) =>\n buildCrudExportUrl('customers/deals', { ...currentParams, exportScope: 'full', all: 'true' }, format),\n },\n }), [currentParams])\n\n React.useEffect(() => {\n let cancelled = false\n async function load() {\n setIsLoading(true)\n setCacheStatus(null)\n try {\n const fallback: DealsResponse = { items: [], total: 0, totalPages: 1 }\n const call = await apiCall<DealsResponse>(`/api/customers/deals?${queryParams}`, undefined, { fallback })\n if (!call.ok) {\n const message =\n typeof (call.result as { error?: string } | undefined)?.error === 'string'\n ? (call.result as { error?: string }).error!\n : t('customers.deals.list.error.load')\n flash(message, 'error')\n if (!cancelled) setCacheStatus(null)\n return\n }\n const payload = call.result ?? fallback\n if (cancelled) return\n setCacheStatus(call.cacheStatus ?? null)\n const items = Array.isArray(payload.items) ? payload.items : []\n const mapped = items\n .map((item) => mapDeal(item as Record<string, unknown>))\n .filter((row): row is DealRow => !!row)\n setRows(mapped)\n setTotal(typeof payload.total === 'number' ? payload.total : mapped.length)\n setTotalPages(typeof payload.totalPages === 'number' ? payload.totalPages : 1)\n } catch (err) {\n if (!cancelled) {\n setCacheStatus(null)\n const message = err instanceof Error ? err.message : t('customers.deals.list.error.load')\n flash(message, 'error')\n }\n } finally {\n if (!cancelled) setIsLoading(false)\n }\n }\n load()\n return () => { cancelled = true }\n }, [queryParams, reloadToken, scopeVersion, t])\n\n React.useEffect(() => {\n if (totalPages > 0 && page > totalPages) {\n setPage(totalPages)\n }\n }, [page, totalPages])\n\n const queryRef = React.useRef(searchParams?.toString() ?? '')\n React.useEffect(() => {\n if (!pathname) return\n const params = new URLSearchParams()\n if (search.trim().length) params.set('search', search.trim())\n if (selectedPersonIds.length) selectedPersonIds.forEach((id) => params.append('personId', id))\n if (selectedCompanyIds.length) selectedCompanyIds.forEach((id) => params.append('companyId', id))\n if (page > 1) params.set('page', String(page))\n const advancedParams = serializeTree(advancedFilterState)\n for (const [key, val] of Object.entries(advancedParams)) {\n params.set(key, val)\n }\n const next = params.toString()\n if (queryRef.current === next) return\n queryRef.current = next\n router.replace(next ? `${pathname}?${next}` : pathname, { scroll: false })\n }, [pathname, router, page, search, selectedPersonIds, selectedCompanyIds, advancedFilterState])\n\n const handleRefresh = React.useCallback(() => {\n void Promise.all([\n invalidateCustomerDictionary(queryClient, 'deal-statuses'),\n invalidateCustomerDictionary(queryClient, 'pipeline-stages'),\n ])\n setReloadToken((token) => token + 1)\n }, [queryClient])\n\n const bulkMutationContextId = 'customers-deals-list:bulk-delete'\n const { runMutation: runBulkMutation, retryLastMutation: retryBulkMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: bulkMutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n const singleMutationContextId = 'customers-deals-list:single-delete'\n const { runMutation: runSingleMutation, retryLastMutation: retrySingleMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n resourceId: string\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: singleMutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n\n const handleDeleteDeal = React.useCallback(\n async (dealId: string) => {\n if (pendingDeleteId) return\n const confirmed = await confirm({\n title: t(\n 'customers.deals.list.deleteConfirm',\n 'Delete this deal? This action cannot be undone.',\n ),\n variant: 'destructive',\n })\n if (!confirmed) return\n const lockVersion = rows.find((row) => row.id === dealId)?.updatedAt ?? null\n setPendingDeleteId(dealId)\n try {\n await runSingleMutation({\n operation: async () => {\n await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(lockVersion),\n () => deleteCrud('customers/deals', {\n body: { id: dealId },\n errorMessage: t('customers.deals.list.deleteError', 'Failed to delete deal.'),\n }),\n )\n },\n context: {\n formId: singleMutationContextId,\n resourceKind: 'customers.deal',\n resourceId: dealId,\n retryLastMutation: retrySingleMutation,\n },\n })\n flash(t('customers.deals.list.deleteSuccess', 'Deal deleted.'), 'success')\n setRows((prev) => prev.filter((row) => row.id !== dealId))\n setTotal((prev) => Math.max(0, prev - 1))\n handleRefresh()\n } catch (err) {\n // A stale delete surfaces the unified conflict bar (via the guarded\n // mutation) \u2014 skip the generic error flash to avoid a double message (#2332).\n if (surfaceRecordConflict(err, t)) {\n handleRefresh()\n return\n }\n const message =\n err instanceof Error && err.message\n ? err.message\n : t('customers.deals.list.deleteError', 'Failed to delete deal.')\n flash(message, 'error')\n } finally {\n setPendingDeleteId(null)\n }\n },\n [confirm, handleRefresh, pendingDeleteId, retrySingleMutation, rows, runSingleMutation, singleMutationContextId, t],\n )\n\n const handlePageSizeChange = React.useCallback((newSize: number) => {\n setPageSize(newSize)\n setPage(1)\n }, [])\n\n const handleBulkDelete = React.useCallback(async (selectedRows: DealRow[]) => {\n const confirmed = await confirm({\n title: t('customers.deals.list.bulkDelete.title', 'Delete {count} deals?', { count: selectedRows.length }),\n description: t('customers.deals.list.bulkDelete.description', 'This action cannot be undone.'),\n variant: 'destructive',\n })\n if (!confirmed) return false\n\n const { succeeded, failures } = await runBulkMutation({\n operation: async () =>\n runBulkDelete(\n selectedRows,\n async (row) => {\n await deleteCrud('customers/deals', {\n body: { id: row.id },\n errorMessage: t('customers.deals.list.deleteError', 'Failed to delete deal.'),\n })\n },\n {\n fallbackErrorMessage: t('customers.deals.list.deleteError', 'Failed to delete deal.'),\n logTag: 'customers.deals.list',\n progress: {\n jobType: 'customers.deals.bulk_delete',\n name: t('customers.deals.list.bulkDelete.progressName', 'Delete selected deals'),\n description: t(\n 'customers.deals.list.bulkDelete.progressDescription',\n '{count} deals selected for deletion',\n { count: selectedRows.length },\n ),\n meta: { source: 'customers.deals.list' },\n },\n },\n ),\n context: {\n formId: bulkMutationContextId,\n resourceKind: 'customers.deal',\n retryLastMutation: retryBulkMutation,\n },\n })\n\n if (succeeded.length > 0) {\n const succeededIds = new Set(succeeded.map((r) => r.id))\n setRows((prev) => prev.filter((r) => !succeededIds.has(r.id)))\n setTotal((prev) => Math.max(0, prev - succeeded.length))\n setReloadToken((prev) => prev + 1)\n if (succeeded.length > 1) {\n coalesceLastOperations(succeeded.length, {\n commandId: 'customers.deals.delete',\n actionLabel: t('customers.deals.list.bulkDelete.operationLabel', 'Delete {count} deals', { count: succeeded.length }),\n resourceKind: 'customers.deal',\n })\n }\n if (failures.length === 0) {\n flash(\n t('customers.deals.list.bulkDelete.success', '{count} deals deleted', { count: succeeded.length }),\n 'success',\n )\n } else {\n flash(\n t('customers.deals.list.bulkDelete.partial', '{deleted} of {total} deals deleted; {failed} failed', {\n deleted: succeeded.length,\n total: selectedRows.length,\n failed: failures.length,\n }),\n 'warning',\n )\n }\n }\n\n for (const group of groupBulkDeleteFailures(failures)) {\n const message = group.count === 1\n ? group.sampleMessage\n : t(\n 'customers.deals.list.bulkDelete.failedGroup',\n '{count} deals could not be deleted: {message}',\n { count: group.count, message: group.sampleMessage },\n )\n flash(message, 'error')\n }\n\n return succeeded.length > 0\n }, [bulkMutationContextId, confirm, retryBulkMutation, runBulkMutation, t])\n\n const { data: customFieldDefs = [] } = useCustomFieldDefs([E.customers.customer_deal], {\n keyExtras: [scopeVersion, reloadToken],\n })\n const currentUserId = useCurrentUserId()\n const [ownerFilterOptions, setOwnerFilterOptions] = React.useState<AdvancedFilterOption[]>([])\n React.useEffect(() => {\n const controller = new AbortController()\n let cancelled = false\n void fetchAssignableStaffMembers('', { pageSize: 100, signal: controller.signal })\n .then((items) => {\n if (!cancelled) setOwnerFilterOptions(mapAssignableStaffToFilterOptions(items))\n })\n .catch(() => {\n if (!cancelled) setOwnerFilterOptions([])\n })\n return () => {\n cancelled = true\n controller.abort()\n }\n }, [scopeVersion])\n const resolvedOwnerFilterOptions = React.useMemo(\n () => ensureCurrentUserFilterOption(\n ownerFilterOptions,\n currentUserId,\n t('customers.filters.currentUser', 'Current user'),\n ),\n [currentUserId, ownerFilterOptions, t],\n )\n const loadOwnerFilterOptions = React.useCallback(async (query?: string): Promise<AdvancedFilterOption[]> => {\n const items = await fetchAssignableStaffMembers(query ?? '', { pageSize: 100 })\n return mapAssignableStaffToFilterOptions(items)\n }, [])\n\n const columns = React.useMemo<ColumnDef<DealRow>[]>(() => {\n const noValue = <span className=\"text-muted-foreground text-sm\">{t('customers.deals.list.noValue')}</span>\n const renderDictionaryCell = (kind: DictionaryKey, value: string | null | undefined) => (\n <DictionaryValue\n value={value}\n map={dictionaryMaps[kind]}\n fallback={value ? <span className=\"text-sm\">{value}</span> : noValue}\n className=\"text-sm\"\n iconWrapperClassName=\"inline-flex h-6 w-6 items-center justify-center rounded border border-border bg-card\"\n iconClassName=\"h-4 w-4\"\n colorClassName=\"h-3 w-3 rounded-full\"\n />\n )\n const renderAssociationSummary = (\n items: { id: string; label: string }[],\n fallbackLabel: string,\n ) => {\n if (!items.length) return noValue\n const labels = normalizeCollectionLabels(\n items.map((entry) => (entry.label && entry.label.trim().length ? entry.label : fallbackLabel)),\n )\n if (!labels.length) return noValue\n return (\n <CollectionPreviewCell labels={labels} maxVisible={1} />\n )\n }\n\n const customColumns = customFieldDefs\n .filter((def) => supportsCustomFieldColumn(def))\n .map<ColumnDef<DealRow>>((def) => ({\n accessorKey: `cf_${def.key}`,\n header: def.label || def.key,\n meta: {\n columnChooserGroup: def.group?.title ?? 'Custom Fields',\n filterGroup: def.group?.title ?? 'Custom Fields',\n filterType: mapCustomFieldKindToFilterType(def.kind),\n filterOptions: normalizeCustomFieldFilterOptions(def.options),\n hidden: def.listVisible === false,\n maxWidth: '220px',\n },\n cell: ({ getValue }) => {\n const value = getValue()\n if (value == null) return noValue\n if (Array.isArray(value)) {\n const normalized = normalizeCollectionLabels(\n value\n .map((item) => {\n if (item == null) return ''\n if (typeof item === 'string') return item\n return String(item)\n }),\n )\n if (!normalized.length) return noValue\n return <CollectionPreviewCell labels={normalized} maxVisible={2} />\n }\n if (typeof value === 'boolean') {\n return (\n <span className=\"text-sm\">\n {value\n ? t('customers.deals.list.booleanYes', 'Yes')\n : t('customers.deals.list.booleanNo', 'No')}\n </span>\n )\n }\n const stringValue = typeof value === 'string' ? value.trim() : String(value)\n if (!stringValue) return noValue\n return <span className=\"text-sm\">{stringValue}</span>\n },\n }))\n\n return [\n {\n accessorKey: 'title',\n header: t('customers.deals.list.columns.title'),\n meta: {\n alwaysVisible: true,\n columnChooserGroup: 'Basic Info',\n filterKey: 'title',\n filterGroup: 'Deal',\n maxWidth: '280px',\n },\n cell: ({ row }) => <span className=\"font-medium text-sm\">{row.original.title}</span>,\n },\n {\n accessorKey: 'status',\n header: t('customers.deals.list.columns.status'),\n meta: {\n filterType: 'select' as const,\n filterOptions: dictionaryOptions.dealStatuses,\n columnChooserGroup: 'Basic Info',\n filterKey: 'status',\n filterGroup: 'Deal',\n },\n cell: ({ row }) => renderDictionaryCell('deal-statuses', row.original.status),\n },\n {\n accessorKey: 'pipelineStage',\n header: t('customers.deals.list.columns.pipelineStage'),\n meta: {\n filterType: 'select' as const,\n filterOptions: dictionaryOptions.pipelineStages,\n columnChooserGroup: 'Pipeline',\n filterKey: 'pipeline_stage',\n filterGroup: 'Deal',\n },\n cell: ({ row }) => renderDictionaryCell('pipeline-stages', row.original.pipelineStage),\n },\n {\n accessorKey: 'pipelineId',\n header: t('customers.deals.list.columns.pipeline', 'Pipeline'),\n meta: {\n columnChooserGroup: 'Pipeline',\n filterKey: 'pipeline_id',\n filterGroup: 'Deal',\n maxWidth: '220px',\n },\n cell: ({ row }) => {\n const name = row.original.pipelineId ? pipelineNames[row.original.pipelineId] : null\n return name ? <span className=\"text-sm\">{name}</span> : noValue\n },\n },\n {\n accessorKey: 'valueAmount',\n header: t('customers.deals.list.columns.value'),\n meta: {\n filterType: 'number' as const,\n columnChooserGroup: 'Financial',\n filterKey: 'value_amount',\n filterGroup: 'Deal',\n },\n cell: ({ row }) => (\n <span className=\"text-sm font-medium\">\n {formatCurrency(row.original.valueAmount ?? null, row.original.valueCurrency ?? null, t('customers.deals.list.noValue'))}\n </span>\n ),\n },\n {\n accessorKey: 'probability',\n header: t('customers.deals.list.columns.probability'),\n meta: {\n filterType: 'number' as const,\n columnChooserGroup: 'Financial',\n filterKey: 'probability',\n filterGroup: 'Deal',\n },\n cell: ({ row }) => {\n const value = row.original.probability\n if (typeof value === 'number' && Number.isFinite(value)) {\n return <span className=\"text-sm\">{`${Math.min(Math.max(value, 0), 100)}%`}</span>\n }\n return noValue\n },\n },\n {\n accessorKey: 'expectedCloseAt',\n header: t('customers.deals.list.columns.expectedClose'),\n meta: {\n columnChooserGroup: 'Dates',\n filterKey: 'expected_close_at',\n filterGroup: 'Activity',\n filterIconName: 'calendar',\n },\n cell: ({ row }) => (\n <span className=\"text-sm\">\n {formatDateValue(row.original.expectedCloseAt ?? null, t('customers.deals.list.noValue'))}\n </span>\n ),\n },\n {\n accessorKey: 'ownerUserId',\n header: t('customers.deals.list.columns.owner', 'Owner'),\n meta: {\n columnChooserGroup: 'CRM',\n filterType: 'select',\n filterOptions: resolvedOwnerFilterOptions,\n filterLoadOptions: loadOwnerFilterOptions,\n filterGroup: 'CRM',\n filterIconName: 'user-round',\n filterKey: 'owner_user_id',\n hidden: true,\n },\n cell: ({ row }) => row.original.ownerUserId ?? null,\n },\n {\n accessorKey: 'companies',\n header: t('customers.deals.list.columns.companies'),\n meta: {\n columnChooserGroup: 'Associations',\n filterable: false,\n filterGroup: 'CRM',\n filterIconName: 'building-2',\n maxWidth: '220px',\n tooltipContent: (row: DealRow) =>\n normalizeCollectionLabels(\n row.companies.map((entry) => (entry.label && entry.label.trim().length ? entry.label : t('customers.deals.list.unnamedCompany'))),\n ).join(', '),\n },\n cell: ({ row }) => renderAssociationSummary(row.original.companies, t('customers.deals.list.unnamedCompany')),\n },\n {\n accessorKey: 'people',\n header: t('customers.deals.list.columns.people'),\n meta: {\n columnChooserGroup: 'Associations',\n filterable: false,\n filterGroup: 'CRM',\n filterIconName: 'user-round',\n maxWidth: '220px',\n tooltipContent: (row: DealRow) =>\n normalizeCollectionLabels(\n row.people.map((entry) => (entry.label && entry.label.trim().length ? entry.label : t('customers.deals.list.unnamedPerson'))),\n ).join(', '),\n },\n cell: ({ row }) => renderAssociationSummary(row.original.people, t('customers.deals.list.unnamedPerson')),\n },\n {\n accessorKey: 'updatedAt',\n header: t('customers.deals.list.columns.updatedAt'),\n meta: {\n columnChooserGroup: 'Dates',\n filterKey: 'updated_at',\n filterGroup: 'Activity',\n filterIconName: 'calendar',\n },\n cell: ({ row }) => (\n <span className=\"text-sm\">\n {formatDateValue(row.original.updatedAt ?? null, t('customers.deals.list.noValue'))}\n </span>\n ),\n },\n ...customColumns,\n ]\n }, [customFieldDefs, dictionaryMaps, dictionaryOptions, loadOwnerFilterOptions, pipelineNames, resolvedOwnerFilterOptions, t])\n\n const { advancedFilterFields } = useAutoDiscoveredFields({ columns, customFieldDefs })\n\n // Sync auto-discovered fields into the `filterPanel` declared at the top of\n // the component. See the comment on the `panelFields` state for why this\n // late-binding is safe. Bail out by content (field-key list) \u2014 every render\n // of `useAutoDiscoveredFields` produces fresh `FilterFieldDef` object refs\n // even when the set of fields hasn't actually changed, so a naive reference\n // setState would loop (\"Maximum update depth exceeded\").\n React.useEffect(() => {\n setPanelFields((prev) => {\n if (prev === advancedFilterFields) return prev\n if (prev.length === advancedFilterFields.length) {\n let same = true\n for (let i = 0; i < prev.length; i++) {\n if (prev[i].key !== advancedFilterFields[i].key) { same = false; break }\n }\n if (same) return prev\n }\n return advancedFilterFields\n })\n }, [advancedFilterFields])\n\n const associationFilterFields = React.useMemo<FilterFieldDef[]>(() => {\n const personLabels = new Map<string, string>()\n const companyLabels = new Map<string, string>()\n for (const row of rows) {\n for (const person of row.people) {\n if (selectedPersonIds.includes(person.id) && person.label.trim().length > 0) {\n personLabels.set(person.id, person.label)\n }\n }\n for (const company of row.companies) {\n if (selectedCompanyIds.includes(company.id) && company.label.trim().length > 0) {\n companyLabels.set(company.id, company.label)\n }\n }\n }\n return [\n {\n key: 'people',\n label: t('customers.deals.list.columns.people', 'People'),\n type: 'select',\n options: selectedPersonIds.map((id) => ({ value: id, label: personLabels.get(id) ?? id })),\n },\n {\n key: 'companies',\n label: t('customers.deals.list.columns.companies', 'Companies'),\n type: 'select',\n options: selectedCompanyIds.map((id) => ({ value: id, label: companyLabels.get(id) ?? id })),\n },\n ]\n }, [rows, selectedCompanyIds, selectedPersonIds, t])\n const associationFilterTree = React.useMemo<AdvancedFilterTree>(() => {\n const rules: Array<{ field: string; operator: 'is_any_of'; value: string[] }> = []\n if (selectedPersonIds.length) rules.push({ field: 'people', operator: 'is_any_of', value: selectedPersonIds })\n if (selectedCompanyIds.length) rules.push({ field: 'companies', operator: 'is_any_of', value: selectedCompanyIds })\n return rules.length ? makeMultiRuleTree(rules) : createEmptyTree()\n }, [selectedCompanyIds, selectedPersonIds])\n const handleAssociationFilterRemove = React.useCallback((nodeId: string) => {\n const node = associationFilterTree.root.children.find((child) => child.id === nodeId)\n if (!node || node.type !== 'rule') return\n if (node.field === 'people') setSelectedPersonIds([])\n if (node.field === 'companies') setSelectedCompanyIds([])\n setPage(1)\n }, [associationFilterTree.root.children])\n\n const dealsPresets = React.useMemo<FilterPreset[]>(() => makeDealsPresets(), [])\n\n return (\n <Page>\n <PageBody>\n <ViewTabsRow active=\"list\" className=\"mb-4\" />\n <DataTable<DealRow>\n stickyFirstColumn\n stickyActionsColumn\n title={t('customers.deals.list.title')}\n actions={(\n <Button asChild>\n <Link href=\"/backend/customers/deals/create\">\n {t('customers.deals.list.actions.new', 'New deal')}\n </Link>\n </Button>\n )}\n columns={columns}\n columnChooser={{ auto: true }}\n data={rows}\n onRowClick={(row) => {\n router.push(`/backend/customers/deals/${row.id}`)\n }}\n rowActions={(row) => {\n const isDeleting = pendingDeleteId === row.id\n return (\n <RowActions\n items={[\n {\n id: 'edit',\n label: t('customers.deals.list.actions.edit', 'Edit'),\n onSelect: () => { router.push(`/backend/customers/deals/${row.id}`) },\n },\n {\n id: 'open-new-tab',\n label: t('customers.deals.list.actions.openInNewTab', 'Open in new tab'),\n onSelect: () => {\n if (typeof window !== 'undefined') {\n window.open(`/backend/customers/deals/${row.id}`, '_blank', 'noopener')\n }\n },\n },\n {\n id: 'delete',\n label: isDeleting\n ? t('customers.deals.list.actions.deleting', 'Deleting\u2026')\n : t('customers.deals.list.actions.delete', 'Delete'),\n destructive: true,\n onSelect: () => handleDeleteDeal(row.id),\n },\n ]}\n />\n )\n }}\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n bulkActions={[\n {\n id: 'delete',\n label: t('customers.deals.list.actions.delete', 'Delete'),\n destructive: true,\n onExecute: handleBulkDelete,\n },\n ]}\n searchValue={search}\n onSearchChange={handleSearchChange}\n searchPlaceholder={t('customers.deals.list.searchPlaceholder')}\n pagination={{\n page,\n pageSize,\n total,\n totalPages,\n onPageChange: (nextPage) => setPage(nextPage),\n pageSizeOptions: [10, 25, 50, 100],\n onPageSizeChange: handlePageSizeChange,\n cacheStatus,\n }}\n isLoading={isLoading}\n refreshButton={{\n label: t('customers.deals.list.refresh'),\n onRefresh: handleRefresh,\n }}\n exporter={exportConfig}\n entityId={E.customers.customer_deal}\n perspective={{ tableId: 'customers.deals.list' }}\n advancedFilter={{\n auto: true,\n value: filterPanel.tree,\n onChange: filterPanel.setTree,\n onApply: () => filterPanel.flush(),\n onClear: handleAdvancedFilterClear,\n triggerRef: filtersTriggerRef,\n externalPopover: true,\n onTriggerClick: () => setFiltersOpen((prev) => !prev),\n onApplyTree: (tree) => {\n filterPanel.replaceTree(tree)\n setPage(1)\n },\n }}\n activeFilterChips={(\n <>\n <ActiveFilterChips\n tree={associationFilterTree}\n fields={associationFilterFields}\n popoverOpen={filtersOpen}\n onRemoveNode={handleAssociationFilterRemove}\n onOpen={() => setFiltersOpen(true)}\n />\n <ActiveFilterChips\n tree={filterPanel.tree}\n fields={advancedFilterFields}\n popoverOpen={filtersOpen}\n onRemoveNode={(id) => filterPanel.dispatch({ type: 'removeNode', nodeId: id })}\n onOpen={() => setFiltersOpen(true)}\n />\n </>\n )}\n filterAwareEmptyState={{\n active: advancedFilterState.root.children.length > 0,\n entityNamePlural: t('customers.deals.entityPlural', 'deals'),\n canRemoveLast: filterPanel.tree.root.children.length > 0,\n onClearAll: handleAdvancedFilterClear,\n onRemoveLast: () => filterPanel.dispatch({ type: 'removeLast' }),\n }}\n virtualized\n />\n <AdvancedFilterPanel\n fields={advancedFilterFields}\n value={filterPanel.tree}\n onChange={filterPanel.setTree}\n onApply={filterPanel.flush}\n onClear={handleAdvancedFilterClear}\n onFlush={filterPanel.flush}\n pendingErrors={filterPanel.pendingErrors}\n userId={currentUserId}\n presets={dealsPresets}\n open={filtersOpen}\n onOpenChange={setFiltersOpen}\n triggerRef={filtersTriggerRef}\n savedFilterStorageKey=\"customers.deals.list\"\n />\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n}\n\nfunction mapDeal(item: Record<string, unknown>): DealRow | null {\n const id = typeof item.id === 'string' ? item.id : null\n if (!id) return null\n const title = typeof item.title === 'string' ? item.title : ''\n const status = typeof item.status === 'string' ? item.status : null\n const pipelineStage = typeof item.pipeline_stage === 'string' ? item.pipeline_stage : null\n const pipelineStageId = typeof item.pipeline_stage_id === 'string' ? item.pipeline_stage_id : null\n const pipelineId = typeof item.pipeline_id === 'string' ? item.pipeline_id : null\n const valueAmountRaw = item.value_amount\n const valueAmount =\n typeof valueAmountRaw === 'number'\n ? valueAmountRaw\n : typeof valueAmountRaw === 'string' && valueAmountRaw.trim()\n ? Number(valueAmountRaw)\n : null\n const valueCurrency =\n typeof item.value_currency === 'string' && item.value_currency.trim().length\n ? item.value_currency.trim().toUpperCase()\n : null\n const probabilityRaw = item.probability\n const probability =\n typeof probabilityRaw === 'number'\n ? probabilityRaw\n : typeof probabilityRaw === 'string' && probabilityRaw.trim().length\n ? Number(probabilityRaw)\n : null\n const expectedCloseAt = typeof item.expected_close_at === 'string' ? item.expected_close_at : null\n const updatedAt = typeof item.updated_at === 'string' ? item.updated_at : null\n const ownerUserId = typeof item.owner_user_id === 'string' ? item.owner_user_id : null\n const peopleRaw = Array.isArray(item.people) ? item.people : []\n const companiesRaw = Array.isArray(item.companies) ? item.companies : []\n const people = peopleRaw\n .map((entry) => {\n if (!entry || typeof entry !== 'object') return null\n const data = entry as Record<string, unknown>\n const pid = typeof data.id === 'string' ? data.id : null\n if (!pid) return null\n const label = typeof data.label === 'string' ? data.label : ''\n return { id: pid, label }\n })\n .filter((entry): entry is { id: string; label: string } => !!entry)\n const companies = companiesRaw\n .map((entry) => {\n if (!entry || typeof entry !== 'object') return null\n const data = entry as Record<string, unknown>\n const cid = typeof data.id === 'string' ? data.id : null\n if (!cid) return null\n const label = typeof data.label === 'string' ? data.label : ''\n return { id: cid, label }\n })\n .filter((entry): entry is { id: string; label: string } => !!entry)\n const customFields: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(item)) {\n if (key.startsWith('cf_')) customFields[key] = value\n }\n return withDataTableNamespaces({\n id,\n title,\n status,\n pipelineStage,\n pipelineStageId,\n pipelineId,\n valueAmount,\n valueCurrency,\n probability,\n expectedCloseAt,\n updatedAt,\n ownerUserId,\n people,\n companies,\n ...customFields,\n }, item)\n}\n"],
5
+ "mappings": ";AAwmBoB,SAgZR,UAhZQ,KAgZR,YAhZQ;AAtmBpB,YAAY,WAAW;AACvB,OAAO,UAAU;AACjB,SAAS,aAAa,WAAW,uBAAuB;AACxD,SAAS,sBAAsB;AAE/B,SAAS,MAAM,gBAAgB;AAC/B,SAAS,WAAuC,+BAA+B;AAE/E,SAAS,iBAAiB,cAAc,yBAAyB;AACjE,SAAS,iBAAiB,2BAA2B,YAAY,0BAA0B,qBAAqF;AAChL,SAAS,wBAAwB;AACjC,SAAS,SAAS,mCAAmC;AACrD,SAAS,iCAAiC;AAC1C,SAAS,6BAA6B;AACtC,SAAS,oBAAoB,kBAAkB;AAC/C,SAAS,yBAAyB,qBAAqB;AACvD,SAAS,0BAA0B;AACnC,SAAS,8BAA8B;AACvC,SAAS,aAAa;AACtB,SAAS,kBAAkB;AAC3B,SAAS,cAAc;AACvB,SAAS,mBAAmB;AAC5B,SAAS,SAAS;AAClB,SAAS,mCAAmC;AAC5C,SAAS,YAAY;AACrB,SAAS,wBAAwB;AACjC;AAAA,EACE;AAAA,OAGK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,uBAAuB,iCAAiC;AACjE,SAAS,+BAA+B;AACxC,SAAS,6BAA6B;AACtC,SAAS,2BAA2B;AACpC,SAAS,yBAAyB;AAElC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,mBAAmC;AAC1C,SAAO;AAAA,IACL;AAAA,MACE,IAAI;AAAA,MACJ,UAAU;AAAA,MACV,cAAc;AAAA,MACd,OAAO,CAAC,EAAE,OAAO,MAAM,aAAa,EAAE,OAAO,iBAAiB,UAAU,MAAM,OAAO,OAAO,CAAC;AAAA,IAC/F;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,UAAU;AAAA,MACV,UAAU;AAAA,MACV,OAAO,CAAC,EAAE,IAAI,MAAM;AAClB,cAAM,QAAQ,IAAI,KAAK,IAAI,YAAY,GAAG,IAAI,SAAS,GAAG,CAAC,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AACtF,cAAM,MAAM,IAAI,KAAK,IAAI,YAAY,GAAG,IAAI,SAAS,IAAI,GAAG,CAAC,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AACxF,eAAO,aAAa,EAAE,OAAO,qBAAqB,UAAU,WAAW,OAAO,CAAC,OAAO,GAAG,EAAE,CAAC;AAAA,MAC9F;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA,IAKA;AAAA,MACE,IAAI;AAAA,MACJ,UAAU;AAAA,MACV,OAAO,CAAC,EAAE,IAAI,MAAM;AAClB,cAAM,UAAU,KAAK,MAAM,IAAI,SAAS,IAAI,CAAC;AAC7C,cAAM,QAAQ,IAAI,KAAK,IAAI,YAAY,GAAG,UAAU,GAAG,CAAC,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AACnF,eAAO,kBAAkB;AAAA,UACvB,EAAE,OAAO,UAAU,UAAU,MAAM,OAAO,MAAM;AAAA,UAChD,EAAE,OAAO,qBAAqB,UAAU,YAAY,OAAO,MAAM;AAAA,QACnE,GAAG,KAAK;AAAA,MACV;AAAA,IACF;AAAA,EACF;AACF;AA8BA,MAAM,YAAY;AAClB,MAAM,aAAa;AAEnB,SAAS,OAAO,OAAmD;AACjE,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO,WAAW,KAAK,MAAM,KAAK,CAAC;AACrC;AAEA,SAAS,sBAAsB,KAA8B;AAC3D,QAAM,MAAM,oBAAI,IAAY;AAC5B,MAAI,QAAQ,CAAC,cAAc;AACzB,cACG,MAAM,GAAG,EACT,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC,EACzB,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,EAChC,QAAQ,CAAC,SAAS;AACjB,UAAI,OAAO,IAAI,EAAG,KAAI,IAAI,IAAI;AAAA,IAChC,CAAC;AAAA,EACL,CAAC;AACD,SAAO,MAAM,KAAK,GAAG;AACvB;AAEA,SAAS,qBAAqB,QAA4C,KAAuB;AAC/F,MAAI,CAAC,OAAQ,QAAO,CAAC;AACrB,QAAM,SAAS,OAAO,OAAO,GAAG;AAChC,SAAO,sBAAsB,MAAM;AACrC;AAEA,SAAS,eAAe,QAAmC,UAAqC,UAA0B;AACxH,MAAI,OAAO,WAAW,YAAY,OAAO,MAAM,MAAM,EAAG,QAAO;AAC/D,MAAI;AACF,QAAI,YAAY,SAAS,KAAK,EAAE,QAAQ;AACtC,YAAMA,aAAY,IAAI,KAAK,aAAa,QAAW,EAAE,OAAO,YAAY,SAAS,CAAC;AAClF,aAAOA,WAAU,OAAO,MAAM;AAAA,IAChC;AACA,UAAM,YAAY,IAAI,KAAK,aAAa,QAAW,EAAE,OAAO,WAAW,uBAAuB,EAAE,CAAC;AACjG,WAAO,UAAU,OAAO,MAAM;AAAA,EAChC,QAAQ;AACN,WAAO,WAAW,GAAG,MAAM,IAAI,QAAQ,KAAK,OAAO,MAAM;AAAA,EAC3D;AACF;AAEA,SAAS,gBAAgB,OAAkC,UAA0B;AACnF,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,OAAO,IAAI,KAAK,KAAK;AAC3B,MAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,EAAG,QAAO;AACzC,SAAO,KAAK,mBAAmB;AACjC;AAEe,SAAR,qBAAsC;AAC3C,QAAM,IAAI,KAAK;AACf,QAAM,EAAE,SAAS,qBAAqB,IAAI,iBAAiB;AAC3D,QAAM,SAAS,UAAU;AACzB,QAAM,WAAW,YAAY;AAC7B,QAAM,eAAe,gBAAgB;AACrC,QAAM,eAAe,4BAA4B;AACjD,QAAM,cAAc,eAAe;AAEnC,QAAM,CAAC,MAAM,OAAO,IAAI,MAAM,SAAoB,CAAC,CAAC;AACpD,QAAM,CAAC,MAAM,OAAO,IAAI,MAAM,SAAS,MAAM;AAC3C,UAAM,MAAM,OAAO,cAAc,IAAI,MAAM,KAAK,GAAG;AACnD,WAAO,OAAO,SAAS,GAAG,KAAK,MAAM,IAAI,MAAM;AAAA,EACjD,CAAC;AACD,QAAM,CAAC,UAAU,WAAW,IAAI,MAAM,SAAS,SAAS;AACxD,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAuD,CAAC,CAAC;AAC7F,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAS,CAAC;AAC1C,QAAM,CAAC,YAAY,aAAa,IAAI,MAAM,SAAS,CAAC;AACpD,QAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,SAAS,MAAM,cAAc,IAAI,QAAQ,GAAG,KAAK,KAAK,EAAE;AAC1F,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,SAAS,KAAK;AACtD,QAAM,CAAC,aAAa,cAAc,IAAI,MAAM,SAAS,CAAC;AACtD,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,MAAM,SAAwB,IAAI;AAKhF,QAAM,oBAAoB,MAAM,QAA4B,MAAM;AAChE,QAAI,CAAC,aAAc,QAAO,gBAAgB;AAC1C,UAAM,SAAiC,CAAC;AACxC,iBAAa,QAAQ,CAAC,OAAO,QAAQ;AACnC,UAAI,IAAI,WAAW,SAAS,EAAG,QAAO,GAAG,IAAI;AAAA,IAC/C,CAAC;AACD,UAAM,KAAK,gBAAgB,MAAM;AACjC,QAAI,GAAI,QAAO;AACf,UAAM,OAAO,0BAA0B,MAAM;AAC7C,QAAI,KAAM,QAAO,WAAW,IAAI;AAChC,WAAO,gBAAgB;AAAA,EAEzB,GAAG,CAAC,CAAC;AAQL,QAAM,CAAC,aAAa,cAAc,IAAI,MAAM,SAA2B,CAAC,CAAC;AACzE,QAAM,CAAC,aAAa,cAAc,IAAI,MAAM,SAAS,KAAK;AAC1D,QAAM,oBAAoB,MAAM,OAAiC,IAAI;AACrE,QAAM,cAAc,sBAAsB;AAAA,IACxC,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,SAAS,MAAM,QAAQ,CAAC;AAAA,EAC1B,CAAC;AACD,QAAM,sBAAsB,YAAY;AACxC,QAAM,4BAA4B,MAAM,YAAY,MAAM;AACxD,gBAAY,MAAM;AAClB,YAAQ,CAAC;AAAA,EACX,GAAG,CAAC,WAAW,CAAC;AAChB,QAAM,CAAC,aAAa,cAAc,IAAI,MAAM,SAAgC,IAAI;AAEhF,QAAM,mBAAmB,MAAM;AAAA,IAC7B,MAAM,qBAAqB,cAAc,UAAU;AAAA,IACnD,CAAC,YAAY;AAAA,EACf;AACA,QAAM,oBAAoB,MAAM;AAAA,IAC9B,MAAM,qBAAqB,cAAc,WAAW;AAAA,IACpD,CAAC,YAAY;AAAA,EACf;AAEA,QAAM,CAAC,mBAAmB,oBAAoB,IAAI,MAAM,SAAmB,gBAAgB;AAC3F,QAAM,CAAC,oBAAoB,qBAAqB,IAAI,MAAM,SAAmB,iBAAiB;AAE9F,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,MAAM,SAAuD;AAAA,IACvG,iBAAiB,CAAC;AAAA,IAClB,mBAAmB,CAAC;AAAA,EACtB,CAAC;AAED,QAAM,CAAC,eAAe,gBAAgB,IAAI,MAAM,SAAiC,CAAC,CAAC;AAEnF,QAAM,yBAAyB,MAAM;AAAA,IACnC,OAAO,SAAwB;AAC7B,UAAI;AACF,cAAM,OAAO,MAAM,yBAAyB,aAAa,MAAM,YAAY;AAC3E,0BAAkB,CAAC,UAAU,EAAE,GAAG,MAAM,CAAC,IAAI,GAAG,KAAK,IAAI,EAAE;AAAA,MAC7D,QAAQ;AACN,0BAAkB,CAAC,UAAU,EAAE,GAAG,MAAM,CAAC,IAAI,GAAG,CAAC,EAAE,EAAE;AAAA,MACvD;AAAA,IACF;AAAA,IACA,CAAC,aAAa,YAAY;AAAA,EAC5B;AAEA,QAAM,UAAU,MAAM;AACpB,QAAI,YAAY;AAChB,mBAAe,mBAAmB;AAChC,UAAI,UAAW;AACf,YAAM,QAAQ,IAAI,CAAC,uBAAuB,eAAe,GAAG,uBAAuB,iBAAiB,CAAC,CAAC;AAAA,IACxG;AACA,qBAAiB,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AACjC,WAAO,MAAM;AAAE,kBAAY;AAAA,IAAK;AAAA,EAClC,GAAG,CAAC,wBAAwB,WAAW,CAAC;AACxC,QAAM,oBAAoB,MAAM,QAAQ,MAAM;AAC5C,UAAM,YAAY,CAAC,QACjB,OAAO,OAAO,OAAO,CAAC,CAAC,EACpB,IAAI,CAAC,UAAU;AACd,YAAM,OAAO,yBAAyB,MAAM,KAAK;AACjD,YAAM,SAAmC,EAAE,OAAO,MAAM,OAAO,OAAO,MAAM,MAAM;AAClF,UAAI,KAAM,QAAO,OAAO;AACxB,aAAO;AAAA,IACT,CAAC,EACA,KAAK,CAAC,GAAG,MAAM,EAAE,MAAM,cAAc,EAAE,OAAO,QAAW,EAAE,aAAa,OAAO,CAAC,CAAC;AACtF,WAAO;AAAA,MACL,cAAc,UAAU,eAAe,eAAe,CAAC;AAAA,MACvD,gBAAgB,UAAU,eAAe,iBAAiB,CAAC;AAAA,IAC7D;AAAA,EACF,GAAG,CAAC,cAAc,CAAC;AAEnB,QAAM,UAAU,MAAM;AACpB,QAAI,YAAY;AAChB,mBAAe,gBAAgB;AAC7B,UAAI;AACF,cAAM,OAAO,MAAM,QAAyD,0BAA0B;AACtG,YAAI,aAAa,CAAC,KAAK,GAAI;AAC3B,cAAM,QAAQ,MAAM,QAAQ,KAAK,QAAQ,KAAK,IAAI,KAAK,OAAO,QAAQ,CAAC;AACvE,cAAM,MAA8B,CAAC;AACrC,cAAM,QAAQ,CAAC,MAAM;AAAE,cAAI,EAAE,MAAM,EAAE,KAAM,KAAI,EAAE,EAAE,IAAI,EAAE;AAAA,QAAK,CAAC;AAC/D,yBAAiB,GAAG;AAAA,MACtB,SAAS,KAAK;AACZ,gBAAQ,KAAK,mDAAmD,GAAG;AAAA,MACrE;AAAA,IACF;AACA,kBAAc,EAAE,MAAM,CAAC,QAAQ;AAC7B,cAAQ,KAAK,8CAA8C,GAAG;AAAA,IAChE,CAAC;AACD,WAAO,MAAM;AAAE,kBAAY;AAAA,IAAK;AAAA,EAClC,GAAG,CAAC,aAAa,YAAY,CAAC;AAE9B,QAAM,qBAAqB,MAAM,YAAY,CAAC,UAAkB;AAC9D,cAAU,MAAM,KAAK,CAAC;AACtB,YAAQ,CAAC;AAAA,EACX,GAAG,CAAC,CAAC;AAEL,QAAM,cAAc,MAAM,QAAQ,MAAM;AACtC,UAAM,SAAS,IAAI,gBAAgB;AACnC,WAAO,IAAI,QAAQ,OAAO,IAAI,CAAC;AAC/B,WAAO,IAAI,YAAY,OAAO,QAAQ,CAAC;AACvC,QAAI,QAAQ,SAAS,GAAG;AACtB,aAAO,IAAI,QAAQ,QAAQ,CAAC,EAAE,EAAE;AAChC,aAAO,IAAI,SAAS,QAAQ,CAAC,EAAE,OAAO,SAAS,KAAK;AAAA,IACtD;AACA,QAAI,OAAO,KAAK,EAAE,OAAQ,QAAO,IAAI,UAAU,OAAO,KAAK,CAAC;AAC5D,QAAI,kBAAkB,OAAQ,QAAO,IAAI,YAAY,kBAAkB,KAAK,GAAG,CAAC;AAChF,QAAI,mBAAmB,OAAQ,QAAO,IAAI,aAAa,mBAAmB,KAAK,GAAG,CAAC;AACnF,UAAM,iBAAiB,cAAc,mBAAmB;AACxD,eAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,cAAc,GAAG;AACvD,aAAO,IAAI,KAAK,GAAG;AAAA,IACrB;AACA,WAAO,OAAO,SAAS;AAAA,EACzB,GAAG,CAAC,qBAAqB,MAAM,UAAU,QAAQ,oBAAoB,mBAAmB,OAAO,CAAC;AAEhG,QAAM,gBAAgB,MAAM;AAAA,IAC1B,MAAM,OAAO,YAAY,IAAI,gBAAgB,WAAW,CAAC;AAAA,IACzD,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,eAAe,MAAM,QAAQ,OAAO;AAAA,IACxC,MAAM;AAAA,MACJ,QAAQ,CAAC,WACP,mBAAmB,mBAAmB,EAAE,GAAG,eAAe,aAAa,OAAO,GAAG,MAAM;AAAA,IAC3F;AAAA,IACA,MAAM;AAAA,MACJ,QAAQ,CAAC,WACP,mBAAmB,mBAAmB,EAAE,GAAG,eAAe,aAAa,QAAQ,KAAK,OAAO,GAAG,MAAM;AAAA,IACxG;AAAA,EACF,IAAI,CAAC,aAAa,CAAC;AAEnB,QAAM,UAAU,MAAM;AACpB,QAAI,YAAY;AAChB,mBAAe,OAAO;AACpB,mBAAa,IAAI;AACjB,qBAAe,IAAI;AACnB,UAAI;AACF,cAAM,WAA0B,EAAE,OAAO,CAAC,GAAG,OAAO,GAAG,YAAY,EAAE;AACrE,cAAM,OAAO,MAAM,QAAuB,wBAAwB,WAAW,IAAI,QAAW,EAAE,SAAS,CAAC;AACxG,YAAI,CAAC,KAAK,IAAI;AACZ,gBAAM,UACJ,OAAQ,KAAK,QAA2C,UAAU,WAC7D,KAAK,OAA8B,QACpC,EAAE,iCAAiC;AACzC,gBAAM,SAAS,OAAO;AACtB,cAAI,CAAC,UAAW,gBAAe,IAAI;AACnC;AAAA,QACF;AACA,cAAM,UAAU,KAAK,UAAU;AAC/B,YAAI,UAAW;AACf,uBAAe,KAAK,eAAe,IAAI;AACvC,cAAM,QAAQ,MAAM,QAAQ,QAAQ,KAAK,IAAI,QAAQ,QAAQ,CAAC;AAC9D,cAAM,SAAS,MACZ,IAAI,CAAC,SAAS,QAAQ,IAA+B,CAAC,EACtD,OAAO,CAAC,QAAwB,CAAC,CAAC,GAAG;AACxC,gBAAQ,MAAM;AACd,iBAAS,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ,OAAO,MAAM;AAC1E,sBAAc,OAAO,QAAQ,eAAe,WAAW,QAAQ,aAAa,CAAC;AAAA,MAC/E,SAAS,KAAK;AACZ,YAAI,CAAC,WAAW;AACd,yBAAe,IAAI;AACnB,gBAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,EAAE,iCAAiC;AACxF,gBAAM,SAAS,OAAO;AAAA,QACxB;AAAA,MACF,UAAE;AACA,YAAI,CAAC,UAAW,cAAa,KAAK;AAAA,MACpC;AAAA,IACF;AACA,SAAK;AACL,WAAO,MAAM;AAAE,kBAAY;AAAA,IAAK;AAAA,EAClC,GAAG,CAAC,aAAa,aAAa,cAAc,CAAC,CAAC;AAE9C,QAAM,UAAU,MAAM;AACpB,QAAI,aAAa,KAAK,OAAO,YAAY;AACvC,cAAQ,UAAU;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,MAAM,UAAU,CAAC;AAErB,QAAM,WAAW,MAAM,OAAO,cAAc,SAAS,KAAK,EAAE;AAC5D,QAAM,UAAU,MAAM;AACpB,QAAI,CAAC,SAAU;AACf,UAAM,SAAS,IAAI,gBAAgB;AACnC,QAAI,OAAO,KAAK,EAAE,OAAQ,QAAO,IAAI,UAAU,OAAO,KAAK,CAAC;AAC5D,QAAI,kBAAkB,OAAQ,mBAAkB,QAAQ,CAAC,OAAO,OAAO,OAAO,YAAY,EAAE,CAAC;AAC7F,QAAI,mBAAmB,OAAQ,oBAAmB,QAAQ,CAAC,OAAO,OAAO,OAAO,aAAa,EAAE,CAAC;AAChG,QAAI,OAAO,EAAG,QAAO,IAAI,QAAQ,OAAO,IAAI,CAAC;AAC7C,UAAM,iBAAiB,cAAc,mBAAmB;AACxD,eAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,cAAc,GAAG;AACvD,aAAO,IAAI,KAAK,GAAG;AAAA,IACrB;AACA,UAAM,OAAO,OAAO,SAAS;AAC7B,QAAI,SAAS,YAAY,KAAM;AAC/B,aAAS,UAAU;AACnB,WAAO,QAAQ,OAAO,GAAG,QAAQ,IAAI,IAAI,KAAK,UAAU,EAAE,QAAQ,MAAM,CAAC;AAAA,EAC3E,GAAG,CAAC,UAAU,QAAQ,MAAM,QAAQ,mBAAmB,oBAAoB,mBAAmB,CAAC;AAE/F,QAAM,gBAAgB,MAAM,YAAY,MAAM;AAC5C,SAAK,QAAQ,IAAI;AAAA,MACf,6BAA6B,aAAa,eAAe;AAAA,MACzD,6BAA6B,aAAa,iBAAiB;AAAA,IAC7D,CAAC;AACD,mBAAe,CAAC,UAAU,QAAQ,CAAC;AAAA,EACrC,GAAG,CAAC,WAAW,CAAC;AAEhB,QAAM,wBAAwB;AAC9B,QAAM,EAAE,aAAa,iBAAiB,mBAAmB,kBAAkB,IAAI,mBAI5E;AAAA,IACD,WAAW;AAAA,IACX,gBAAgB,EAAE,8BAA8B,4BAA4B;AAAA,EAC9E,CAAC;AACD,QAAM,0BAA0B;AAChC,QAAM,EAAE,aAAa,mBAAmB,mBAAmB,oBAAoB,IAAI,mBAKhF;AAAA,IACD,WAAW;AAAA,IACX,gBAAgB,EAAE,8BAA8B,4BAA4B;AAAA,EAC9E,CAAC;AAED,QAAM,mBAAmB,MAAM;AAAA,IAC7B,OAAO,WAAmB;AACxB,UAAI,gBAAiB;AACrB,YAAM,YAAY,MAAM,QAAQ;AAAA,QAC9B,OAAO;AAAA,UACL;AAAA,UACA;AAAA,QACF;AAAA,QACA,SAAS;AAAA,MACX,CAAC;AACD,UAAI,CAAC,UAAW;AAChB,YAAM,cAAc,KAAK,KAAK,CAAC,QAAQ,IAAI,OAAO,MAAM,GAAG,aAAa;AACxE,yBAAmB,MAAM;AACzB,UAAI;AACF,cAAM,kBAAkB;AAAA,UACtB,WAAW,YAAY;AACrB,kBAAM;AAAA,cACJ,0BAA0B,WAAW;AAAA,cACrC,MAAM,WAAW,mBAAmB;AAAA,gBAClC,MAAM,EAAE,IAAI,OAAO;AAAA,gBACnB,cAAc,EAAE,oCAAoC,wBAAwB;AAAA,cAC9E,CAAC;AAAA,YACH;AAAA,UACF;AAAA,UACA,SAAS;AAAA,YACP,QAAQ;AAAA,YACR,cAAc;AAAA,YACd,YAAY;AAAA,YACZ,mBAAmB;AAAA,UACrB;AAAA,QACF,CAAC;AACD,cAAM,EAAE,sCAAsC,eAAe,GAAG,SAAS;AACzE,gBAAQ,CAAC,SAAS,KAAK,OAAO,CAAC,QAAQ,IAAI,OAAO,MAAM,CAAC;AACzD,iBAAS,CAAC,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,CAAC;AACxC,sBAAc;AAAA,MAChB,SAAS,KAAK;AAGZ,YAAI,sBAAsB,KAAK,CAAC,GAAG;AACjC,wBAAc;AACd;AAAA,QACF;AACA,cAAM,UACJ,eAAe,SAAS,IAAI,UACxB,IAAI,UACJ,EAAE,oCAAoC,wBAAwB;AACpE,cAAM,SAAS,OAAO;AAAA,MACxB,UAAE;AACA,2BAAmB,IAAI;AAAA,MACzB;AAAA,IACF;AAAA,IACA,CAAC,SAAS,eAAe,iBAAiB,qBAAqB,MAAM,mBAAmB,yBAAyB,CAAC;AAAA,EACpH;AAEA,QAAM,uBAAuB,MAAM,YAAY,CAAC,YAAoB;AAClE,gBAAY,OAAO;AACnB,YAAQ,CAAC;AAAA,EACX,GAAG,CAAC,CAAC;AAEL,QAAM,mBAAmB,MAAM,YAAY,OAAO,iBAA4B;AAC5E,UAAM,YAAY,MAAM,QAAQ;AAAA,MAC9B,OAAO,EAAE,yCAAyC,yBAAyB,EAAE,OAAO,aAAa,OAAO,CAAC;AAAA,MACzG,aAAa,EAAE,+CAA+C,+BAA+B;AAAA,MAC7F,SAAS;AAAA,IACX,CAAC;AACD,QAAI,CAAC,UAAW,QAAO;AAEvB,UAAM,EAAE,WAAW,SAAS,IAAI,MAAM,gBAAgB;AAAA,MACpD,WAAW,YACT;AAAA,QACE;AAAA,QACA,OAAO,QAAQ;AACb,gBAAM,WAAW,mBAAmB;AAAA,YAClC,MAAM,EAAE,IAAI,IAAI,GAAG;AAAA,YACnB,cAAc,EAAE,oCAAoC,wBAAwB;AAAA,UAC9E,CAAC;AAAA,QACH;AAAA,QACA;AAAA,UACE,sBAAsB,EAAE,oCAAoC,wBAAwB;AAAA,UACpF,QAAQ;AAAA,UACR,UAAU;AAAA,YACR,SAAS;AAAA,YACT,MAAM,EAAE,gDAAgD,uBAAuB;AAAA,YAC/E,aAAa;AAAA,cACX;AAAA,cACA;AAAA,cACA,EAAE,OAAO,aAAa,OAAO;AAAA,YAC/B;AAAA,YACA,MAAM,EAAE,QAAQ,uBAAuB;AAAA,UACzC;AAAA,QACF;AAAA,MACF;AAAA,MACF,SAAS;AAAA,QACP,QAAQ;AAAA,QACR,cAAc;AAAA,QACd,mBAAmB;AAAA,MACrB;AAAA,IACF,CAAC;AAED,QAAI,UAAU,SAAS,GAAG;AACxB,YAAM,eAAe,IAAI,IAAI,UAAU,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AACvD,cAAQ,CAAC,SAAS,KAAK,OAAO,CAAC,MAAM,CAAC,aAAa,IAAI,EAAE,EAAE,CAAC,CAAC;AAC7D,eAAS,CAAC,SAAS,KAAK,IAAI,GAAG,OAAO,UAAU,MAAM,CAAC;AACvD,qBAAe,CAAC,SAAS,OAAO,CAAC;AACjC,UAAI,UAAU,SAAS,GAAG;AACxB,+BAAuB,UAAU,QAAQ;AAAA,UACvC,WAAW;AAAA,UACX,aAAa,EAAE,kDAAkD,wBAAwB,EAAE,OAAO,UAAU,OAAO,CAAC;AAAA,UACpH,cAAc;AAAA,QAChB,CAAC;AAAA,MACH;AACA,UAAI,SAAS,WAAW,GAAG;AACzB;AAAA,UACE,EAAE,2CAA2C,yBAAyB,EAAE,OAAO,UAAU,OAAO,CAAC;AAAA,UACjG;AAAA,QACF;AAAA,MACF,OAAO;AACL;AAAA,UACE,EAAE,2CAA2C,uDAAuD;AAAA,YAClG,SAAS,UAAU;AAAA,YACnB,OAAO,aAAa;AAAA,YACpB,QAAQ,SAAS;AAAA,UACnB,CAAC;AAAA,UACD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,eAAW,SAAS,wBAAwB,QAAQ,GAAG;AACrD,YAAM,UAAU,MAAM,UAAU,IAC5B,MAAM,gBACN;AAAA,QACE;AAAA,QACA;AAAA,QACA,EAAE,OAAO,MAAM,OAAO,SAAS,MAAM,cAAc;AAAA,MACrD;AACJ,YAAM,SAAS,OAAO;AAAA,IACxB;AAEA,WAAO,UAAU,SAAS;AAAA,EAC5B,GAAG,CAAC,uBAAuB,SAAS,mBAAmB,iBAAiB,CAAC,CAAC;AAE1E,QAAM,EAAE,MAAM,kBAAkB,CAAC,EAAE,IAAI,mBAAmB,CAAC,EAAE,UAAU,aAAa,GAAG;AAAA,IACrF,WAAW,CAAC,cAAc,WAAW;AAAA,EACvC,CAAC;AACD,QAAM,gBAAgB,iBAAiB;AACvC,QAAM,CAAC,oBAAoB,qBAAqB,IAAI,MAAM,SAAiC,CAAC,CAAC;AAC7F,QAAM,UAAU,MAAM;AACpB,UAAM,aAAa,IAAI,gBAAgB;AACvC,QAAI,YAAY;AAChB,SAAK,4BAA4B,IAAI,EAAE,UAAU,KAAK,QAAQ,WAAW,OAAO,CAAC,EAC9E,KAAK,CAAC,UAAU;AACf,UAAI,CAAC,UAAW,uBAAsB,kCAAkC,KAAK,CAAC;AAAA,IAChF,CAAC,EACA,MAAM,MAAM;AACX,UAAI,CAAC,UAAW,uBAAsB,CAAC,CAAC;AAAA,IAC1C,CAAC;AACH,WAAO,MAAM;AACX,kBAAY;AACZ,iBAAW,MAAM;AAAA,IACnB;AAAA,EACF,GAAG,CAAC,YAAY,CAAC;AACjB,QAAM,6BAA6B,MAAM;AAAA,IACvC,MAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA,EAAE,iCAAiC,cAAc;AAAA,IACnD;AAAA,IACA,CAAC,eAAe,oBAAoB,CAAC;AAAA,EACvC;AACA,QAAM,yBAAyB,MAAM,YAAY,OAAO,UAAoD;AAC1G,UAAM,QAAQ,MAAM,4BAA4B,SAAS,IAAI,EAAE,UAAU,IAAI,CAAC;AAC9E,WAAO,kCAAkC,KAAK;AAAA,EAChD,GAAG,CAAC,CAAC;AAEL,QAAM,UAAU,MAAM,QAA8B,MAAM;AACxD,UAAM,UAAU,oBAAC,UAAK,WAAU,iCAAiC,YAAE,8BAA8B,GAAE;AACnG,UAAM,uBAAuB,CAAC,MAAqB,UACjD;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,KAAK,eAAe,IAAI;AAAA,QACxB,UAAU,QAAQ,oBAAC,UAAK,WAAU,WAAW,iBAAM,IAAU;AAAA,QAC7D,WAAU;AAAA,QACV,sBAAqB;AAAA,QACrB,eAAc;AAAA,QACd,gBAAe;AAAA;AAAA,IACjB;AAEF,UAAM,2BAA2B,CAC/B,OACA,kBACG;AACH,UAAI,CAAC,MAAM,OAAQ,QAAO;AAC1B,YAAM,SAAS;AAAA,QACb,MAAM,IAAI,CAAC,UAAW,MAAM,SAAS,MAAM,MAAM,KAAK,EAAE,SAAS,MAAM,QAAQ,aAAc;AAAA,MAC/F;AACA,UAAI,CAAC,OAAO,OAAQ,QAAO;AAC3B,aACE,oBAAC,yBAAsB,QAAgB,YAAY,GAAG;AAAA,IAE1D;AAEA,UAAM,gBAAgB,gBACnB,OAAO,CAAC,QAAQ,0BAA0B,GAAG,CAAC,EAC9C,IAAwB,CAAC,SAAS;AAAA,MACjC,aAAa,MAAM,IAAI,GAAG;AAAA,MAC1B,QAAQ,IAAI,SAAS,IAAI;AAAA,MACzB,MAAM;AAAA,QACJ,oBAAoB,IAAI,OAAO,SAAS;AAAA,QACxC,aAAa,IAAI,OAAO,SAAS;AAAA,QACjC,YAAY,+BAA+B,IAAI,IAAI;AAAA,QACnD,eAAe,kCAAkC,IAAI,OAAO;AAAA,QAC5D,QAAQ,IAAI,gBAAgB;AAAA,QAC5B,UAAU;AAAA,MACZ;AAAA,MACA,MAAM,CAAC,EAAE,SAAS,MAAM;AACtB,cAAM,QAAQ,SAAS;AACvB,YAAI,SAAS,KAAM,QAAO;AAC1B,YAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,gBAAM,aAAa;AAAA,YACjB,MACG,IAAI,CAAC,SAAS;AACb,kBAAI,QAAQ,KAAM,QAAO;AACzB,kBAAI,OAAO,SAAS,SAAU,QAAO;AACrC,qBAAO,OAAO,IAAI;AAAA,YACpB,CAAC;AAAA,UACL;AACA,cAAI,CAAC,WAAW,OAAQ,QAAO;AAC/B,iBAAO,oBAAC,yBAAsB,QAAQ,YAAY,YAAY,GAAG;AAAA,QACnE;AACA,YAAI,OAAO,UAAU,WAAW;AAC9B,iBACE,oBAAC,UAAK,WAAU,WACb,kBACG,EAAE,mCAAmC,KAAK,IAC1C,EAAE,kCAAkC,IAAI,GAC9C;AAAA,QAEJ;AACA,cAAM,cAAc,OAAO,UAAU,WAAW,MAAM,KAAK,IAAI,OAAO,KAAK;AAC3E,YAAI,CAAC,YAAa,QAAO;AACzB,eAAO,oBAAC,UAAK,WAAU,WAAW,uBAAY;AAAA,MAChD;AAAA,IACF,EAAE;AAEJ,WAAO;AAAA,MACL;AAAA,QACE,aAAa;AAAA,QACb,QAAQ,EAAE,oCAAoC;AAAA,QAC9C,MAAM;AAAA,UACJ,eAAe;AAAA,UACf,oBAAoB;AAAA,UACpB,WAAW;AAAA,UACX,aAAa;AAAA,UACb,UAAU;AAAA,QACZ;AAAA,QACA,MAAM,CAAC,EAAE,IAAI,MAAM,oBAAC,UAAK,WAAU,uBAAuB,cAAI,SAAS,OAAM;AAAA,MAC/E;AAAA,MACA;AAAA,QACE,aAAa;AAAA,QACb,QAAQ,EAAE,qCAAqC;AAAA,QAC/C,MAAM;AAAA,UACJ,YAAY;AAAA,UACZ,eAAe,kBAAkB;AAAA,UACjC,oBAAoB;AAAA,UACpB,WAAW;AAAA,UACX,aAAa;AAAA,QACf;AAAA,QACA,MAAM,CAAC,EAAE,IAAI,MAAM,qBAAqB,iBAAiB,IAAI,SAAS,MAAM;AAAA,MAC9E;AAAA,MACA;AAAA,QACE,aAAa;AAAA,QACb,QAAQ,EAAE,4CAA4C;AAAA,QACtD,MAAM;AAAA,UACJ,YAAY;AAAA,UACZ,eAAe,kBAAkB;AAAA,UACjC,oBAAoB;AAAA,UACpB,WAAW;AAAA,UACX,aAAa;AAAA,QACf;AAAA,QACA,MAAM,CAAC,EAAE,IAAI,MAAM,qBAAqB,mBAAmB,IAAI,SAAS,aAAa;AAAA,MACvF;AAAA,MACA;AAAA,QACE,aAAa;AAAA,QACb,QAAQ,EAAE,yCAAyC,UAAU;AAAA,QAC7D,MAAM;AAAA,UACJ,oBAAoB;AAAA,UACpB,WAAW;AAAA,UACX,aAAa;AAAA,UACb,UAAU;AAAA,QACZ;AAAA,QACA,MAAM,CAAC,EAAE,IAAI,MAAM;AACjB,gBAAM,OAAO,IAAI,SAAS,aAAa,cAAc,IAAI,SAAS,UAAU,IAAI;AAChF,iBAAO,OAAO,oBAAC,UAAK,WAAU,WAAW,gBAAK,IAAU;AAAA,QAC1D;AAAA,MACF;AAAA,MACA;AAAA,QACE,aAAa;AAAA,QACb,QAAQ,EAAE,oCAAoC;AAAA,QAC9C,MAAM;AAAA,UACJ,YAAY;AAAA,UACZ,oBAAoB;AAAA,UACpB,WAAW;AAAA,UACX,aAAa;AAAA,QACf;AAAA,QACA,MAAM,CAAC,EAAE,IAAI,MACX,oBAAC,UAAK,WAAU,uBACb,yBAAe,IAAI,SAAS,eAAe,MAAM,IAAI,SAAS,iBAAiB,MAAM,EAAE,8BAA8B,CAAC,GACzH;AAAA,MAEJ;AAAA,MACA;AAAA,QACE,aAAa;AAAA,QACb,QAAQ,EAAE,0CAA0C;AAAA,QACpD,MAAM;AAAA,UACJ,YAAY;AAAA,UACZ,oBAAoB;AAAA,UACpB,WAAW;AAAA,UACX,aAAa;AAAA,QACf;AAAA,QACA,MAAM,CAAC,EAAE,IAAI,MAAM;AACjB,gBAAM,QAAQ,IAAI,SAAS;AAC3B,cAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,GAAG;AACvD,mBAAO,oBAAC,UAAK,WAAU,WAAW,aAAG,KAAK,IAAI,KAAK,IAAI,OAAO,CAAC,GAAG,GAAG,CAAC,KAAI;AAAA,UAC5E;AACA,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA;AAAA,QACE,aAAa;AAAA,QACb,QAAQ,EAAE,4CAA4C;AAAA,QACtD,MAAM;AAAA,UACJ,oBAAoB;AAAA,UACpB,WAAW;AAAA,UACX,aAAa;AAAA,UACb,gBAAgB;AAAA,QAClB;AAAA,QACA,MAAM,CAAC,EAAE,IAAI,MACX,oBAAC,UAAK,WAAU,WACb,0BAAgB,IAAI,SAAS,mBAAmB,MAAM,EAAE,8BAA8B,CAAC,GAC1F;AAAA,MAEJ;AAAA,MACA;AAAA,QACE,aAAa;AAAA,QACb,QAAQ,EAAE,sCAAsC,OAAO;AAAA,QACvD,MAAM;AAAA,UACJ,oBAAoB;AAAA,UACpB,YAAY;AAAA,UACZ,eAAe;AAAA,UACf,mBAAmB;AAAA,UACnB,aAAa;AAAA,UACb,gBAAgB;AAAA,UAChB,WAAW;AAAA,UACX,QAAQ;AAAA,QACV;AAAA,QACA,MAAM,CAAC,EAAE,IAAI,MAAM,IAAI,SAAS,eAAe;AAAA,MACjD;AAAA,MACA;AAAA,QACE,aAAa;AAAA,QACb,QAAQ,EAAE,wCAAwC;AAAA,QAClD,MAAM;AAAA,UACJ,oBAAoB;AAAA,UACpB,YAAY;AAAA,UACZ,aAAa;AAAA,UACb,gBAAgB;AAAA,UAChB,UAAU;AAAA,UACV,gBAAgB,CAAC,QACf;AAAA,YACE,IAAI,UAAU,IAAI,CAAC,UAAW,MAAM,SAAS,MAAM,MAAM,KAAK,EAAE,SAAS,MAAM,QAAQ,EAAE,qCAAqC,CAAE;AAAA,UAClI,EAAE,KAAK,IAAI;AAAA,QACf;AAAA,QACA,MAAM,CAAC,EAAE,IAAI,MAAM,yBAAyB,IAAI,SAAS,WAAW,EAAE,qCAAqC,CAAC;AAAA,MAC9G;AAAA,MACA;AAAA,QACE,aAAa;AAAA,QACb,QAAQ,EAAE,qCAAqC;AAAA,QAC/C,MAAM;AAAA,UACJ,oBAAoB;AAAA,UACpB,YAAY;AAAA,UACZ,aAAa;AAAA,UACb,gBAAgB;AAAA,UAChB,UAAU;AAAA,UACV,gBAAgB,CAAC,QACf;AAAA,YACE,IAAI,OAAO,IAAI,CAAC,UAAW,MAAM,SAAS,MAAM,MAAM,KAAK,EAAE,SAAS,MAAM,QAAQ,EAAE,oCAAoC,CAAE;AAAA,UAC9H,EAAE,KAAK,IAAI;AAAA,QACf;AAAA,QACA,MAAM,CAAC,EAAE,IAAI,MAAM,yBAAyB,IAAI,SAAS,QAAQ,EAAE,oCAAoC,CAAC;AAAA,MAC1G;AAAA,MACA;AAAA,QACE,aAAa;AAAA,QACb,QAAQ,EAAE,wCAAwC;AAAA,QAClD,MAAM;AAAA,UACJ,oBAAoB;AAAA,UACpB,WAAW;AAAA,UACX,aAAa;AAAA,UACb,gBAAgB;AAAA,QAClB;AAAA,QACA,MAAM,CAAC,EAAE,IAAI,MACX,oBAAC,UAAK,WAAU,WACb,0BAAgB,IAAI,SAAS,aAAa,MAAM,EAAE,8BAA8B,CAAC,GACpF;AAAA,MAEJ;AAAA,MACA,GAAG;AAAA,IACL;AAAA,EACF,GAAG,CAAC,iBAAiB,gBAAgB,mBAAmB,wBAAwB,eAAe,4BAA4B,CAAC,CAAC;AAE7H,QAAM,EAAE,qBAAqB,IAAI,wBAAwB,EAAE,SAAS,gBAAgB,CAAC;AAQrF,QAAM,UAAU,MAAM;AACpB,mBAAe,CAAC,SAAS;AACvB,UAAI,SAAS,qBAAsB,QAAO;AAC1C,UAAI,KAAK,WAAW,qBAAqB,QAAQ;AAC/C,YAAI,OAAO;AACX,iBAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,cAAI,KAAK,CAAC,EAAE,QAAQ,qBAAqB,CAAC,EAAE,KAAK;AAAE,mBAAO;AAAO;AAAA,UAAM;AAAA,QACzE;AACA,YAAI,KAAM,QAAO;AAAA,MACnB;AACA,aAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,oBAAoB,CAAC;AAEzB,QAAM,0BAA0B,MAAM,QAA0B,MAAM;AACpE,UAAM,eAAe,oBAAI,IAAoB;AAC7C,UAAM,gBAAgB,oBAAI,IAAoB;AAC9C,eAAW,OAAO,MAAM;AACtB,iBAAW,UAAU,IAAI,QAAQ;AAC/B,YAAI,kBAAkB,SAAS,OAAO,EAAE,KAAK,OAAO,MAAM,KAAK,EAAE,SAAS,GAAG;AAC3E,uBAAa,IAAI,OAAO,IAAI,OAAO,KAAK;AAAA,QAC1C;AAAA,MACF;AACA,iBAAW,WAAW,IAAI,WAAW;AACnC,YAAI,mBAAmB,SAAS,QAAQ,EAAE,KAAK,QAAQ,MAAM,KAAK,EAAE,SAAS,GAAG;AAC9E,wBAAc,IAAI,QAAQ,IAAI,QAAQ,KAAK;AAAA,QAC7C;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,MACL;AAAA,QACE,KAAK;AAAA,QACL,OAAO,EAAE,uCAAuC,QAAQ;AAAA,QACxD,MAAM;AAAA,QACN,SAAS,kBAAkB,IAAI,CAAC,QAAQ,EAAE,OAAO,IAAI,OAAO,aAAa,IAAI,EAAE,KAAK,GAAG,EAAE;AAAA,MAC3F;AAAA,MACA;AAAA,QACE,KAAK;AAAA,QACL,OAAO,EAAE,0CAA0C,WAAW;AAAA,QAC9D,MAAM;AAAA,QACN,SAAS,mBAAmB,IAAI,CAAC,QAAQ,EAAE,OAAO,IAAI,OAAO,cAAc,IAAI,EAAE,KAAK,GAAG,EAAE;AAAA,MAC7F;AAAA,IACF;AAAA,EACF,GAAG,CAAC,MAAM,oBAAoB,mBAAmB,CAAC,CAAC;AACnD,QAAM,wBAAwB,MAAM,QAA4B,MAAM;AACpE,UAAM,QAA0E,CAAC;AACjF,QAAI,kBAAkB,OAAQ,OAAM,KAAK,EAAE,OAAO,UAAU,UAAU,aAAa,OAAO,kBAAkB,CAAC;AAC7G,QAAI,mBAAmB,OAAQ,OAAM,KAAK,EAAE,OAAO,aAAa,UAAU,aAAa,OAAO,mBAAmB,CAAC;AAClH,WAAO,MAAM,SAAS,kBAAkB,KAAK,IAAI,gBAAgB;AAAA,EACnE,GAAG,CAAC,oBAAoB,iBAAiB,CAAC;AAC1C,QAAM,gCAAgC,MAAM,YAAY,CAAC,WAAmB;AAC1E,UAAM,OAAO,sBAAsB,KAAK,SAAS,KAAK,CAAC,UAAU,MAAM,OAAO,MAAM;AACpF,QAAI,CAAC,QAAQ,KAAK,SAAS,OAAQ;AACnC,QAAI,KAAK,UAAU,SAAU,sBAAqB,CAAC,CAAC;AACpD,QAAI,KAAK,UAAU,YAAa,uBAAsB,CAAC,CAAC;AACxD,YAAQ,CAAC;AAAA,EACX,GAAG,CAAC,sBAAsB,KAAK,QAAQ,CAAC;AAExC,QAAM,eAAe,MAAM,QAAwB,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAE/E,SACE,qBAAC,QACC;AAAA,yBAAC,YACC;AAAA,0BAAC,eAAY,QAAO,QAAO,WAAU,QAAO;AAAA,MAC5C;AAAA,QAAC;AAAA;AAAA,UACC,mBAAiB;AAAA,UACjB,qBAAmB;AAAA,UACnB,OAAO,EAAE,4BAA4B;AAAA,UACrC,SACE,oBAAC,UAAO,SAAO,MACb,8BAAC,QAAK,MAAK,mCACR,YAAE,oCAAoC,UAAU,GACnD,GACF;AAAA,UAEF;AAAA,UACA,eAAe,EAAE,MAAM,KAAK;AAAA,UAC5B,MAAM;AAAA,UACN,YAAY,CAAC,QAAQ;AACnB,mBAAO,KAAK,4BAA4B,IAAI,EAAE,EAAE;AAAA,UAClD;AAAA,UACA,YAAY,CAAC,QAAQ;AACnB,kBAAM,aAAa,oBAAoB,IAAI;AAC3C,mBACE;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO;AAAA,kBACL;AAAA,oBACE,IAAI;AAAA,oBACJ,OAAO,EAAE,qCAAqC,MAAM;AAAA,oBACpD,UAAU,MAAM;AAAE,6BAAO,KAAK,4BAA4B,IAAI,EAAE,EAAE;AAAA,oBAAE;AAAA,kBACtE;AAAA,kBACA;AAAA,oBACE,IAAI;AAAA,oBACJ,OAAO,EAAE,6CAA6C,iBAAiB;AAAA,oBACvE,UAAU,MAAM;AACd,0BAAI,OAAO,WAAW,aAAa;AACjC,+BAAO,KAAK,4BAA4B,IAAI,EAAE,IAAI,UAAU,UAAU;AAAA,sBACxE;AAAA,oBACF;AAAA,kBACF;AAAA,kBACA;AAAA,oBACE,IAAI;AAAA,oBACJ,OAAO,aACH,EAAE,yCAAyC,gBAAW,IACtD,EAAE,uCAAuC,QAAQ;AAAA,oBACrD,aAAa;AAAA,oBACb,UAAU,MAAM,iBAAiB,IAAI,EAAE;AAAA,kBACzC;AAAA,gBACF;AAAA;AAAA,YACF;AAAA,UAEJ;AAAA,UACA,UAAQ;AAAA,UACR;AAAA,UACA,iBAAiB;AAAA,UACjB,aAAa;AAAA,YACX;AAAA,cACE,IAAI;AAAA,cACJ,OAAO,EAAE,uCAAuC,QAAQ;AAAA,cACxD,aAAa;AAAA,cACb,WAAW;AAAA,YACb;AAAA,UACF;AAAA,UACA,aAAa;AAAA,UACb,gBAAgB;AAAA,UAChB,mBAAmB,EAAE,wCAAwC;AAAA,UAC7D,YAAY;AAAA,YACV;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,cAAc,CAAC,aAAa,QAAQ,QAAQ;AAAA,YAC5C,iBAAiB,CAAC,IAAI,IAAI,IAAI,GAAG;AAAA,YACjC,kBAAkB;AAAA,YAClB;AAAA,UACF;AAAA,UACA;AAAA,UACA,eAAe;AAAA,YACb,OAAO,EAAE,8BAA8B;AAAA,YACvC,WAAW;AAAA,UACb;AAAA,UACA,UAAU;AAAA,UACV,UAAU,EAAE,UAAU;AAAA,UACtB,aAAa,EAAE,SAAS,uBAAuB;AAAA,UAC/C,gBAAgB;AAAA,YACd,MAAM;AAAA,YACN,OAAO,YAAY;AAAA,YACnB,UAAU,YAAY;AAAA,YACtB,SAAS,MAAM,YAAY,MAAM;AAAA,YACjC,SAAS;AAAA,YACT,YAAY;AAAA,YACZ,iBAAiB;AAAA,YACjB,gBAAgB,MAAM,eAAe,CAAC,SAAS,CAAC,IAAI;AAAA,YACpD,aAAa,CAAC,SAAS;AACrB,0BAAY,YAAY,IAAI;AAC5B,sBAAQ,CAAC;AAAA,YACX;AAAA,UACF;AAAA,UACA,mBACE,iCACE;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAM;AAAA,gBACN,QAAQ;AAAA,gBACR,aAAa;AAAA,gBACb,cAAc;AAAA,gBACd,QAAQ,MAAM,eAAe,IAAI;AAAA;AAAA,YACnC;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAM,YAAY;AAAA,gBAClB,QAAQ;AAAA,gBACR,aAAa;AAAA,gBACb,cAAc,CAAC,OAAO,YAAY,SAAS,EAAE,MAAM,cAAc,QAAQ,GAAG,CAAC;AAAA,gBAC7E,QAAQ,MAAM,eAAe,IAAI;AAAA;AAAA,YACnC;AAAA,aACF;AAAA,UAEF,uBAAuB;AAAA,YACrB,QAAQ,oBAAoB,KAAK,SAAS,SAAS;AAAA,YACnD,kBAAkB,EAAE,gCAAgC,OAAO;AAAA,YAC3D,eAAe,YAAY,KAAK,KAAK,SAAS,SAAS;AAAA,YACvD,YAAY;AAAA,YACZ,cAAc,MAAM,YAAY,SAAS,EAAE,MAAM,aAAa,CAAC;AAAA,UACjE;AAAA,UACA,aAAW;AAAA;AAAA,MACb;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,QAAQ;AAAA,UACR,OAAO,YAAY;AAAA,UACnB,UAAU,YAAY;AAAA,UACtB,SAAS,YAAY;AAAA,UACrB,SAAS;AAAA,UACT,SAAS,YAAY;AAAA,UACrB,eAAe,YAAY;AAAA,UAC3B,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,MAAM;AAAA,UACN,cAAc;AAAA,UACd,YAAY;AAAA,UACZ,uBAAsB;AAAA;AAAA,MACxB;AAAA,OACF;AAAA,IACC;AAAA,KACH;AAEJ;AAEA,SAAS,QAAQ,MAA+C;AAC9D,QAAM,KAAK,OAAO,KAAK,OAAO,WAAW,KAAK,KAAK;AACnD,MAAI,CAAC,GAAI,QAAO;AAChB,QAAM,QAAQ,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ;AAC5D,QAAM,SAAS,OAAO,KAAK,WAAW,WAAW,KAAK,SAAS;AAC/D,QAAM,gBAAgB,OAAO,KAAK,mBAAmB,WAAW,KAAK,iBAAiB;AACtF,QAAM,kBAAkB,OAAO,KAAK,sBAAsB,WAAW,KAAK,oBAAoB;AAC9F,QAAM,aAAa,OAAO,KAAK,gBAAgB,WAAW,KAAK,cAAc;AAC7E,QAAM,iBAAiB,KAAK;AAC5B,QAAM,cACJ,OAAO,mBAAmB,WACtB,iBACA,OAAO,mBAAmB,YAAY,eAAe,KAAK,IACxD,OAAO,cAAc,IACrB;AACR,QAAM,gBACJ,OAAO,KAAK,mBAAmB,YAAY,KAAK,eAAe,KAAK,EAAE,SAClE,KAAK,eAAe,KAAK,EAAE,YAAY,IACvC;AACN,QAAM,iBAAiB,KAAK;AAC5B,QAAM,cACJ,OAAO,mBAAmB,WACtB,iBACA,OAAO,mBAAmB,YAAY,eAAe,KAAK,EAAE,SAC1D,OAAO,cAAc,IACrB;AACR,QAAM,kBAAkB,OAAO,KAAK,sBAAsB,WAAW,KAAK,oBAAoB;AAC9F,QAAM,YAAY,OAAO,KAAK,eAAe,WAAW,KAAK,aAAa;AAC1E,QAAM,cAAc,OAAO,KAAK,kBAAkB,WAAW,KAAK,gBAAgB;AAClF,QAAM,YAAY,MAAM,QAAQ,KAAK,MAAM,IAAI,KAAK,SAAS,CAAC;AAC9D,QAAM,eAAe,MAAM,QAAQ,KAAK,SAAS,IAAI,KAAK,YAAY,CAAC;AACvE,QAAM,SAAS,UACZ,IAAI,CAAC,UAAU;AACd,QAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,UAAM,OAAO;AACb,UAAM,MAAM,OAAO,KAAK,OAAO,WAAW,KAAK,KAAK;AACpD,QAAI,CAAC,IAAK,QAAO;AACjB,UAAM,QAAQ,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ;AAC5D,WAAO,EAAE,IAAI,KAAK,MAAM;AAAA,EAC1B,CAAC,EACA,OAAO,CAAC,UAAkD,CAAC,CAAC,KAAK;AACpE,QAAM,YAAY,aACf,IAAI,CAAC,UAAU;AACd,QAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,UAAM,OAAO;AACb,UAAM,MAAM,OAAO,KAAK,OAAO,WAAW,KAAK,KAAK;AACpD,QAAI,CAAC,IAAK,QAAO;AACjB,UAAM,QAAQ,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ;AAC5D,WAAO,EAAE,IAAI,KAAK,MAAM;AAAA,EAC1B,CAAC,EACA,OAAO,CAAC,UAAkD,CAAC,CAAC,KAAK;AACpE,QAAM,eAAwC,CAAC;AAC/C,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC/C,QAAI,IAAI,WAAW,KAAK,EAAG,cAAa,GAAG,IAAI;AAAA,EACjD;AACA,SAAO,wBAAwB;AAAA,IAC7B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL,GAAG,IAAI;AACT;",
6
6
  "names": ["formatter"]
7
7
  }
@@ -38,7 +38,9 @@ import {
38
38
  SelectTrigger,
39
39
  SelectValue
40
40
  } from "@open-mercato/ui/primitives/select";
41
- import { apiCall, apiCallOrThrow, readApiResultOrThrow } from "@open-mercato/ui/backend/utils/apiCall";
41
+ import { apiCall, apiCallOrThrow, readApiResultOrThrow, withScopedApiRequestHeaders } from "@open-mercato/ui/backend/utils/apiCall";
42
+ import { buildOptimisticLockHeader } from "@open-mercato/ui/backend/utils/optimisticLock";
43
+ import { surfaceRecordConflict } from "@open-mercato/ui/backend/conflicts";
42
44
  import { useCurrentUserId } from "@open-mercato/ui/backend/utils/useCurrentUserId";
43
45
  import { flash } from "@open-mercato/ui/backend/FlashMessages";
44
46
  import { useConfirmDialog } from "@open-mercato/ui/backend/confirm-dialog";
@@ -846,22 +848,26 @@ function DealsKanbanPage() {
846
848
  }
847
849
  }
848
850
  setPendingDealId(dealId);
851
+ const dealVersion = typeof movingItem?.updated_at === "string" ? movingItem.updated_at : null;
849
852
  runMoveMutation({
850
853
  operation: async () => {
851
- await apiCallOrThrow(
852
- "/api/customers/deals",
853
- {
854
- method: "PUT",
855
- headers: { "content-type": "application/json" },
856
- body: JSON.stringify({ id: dealId, pipelineStageId: targetStageId })
857
- },
858
- {
859
- errorMessage: translateWithFallback(
860
- t,
861
- "customers.deals.pipeline.moveError",
862
- "Failed to update deal stage."
863
- )
864
- }
854
+ await withScopedApiRequestHeaders(
855
+ buildOptimisticLockHeader(dealVersion),
856
+ () => apiCallOrThrow(
857
+ "/api/customers/deals",
858
+ {
859
+ method: "PUT",
860
+ headers: { "content-type": "application/json" },
861
+ body: JSON.stringify({ id: dealId, pipelineStageId: targetStageId })
862
+ },
863
+ {
864
+ errorMessage: translateWithFallback(
865
+ t,
866
+ "customers.deals.pipeline.moveError",
867
+ "Failed to update deal stage."
868
+ )
869
+ }
870
+ )
865
871
  );
866
872
  },
867
873
  context: {
@@ -880,6 +886,7 @@ function DealsKanbanPage() {
880
886
  queryClient.setQueryData(key, data);
881
887
  }
882
888
  setExtraCardsByStage(extraSnapshot);
889
+ if (surfaceRecordConflict(error, t)) return;
883
890
  const message = error instanceof Error && error.message ? error.message : translateWithFallback(
884
891
  t,
885
892
  "customers.deals.pipeline.moveError",
@@ -1349,24 +1356,28 @@ function DealsKanbanPage() {
1349
1356
  }, [invalidateKanbanData, scopeVersion, selectedPipelineId]);
1350
1357
  const updateDealStatus = React.useCallback(
1351
1358
  async (dealId, status) => {
1359
+ const dealVersion = deals.find((deal) => deal.id === dealId)?.updatedAt ?? null;
1352
1360
  setPendingDealId(dealId);
1353
1361
  try {
1354
1362
  await runDealMutation({
1355
1363
  operation: async () => {
1356
- await apiCallOrThrow(
1357
- "/api/customers/deals",
1358
- {
1359
- method: "PUT",
1360
- headers: { "content-type": "application/json" },
1361
- body: JSON.stringify({ id: dealId, status })
1362
- },
1363
- {
1364
- errorMessage: translateWithFallback(
1365
- t,
1366
- "customers.deals.kanban.menu.error.status",
1367
- "Failed to update deal status."
1368
- )
1369
- }
1364
+ await withScopedApiRequestHeaders(
1365
+ buildOptimisticLockHeader(dealVersion),
1366
+ () => apiCallOrThrow(
1367
+ "/api/customers/deals",
1368
+ {
1369
+ method: "PUT",
1370
+ headers: { "content-type": "application/json" },
1371
+ body: JSON.stringify({ id: dealId, status })
1372
+ },
1373
+ {
1374
+ errorMessage: translateWithFallback(
1375
+ t,
1376
+ "customers.deals.kanban.menu.error.status",
1377
+ "Failed to update deal status."
1378
+ )
1379
+ }
1380
+ )
1370
1381
  );
1371
1382
  },
1372
1383
  context: {
@@ -1390,6 +1401,10 @@ function DealsKanbanPage() {
1390
1401
  );
1391
1402
  invalidateKanbanData();
1392
1403
  } catch (error) {
1404
+ if (surfaceRecordConflict(error, t)) {
1405
+ invalidateKanbanData();
1406
+ return;
1407
+ }
1393
1408
  const message = error instanceof Error && error.message ? error.message : translateWithFallback(
1394
1409
  t,
1395
1410
  "customers.deals.kanban.menu.error.status",
@@ -1400,7 +1415,7 @@ function DealsKanbanPage() {
1400
1415
  setPendingDealId(null);
1401
1416
  }
1402
1417
  },
1403
- [invalidateKanbanData, retryDealMutation, runDealMutation, t]
1418
+ [deals, invalidateKanbanData, retryDealMutation, runDealMutation, t]
1404
1419
  );
1405
1420
  const deleteDeal = React.useCallback(
1406
1421
  async (dealId, dealTitle) => {
@@ -1420,18 +1435,22 @@ function DealsKanbanPage() {
1420
1435
  confirmText: translateWithFallback(t, "customers.deals.kanban.menu.delete", "Delete")
1421
1436
  });
1422
1437
  if (!confirmed) return;
1438
+ const lockVersion = deals.find((deal) => deal.id === dealId)?.updatedAt ?? null;
1423
1439
  setPendingDealId(dealId);
1424
1440
  try {
1425
1441
  await runDealMutation({
1426
1442
  operation: async () => {
1427
- await deleteCrud("customers/deals", {
1428
- body: { id: dealId },
1429
- errorMessage: translateWithFallback(
1430
- t,
1431
- "customers.deals.kanban.menu.delete.error",
1432
- "Failed to delete deal."
1433
- )
1434
- });
1443
+ await withScopedApiRequestHeaders(
1444
+ buildOptimisticLockHeader(lockVersion),
1445
+ () => deleteCrud("customers/deals", {
1446
+ body: { id: dealId },
1447
+ errorMessage: translateWithFallback(
1448
+ t,
1449
+ "customers.deals.kanban.menu.delete.error",
1450
+ "Failed to delete deal."
1451
+ )
1452
+ })
1453
+ );
1435
1454
  },
1436
1455
  context: {
1437
1456
  formId: dealMutationContextId,
@@ -1446,6 +1465,10 @@ function DealsKanbanPage() {
1446
1465
  );
1447
1466
  invalidateKanbanData();
1448
1467
  } catch (error) {
1468
+ if (surfaceRecordConflict(error, t)) {
1469
+ invalidateKanbanData();
1470
+ return;
1471
+ }
1449
1472
  const message = error instanceof Error && error.message ? error.message : translateWithFallback(
1450
1473
  t,
1451
1474
  "customers.deals.kanban.menu.delete.error",
@@ -1456,7 +1479,7 @@ function DealsKanbanPage() {
1456
1479
  setPendingDealId(null);
1457
1480
  }
1458
1481
  },
1459
- [confirm, invalidateKanbanData, retryDealMutation, runDealMutation, t]
1482
+ [confirm, deals, invalidateKanbanData, retryDealMutation, runDealMutation, t]
1460
1483
  );
1461
1484
  const bulkSelectionSummary = React.useMemo(() => {
1462
1485
  if (selectedDealIds.size === 0) return { count: 0, totalLabel: null, currency: null, ids: [] };