@open-mercato/core 0.5.1-develop.2663.2c29774b5b → 0.5.1-develop.2681.c559bb2bc3

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 (687) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/generated/entities/action_log/index.js +8 -0
  3. package/dist/generated/entities/action_log/index.js.map +2 -2
  4. package/dist/generated/entities/customer_company_billing/index.js +23 -0
  5. package/dist/generated/entities/customer_company_billing/index.js.map +7 -0
  6. package/dist/generated/entities/customer_deal/index.js +8 -0
  7. package/dist/generated/entities/customer_deal/index.js.map +2 -2
  8. package/dist/generated/entities/customer_deal_stage_transition/index.js +31 -0
  9. package/dist/generated/entities/customer_deal_stage_transition/index.js.map +7 -0
  10. package/dist/generated/entities/customer_dictionary_kind_setting/index.js +21 -0
  11. package/dist/generated/entities/customer_dictionary_kind_setting/index.js.map +7 -0
  12. package/dist/generated/entities/customer_entity/index.js +8 -0
  13. package/dist/generated/entities/customer_entity/index.js.map +2 -2
  14. package/dist/generated/entities/customer_entity_role/index.js +23 -0
  15. package/dist/generated/entities/customer_entity_role/index.js.map +7 -0
  16. package/dist/generated/entities/customer_interaction/index.js +23 -1
  17. package/dist/generated/entities/customer_interaction/index.js.map +2 -2
  18. package/dist/generated/entities/customer_label/index.js +19 -0
  19. package/dist/generated/entities/customer_label/index.js.map +7 -0
  20. package/dist/generated/entities/customer_label_assignment/index.js +17 -0
  21. package/dist/generated/entities/customer_label_assignment/index.js.map +7 -0
  22. package/dist/generated/entities/customer_person_company_link/index.js +21 -0
  23. package/dist/generated/entities/customer_person_company_link/index.js.map +7 -0
  24. package/dist/generated/entities/customer_person_company_role/index.js +17 -0
  25. package/dist/generated/entities/customer_person_company_role/index.js.map +7 -0
  26. package/dist/generated/entities/dictionary_entry/index.js +4 -0
  27. package/dist/generated/entities/dictionary_entry/index.js.map +2 -2
  28. package/dist/generated/entities.ids.generated.js +9 -1
  29. package/dist/generated/entities.ids.generated.js.map +2 -2
  30. package/dist/generated/entity-fields-registry.js +116 -1
  31. package/dist/generated/entity-fields-registry.js.map +2 -2
  32. package/dist/modules/attachments/api/route.js +46 -8
  33. package/dist/modules/attachments/api/route.js.map +2 -2
  34. package/dist/modules/audit_logs/api/audit-logs/actions/export/route.js +208 -0
  35. package/dist/modules/audit_logs/api/audit-logs/actions/export/route.js.map +7 -0
  36. package/dist/modules/audit_logs/api/audit-logs/actions/route.js +52 -6
  37. package/dist/modules/audit_logs/api/audit-logs/actions/route.js.map +2 -2
  38. package/dist/modules/audit_logs/cli.js +62 -0
  39. package/dist/modules/audit_logs/cli.js.map +7 -0
  40. package/dist/modules/audit_logs/data/entities.js +21 -1
  41. package/dist/modules/audit_logs/data/entities.js.map +2 -2
  42. package/dist/modules/audit_logs/data/validators.js +9 -1
  43. package/dist/modules/audit_logs/data/validators.js.map +2 -2
  44. package/dist/modules/audit_logs/lib/changeRows.js +34 -0
  45. package/dist/modules/audit_logs/lib/changeRows.js.map +7 -0
  46. package/dist/modules/audit_logs/lib/display-helpers.js +2 -20
  47. package/dist/modules/audit_logs/lib/display-helpers.js.map +3 -3
  48. package/dist/modules/audit_logs/lib/projections.js +58 -0
  49. package/dist/modules/audit_logs/lib/projections.js.map +7 -0
  50. package/dist/modules/audit_logs/migrations/Migration20260412160533.js +21 -0
  51. package/dist/modules/audit_logs/migrations/Migration20260412160533.js.map +7 -0
  52. package/dist/modules/audit_logs/services/actionLogService.js +313 -79
  53. package/dist/modules/audit_logs/services/actionLogService.js.map +2 -2
  54. package/dist/modules/customers/acl.js +3 -1
  55. package/dist/modules/customers/acl.js.map +2 -2
  56. package/dist/modules/customers/api/activities/route.js +4 -0
  57. package/dist/modules/customers/api/activities/route.js.map +2 -2
  58. package/dist/modules/customers/api/assignable-staff/route.js +208 -0
  59. package/dist/modules/customers/api/assignable-staff/route.js.map +7 -0
  60. package/dist/modules/customers/api/companies/[id]/people/route.js +205 -0
  61. package/dist/modules/customers/api/companies/[id]/people/route.js.map +7 -0
  62. package/dist/modules/customers/api/companies/[id]/roles/route.js +22 -0
  63. package/dist/modules/customers/api/companies/[id]/roles/route.js.map +7 -0
  64. package/dist/modules/customers/api/companies/[id]/route.js +374 -32
  65. package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
  66. package/dist/modules/customers/api/companies/route.js +82 -7
  67. package/dist/modules/customers/api/companies/route.js.map +2 -2
  68. package/dist/modules/customers/api/deals/[id]/companies/route.js +172 -0
  69. package/dist/modules/customers/api/deals/[id]/companies/route.js.map +7 -0
  70. package/dist/modules/customers/api/deals/[id]/people/route.js +156 -0
  71. package/dist/modules/customers/api/deals/[id]/people/route.js.map +7 -0
  72. package/dist/modules/customers/api/deals/[id]/route.js +459 -53
  73. package/dist/modules/customers/api/deals/[id]/route.js.map +2 -2
  74. package/dist/modules/customers/api/deals/[id]/stats/route.js +195 -0
  75. package/dist/modules/customers/api/deals/[id]/stats/route.js.map +7 -0
  76. package/dist/modules/customers/api/deals/route.js +20 -10
  77. package/dist/modules/customers/api/deals/route.js.map +3 -3
  78. package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js +105 -4
  79. package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js.map +2 -2
  80. package/dist/modules/customers/api/dictionaries/[kind]/route.js +118 -42
  81. package/dist/modules/customers/api/dictionaries/[kind]/route.js.map +2 -2
  82. package/dist/modules/customers/api/dictionaries/context.js +30 -6
  83. package/dist/modules/customers/api/dictionaries/context.js.map +2 -2
  84. package/dist/modules/customers/api/dictionaries/kind-settings/route.js +207 -0
  85. package/dist/modules/customers/api/dictionaries/kind-settings/route.js.map +7 -0
  86. package/dist/modules/customers/api/entity-roles-factory.js +471 -0
  87. package/dist/modules/customers/api/entity-roles-factory.js.map +7 -0
  88. package/dist/modules/customers/api/interactions/conflicts/route.js +158 -0
  89. package/dist/modules/customers/api/interactions/conflicts/route.js.map +7 -0
  90. package/dist/modules/customers/api/interactions/counts/route.js +92 -0
  91. package/dist/modules/customers/api/interactions/counts/route.js.map +7 -0
  92. package/dist/modules/customers/api/interactions/route.js +83 -4
  93. package/dist/modules/customers/api/interactions/route.js.map +2 -2
  94. package/dist/modules/customers/api/labels/assign/route.js +189 -0
  95. package/dist/modules/customers/api/labels/assign/route.js.map +7 -0
  96. package/dist/modules/customers/api/labels/auth.js +17 -0
  97. package/dist/modules/customers/api/labels/auth.js.map +7 -0
  98. package/dist/modules/customers/api/labels/route.js +281 -0
  99. package/dist/modules/customers/api/labels/route.js.map +7 -0
  100. package/dist/modules/customers/api/labels/table-errors.js +38 -0
  101. package/dist/modules/customers/api/labels/table-errors.js.map +7 -0
  102. package/dist/modules/customers/api/labels/unassign/route.js +184 -0
  103. package/dist/modules/customers/api/labels/unassign/route.js.map +7 -0
  104. package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js +292 -0
  105. package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js.map +7 -0
  106. package/dist/modules/customers/api/people/[id]/companies/context.js +66 -0
  107. package/dist/modules/customers/api/people/[id]/companies/context.js.map +7 -0
  108. package/dist/modules/customers/api/people/[id]/companies/enriched/route.js +334 -0
  109. package/dist/modules/customers/api/people/[id]/companies/enriched/route.js.map +7 -0
  110. package/dist/modules/customers/api/people/[id]/companies/route.js +205 -0
  111. package/dist/modules/customers/api/people/[id]/companies/route.js.map +7 -0
  112. package/dist/modules/customers/api/people/[id]/roles/route.js +22 -0
  113. package/dist/modules/customers/api/people/[id]/roles/route.js.map +7 -0
  114. package/dist/modules/customers/api/people/[id]/route.js +134 -21
  115. package/dist/modules/customers/api/people/[id]/route.js.map +2 -2
  116. package/dist/modules/customers/api/people/route.js +122 -23
  117. package/dist/modules/customers/api/people/route.js.map +2 -2
  118. package/dist/modules/customers/api/todos/route.js +4 -0
  119. package/dist/modules/customers/api/todos/route.js.map +2 -2
  120. package/dist/modules/customers/api/utils.js +22 -0
  121. package/dist/modules/customers/api/utils.js.map +2 -2
  122. package/dist/modules/customers/backend/config/customers/page.js +2 -6
  123. package/dist/modules/customers/backend/config/customers/page.js.map +2 -2
  124. package/dist/modules/customers/backend/customers/companies/page.js +37 -26
  125. package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
  126. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +265 -262
  127. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +3 -3
  128. package/dist/modules/customers/backend/customers/deals/[id]/hooks/formatters.js +23 -0
  129. package/dist/modules/customers/backend/customers/deals/[id]/hooks/formatters.js.map +7 -0
  130. package/dist/modules/customers/backend/customers/deals/[id]/hooks/types.js +1 -0
  131. package/dist/modules/customers/backend/customers/deals/[id]/hooks/types.js.map +7 -0
  132. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.js +43 -0
  133. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.js.map +7 -0
  134. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.js +264 -0
  135. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.js.map +7 -0
  136. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealClosure.js +88 -0
  137. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealClosure.js.map +7 -0
  138. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealData.js +41 -0
  139. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealData.js.map +7 -0
  140. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.js +66 -0
  141. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.js.map +7 -0
  142. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealInjectedTabs.js +39 -0
  143. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealInjectedTabs.js.map +7 -0
  144. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealMutationContext.js +49 -0
  145. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealMutationContext.js.map +7 -0
  146. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealPipeline.js +43 -0
  147. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealPipeline.js.map +7 -0
  148. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useScheduleDialog.js +28 -0
  149. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useScheduleDialog.js.map +7 -0
  150. package/dist/modules/customers/backend/customers/deals/[id]/page.js +556 -503
  151. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +3 -3
  152. package/dist/modules/customers/backend/customers/deals/page.js +66 -21
  153. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  154. package/dist/modules/customers/backend/customers/people/page.js +36 -28
  155. package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
  156. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +318 -203
  157. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +3 -3
  158. package/dist/modules/customers/cli.js +105 -13
  159. package/dist/modules/customers/cli.js.map +2 -2
  160. package/dist/modules/customers/commands/activities.js +6 -0
  161. package/dist/modules/customers/commands/activities.js.map +2 -2
  162. package/dist/modules/customers/commands/deals.js +315 -107
  163. package/dist/modules/customers/commands/deals.js.map +2 -2
  164. package/dist/modules/customers/commands/dictionaries.js +166 -32
  165. package/dist/modules/customers/commands/dictionaries.js.map +2 -2
  166. package/dist/modules/customers/commands/dictionaryKindSettings.js +208 -0
  167. package/dist/modules/customers/commands/dictionaryKindSettings.js.map +7 -0
  168. package/dist/modules/customers/commands/entity-roles.js +415 -0
  169. package/dist/modules/customers/commands/entity-roles.js.map +7 -0
  170. package/dist/modules/customers/commands/index.js +4 -0
  171. package/dist/modules/customers/commands/index.js.map +2 -2
  172. package/dist/modules/customers/commands/interactions.js +108 -21
  173. package/dist/modules/customers/commands/interactions.js.map +2 -2
  174. package/dist/modules/customers/commands/labels.js +539 -0
  175. package/dist/modules/customers/commands/labels.js.map +7 -0
  176. package/dist/modules/customers/commands/people.js +560 -463
  177. package/dist/modules/customers/commands/people.js.map +3 -3
  178. package/dist/modules/customers/commands/personCompanyLinks.js +568 -0
  179. package/dist/modules/customers/commands/personCompanyLinks.js.map +7 -0
  180. package/dist/modules/customers/commands/shared.js +12 -4
  181. package/dist/modules/customers/commands/shared.js.map +2 -2
  182. package/dist/modules/customers/commands/todos.js +10 -1
  183. package/dist/modules/customers/commands/todos.js.map +2 -2
  184. package/dist/modules/customers/components/AddressEditor.js +1 -1
  185. package/dist/modules/customers/components/AddressEditor.js.map +2 -2
  186. package/dist/modules/customers/components/CustomersConfigurationSections.js +31 -0
  187. package/dist/modules/customers/components/CustomersConfigurationSections.js.map +7 -0
  188. package/dist/modules/customers/components/DictionarySettings.js +37 -2
  189. package/dist/modules/customers/components/DictionarySettings.js.map +2 -2
  190. package/dist/modules/customers/components/detail/ActiveDealCard.js +121 -0
  191. package/dist/modules/customers/components/detail/ActiveDealCard.js.map +7 -0
  192. package/dist/modules/customers/components/detail/ActivitiesSection.js +222 -331
  193. package/dist/modules/customers/components/detail/ActivitiesSection.js.map +3 -3
  194. package/dist/modules/customers/components/detail/ActivityAiActions.js +36 -0
  195. package/dist/modules/customers/components/detail/ActivityAiActions.js.map +7 -0
  196. package/dist/modules/customers/components/detail/ActivityCard.js +126 -0
  197. package/dist/modules/customers/components/detail/ActivityCard.js.map +7 -0
  198. package/dist/modules/customers/components/detail/ActivityHistorySection.js +340 -0
  199. package/dist/modules/customers/components/detail/ActivityHistorySection.js.map +7 -0
  200. package/dist/modules/customers/components/detail/ActivityLogTab.js +56 -0
  201. package/dist/modules/customers/components/detail/ActivityLogTab.js.map +7 -0
  202. package/dist/modules/customers/components/detail/ActivityTimeline.js +108 -0
  203. package/dist/modules/customers/components/detail/ActivityTimeline.js.map +7 -0
  204. package/dist/modules/customers/components/detail/ActivityTimelineFilters.js +139 -0
  205. package/dist/modules/customers/components/detail/ActivityTimelineFilters.js.map +7 -0
  206. package/dist/modules/customers/components/detail/ActivityTypeSelector.js +42 -0
  207. package/dist/modules/customers/components/detail/ActivityTypeSelector.js.map +7 -0
  208. package/dist/modules/customers/components/detail/AiActionChips.js +38 -0
  209. package/dist/modules/customers/components/detail/AiActionChips.js.map +7 -0
  210. package/dist/modules/customers/components/detail/AssignRoleDialog.js +534 -0
  211. package/dist/modules/customers/components/detail/AssignRoleDialog.js.map +7 -0
  212. package/dist/modules/customers/components/detail/ChangelogEntryRow.js +79 -0
  213. package/dist/modules/customers/components/detail/ChangelogEntryRow.js.map +7 -0
  214. package/dist/modules/customers/components/detail/ChangelogFilters.js +176 -0
  215. package/dist/modules/customers/components/detail/ChangelogFilters.js.map +7 -0
  216. package/dist/modules/customers/components/detail/ChangelogKpiCards.js +88 -0
  217. package/dist/modules/customers/components/detail/ChangelogKpiCards.js.map +7 -0
  218. package/dist/modules/customers/components/detail/ChangelogTab.js +470 -0
  219. package/dist/modules/customers/components/detail/ChangelogTab.js.map +7 -0
  220. package/dist/modules/customers/components/detail/ComingSoonPlaceholder.js +16 -0
  221. package/dist/modules/customers/components/detail/ComingSoonPlaceholder.js.map +7 -0
  222. package/dist/modules/customers/components/detail/CompanyCard.js +283 -0
  223. package/dist/modules/customers/components/detail/CompanyCard.js.map +7 -0
  224. package/dist/modules/customers/components/detail/CompanyDashboardTab.js +133 -0
  225. package/dist/modules/customers/components/detail/CompanyDashboardTab.js.map +7 -0
  226. package/dist/modules/customers/components/detail/CompanyDetailHeader.js +191 -0
  227. package/dist/modules/customers/components/detail/CompanyDetailHeader.js.map +7 -0
  228. package/dist/modules/customers/components/detail/CompanyDetailTabs.js +123 -0
  229. package/dist/modules/customers/components/detail/CompanyDetailTabs.js.map +7 -0
  230. package/dist/modules/customers/components/detail/CompanyKpiBar.js +174 -0
  231. package/dist/modules/customers/components/detail/CompanyKpiBar.js.map +7 -0
  232. package/dist/modules/customers/components/detail/CompanyPeopleSection.js +514 -230
  233. package/dist/modules/customers/components/detail/CompanyPeopleSection.js.map +2 -2
  234. package/dist/modules/customers/components/detail/CompanyTagsDialog.js +22 -0
  235. package/dist/modules/customers/components/detail/CompanyTagsDialog.js.map +7 -0
  236. package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js +159 -0
  237. package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js.map +7 -0
  238. package/dist/modules/customers/components/detail/CreatePersonDialog.js +135 -0
  239. package/dist/modules/customers/components/detail/CreatePersonDialog.js.map +7 -0
  240. package/dist/modules/customers/components/detail/DealClosureActionBar.js +59 -0
  241. package/dist/modules/customers/components/detail/DealClosureActionBar.js.map +7 -0
  242. package/dist/modules/customers/components/detail/DealDetailHeader.js +237 -0
  243. package/dist/modules/customers/components/detail/DealDetailHeader.js.map +7 -0
  244. package/dist/modules/customers/components/detail/DealDetailTabs.js +109 -0
  245. package/dist/modules/customers/components/detail/DealDetailTabs.js.map +7 -0
  246. package/dist/modules/customers/components/detail/DealForm.js +219 -92
  247. package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
  248. package/dist/modules/customers/components/detail/DealLinkedEntitiesTab.js +295 -0
  249. package/dist/modules/customers/components/detail/DealLinkedEntitiesTab.js.map +7 -0
  250. package/dist/modules/customers/components/detail/DealLostSummaryDialog.js +107 -0
  251. package/dist/modules/customers/components/detail/DealLostSummaryDialog.js.map +7 -0
  252. package/dist/modules/customers/components/detail/DealWonPopup.js +113 -0
  253. package/dist/modules/customers/components/detail/DealWonPopup.js.map +7 -0
  254. package/dist/modules/customers/components/detail/DealsSection.js +206 -193
  255. package/dist/modules/customers/components/detail/DealsSection.js.map +2 -2
  256. package/dist/modules/customers/components/detail/DecisionMakersFooter.js +39 -0
  257. package/dist/modules/customers/components/detail/DecisionMakersFooter.js.map +7 -0
  258. package/dist/modules/customers/components/detail/EntityTagsDialog.js +1096 -0
  259. package/dist/modules/customers/components/detail/EntityTagsDialog.js.map +7 -0
  260. package/dist/modules/customers/components/detail/InlineActivityComposer.js +197 -0
  261. package/dist/modules/customers/components/detail/InlineActivityComposer.js.map +7 -0
  262. package/dist/modules/customers/components/detail/ManageTagsDialog.js +1091 -0
  263. package/dist/modules/customers/components/detail/ManageTagsDialog.js.map +7 -0
  264. package/dist/modules/customers/components/detail/MiniWeekCalendar.js +272 -0
  265. package/dist/modules/customers/components/detail/MiniWeekCalendar.js.map +7 -0
  266. package/dist/modules/customers/components/detail/MobilePersonDetail.js +106 -0
  267. package/dist/modules/customers/components/detail/MobilePersonDetail.js.map +7 -0
  268. package/dist/modules/customers/components/detail/NextStepCard.js +72 -0
  269. package/dist/modules/customers/components/detail/NextStepCard.js.map +7 -0
  270. package/dist/modules/customers/components/detail/PersonCard.js +192 -0
  271. package/dist/modules/customers/components/detail/PersonCard.js.map +7 -0
  272. package/dist/modules/customers/components/detail/PersonCompaniesSection.js +345 -0
  273. package/dist/modules/customers/components/detail/PersonCompaniesSection.js.map +7 -0
  274. package/dist/modules/customers/components/detail/PersonDetailHeader.js +220 -0
  275. package/dist/modules/customers/components/detail/PersonDetailHeader.js.map +7 -0
  276. package/dist/modules/customers/components/detail/PersonDetailTabs.js +122 -0
  277. package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +7 -0
  278. package/dist/modules/customers/components/detail/PersonTagsDialog.js +24 -0
  279. package/dist/modules/customers/components/detail/PersonTagsDialog.js.map +7 -0
  280. package/dist/modules/customers/components/detail/PipelineStepper.js +191 -0
  281. package/dist/modules/customers/components/detail/PipelineStepper.js.map +7 -0
  282. package/dist/modules/customers/components/detail/PlannedActivitiesSection.js +222 -0
  283. package/dist/modules/customers/components/detail/PlannedActivitiesSection.js.map +7 -0
  284. package/dist/modules/customers/components/detail/RelationshipHealthCard.js +49 -0
  285. package/dist/modules/customers/components/detail/RelationshipHealthCard.js.map +7 -0
  286. package/dist/modules/customers/components/detail/RoleAssignmentRow.js +189 -0
  287. package/dist/modules/customers/components/detail/RoleAssignmentRow.js.map +7 -0
  288. package/dist/modules/customers/components/detail/RolesSection.js +234 -0
  289. package/dist/modules/customers/components/detail/RolesSection.js.map +7 -0
  290. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +410 -0
  291. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +7 -0
  292. package/dist/modules/customers/components/detail/aiActionCatalog.js +41 -0
  293. package/dist/modules/customers/components/detail/aiActionCatalog.js.map +7 -0
  294. package/dist/modules/customers/components/detail/assignableStaff.js +48 -0
  295. package/dist/modules/customers/components/detail/assignableStaff.js.map +7 -0
  296. package/dist/modules/customers/components/detail/dashboard/ActiveDealWidget.js +48 -0
  297. package/dist/modules/customers/components/detail/dashboard/ActiveDealWidget.js.map +7 -0
  298. package/dist/modules/customers/components/detail/dashboard/OpenTasksWidget.js +86 -0
  299. package/dist/modules/customers/components/detail/dashboard/OpenTasksWidget.js.map +7 -0
  300. package/dist/modules/customers/components/detail/dashboard/RecentActivityWidget.js +53 -0
  301. package/dist/modules/customers/components/detail/dashboard/RecentActivityWidget.js.map +7 -0
  302. package/dist/modules/customers/components/detail/dashboard/RelationshipHealthWidget.js +30 -0
  303. package/dist/modules/customers/components/detail/dashboard/RelationshipHealthWidget.js.map +7 -0
  304. package/dist/modules/customers/components/detail/dashboard/UpcomingMeetingsWidget.js +43 -0
  305. package/dist/modules/customers/components/detail/dashboard/UpcomingMeetingsWidget.js.map +7 -0
  306. package/dist/modules/customers/components/detail/dashboard/helpers.js +71 -0
  307. package/dist/modules/customers/components/detail/dashboard/helpers.js.map +7 -0
  308. package/dist/modules/customers/components/detail/healthScoreUtils.js +69 -0
  309. package/dist/modules/customers/components/detail/healthScoreUtils.js.map +7 -0
  310. package/dist/modules/customers/components/detail/hooks/useCurrencyDictionary.js +5 -5
  311. package/dist/modules/customers/components/detail/hooks/useCurrencyDictionary.js.map +2 -2
  312. package/dist/modules/customers/components/detail/hooks/useCustomerDictionary.js +9 -8
  313. package/dist/modules/customers/components/detail/hooks/useCustomerDictionary.js.map +3 -3
  314. package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js +65 -0
  315. package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js.map +7 -0
  316. package/dist/modules/customers/components/detail/notesAdapter.js +70 -30
  317. package/dist/modules/customers/components/detail/notesAdapter.js.map +2 -2
  318. package/dist/modules/customers/components/detail/pipelineStageUtils.js +26 -0
  319. package/dist/modules/customers/components/detail/pipelineStageUtils.js.map +7 -0
  320. package/dist/modules/customers/components/detail/schedule/DateTimeFields.js +144 -0
  321. package/dist/modules/customers/components/detail/schedule/DateTimeFields.js.map +7 -0
  322. package/dist/modules/customers/components/detail/schedule/FooterFields.js +60 -0
  323. package/dist/modules/customers/components/detail/schedule/FooterFields.js.map +7 -0
  324. package/dist/modules/customers/components/detail/schedule/LinkedEntitiesField.js +216 -0
  325. package/dist/modules/customers/components/detail/schedule/LinkedEntitiesField.js.map +7 -0
  326. package/dist/modules/customers/components/detail/schedule/LocationField.js +34 -0
  327. package/dist/modules/customers/components/detail/schedule/LocationField.js.map +7 -0
  328. package/dist/modules/customers/components/detail/schedule/ParticipantsField.js +226 -0
  329. package/dist/modules/customers/components/detail/schedule/ParticipantsField.js.map +7 -0
  330. package/dist/modules/customers/components/detail/schedule/fieldConfig.js +69 -0
  331. package/dist/modules/customers/components/detail/schedule/fieldConfig.js.map +7 -0
  332. package/dist/modules/customers/components/detail/schedule/index.js +21 -0
  333. package/dist/modules/customers/components/detail/schedule/index.js.map +7 -0
  334. package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js +172 -0
  335. package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +7 -0
  336. package/dist/modules/customers/components/detail/utils.js +23 -0
  337. package/dist/modules/customers/components/detail/utils.js.map +2 -2
  338. package/dist/modules/customers/components/formConfig.js +144 -22
  339. package/dist/modules/customers/components/formConfig.js.map +2 -2
  340. package/dist/modules/customers/components/linking/LinkEntityDialog.js +661 -0
  341. package/dist/modules/customers/components/linking/LinkEntityDialog.js.map +7 -0
  342. package/dist/modules/customers/components/linking/adapters/companyAdapter.js +252 -0
  343. package/dist/modules/customers/components/linking/adapters/companyAdapter.js.map +7 -0
  344. package/dist/modules/customers/components/linking/adapters/dealAdapter.js +384 -0
  345. package/dist/modules/customers/components/linking/adapters/dealAdapter.js.map +7 -0
  346. package/dist/modules/customers/components/linking/adapters/personAdapter.js +324 -0
  347. package/dist/modules/customers/components/linking/adapters/personAdapter.js.map +7 -0
  348. package/dist/modules/customers/components/list/CollectionPreviewCell.js +53 -0
  349. package/dist/modules/customers/components/list/CollectionPreviewCell.js.map +7 -0
  350. package/dist/modules/customers/data/entities.js +407 -1
  351. package/dist/modules/customers/data/entities.js.map +2 -2
  352. package/dist/modules/customers/data/validators.js +139 -21
  353. package/dist/modules/customers/data/validators.js.map +2 -2
  354. package/dist/modules/customers/events.js +19 -1
  355. package/dist/modules/customers/events.js.map +2 -2
  356. package/dist/modules/customers/lib/customerRoleTypes.js +19 -0
  357. package/dist/modules/customers/lib/customerRoleTypes.js.map +7 -0
  358. package/dist/modules/customers/lib/dealClosureNotification.js +39 -0
  359. package/dist/modules/customers/lib/dealClosureNotification.js.map +7 -0
  360. package/dist/modules/customers/lib/dealStageTransitionTable.js +29 -0
  361. package/dist/modules/customers/lib/dealStageTransitionTable.js.map +7 -0
  362. package/dist/modules/customers/lib/dictionaries.js +25 -0
  363. package/dist/modules/customers/lib/dictionaries.js.map +2 -2
  364. package/dist/modules/customers/lib/interactionReadModel.js +10 -0
  365. package/dist/modules/customers/lib/interactionReadModel.js.map +2 -2
  366. package/dist/modules/customers/lib/personCompanies.js +235 -0
  367. package/dist/modules/customers/lib/personCompanies.js.map +7 -0
  368. package/dist/modules/customers/lib/personCompanyLinkTable.js +42 -0
  369. package/dist/modules/customers/lib/personCompanyLinkTable.js.map +7 -0
  370. package/dist/modules/customers/lib/roleTypeUsage.js +104 -0
  371. package/dist/modules/customers/lib/roleTypeUsage.js.map +7 -0
  372. package/dist/modules/customers/migrations/Migration20260406214502.js +18 -0
  373. package/dist/modules/customers/migrations/Migration20260406214502.js.map +7 -0
  374. package/dist/modules/customers/migrations/Migration20260408135736.js +17 -0
  375. package/dist/modules/customers/migrations/Migration20260408135736.js.map +7 -0
  376. package/dist/modules/customers/migrations/Migration20260408225345.js +21 -0
  377. package/dist/modules/customers/migrations/Migration20260408225345.js.map +7 -0
  378. package/dist/modules/customers/migrations/Migration20260411075533.js +27 -0
  379. package/dist/modules/customers/migrations/Migration20260411075533.js.map +7 -0
  380. package/dist/modules/customers/migrations/Migration20260411103551.js +13 -0
  381. package/dist/modules/customers/migrations/Migration20260411103551.js.map +7 -0
  382. package/dist/modules/customers/migrations/Migration20260411130944.js +26 -0
  383. package/dist/modules/customers/migrations/Migration20260411130944.js.map +7 -0
  384. package/dist/modules/customers/migrations/Migration20260415095203.js +13 -0
  385. package/dist/modules/customers/migrations/Migration20260415095203.js.map +7 -0
  386. package/dist/modules/customers/migrations/Migration20260415135056.js +20 -0
  387. package/dist/modules/customers/migrations/Migration20260415135056.js.map +7 -0
  388. package/dist/modules/customers/migrations/Migration20260417140000.js +15 -0
  389. package/dist/modules/customers/migrations/Migration20260417140000.js.map +7 -0
  390. package/dist/modules/customers/migrations/Migration20260417160000.js +17 -0
  391. package/dist/modules/customers/migrations/Migration20260417160000.js.map +7 -0
  392. package/dist/modules/customers/migrations/Migration20260417235407.js +13 -0
  393. package/dist/modules/customers/migrations/Migration20260417235407.js.map +7 -0
  394. package/dist/modules/customers/setup.js +16 -1
  395. package/dist/modules/customers/setup.js.map +2 -2
  396. package/dist/modules/customers/subscribers/deal-closure-notification.js +16 -0
  397. package/dist/modules/customers/subscribers/deal-closure-notification.js.map +7 -0
  398. package/dist/modules/customers/subscribers/deal-lost-notification.js +16 -0
  399. package/dist/modules/customers/subscribers/deal-lost-notification.js.map +7 -0
  400. package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js +2 -0
  401. package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js.map +2 -2
  402. package/dist/modules/dictionaries/api/[dictionaryId]/entries/reorder/route.js +154 -0
  403. package/dist/modules/dictionaries/api/[dictionaryId]/entries/reorder/route.js.map +7 -0
  404. package/dist/modules/dictionaries/api/[dictionaryId]/entries/route.js +6 -2
  405. package/dist/modules/dictionaries/api/[dictionaryId]/entries/route.js.map +2 -2
  406. package/dist/modules/dictionaries/api/[dictionaryId]/entries/set-default/route.js +154 -0
  407. package/dist/modules/dictionaries/api/[dictionaryId]/entries/set-default/route.js.map +7 -0
  408. package/dist/modules/dictionaries/api/context.js +8 -1
  409. package/dist/modules/dictionaries/api/context.js.map +2 -2
  410. package/dist/modules/dictionaries/api/openapi.js +18 -1
  411. package/dist/modules/dictionaries/api/openapi.js.map +2 -2
  412. package/dist/modules/dictionaries/commands/entry-operations.js +388 -0
  413. package/dist/modules/dictionaries/commands/entry-operations.js.map +7 -0
  414. package/dist/modules/dictionaries/commands/factory.js +24 -3
  415. package/dist/modules/dictionaries/commands/factory.js.map +2 -2
  416. package/dist/modules/dictionaries/commands/index.js +1 -0
  417. package/dist/modules/dictionaries/commands/index.js.map +2 -2
  418. package/dist/modules/dictionaries/components/DictionaryTable.js +6 -3
  419. package/dist/modules/dictionaries/components/DictionaryTable.js.map +2 -2
  420. package/dist/modules/dictionaries/data/entities.js +11 -1
  421. package/dist/modules/dictionaries/data/entities.js.map +2 -2
  422. package/dist/modules/dictionaries/data/validators.js +28 -2
  423. package/dist/modules/dictionaries/data/validators.js.map +2 -2
  424. package/dist/modules/dictionaries/events.js +18 -0
  425. package/dist/modules/dictionaries/events.js.map +7 -0
  426. package/dist/modules/dictionaries/lib/clientEntries.js +43 -0
  427. package/dist/modules/dictionaries/lib/clientEntries.js.map +7 -0
  428. package/dist/modules/dictionaries/migrations/Migration20260410171544.js +45 -0
  429. package/dist/modules/dictionaries/migrations/Migration20260410171544.js.map +7 -0
  430. package/dist/modules/inbox_ops/api/proposals/[id]/route.js +4 -1
  431. package/dist/modules/inbox_ops/api/proposals/[id]/route.js.map +2 -2
  432. package/dist/modules/query_index/lib/engine.js +1 -1
  433. package/dist/modules/query_index/lib/engine.js.map +2 -2
  434. package/dist/modules/sales/components/documents/AddressesSection.js +82 -42
  435. package/dist/modules/sales/components/documents/AddressesSection.js.map +2 -2
  436. package/dist/modules/sales/lib/dictionaries.js +16 -0
  437. package/dist/modules/sales/lib/dictionaries.js.map +2 -2
  438. package/dist/modules/sales/widgets/injection-table.js +5 -1
  439. package/dist/modules/sales/widgets/injection-table.js.map +2 -2
  440. package/generated/entities/action_log/index.ts +4 -0
  441. package/generated/entities/customer_company_billing/index.ts +10 -0
  442. package/generated/entities/customer_deal/index.ts +4 -0
  443. package/generated/entities/customer_deal_stage_transition/index.ts +14 -0
  444. package/generated/entities/customer_dictionary_kind_setting/index.ts +9 -0
  445. package/generated/entities/customer_entity/index.ts +4 -0
  446. package/generated/entities/customer_entity_role/index.ts +10 -0
  447. package/generated/entities/customer_interaction/index.ts +11 -0
  448. package/generated/entities/customer_label/index.ts +8 -0
  449. package/generated/entities/customer_label_assignment/index.ts +7 -0
  450. package/generated/entities/customer_person_company_link/index.ts +9 -0
  451. package/generated/entities/customer_person_company_role/index.ts +7 -0
  452. package/generated/entities/dictionary_entry/index.ts +2 -0
  453. package/generated/entities.ids.generated.ts +9 -1
  454. package/generated/entity-fields-registry.ts +116 -1
  455. package/package.json +3 -3
  456. package/src/modules/attachments/api/route.ts +48 -6
  457. package/src/modules/attachments/i18n/de.json +4 -0
  458. package/src/modules/attachments/i18n/en.json +4 -0
  459. package/src/modules/attachments/i18n/es.json +4 -0
  460. package/src/modules/attachments/i18n/pl.json +4 -0
  461. package/src/modules/audit_logs/api/audit-logs/actions/export/route.ts +260 -0
  462. package/src/modules/audit_logs/api/audit-logs/actions/route.ts +81 -6
  463. package/src/modules/audit_logs/cli.ts +79 -0
  464. package/src/modules/audit_logs/data/entities.ts +17 -0
  465. package/src/modules/audit_logs/data/validators.ts +9 -1
  466. package/src/modules/audit_logs/lib/changeRows.ts +47 -0
  467. package/src/modules/audit_logs/lib/display-helpers.tsx +4 -30
  468. package/src/modules/audit_logs/lib/projections.ts +110 -0
  469. package/src/modules/audit_logs/migrations/.snapshot-open-mercato.json +325 -2
  470. package/src/modules/audit_logs/migrations/Migration20260412160533.ts +21 -0
  471. package/src/modules/audit_logs/services/actionLogService.ts +455 -85
  472. package/src/modules/catalog/i18n/de.json +1 -0
  473. package/src/modules/catalog/i18n/en.json +1 -0
  474. package/src/modules/catalog/i18n/es.json +1 -0
  475. package/src/modules/catalog/i18n/pl.json +1 -0
  476. package/src/modules/customer_accounts/i18n/de.json +2 -0
  477. package/src/modules/customer_accounts/i18n/en.json +2 -0
  478. package/src/modules/customer_accounts/i18n/es.json +2 -0
  479. package/src/modules/customer_accounts/i18n/pl.json +2 -0
  480. package/src/modules/customers/acl.ts +2 -0
  481. package/src/modules/customers/api/activities/route.ts +4 -0
  482. package/src/modules/customers/api/assignable-staff/route.ts +250 -0
  483. package/src/modules/customers/api/companies/[id]/people/route.ts +244 -0
  484. package/src/modules/customers/api/companies/[id]/roles/route.ts +15 -0
  485. package/src/modules/customers/api/companies/[id]/route.ts +458 -40
  486. package/src/modules/customers/api/companies/route.ts +93 -15
  487. package/src/modules/customers/api/deals/[id]/companies/route.ts +203 -0
  488. package/src/modules/customers/api/deals/[id]/people/route.ts +182 -0
  489. package/src/modules/customers/api/deals/[id]/route.ts +554 -57
  490. package/src/modules/customers/api/deals/[id]/stats/route.ts +221 -0
  491. package/src/modules/customers/api/deals/route.ts +35 -46
  492. package/src/modules/customers/api/dictionaries/[kind]/[id]/route.ts +105 -3
  493. package/src/modules/customers/api/dictionaries/[kind]/route.ts +143 -44
  494. package/src/modules/customers/api/dictionaries/context.ts +45 -16
  495. package/src/modules/customers/api/dictionaries/kind-settings/route.ts +232 -0
  496. package/src/modules/customers/api/entity-roles-factory.ts +520 -0
  497. package/src/modules/customers/api/interactions/conflicts/route.ts +196 -0
  498. package/src/modules/customers/api/interactions/counts/route.ts +112 -0
  499. package/src/modules/customers/api/interactions/route.ts +95 -2
  500. package/src/modules/customers/api/labels/assign/route.ts +202 -0
  501. package/src/modules/customers/api/labels/auth.ts +19 -0
  502. package/src/modules/customers/api/labels/route.ts +310 -0
  503. package/src/modules/customers/api/labels/table-errors.ts +36 -0
  504. package/src/modules/customers/api/labels/unassign/route.ts +197 -0
  505. package/src/modules/customers/api/people/[id]/companies/[linkId]/route.ts +331 -0
  506. package/src/modules/customers/api/people/[id]/companies/context.ts +70 -0
  507. package/src/modules/customers/api/people/[id]/companies/enriched/route.ts +384 -0
  508. package/src/modules/customers/api/people/[id]/companies/route.ts +215 -0
  509. package/src/modules/customers/api/people/[id]/roles/route.ts +15 -0
  510. package/src/modules/customers/api/people/[id]/route.ts +153 -26
  511. package/src/modules/customers/api/people/route.ts +134 -31
  512. package/src/modules/customers/api/todos/route.ts +4 -0
  513. package/src/modules/customers/api/utils.ts +36 -0
  514. package/src/modules/customers/backend/config/customers/page.tsx +2 -6
  515. package/src/modules/customers/backend/customers/companies/page.tsx +36 -26
  516. package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +277 -262
  517. package/src/modules/customers/backend/customers/deals/[id]/hooks/formatters.ts +19 -0
  518. package/src/modules/customers/backend/customers/deals/[id]/hooks/types.ts +104 -0
  519. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.ts +60 -0
  520. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.ts +362 -0
  521. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealClosure.ts +113 -0
  522. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealData.ts +52 -0
  523. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.ts +86 -0
  524. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealInjectedTabs.tsx +60 -0
  525. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealMutationContext.ts +76 -0
  526. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealPipeline.ts +56 -0
  527. package/src/modules/customers/backend/customers/deals/[id]/hooks/useScheduleDialog.ts +38 -0
  528. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +587 -624
  529. package/src/modules/customers/backend/customers/deals/page.tsx +71 -28
  530. package/src/modules/customers/backend/customers/people/page.tsx +35 -29
  531. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +343 -209
  532. package/src/modules/customers/cli.ts +107 -12
  533. package/src/modules/customers/commands/activities.ts +13 -0
  534. package/src/modules/customers/commands/deals.ts +386 -114
  535. package/src/modules/customers/commands/dictionaries.ts +175 -32
  536. package/src/modules/customers/commands/dictionaryKindSettings.ts +268 -0
  537. package/src/modules/customers/commands/entity-roles.ts +494 -0
  538. package/src/modules/customers/commands/index.ts +4 -0
  539. package/src/modules/customers/commands/interactions.ts +125 -21
  540. package/src/modules/customers/commands/labels.ts +626 -0
  541. package/src/modules/customers/commands/people.ts +373 -259
  542. package/src/modules/customers/commands/personCompanyLinks.ts +654 -0
  543. package/src/modules/customers/commands/shared.ts +16 -15
  544. package/src/modules/customers/commands/todos.ts +17 -1
  545. package/src/modules/customers/components/AddressEditor.tsx +1 -1
  546. package/src/modules/customers/components/CustomersConfigurationSections.tsx +36 -0
  547. package/src/modules/customers/components/DictionarySettings.tsx +43 -2
  548. package/src/modules/customers/components/detail/ActiveDealCard.tsx +175 -0
  549. package/src/modules/customers/components/detail/ActivitiesSection.tsx +267 -361
  550. package/src/modules/customers/components/detail/ActivityAiActions.tsx +49 -0
  551. package/src/modules/customers/components/detail/ActivityCard.tsx +154 -0
  552. package/src/modules/customers/components/detail/ActivityHistorySection.tsx +412 -0
  553. package/src/modules/customers/components/detail/ActivityLogTab.tsx +67 -0
  554. package/src/modules/customers/components/detail/ActivityTimeline.tsx +158 -0
  555. package/src/modules/customers/components/detail/ActivityTimelineFilters.tsx +163 -0
  556. package/src/modules/customers/components/detail/ActivityTypeSelector.tsx +53 -0
  557. package/src/modules/customers/components/detail/AiActionChips.tsx +48 -0
  558. package/src/modules/customers/components/detail/AssignRoleDialog.tsx +672 -0
  559. package/src/modules/customers/components/detail/ChangelogEntryRow.tsx +132 -0
  560. package/src/modules/customers/components/detail/ChangelogFilters.tsx +193 -0
  561. package/src/modules/customers/components/detail/ChangelogKpiCards.tsx +107 -0
  562. package/src/modules/customers/components/detail/ChangelogTab.tsx +629 -0
  563. package/src/modules/customers/components/detail/ComingSoonPlaceholder.tsx +21 -0
  564. package/src/modules/customers/components/detail/CompanyCard.tsx +419 -0
  565. package/src/modules/customers/components/detail/CompanyDashboardTab.tsx +161 -0
  566. package/src/modules/customers/components/detail/CompanyDetailHeader.tsx +243 -0
  567. package/src/modules/customers/components/detail/CompanyDetailTabs.tsx +172 -0
  568. package/src/modules/customers/components/detail/CompanyKpiBar.tsx +206 -0
  569. package/src/modules/customers/components/detail/CompanyPeopleSection.tsx +582 -288
  570. package/src/modules/customers/components/detail/CompanyTagsDialog.tsx +23 -0
  571. package/src/modules/customers/components/detail/ConfirmDealLostDialog.tsx +210 -0
  572. package/src/modules/customers/components/detail/CreatePersonDialog.tsx +178 -0
  573. package/src/modules/customers/components/detail/DealClosureActionBar.tsx +63 -0
  574. package/src/modules/customers/components/detail/DealDetailHeader.tsx +335 -0
  575. package/src/modules/customers/components/detail/DealDetailTabs.tsx +154 -0
  576. package/src/modules/customers/components/detail/DealForm.tsx +253 -101
  577. package/src/modules/customers/components/detail/DealLinkedEntitiesTab.tsx +349 -0
  578. package/src/modules/customers/components/detail/DealLostSummaryDialog.tsx +156 -0
  579. package/src/modules/customers/components/detail/DealWonPopup.tsx +164 -0
  580. package/src/modules/customers/components/detail/DealsSection.tsx +276 -221
  581. package/src/modules/customers/components/detail/DecisionMakersFooter.tsx +56 -0
  582. package/src/modules/customers/components/detail/EntityTagsDialog.tsx +1372 -0
  583. package/src/modules/customers/components/detail/InlineActivityComposer.tsx +239 -0
  584. package/src/modules/customers/components/detail/ManageTagsDialog.tsx +1331 -0
  585. package/src/modules/customers/components/detail/MiniWeekCalendar.tsx +338 -0
  586. package/src/modules/customers/components/detail/MobilePersonDetail.tsx +124 -0
  587. package/src/modules/customers/components/detail/NextStepCard.tsx +104 -0
  588. package/src/modules/customers/components/detail/PersonCard.tsx +238 -0
  589. package/src/modules/customers/components/detail/PersonCompaniesSection.tsx +426 -0
  590. package/src/modules/customers/components/detail/PersonDetailHeader.tsx +294 -0
  591. package/src/modules/customers/components/detail/PersonDetailTabs.tsx +172 -0
  592. package/src/modules/customers/components/detail/PersonTagsDialog.tsx +26 -0
  593. package/src/modules/customers/components/detail/PipelineStepper.tsx +245 -0
  594. package/src/modules/customers/components/detail/PlannedActivitiesSection.tsx +255 -0
  595. package/src/modules/customers/components/detail/RelationshipHealthCard.tsx +63 -0
  596. package/src/modules/customers/components/detail/RoleAssignmentRow.tsx +248 -0
  597. package/src/modules/customers/components/detail/RolesSection.tsx +311 -0
  598. package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +481 -0
  599. package/src/modules/customers/components/detail/aiActionCatalog.ts +77 -0
  600. package/src/modules/customers/components/detail/assignableStaff.ts +124 -0
  601. package/src/modules/customers/components/detail/dashboard/ActiveDealWidget.tsx +63 -0
  602. package/src/modules/customers/components/detail/dashboard/OpenTasksWidget.tsx +114 -0
  603. package/src/modules/customers/components/detail/dashboard/RecentActivityWidget.tsx +69 -0
  604. package/src/modules/customers/components/detail/dashboard/RelationshipHealthWidget.tsx +40 -0
  605. package/src/modules/customers/components/detail/dashboard/UpcomingMeetingsWidget.tsx +64 -0
  606. package/src/modules/customers/components/detail/dashboard/helpers.ts +78 -0
  607. package/src/modules/customers/components/detail/healthScoreUtils.ts +91 -0
  608. package/src/modules/customers/components/detail/hooks/useCurrencyDictionary.ts +8 -8
  609. package/src/modules/customers/components/detail/hooks/useCustomerDictionary.ts +10 -6
  610. package/src/modules/customers/components/detail/hooks/useInteractionMutations.ts +91 -0
  611. package/src/modules/customers/components/detail/notesAdapter.ts +91 -30
  612. package/src/modules/customers/components/detail/pipelineStageUtils.ts +29 -0
  613. package/src/modules/customers/components/detail/schedule/DateTimeFields.tsx +187 -0
  614. package/src/modules/customers/components/detail/schedule/FooterFields.tsx +79 -0
  615. package/src/modules/customers/components/detail/schedule/LinkedEntitiesField.tsx +277 -0
  616. package/src/modules/customers/components/detail/schedule/LocationField.tsx +42 -0
  617. package/src/modules/customers/components/detail/schedule/ParticipantsField.tsx +255 -0
  618. package/src/modules/customers/components/detail/schedule/fieldConfig.ts +70 -0
  619. package/src/modules/customers/components/detail/schedule/index.ts +9 -0
  620. package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +221 -0
  621. package/src/modules/customers/components/detail/types.ts +16 -0
  622. package/src/modules/customers/components/detail/utils.ts +25 -0
  623. package/src/modules/customers/components/formConfig.tsx +223 -28
  624. package/src/modules/customers/components/linking/LinkEntityDialog.tsx +920 -0
  625. package/src/modules/customers/components/linking/adapters/companyAdapter.tsx +398 -0
  626. package/src/modules/customers/components/linking/adapters/dealAdapter.tsx +578 -0
  627. package/src/modules/customers/components/linking/adapters/personAdapter.tsx +512 -0
  628. package/src/modules/customers/components/list/CollectionPreviewCell.tsx +66 -0
  629. package/src/modules/customers/data/entities.ts +353 -1
  630. package/src/modules/customers/data/validators.ts +170 -19
  631. package/src/modules/customers/events.ts +22 -0
  632. package/src/modules/customers/i18n/de.json +841 -2
  633. package/src/modules/customers/i18n/en.json +841 -2
  634. package/src/modules/customers/i18n/es.json +840 -1
  635. package/src/modules/customers/i18n/pl.json +841 -2
  636. package/src/modules/customers/lib/customerRoleTypes.ts +24 -0
  637. package/src/modules/customers/lib/dealClosureNotification.ts +64 -0
  638. package/src/modules/customers/lib/dealStageTransitionTable.ts +32 -0
  639. package/src/modules/customers/lib/dictionaries.ts +26 -10
  640. package/src/modules/customers/lib/interactionReadModel.ts +10 -0
  641. package/src/modules/customers/lib/personCompanies.ts +317 -0
  642. package/src/modules/customers/lib/personCompanyLinkTable.ts +58 -0
  643. package/src/modules/customers/lib/roleTypeUsage.ts +146 -0
  644. package/src/modules/customers/migrations/.snapshot-open-mercato.json +2747 -798
  645. package/src/modules/customers/migrations/Migration20260406214502.ts +19 -0
  646. package/src/modules/customers/migrations/Migration20260408135736.ts +15 -0
  647. package/src/modules/customers/migrations/Migration20260408225345.ts +23 -0
  648. package/src/modules/customers/migrations/Migration20260411075533.ts +30 -0
  649. package/src/modules/customers/migrations/Migration20260411103551.ts +13 -0
  650. package/src/modules/customers/migrations/Migration20260411130944.ts +30 -0
  651. package/src/modules/customers/migrations/Migration20260415095203.ts +13 -0
  652. package/src/modules/customers/migrations/Migration20260415135056.ts +22 -0
  653. package/src/modules/customers/migrations/Migration20260417140000.ts +15 -0
  654. package/src/modules/customers/migrations/Migration20260417160000.ts +17 -0
  655. package/src/modules/customers/migrations/Migration20260417235407.ts +13 -0
  656. package/src/modules/customers/setup.ts +15 -0
  657. package/src/modules/customers/subscribers/deal-closure-notification.ts +22 -0
  658. package/src/modules/customers/subscribers/deal-lost-notification.ts +22 -0
  659. package/src/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.ts +2 -0
  660. package/src/modules/dictionaries/api/[dictionaryId]/entries/reorder/route.ts +162 -0
  661. package/src/modules/dictionaries/api/[dictionaryId]/entries/route.ts +6 -2
  662. package/src/modules/dictionaries/api/[dictionaryId]/entries/set-default/route.ts +162 -0
  663. package/src/modules/dictionaries/api/context.ts +9 -0
  664. package/src/modules/dictionaries/api/openapi.ts +17 -0
  665. package/src/modules/dictionaries/commands/entry-operations.ts +457 -0
  666. package/src/modules/dictionaries/commands/factory.ts +31 -3
  667. package/src/modules/dictionaries/commands/index.ts +1 -0
  668. package/src/modules/dictionaries/components/DictionaryTable.tsx +15 -6
  669. package/src/modules/dictionaries/data/entities.ts +9 -0
  670. package/src/modules/dictionaries/data/validators.ts +34 -0
  671. package/src/modules/dictionaries/events.ts +20 -0
  672. package/src/modules/dictionaries/i18n/de.json +2 -0
  673. package/src/modules/dictionaries/i18n/en.json +2 -0
  674. package/src/modules/dictionaries/i18n/es.json +2 -0
  675. package/src/modules/dictionaries/i18n/pl.json +2 -0
  676. package/src/modules/dictionaries/lib/clientEntries.ts +66 -0
  677. package/src/modules/dictionaries/migrations/.snapshot-open-mercato.json +185 -3
  678. package/src/modules/dictionaries/migrations/Migration20260410171544.ts +49 -0
  679. package/src/modules/inbox_ops/api/proposals/[id]/route.ts +4 -1
  680. package/src/modules/query_index/lib/engine.ts +9 -1
  681. package/src/modules/sales/components/documents/AddressesSection.tsx +92 -42
  682. package/src/modules/sales/i18n/de.json +28 -0
  683. package/src/modules/sales/i18n/en.json +28 -0
  684. package/src/modules/sales/i18n/es.json +28 -0
  685. package/src/modules/sales/i18n/pl.json +28 -0
  686. package/src/modules/sales/lib/dictionaries.ts +18 -0
  687. package/src/modules/sales/widgets/injection-table.ts +4 -0
@@ -0,0 +1,48 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { Users, ArrowUpRight } from "lucide-react";
4
+ import { Badge } from "@open-mercato/ui/primitives/badge";
5
+ import { formatCurrency } from "../utils.js";
6
+ function ActiveDealWidget({ deals, t }) {
7
+ const topDeal = deals.sort((a, b) => {
8
+ const va = typeof a.valueAmount === "number" ? a.valueAmount : parseFloat(String(a.valueAmount ?? "0"));
9
+ const vb = typeof b.valueAmount === "number" ? b.valueAmount : parseFloat(String(b.valueAmount ?? "0"));
10
+ return vb - va;
11
+ })[0];
12
+ if (!topDeal) {
13
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-card p-5", children: [
14
+ /* @__PURE__ */ jsxs("h3", { className: "flex items-center gap-2 text-sm font-semibold text-foreground", children: [
15
+ /* @__PURE__ */ jsx(Users, { className: "size-4" }),
16
+ t("customers.companies.dashboard.activeDeal", "Active deal")
17
+ ] }),
18
+ /* @__PURE__ */ jsx("p", { className: "mt-3 text-sm text-muted-foreground", children: t("customers.companies.dashboard.noDeals", "No active deals") })
19
+ ] });
20
+ }
21
+ const amount = typeof topDeal.valueAmount === "number" ? topDeal.valueAmount : parseFloat(String(topDeal.valueAmount ?? "0"));
22
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-card p-5", children: [
23
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
24
+ /* @__PURE__ */ jsxs("h3", { className: "flex items-center gap-2 text-sm font-semibold text-foreground", children: [
25
+ /* @__PURE__ */ jsx(Users, { className: "size-4" }),
26
+ t("customers.companies.dashboard.activeDeal", "Active deal")
27
+ ] }),
28
+ /* @__PURE__ */ jsx(ArrowUpRight, { className: "size-4 text-muted-foreground" })
29
+ ] }),
30
+ /* @__PURE__ */ jsxs("div", { className: "mt-3", children: [
31
+ /* @__PURE__ */ jsx("p", { className: "font-semibold text-foreground", children: topDeal.title }),
32
+ topDeal.createdAt && /* @__PURE__ */ jsxs("p", { className: "mt-0.5 text-xs text-muted-foreground", children: [
33
+ t("customers.companies.dashboard.created", "Created"),
34
+ " ",
35
+ new Date(topDeal.createdAt).toLocaleDateString()
36
+ ] }),
37
+ topDeal.pipelineStage && /* @__PURE__ */ jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsx(Badge, { variant: "outline", className: "text-xs", children: topDeal.pipelineStage }) }),
38
+ Number.isFinite(amount) && amount > 0 && /* @__PURE__ */ jsxs("p", { className: "mt-2 text-lg font-bold text-foreground", children: [
39
+ formatCurrency(amount, topDeal.valueCurrency),
40
+ /* @__PURE__ */ jsx("span", { className: "ml-1.5 text-xs font-normal text-muted-foreground", children: t("customers.companies.dashboard.potentialValue", "potential value") })
41
+ ] })
42
+ ] })
43
+ ] });
44
+ }
45
+ export {
46
+ ActiveDealWidget
47
+ };
48
+ //# sourceMappingURL=ActiveDealWidget.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/customers/components/detail/dashboard/ActiveDealWidget.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Users, ArrowUpRight } from 'lucide-react'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport type { TranslateFn } from '@open-mercato/shared/lib/i18n/context'\nimport type { DealSummary } from '../../formConfig'\nimport { formatCurrency } from '../utils'\n\nexport function ActiveDealWidget({ deals, t }: { deals: DealSummary[]; t: TranslateFn }) {\n const topDeal = deals.sort((a, b) => {\n const va = typeof a.valueAmount === 'number' ? a.valueAmount : parseFloat(String(a.valueAmount ?? '0'))\n const vb = typeof b.valueAmount === 'number' ? b.valueAmount : parseFloat(String(b.valueAmount ?? '0'))\n return vb - va\n })[0]\n\n if (!topDeal) {\n return (\n <div className=\"rounded-lg border bg-card p-5\">\n <h3 className=\"flex items-center gap-2 text-sm font-semibold text-foreground\">\n <Users className=\"size-4\" />\n {t('customers.companies.dashboard.activeDeal', 'Active deal')}\n </h3>\n <p className=\"mt-3 text-sm text-muted-foreground\">{t('customers.companies.dashboard.noDeals', 'No active deals')}</p>\n </div>\n )\n }\n\n const amount = typeof topDeal.valueAmount === 'number' ? topDeal.valueAmount : parseFloat(String(topDeal.valueAmount ?? '0'))\n\n return (\n <div className=\"rounded-lg border bg-card p-5\">\n <div className=\"flex items-center justify-between\">\n <h3 className=\"flex items-center gap-2 text-sm font-semibold text-foreground\">\n <Users className=\"size-4\" />\n {t('customers.companies.dashboard.activeDeal', 'Active deal')}\n </h3>\n <ArrowUpRight className=\"size-4 text-muted-foreground\" />\n </div>\n <div className=\"mt-3\">\n <p className=\"font-semibold text-foreground\">{topDeal.title}</p>\n {topDeal.createdAt && (\n <p className=\"mt-0.5 text-xs text-muted-foreground\">\n {t('customers.companies.dashboard.created', 'Created')} {new Date(topDeal.createdAt).toLocaleDateString()}\n </p>\n )}\n {topDeal.pipelineStage && (\n <div className=\"mt-2\">\n <Badge variant=\"outline\" className=\"text-xs\">{topDeal.pipelineStage}</Badge>\n </div>\n )}\n {Number.isFinite(amount) && amount > 0 && (\n <p className=\"mt-2 text-lg font-bold text-foreground\">\n {formatCurrency(amount, topDeal.valueCurrency)}\n <span className=\"ml-1.5 text-xs font-normal text-muted-foreground\">\n {t('customers.companies.dashboard.potentialValue', 'potential value')}\n </span>\n </p>\n )}\n </div>\n </div>\n )\n}\n"],
5
+ "mappings": ";AAmBQ,SACE,KADF;AAhBR,SAAS,OAAO,oBAAoB;AACpC,SAAS,aAAa;AAGtB,SAAS,sBAAsB;AAExB,SAAS,iBAAiB,EAAE,OAAO,EAAE,GAA6C;AACvF,QAAM,UAAU,MAAM,KAAK,CAAC,GAAG,MAAM;AACnC,UAAM,KAAK,OAAO,EAAE,gBAAgB,WAAW,EAAE,cAAc,WAAW,OAAO,EAAE,eAAe,GAAG,CAAC;AACtG,UAAM,KAAK,OAAO,EAAE,gBAAgB,WAAW,EAAE,cAAc,WAAW,OAAO,EAAE,eAAe,GAAG,CAAC;AACtG,WAAO,KAAK;AAAA,EACd,CAAC,EAAE,CAAC;AAEJ,MAAI,CAAC,SAAS;AACZ,WACE,qBAAC,SAAI,WAAU,iCACb;AAAA,2BAAC,QAAG,WAAU,iEACZ;AAAA,4BAAC,SAAM,WAAU,UAAS;AAAA,QACzB,EAAE,4CAA4C,aAAa;AAAA,SAC9D;AAAA,MACA,oBAAC,OAAE,WAAU,sCAAsC,YAAE,yCAAyC,iBAAiB,GAAE;AAAA,OACnH;AAAA,EAEJ;AAEA,QAAM,SAAS,OAAO,QAAQ,gBAAgB,WAAW,QAAQ,cAAc,WAAW,OAAO,QAAQ,eAAe,GAAG,CAAC;AAE5H,SACE,qBAAC,SAAI,WAAU,iCACb;AAAA,yBAAC,SAAI,WAAU,qCACb;AAAA,2BAAC,QAAG,WAAU,iEACZ;AAAA,4BAAC,SAAM,WAAU,UAAS;AAAA,QACzB,EAAE,4CAA4C,aAAa;AAAA,SAC9D;AAAA,MACA,oBAAC,gBAAa,WAAU,gCAA+B;AAAA,OACzD;AAAA,IACA,qBAAC,SAAI,WAAU,QACb;AAAA,0BAAC,OAAE,WAAU,iCAAiC,kBAAQ,OAAM;AAAA,MAC3D,QAAQ,aACP,qBAAC,OAAE,WAAU,wCACV;AAAA,UAAE,yCAAyC,SAAS;AAAA,QAAE;AAAA,QAAE,IAAI,KAAK,QAAQ,SAAS,EAAE,mBAAmB;AAAA,SAC1G;AAAA,MAED,QAAQ,iBACP,oBAAC,SAAI,WAAU,QACb,8BAAC,SAAM,SAAQ,WAAU,WAAU,WAAW,kBAAQ,eAAc,GACtE;AAAA,MAED,OAAO,SAAS,MAAM,KAAK,SAAS,KACnC,qBAAC,OAAE,WAAU,0CACV;AAAA,uBAAe,QAAQ,QAAQ,aAAa;AAAA,QAC7C,oBAAC,UAAK,WAAU,oDACb,YAAE,gDAAgD,iBAAiB,GACtE;AAAA,SACF;AAAA,OAEJ;AAAA,KACF;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,86 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { CheckCircle2, AlertCircle, ArrowUpRight } from "lucide-react";
5
+ import { cn } from "@open-mercato/shared/lib/utils";
6
+ import { Button } from "@open-mercato/ui/primitives/button";
7
+ import { Badge } from "@open-mercato/ui/primitives/badge";
8
+ function isOverdue(dueAt) {
9
+ if (!dueAt) return false;
10
+ return new Date(dueAt) < /* @__PURE__ */ new Date();
11
+ }
12
+ function priorityLabel(priority) {
13
+ if (priority === null || priority === void 0) return { label: "None", variant: "muted" };
14
+ if (priority >= 3) return { label: "High", variant: "destructive" };
15
+ if (priority === 2) return { label: "Medium", variant: "default" };
16
+ return { label: "Low", variant: "secondary" };
17
+ }
18
+ function OpenTasksWidget({
19
+ tasks,
20
+ currentUserId,
21
+ t,
22
+ onViewAll
23
+ }) {
24
+ const [taskFilter, setTaskFilter] = React.useState("all");
25
+ const overdueTasks = tasks.filter((task) => isOverdue(task.dueAt));
26
+ const mineTasks = currentUserId ? tasks.filter((task) => {
27
+ const assignee = task.assignedToUserId ?? task.createdByUserId;
28
+ return assignee === currentUserId;
29
+ }) : tasks;
30
+ const filteredTasks = taskFilter === "overdue" ? overdueTasks : taskFilter === "mine" ? mineTasks : tasks;
31
+ const filterTabs = [
32
+ { key: "all", label: t("customers.tasks.filters.all", "All"), count: tasks.length },
33
+ { key: "mine", label: t("customers.tasks.filters.mine", "Mine"), count: mineTasks.length },
34
+ { key: "overdue", label: t("customers.tasks.filters.overdue", "Overdue"), count: overdueTasks.length }
35
+ ];
36
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-card p-5", children: [
37
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
38
+ /* @__PURE__ */ jsxs("h3", { className: "flex items-center gap-2 text-sm font-semibold text-foreground", children: [
39
+ /* @__PURE__ */ jsx(CheckCircle2, { className: "size-4" }),
40
+ t("customers.companies.dashboard.openTasks", "Open tasks"),
41
+ /* @__PURE__ */ jsx("span", { className: "rounded-full bg-muted px-1.5 py-0.5 text-xs font-medium text-muted-foreground", children: tasks.length })
42
+ ] }),
43
+ /* @__PURE__ */ jsxs(Button, { type: "button", variant: "outline", size: "sm", className: "h-7 text-xs", onClick: onViewAll, children: [
44
+ "+ ",
45
+ t("customers.companies.dashboard.newTask", "New task")
46
+ ] })
47
+ ] }),
48
+ /* @__PURE__ */ jsx("div", { className: "mt-2 flex items-center gap-1", children: filterTabs.map((tab) => /* @__PURE__ */ jsxs(
49
+ Button,
50
+ {
51
+ type: "button",
52
+ variant: taskFilter === tab.key ? "default" : "outline",
53
+ size: "sm",
54
+ className: "h-6 px-2 text-xs",
55
+ onClick: () => setTaskFilter(tab.key),
56
+ children: [
57
+ tab.label,
58
+ /* @__PURE__ */ jsx("span", { className: "ml-1 rounded-full bg-muted/50 px-1 text-overline", children: tab.count })
59
+ ]
60
+ },
61
+ tab.key
62
+ )) }),
63
+ /* @__PURE__ */ jsxs("div", { className: "mt-3 divide-y", children: [
64
+ filteredTasks.slice(0, 4).map((task) => {
65
+ const overdue = isOverdue(task.dueAt);
66
+ const prio = priorityLabel(task.priority);
67
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 py-2.5 first:pt-0 last:pb-0", children: [
68
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
69
+ /* @__PURE__ */ jsx("p", { className: "truncate text-sm text-foreground", children: task.title || "\u2014" }),
70
+ task.dueAt && /* @__PURE__ */ jsxs("p", { className: cn("mt-0.5 text-xs", overdue ? "text-destructive" : "text-muted-foreground"), children: [
71
+ overdue && /* @__PURE__ */ jsx(AlertCircle, { className: "mr-1 inline size-3" }),
72
+ overdue ? t("customers.companies.dashboard.overdueBy", "Overdue by {{days}} days", { days: Math.ceil((Date.now() - new Date(task.dueAt).getTime()) / 864e5) }) : t("customers.companies.dashboard.dueOn", "Due: {{date}}", { date: new Date(task.dueAt).toLocaleDateString() })
73
+ ] })
74
+ ] }),
75
+ /* @__PURE__ */ jsx(Badge, { variant: prio.variant, className: "shrink-0 text-xs", children: prio.label }),
76
+ /* @__PURE__ */ jsx(ArrowUpRight, { className: "size-3.5 shrink-0 text-muted-foreground" })
77
+ ] }, task.id);
78
+ }),
79
+ filteredTasks.length === 0 && /* @__PURE__ */ jsx("p", { className: "py-3 text-sm text-muted-foreground", children: t("customers.companies.dashboard.noTasks", "No open tasks") })
80
+ ] })
81
+ ] });
82
+ }
83
+ export {
84
+ OpenTasksWidget
85
+ };
86
+ //# sourceMappingURL=OpenTasksWidget.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/customers/components/detail/dashboard/OpenTasksWidget.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { CheckCircle2, AlertCircle, ArrowUpRight } from 'lucide-react'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport type { TodoLinkSummary } from '../../formConfig'\n\nfunction isOverdue(dueAt: string | null | undefined): boolean {\n if (!dueAt) return false\n return new Date(dueAt) < new Date()\n}\n\nfunction priorityLabel(priority: number | null | undefined): { label: string; variant: 'destructive' | 'default' | 'secondary' | 'muted' } {\n if (priority === null || priority === undefined) return { label: 'None', variant: 'muted' }\n if (priority >= 3) return { label: 'High', variant: 'destructive' }\n if (priority === 2) return { label: 'Medium', variant: 'default' }\n return { label: 'Low', variant: 'secondary' }\n}\n\ntype TranslateFnWithParams = (key: string, fallback?: string, params?: Record<string, string | number>) => string\n\nexport function OpenTasksWidget({\n tasks,\n currentUserId,\n t,\n onViewAll,\n}: {\n tasks: TodoLinkSummary[]\n currentUserId?: string | null\n t: TranslateFnWithParams\n onViewAll: () => void\n}) {\n const [taskFilter, setTaskFilter] = React.useState<'all' | 'mine' | 'overdue'>('all')\n const overdueTasks = tasks.filter((task) => isOverdue(task.dueAt))\n const mineTasks = currentUserId\n ? tasks.filter((task) => {\n const assignee = (task as Record<string, unknown>).assignedToUserId ?? (task as Record<string, unknown>).createdByUserId\n return assignee === currentUserId\n })\n : tasks\n\n const filteredTasks = taskFilter === 'overdue'\n ? overdueTasks\n : taskFilter === 'mine'\n ? mineTasks\n : tasks\n\n const filterTabs: Array<{ key: 'all' | 'mine' | 'overdue'; label: string; count: number }> = [\n { key: 'all', label: t('customers.tasks.filters.all', 'All'), count: tasks.length },\n { key: 'mine', label: t('customers.tasks.filters.mine', 'Mine'), count: mineTasks.length },\n { key: 'overdue', label: t('customers.tasks.filters.overdue', 'Overdue'), count: overdueTasks.length },\n ]\n\n return (\n <div className=\"rounded-lg border bg-card p-5\">\n <div className=\"flex items-center justify-between\">\n <h3 className=\"flex items-center gap-2 text-sm font-semibold text-foreground\">\n <CheckCircle2 className=\"size-4\" />\n {t('customers.companies.dashboard.openTasks', 'Open tasks')}\n <span className=\"rounded-full bg-muted px-1.5 py-0.5 text-xs font-medium text-muted-foreground\">\n {tasks.length}\n </span>\n </h3>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" className=\"h-7 text-xs\" onClick={onViewAll}>\n + {t('customers.companies.dashboard.newTask', 'New task')}\n </Button>\n </div>\n <div className=\"mt-2 flex items-center gap-1\">\n {filterTabs.map((tab) => (\n <Button\n key={tab.key}\n type=\"button\"\n variant={taskFilter === tab.key ? 'default' : 'outline'}\n size=\"sm\"\n className=\"h-6 px-2 text-xs\"\n onClick={() => setTaskFilter(tab.key)}\n >\n {tab.label}\n <span className=\"ml-1 rounded-full bg-muted/50 px-1 text-overline\">{tab.count}</span>\n </Button>\n ))}\n </div>\n <div className=\"mt-3 divide-y\">\n {filteredTasks.slice(0, 4).map((task) => {\n const overdue = isOverdue(task.dueAt)\n const prio = priorityLabel(task.priority)\n return (\n <div key={task.id} className=\"flex items-center gap-3 py-2.5 first:pt-0 last:pb-0\">\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm text-foreground\">{task.title || '\u2014'}</p>\n {task.dueAt && (\n <p className={cn('mt-0.5 text-xs', overdue ? 'text-destructive' : 'text-muted-foreground')}>\n {overdue && <AlertCircle className=\"mr-1 inline size-3\" />}\n {overdue\n ? t('customers.companies.dashboard.overdueBy', 'Overdue by {{days}} days', { days: Math.ceil((Date.now() - new Date(task.dueAt).getTime()) / 86_400_000) })\n : t('customers.companies.dashboard.dueOn', 'Due: {{date}}', { date: new Date(task.dueAt).toLocaleDateString() })\n }\n </p>\n )}\n </div>\n <Badge variant={prio.variant} className=\"shrink-0 text-xs\">{prio.label}</Badge>\n <ArrowUpRight className=\"size-3.5 shrink-0 text-muted-foreground\" />\n </div>\n )\n })}\n {filteredTasks.length === 0 && (\n <p className=\"py-3 text-sm text-muted-foreground\">{t('customers.companies.dashboard.noTasks', 'No open tasks')}</p>\n )}\n </div>\n </div>\n )\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,53 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { Phone, Mail, Users, StickyNote, Clock, ArrowUpRight, ChevronRight } from "lucide-react";
4
+ import { Button } from "@open-mercato/ui/primitives/button";
5
+ import { formatRelativeTime } from "@open-mercato/shared/lib/time";
6
+ function interactionIcon(type) {
7
+ switch (type) {
8
+ case "call":
9
+ return /* @__PURE__ */ jsx(Phone, { className: "size-4" });
10
+ case "email":
11
+ return /* @__PURE__ */ jsx(Mail, { className: "size-4" });
12
+ case "meeting":
13
+ return /* @__PURE__ */ jsx(Users, { className: "size-4" });
14
+ case "note":
15
+ return /* @__PURE__ */ jsx(StickyNote, { className: "size-4" });
16
+ default:
17
+ return /* @__PURE__ */ jsx(Clock, { className: "size-4" });
18
+ }
19
+ }
20
+ function RecentActivityWidget({ interactions, t }) {
21
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-card p-5", children: [
22
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsxs("h3", { className: "flex items-center gap-2 text-sm font-semibold text-foreground", children: [
23
+ /* @__PURE__ */ jsx(Clock, { className: "size-4" }),
24
+ t("customers.companies.dashboard.recentActivity", "Recent activity"),
25
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-normal text-muted-foreground", children: t("customers.companies.dashboard.last7days", "last 7 days") })
26
+ ] }) }),
27
+ /* @__PURE__ */ jsxs("div", { className: "mt-3 divide-y", children: [
28
+ interactions.map((interaction) => {
29
+ const date = interaction.occurredAt ?? interaction.scheduledAt;
30
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 py-3 first:pt-0 last:pb-0", children: [
31
+ /* @__PURE__ */ jsx("div", { className: "mt-0.5 flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground", children: interactionIcon(interaction.interactionType) }),
32
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
33
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-foreground", children: interaction.title || interaction.interactionType }),
34
+ /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-xs text-muted-foreground", children: interaction.authorName && /* @__PURE__ */ jsx("span", { children: interaction.authorName }) })
35
+ ] }),
36
+ /* @__PURE__ */ jsxs("div", { className: "shrink-0 text-right", children: [
37
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: date ? formatRelativeTime(date) : "\u2014" }),
38
+ /* @__PURE__ */ jsx(ArrowUpRight, { className: "ml-auto mt-1 size-3.5 text-muted-foreground" })
39
+ ] })
40
+ ] }, interaction.id);
41
+ }),
42
+ interactions.length === 0 && /* @__PURE__ */ jsx("p", { className: "py-3 text-sm text-muted-foreground", children: t("customers.companies.dashboard.noActivity", "No recent activity") })
43
+ ] }),
44
+ interactions.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-3 border-t pt-3", children: /* @__PURE__ */ jsxs(Button, { type: "button", variant: "link", size: "sm", className: "h-auto p-0 text-xs", children: [
45
+ t("customers.companies.dashboard.seeAllActivity", "See all {{count}} activities", { count: String(interactions.length) }),
46
+ /* @__PURE__ */ jsx(ChevronRight, { className: "ml-0.5 size-3" })
47
+ ] }) })
48
+ ] });
49
+ }
50
+ export {
51
+ RecentActivityWidget
52
+ };
53
+ //# sourceMappingURL=RecentActivityWidget.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/customers/components/detail/dashboard/RecentActivityWidget.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Phone, Mail, Users, StickyNote, Clock, ArrowUpRight, ChevronRight } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { formatRelativeTime } from '@open-mercato/shared/lib/time'\nimport type { TranslateFn } from '@open-mercato/shared/lib/i18n/context'\nimport type { InteractionSummary } from '../../formConfig'\n\nfunction interactionIcon(type: string) {\n switch (type) {\n case 'call': return <Phone className=\"size-4\" />\n case 'email': return <Mail className=\"size-4\" />\n case 'meeting': return <Users className=\"size-4\" />\n case 'note': return <StickyNote className=\"size-4\" />\n default: return <Clock className=\"size-4\" />\n }\n}\n\nexport function RecentActivityWidget({ interactions, t }: { interactions: InteractionSummary[]; t: TranslateFn }) {\n return (\n <div className=\"rounded-lg border bg-card p-5\">\n <div className=\"flex items-center justify-between\">\n <h3 className=\"flex items-center gap-2 text-sm font-semibold text-foreground\">\n <Clock className=\"size-4\" />\n {t('customers.companies.dashboard.recentActivity', 'Recent activity')}\n <span className=\"text-xs font-normal text-muted-foreground\">\n {t('customers.companies.dashboard.last7days', 'last 7 days')}\n </span>\n </h3>\n </div>\n <div className=\"mt-3 divide-y\">\n {interactions.map((interaction) => {\n const date = interaction.occurredAt ?? interaction.scheduledAt\n return (\n <div key={interaction.id} className=\"flex items-start gap-3 py-3 first:pt-0 last:pb-0\">\n <div className=\"mt-0.5 flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground\">\n {interactionIcon(interaction.interactionType)}\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm text-foreground\">{interaction.title || interaction.interactionType}</p>\n <p className=\"mt-0.5 text-xs text-muted-foreground\">\n {interaction.authorName && <span>{interaction.authorName}</span>}\n </p>\n </div>\n <div className=\"shrink-0 text-right\">\n <p className=\"text-xs text-muted-foreground\">\n {date ? formatRelativeTime(date) : '\u2014'}\n </p>\n <ArrowUpRight className=\"ml-auto mt-1 size-3.5 text-muted-foreground\" />\n </div>\n </div>\n )\n })}\n {interactions.length === 0 && (\n <p className=\"py-3 text-sm text-muted-foreground\">{t('customers.companies.dashboard.noActivity', 'No recent activity')}</p>\n )}\n </div>\n {interactions.length > 0 && (\n <div className=\"mt-3 border-t pt-3\">\n <Button type=\"button\" variant=\"link\" size=\"sm\" className=\"h-auto p-0 text-xs\">\n {t('customers.companies.dashboard.seeAllActivity', 'See all {{count}} activities', { count: String(interactions.length) })}\n <ChevronRight className=\"ml-0.5 size-3\" />\n </Button>\n </div>\n )}\n </div>\n )\n}\n"],
5
+ "mappings": ";AAWwB,cAYhB,YAZgB;AARxB,SAAS,OAAO,MAAM,OAAO,YAAY,OAAO,cAAc,oBAAoB;AAClF,SAAS,cAAc;AACvB,SAAS,0BAA0B;AAInC,SAAS,gBAAgB,MAAc;AACrC,UAAQ,MAAM;AAAA,IACZ,KAAK;AAAQ,aAAO,oBAAC,SAAM,WAAU,UAAS;AAAA,IAC9C,KAAK;AAAS,aAAO,oBAAC,QAAK,WAAU,UAAS;AAAA,IAC9C,KAAK;AAAW,aAAO,oBAAC,SAAM,WAAU,UAAS;AAAA,IACjD,KAAK;AAAQ,aAAO,oBAAC,cAAW,WAAU,UAAS;AAAA,IACnD;AAAS,aAAO,oBAAC,SAAM,WAAU,UAAS;AAAA,EAC5C;AACF;AAEO,SAAS,qBAAqB,EAAE,cAAc,EAAE,GAA2D;AAChH,SACE,qBAAC,SAAI,WAAU,iCACb;AAAA,wBAAC,SAAI,WAAU,qCACb,+BAAC,QAAG,WAAU,iEACZ;AAAA,0BAAC,SAAM,WAAU,UAAS;AAAA,MACzB,EAAE,gDAAgD,iBAAiB;AAAA,MACpE,oBAAC,UAAK,WAAU,6CACb,YAAE,2CAA2C,aAAa,GAC7D;AAAA,OACF,GACF;AAAA,IACA,qBAAC,SAAI,WAAU,iBACZ;AAAA,mBAAa,IAAI,CAAC,gBAAgB;AACjC,cAAM,OAAO,YAAY,cAAc,YAAY;AACnD,eACE,qBAAC,SAAyB,WAAU,oDAClC;AAAA,8BAAC,SAAI,WAAU,uGACZ,0BAAgB,YAAY,eAAe,GAC9C;AAAA,UACA,qBAAC,SAAI,WAAU,kBACb;AAAA,gCAAC,OAAE,WAAU,2BAA2B,sBAAY,SAAS,YAAY,iBAAgB;AAAA,YACzF,oBAAC,OAAE,WAAU,wCACV,sBAAY,cAAc,oBAAC,UAAM,sBAAY,YAAW,GAC3D;AAAA,aACF;AAAA,UACA,qBAAC,SAAI,WAAU,uBACb;AAAA,gCAAC,OAAE,WAAU,iCACV,iBAAO,mBAAmB,IAAI,IAAI,UACrC;AAAA,YACA,oBAAC,gBAAa,WAAU,+CAA8C;AAAA,aACxE;AAAA,aAfQ,YAAY,EAgBtB;AAAA,MAEJ,CAAC;AAAA,MACA,aAAa,WAAW,KACvB,oBAAC,OAAE,WAAU,sCAAsC,YAAE,4CAA4C,oBAAoB,GAAE;AAAA,OAE3H;AAAA,IACC,aAAa,SAAS,KACrB,oBAAC,SAAI,WAAU,sBACb,+BAAC,UAAO,MAAK,UAAS,SAAQ,QAAO,MAAK,MAAK,WAAU,sBACtD;AAAA,QAAE,gDAAgD,gCAAgC,EAAE,OAAO,OAAO,aAAa,MAAM,EAAE,CAAC;AAAA,MACzH,oBAAC,gBAAa,WAAU,iBAAgB;AAAA,OAC1C,GACF;AAAA,KAEJ;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,30 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { Heart } from "lucide-react";
4
+ import { cn } from "@open-mercato/shared/lib/utils";
5
+ import { Badge } from "@open-mercato/ui/primitives/badge";
6
+ import { HEALTH_BADGE_CLASSES, HEALTH_ICON_CLASSES } from "../healthScoreUtils.js";
7
+ function RelationshipHealthWidget({ health, t }) {
8
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-card p-5", children: [
9
+ /* @__PURE__ */ jsxs("h3", { className: "flex items-center gap-2 text-sm font-semibold text-foreground", children: [
10
+ /* @__PURE__ */ jsx(Heart, { className: cn("size-4", HEALTH_ICON_CLASSES[health.variant]) }),
11
+ t("customers.companies.dashboard.relationshipHealth", "Relationship health")
12
+ ] }),
13
+ /* @__PURE__ */ jsx("div", { className: "mt-4 flex items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "text-center space-y-2", children: [
14
+ /* @__PURE__ */ jsxs("div", { className: "relative inline-flex items-center justify-center", children: [
15
+ /* @__PURE__ */ jsx("span", { className: cn("text-4xl font-bold", HEALTH_ICON_CLASSES[health.variant]), children: health.score }),
16
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "/100" })
17
+ ] }),
18
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Badge, { className: cn("text-xs", HEALTH_BADGE_CLASSES[health.variant]), children: t(`customers.health.${health.label}`, health.label) }) }),
19
+ health.lastContactDays !== null && /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
20
+ t("customers.health.lastContact", "Last contact"),
21
+ ": ",
22
+ health.lastContactDays === 0 ? t("customers.health.today", "today") : t("customers.health.daysAgo", "{{days}} days ago", { days: health.lastContactDays })
23
+ ] })
24
+ ] }) })
25
+ ] });
26
+ }
27
+ export {
28
+ RelationshipHealthWidget
29
+ };
30
+ //# sourceMappingURL=RelationshipHealthWidget.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/customers/components/detail/dashboard/RelationshipHealthWidget.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Heart } from 'lucide-react'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { HEALTH_BADGE_CLASSES, HEALTH_ICON_CLASSES, type HealthScore } from '../healthScoreUtils'\n\ntype TranslateFnWithParams = (key: string, fallback?: string, params?: Record<string, string | number>) => string\n\nexport function RelationshipHealthWidget({ health, t }: { health: HealthScore; t: TranslateFnWithParams }) {\n return (\n <div className=\"rounded-lg border bg-card p-5\">\n <h3 className=\"flex items-center gap-2 text-sm font-semibold text-foreground\">\n <Heart className={cn('size-4', HEALTH_ICON_CLASSES[health.variant])} />\n {t('customers.companies.dashboard.relationshipHealth', 'Relationship health')}\n </h3>\n <div className=\"mt-4 flex items-center justify-center\">\n <div className=\"text-center space-y-2\">\n <div className=\"relative inline-flex items-center justify-center\">\n <span className={cn('text-4xl font-bold', HEALTH_ICON_CLASSES[health.variant])}>{health.score}</span>\n <span className=\"text-sm text-muted-foreground\">/100</span>\n </div>\n <div>\n <Badge className={cn('text-xs', HEALTH_BADGE_CLASSES[health.variant])}>\n {t(`customers.health.${health.label}`, health.label)}\n </Badge>\n </div>\n {health.lastContactDays !== null && (\n <p className=\"text-xs text-muted-foreground\">\n {t('customers.health.lastContact', 'Last contact')}: {health.lastContactDays === 0\n ? t('customers.health.today', 'today')\n : t('customers.health.daysAgo', '{{days}} days ago', { days: health.lastContactDays })}\n </p>\n )}\n </div>\n </div>\n </div>\n )\n}\n"],
5
+ "mappings": ";AAaM,SACE,KADF;AAVN,SAAS,aAAa;AACtB,SAAS,UAAU;AACnB,SAAS,aAAa;AACtB,SAAS,sBAAsB,2BAA6C;AAIrE,SAAS,yBAAyB,EAAE,QAAQ,EAAE,GAAsD;AACzG,SACE,qBAAC,SAAI,WAAU,iCACb;AAAA,yBAAC,QAAG,WAAU,iEACZ;AAAA,0BAAC,SAAM,WAAW,GAAG,UAAU,oBAAoB,OAAO,OAAO,CAAC,GAAG;AAAA,MACpE,EAAE,oDAAoD,qBAAqB;AAAA,OAC9E;AAAA,IACA,oBAAC,SAAI,WAAU,yCACb,+BAAC,SAAI,WAAU,yBACb;AAAA,2BAAC,SAAI,WAAU,oDACb;AAAA,4BAAC,UAAK,WAAW,GAAG,sBAAsB,oBAAoB,OAAO,OAAO,CAAC,GAAI,iBAAO,OAAM;AAAA,QAC9F,oBAAC,UAAK,WAAU,iCAAgC,kBAAI;AAAA,SACtD;AAAA,MACA,oBAAC,SACC,8BAAC,SAAM,WAAW,GAAG,WAAW,qBAAqB,OAAO,OAAO,CAAC,GACjE,YAAE,oBAAoB,OAAO,KAAK,IAAI,OAAO,KAAK,GACrD,GACF;AAAA,MACC,OAAO,oBAAoB,QAC1B,qBAAC,OAAE,WAAU,iCACV;AAAA,UAAE,gCAAgC,cAAc;AAAA,QAAE;AAAA,QAAG,OAAO,oBAAoB,IAC7E,EAAE,0BAA0B,OAAO,IACnC,EAAE,4BAA4B,qBAAqB,EAAE,MAAM,OAAO,gBAAgB,CAAC;AAAA,SACzF;AAAA,OAEJ,GACF;AAAA,KACF;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,43 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { Calendar, ChevronRight } from "lucide-react";
4
+ import { Button } from "@open-mercato/ui/primitives/button";
5
+ function UpcomingMeetingsWidget({ meetings, t }) {
6
+ if (meetings.length === 0) {
7
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-card p-5", children: [
8
+ /* @__PURE__ */ jsxs("h3", { className: "flex items-center gap-2 text-sm font-semibold text-foreground", children: [
9
+ /* @__PURE__ */ jsx(Calendar, { className: "size-4" }),
10
+ t("customers.companies.dashboard.upcomingMeetings", "Upcoming meetings")
11
+ ] }),
12
+ /* @__PURE__ */ jsx("p", { className: "mt-3 text-sm text-muted-foreground", children: t("customers.companies.dashboard.noMeetings", "No upcoming meetings") })
13
+ ] });
14
+ }
15
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-card p-5", children: [
16
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
17
+ /* @__PURE__ */ jsxs("h3", { className: "flex items-center gap-2 text-sm font-semibold text-foreground", children: [
18
+ /* @__PURE__ */ jsx(Calendar, { className: "size-4" }),
19
+ t("customers.companies.dashboard.upcomingMeetings", "Upcoming meetings"),
20
+ /* @__PURE__ */ jsx("span", { className: "rounded-full bg-muted px-1.5 py-0.5 text-xs font-medium text-muted-foreground", children: meetings.length })
21
+ ] }),
22
+ /* @__PURE__ */ jsxs(Button, { type: "button", variant: "link", size: "sm", className: "h-auto p-0 text-xs", children: [
23
+ t("customers.companies.dashboard.seeAll", "See all"),
24
+ /* @__PURE__ */ jsx(ChevronRight, { className: "ml-0.5 size-3" })
25
+ ] })
26
+ ] }),
27
+ /* @__PURE__ */ jsx("div", { className: "mt-3 divide-y", children: meetings.map((meeting) => {
28
+ const date = meeting.scheduledAt ? new Date(meeting.scheduledAt) : null;
29
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4 py-3 first:pt-0 last:pb-0", children: [
30
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
31
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: date ? date.toLocaleDateString(void 0, { weekday: "short", month: "short", day: "numeric" }) : "\u2014" }) }),
32
+ /* @__PURE__ */ jsx("p", { className: "mt-0.5 truncate text-sm font-medium text-foreground", children: meeting.title || meeting.interactionType }),
33
+ meeting.authorName && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: meeting.authorName })
34
+ ] }),
35
+ /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center gap-2", children: /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", size: "sm", className: "h-7 text-xs", children: t("customers.companies.dashboard.details", "Details") }) })
36
+ ] }, meeting.id);
37
+ }) })
38
+ ] });
39
+ }
40
+ export {
41
+ UpcomingMeetingsWidget
42
+ };
43
+ //# sourceMappingURL=UpcomingMeetingsWidget.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/customers/components/detail/dashboard/UpcomingMeetingsWidget.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Calendar, ChevronRight } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport type { TranslateFn } from '@open-mercato/shared/lib/i18n/context'\nimport type { InteractionSummary } from '../../formConfig'\n\nexport function UpcomingMeetingsWidget({ meetings, t }: { meetings: InteractionSummary[]; t: TranslateFn }) {\n if (meetings.length === 0) {\n return (\n <div className=\"rounded-lg border bg-card p-5\">\n <h3 className=\"flex items-center gap-2 text-sm font-semibold text-foreground\">\n <Calendar className=\"size-4\" />\n {t('customers.companies.dashboard.upcomingMeetings', 'Upcoming meetings')}\n </h3>\n <p className=\"mt-3 text-sm text-muted-foreground\">{t('customers.companies.dashboard.noMeetings', 'No upcoming meetings')}</p>\n </div>\n )\n }\n\n return (\n <div className=\"rounded-lg border bg-card p-5\">\n <div className=\"flex items-center justify-between\">\n <h3 className=\"flex items-center gap-2 text-sm font-semibold text-foreground\">\n <Calendar className=\"size-4\" />\n {t('customers.companies.dashboard.upcomingMeetings', 'Upcoming meetings')}\n <span className=\"rounded-full bg-muted px-1.5 py-0.5 text-xs font-medium text-muted-foreground\">\n {meetings.length}\n </span>\n </h3>\n <Button type=\"button\" variant=\"link\" size=\"sm\" className=\"h-auto p-0 text-xs\">\n {t('customers.companies.dashboard.seeAll', 'See all')}\n <ChevronRight className=\"ml-0.5 size-3\" />\n </Button>\n </div>\n <div className=\"mt-3 divide-y\">\n {meetings.map((meeting) => {\n const date = meeting.scheduledAt ? new Date(meeting.scheduledAt) : null\n return (\n <div key={meeting.id} className=\"flex items-center justify-between gap-4 py-3 first:pt-0 last:pb-0\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs text-muted-foreground\">\n {date ? date.toLocaleDateString(undefined, { weekday: 'short', month: 'short', day: 'numeric' }) : '\u2014'}\n </span>\n </div>\n <p className=\"mt-0.5 truncate text-sm font-medium text-foreground\">{meeting.title || meeting.interactionType}</p>\n {meeting.authorName && (\n <p className=\"text-xs text-muted-foreground\">{meeting.authorName}</p>\n )}\n </div>\n <div className=\"flex shrink-0 items-center gap-2\">\n <Button type=\"button\" variant=\"outline\" size=\"sm\" className=\"h-7 text-xs\">\n {t('customers.companies.dashboard.details', 'Details')}\n </Button>\n </div>\n </div>\n )\n })}\n </div>\n </div>\n )\n}\n"],
5
+ "mappings": ";AAYQ,SACE,KADF;AATR,SAAS,UAAU,oBAAoB;AACvC,SAAS,cAAc;AAIhB,SAAS,uBAAuB,EAAE,UAAU,EAAE,GAAuD;AAC1G,MAAI,SAAS,WAAW,GAAG;AACzB,WACE,qBAAC,SAAI,WAAU,iCACb;AAAA,2BAAC,QAAG,WAAU,iEACZ;AAAA,4BAAC,YAAS,WAAU,UAAS;AAAA,QAC5B,EAAE,kDAAkD,mBAAmB;AAAA,SAC1E;AAAA,MACA,oBAAC,OAAE,WAAU,sCAAsC,YAAE,4CAA4C,sBAAsB,GAAE;AAAA,OAC3H;AAAA,EAEJ;AAEA,SACE,qBAAC,SAAI,WAAU,iCACb;AAAA,yBAAC,SAAI,WAAU,qCACb;AAAA,2BAAC,QAAG,WAAU,iEACZ;AAAA,4BAAC,YAAS,WAAU,UAAS;AAAA,QAC5B,EAAE,kDAAkD,mBAAmB;AAAA,QACxE,oBAAC,UAAK,WAAU,iFACb,mBAAS,QACZ;AAAA,SACF;AAAA,MACA,qBAAC,UAAO,MAAK,UAAS,SAAQ,QAAO,MAAK,MAAK,WAAU,sBACtD;AAAA,UAAE,wCAAwC,SAAS;AAAA,QACpD,oBAAC,gBAAa,WAAU,iBAAgB;AAAA,SAC1C;AAAA,OACF;AAAA,IACA,oBAAC,SAAI,WAAU,iBACZ,mBAAS,IAAI,CAAC,YAAY;AACzB,YAAM,OAAO,QAAQ,cAAc,IAAI,KAAK,QAAQ,WAAW,IAAI;AACnE,aACE,qBAAC,SAAqB,WAAU,qEAC9B;AAAA,6BAAC,SAAI,WAAU,kBACb;AAAA,8BAAC,SAAI,WAAU,2BACb,8BAAC,UAAK,WAAU,iCACb,iBAAO,KAAK,mBAAmB,QAAW,EAAE,SAAS,SAAS,OAAO,SAAS,KAAK,UAAU,CAAC,IAAI,UACrG,GACF;AAAA,UACA,oBAAC,OAAE,WAAU,uDAAuD,kBAAQ,SAAS,QAAQ,iBAAgB;AAAA,UAC5G,QAAQ,cACP,oBAAC,OAAE,WAAU,iCAAiC,kBAAQ,YAAW;AAAA,WAErE;AAAA,QACA,oBAAC,SAAI,WAAU,oCACb,8BAAC,UAAO,MAAK,UAAS,SAAQ,WAAU,MAAK,MAAK,WAAU,eACzD,YAAE,yCAAyC,SAAS,GACvD,GACF;AAAA,WAhBQ,QAAQ,EAiBlB;AAAA,IAEJ,CAAC,GACH;AAAA,KACF;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,71 @@
1
+ function sumActiveDeals(deals) {
2
+ return deals.filter((d) => d.status !== "won" && d.status !== "lost" && d.status !== "closed").reduce((sum, d) => {
3
+ const amount = typeof d.valueAmount === "number" ? d.valueAmount : parseFloat(String(d.valueAmount ?? "0"));
4
+ return sum + (Number.isFinite(amount) ? amount : 0);
5
+ }, 0);
6
+ }
7
+ function getActiveDeals(deals) {
8
+ return deals.filter((d) => d.status !== "won" && d.status !== "lost" && d.status !== "closed");
9
+ }
10
+ function getOpenTasks(todos) {
11
+ return todos.filter((t) => !t.isDone).sort((a, b) => {
12
+ if (!a.dueAt && !b.dueAt) return 0;
13
+ if (!a.dueAt) return 1;
14
+ if (!b.dueAt) return -1;
15
+ return new Date(a.dueAt).getTime() - new Date(b.dueAt).getTime();
16
+ });
17
+ }
18
+ function getUpcomingMeetings(interactions) {
19
+ const now = /* @__PURE__ */ new Date();
20
+ return interactions.filter((i) => i.scheduledAt && new Date(i.scheduledAt) > now).sort((a, b) => new Date(a.scheduledAt).getTime() - new Date(b.scheduledAt).getTime()).slice(0, 3);
21
+ }
22
+ function getRecentActivity(interactions) {
23
+ const weekAgo = /* @__PURE__ */ new Date();
24
+ weekAgo.setDate(weekAgo.getDate() - 7);
25
+ return interactions.filter((i) => {
26
+ const date = i.occurredAt ?? i.scheduledAt;
27
+ return date && new Date(date) >= weekAgo;
28
+ }).sort((a, b) => {
29
+ const da = a.occurredAt ?? a.scheduledAt ?? "";
30
+ const db = b.occurredAt ?? b.scheduledAt ?? "";
31
+ return new Date(db).getTime() - new Date(da).getTime();
32
+ }).slice(0, 4);
33
+ }
34
+ function computeActivityTrend(interactions) {
35
+ const now = Date.now();
36
+ const weekMs = 7 * 864e5;
37
+ const thisWeek = interactions.filter((i) => {
38
+ const d = i.occurredAt ?? i.scheduledAt;
39
+ return d && now - new Date(d).getTime() < weekMs;
40
+ }).length;
41
+ const lastWeek = interactions.filter((i) => {
42
+ const d = i.occurredAt ?? i.scheduledAt;
43
+ if (!d) return false;
44
+ const diff = now - new Date(d).getTime();
45
+ return diff >= weekMs && diff < weekMs * 2;
46
+ }).length;
47
+ if (lastWeek === 0 && thisWeek === 0) return void 0;
48
+ if (lastWeek === 0) return { value: 100, direction: "up" };
49
+ const pct = (thisWeek - lastWeek) / lastWeek * 100;
50
+ if (Math.abs(pct) < 0.5) return { value: 0, direction: "unchanged" };
51
+ return { value: Math.abs(pct), direction: pct > 0 ? "up" : "down" };
52
+ }
53
+ function computeDealTrend(deals) {
54
+ const active = deals.filter((d) => d.status !== "won" && d.status !== "lost" && d.status !== "closed");
55
+ if (active.length === 0) return void 0;
56
+ const now = Date.now();
57
+ const monthMs = 30 * 864e5;
58
+ const recentDeals = active.filter((d) => d.createdAt && now - new Date(d.createdAt).getTime() < monthMs).length;
59
+ if (recentDeals > 0) return { value: recentDeals * 10, direction: "up" };
60
+ return { value: 0, direction: "unchanged" };
61
+ }
62
+ export {
63
+ computeActivityTrend,
64
+ computeDealTrend,
65
+ getActiveDeals,
66
+ getOpenTasks,
67
+ getRecentActivity,
68
+ getUpcomingMeetings,
69
+ sumActiveDeals
70
+ };
71
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/customers/components/detail/dashboard/helpers.ts"],
4
+ "sourcesContent": ["import type { KpiTrend } from '@open-mercato/ui/backend/charts/KpiCard'\nimport type { DealSummary, InteractionSummary, TodoLinkSummary } from '../../formConfig'\n\nexport function sumActiveDeals(deals: DealSummary[]): number {\n return deals\n .filter((d) => d.status !== 'won' && d.status !== 'lost' && d.status !== 'closed')\n .reduce((sum, d) => {\n const amount = typeof d.valueAmount === 'number' ? d.valueAmount : parseFloat(String(d.valueAmount ?? '0'))\n return sum + (Number.isFinite(amount) ? amount : 0)\n }, 0)\n}\n\nexport function getActiveDeals(deals: DealSummary[]): DealSummary[] {\n return deals.filter((d) => d.status !== 'won' && d.status !== 'lost' && d.status !== 'closed')\n}\n\nexport function getOpenTasks(todos: TodoLinkSummary[]): TodoLinkSummary[] {\n return todos.filter((t) => !t.isDone).sort((a, b) => {\n if (!a.dueAt && !b.dueAt) return 0\n if (!a.dueAt) return 1\n if (!b.dueAt) return -1\n return new Date(a.dueAt).getTime() - new Date(b.dueAt).getTime()\n })\n}\n\nexport function getUpcomingMeetings(interactions: InteractionSummary[]): InteractionSummary[] {\n const now = new Date()\n return interactions\n .filter((i) => i.scheduledAt && new Date(i.scheduledAt) > now)\n .sort((a, b) => new Date(a.scheduledAt!).getTime() - new Date(b.scheduledAt!).getTime())\n .slice(0, 3)\n}\n\nexport function getRecentActivity(interactions: InteractionSummary[]): InteractionSummary[] {\n const weekAgo = new Date()\n weekAgo.setDate(weekAgo.getDate() - 7)\n return interactions\n .filter((i) => {\n const date = i.occurredAt ?? i.scheduledAt\n return date && new Date(date) >= weekAgo\n })\n .sort((a, b) => {\n const da = a.occurredAt ?? a.scheduledAt ?? ''\n const db = b.occurredAt ?? b.scheduledAt ?? ''\n return new Date(db).getTime() - new Date(da).getTime()\n })\n .slice(0, 4)\n}\n\nexport function computeActivityTrend(interactions: InteractionSummary[]): KpiTrend | undefined {\n const now = Date.now()\n const weekMs = 7 * 86_400_000\n const thisWeek = interactions.filter((i) => {\n const d = i.occurredAt ?? i.scheduledAt\n return d && now - new Date(d).getTime() < weekMs\n }).length\n const lastWeek = interactions.filter((i) => {\n const d = i.occurredAt ?? i.scheduledAt\n if (!d) return false\n const diff = now - new Date(d).getTime()\n return diff >= weekMs && diff < weekMs * 2\n }).length\n if (lastWeek === 0 && thisWeek === 0) return undefined\n if (lastWeek === 0) return { value: 100, direction: 'up' }\n const pct = ((thisWeek - lastWeek) / lastWeek) * 100\n if (Math.abs(pct) < 0.5) return { value: 0, direction: 'unchanged' }\n return { value: Math.abs(pct), direction: pct > 0 ? 'up' : 'down' }\n}\n\nexport function computeDealTrend(deals: DealSummary[]): KpiTrend | undefined {\n const active = deals.filter((d) => d.status !== 'won' && d.status !== 'lost' && d.status !== 'closed')\n if (active.length === 0) return undefined\n const now = Date.now()\n const monthMs = 30 * 86_400_000\n const recentDeals = active.filter((d) => d.createdAt && now - new Date(d.createdAt).getTime() < monthMs).length\n if (recentDeals > 0) return { value: recentDeals * 10, direction: 'up' }\n return { value: 0, direction: 'unchanged' }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,69 @@
1
+ function computeHealthScore(interactions) {
2
+ const now = Date.now();
3
+ const dayMs = 864e5;
4
+ const dates = interactions.map((i) => i.occurredAt ?? i.scheduledAt).filter(Boolean).map((d) => new Date(d).getTime());
5
+ const lastContactMs = dates.length > 0 ? Math.max(...dates) : 0;
6
+ const daysSinceContact = lastContactMs > 0 ? Math.floor((now - lastContactMs) / dayMs) : 999;
7
+ let recencyScore;
8
+ if (daysSinceContact <= 7) recencyScore = 100;
9
+ else if (daysSinceContact <= 30) recencyScore = 75;
10
+ else if (daysSinceContact <= 60) recencyScore = 50;
11
+ else if (daysSinceContact <= 90) recencyScore = 25;
12
+ else recencyScore = 0;
13
+ const last30 = interactions.filter((i) => {
14
+ const d = i.occurredAt ?? i.scheduledAt;
15
+ return d && now - new Date(d).getTime() < 30 * dayMs;
16
+ }).length;
17
+ let frequencyScore;
18
+ if (last30 >= 5) frequencyScore = 100;
19
+ else if (last30 >= 3) frequencyScore = 75;
20
+ else if (last30 >= 1) frequencyScore = 50;
21
+ else frequencyScore = 0;
22
+ const types = new Set(interactions.map((i) => i.interactionType));
23
+ let diversityScore;
24
+ if (types.size >= 4) diversityScore = 100;
25
+ else if (types.size >= 3) diversityScore = 75;
26
+ else if (types.size >= 2) diversityScore = 50;
27
+ else if (types.size >= 1) diversityScore = 25;
28
+ else diversityScore = 0;
29
+ const weekBuckets = new Set(
30
+ interactions.map((i) => i.occurredAt ?? i.scheduledAt).filter(Boolean).map((d) => Math.floor(new Date(d).getTime() / (7 * dayMs)))
31
+ );
32
+ let consistencyScore;
33
+ if (weekBuckets.size >= 8) consistencyScore = 100;
34
+ else if (weekBuckets.size >= 4) consistencyScore = 75;
35
+ else if (weekBuckets.size >= 2) consistencyScore = 50;
36
+ else consistencyScore = 25;
37
+ const score = Math.round(
38
+ recencyScore * 0.4 + frequencyScore * 0.3 + diversityScore * 0.15 + consistencyScore * 0.15
39
+ );
40
+ let label;
41
+ let variant;
42
+ if (score >= 70) {
43
+ label = "healthy";
44
+ variant = "success";
45
+ } else if (score >= 40) {
46
+ label = "watchful";
47
+ variant = "warning";
48
+ } else {
49
+ label = "at risk";
50
+ variant = "error";
51
+ }
52
+ return { score, label, variant, lastContactDays: daysSinceContact < 999 ? daysSinceContact : null };
53
+ }
54
+ const HEALTH_ICON_CLASSES = {
55
+ success: "text-status-success-icon",
56
+ warning: "text-status-warning-icon",
57
+ error: "text-status-error-icon"
58
+ };
59
+ const HEALTH_BADGE_CLASSES = {
60
+ success: "bg-status-success-bg text-status-success-text",
61
+ warning: "bg-status-warning-bg text-status-warning-text",
62
+ error: "bg-status-error-bg text-status-error-text"
63
+ };
64
+ export {
65
+ HEALTH_BADGE_CLASSES,
66
+ HEALTH_ICON_CLASSES,
67
+ computeHealthScore
68
+ };
69
+ //# sourceMappingURL=healthScoreUtils.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/customers/components/detail/healthScoreUtils.ts"],
4
+ "sourcesContent": ["/**\n * Shared health score computation for CRM relationship health widgets.\n */\nimport type { InteractionSummary } from '../formConfig'\n\nexport type HealthVariant = 'success' | 'warning' | 'error'\n\nexport type HealthScore = {\n score: number\n label: string\n variant: HealthVariant\n lastContactDays: number | null\n}\n\nexport function computeHealthScore(interactions: InteractionSummary[]): HealthScore {\n const now = Date.now()\n const dayMs = 86_400_000\n\n const dates = interactions\n .map((i) => i.occurredAt ?? i.scheduledAt)\n .filter(Boolean)\n .map((d) => new Date(d!).getTime())\n const lastContactMs = dates.length > 0 ? Math.max(...dates) : 0\n const daysSinceContact = lastContactMs > 0 ? Math.floor((now - lastContactMs) / dayMs) : 999\n\n let recencyScore: number\n if (daysSinceContact <= 7) recencyScore = 100\n else if (daysSinceContact <= 30) recencyScore = 75\n else if (daysSinceContact <= 60) recencyScore = 50\n else if (daysSinceContact <= 90) recencyScore = 25\n else recencyScore = 0\n\n const last30 = interactions.filter((i) => {\n const d = i.occurredAt ?? i.scheduledAt\n return d && now - new Date(d).getTime() < 30 * dayMs\n }).length\n\n let frequencyScore: number\n if (last30 >= 5) frequencyScore = 100\n else if (last30 >= 3) frequencyScore = 75\n else if (last30 >= 1) frequencyScore = 50\n else frequencyScore = 0\n\n const types = new Set(interactions.map((i) => i.interactionType))\n let diversityScore: number\n if (types.size >= 4) diversityScore = 100\n else if (types.size >= 3) diversityScore = 75\n else if (types.size >= 2) diversityScore = 50\n else if (types.size >= 1) diversityScore = 25\n else diversityScore = 0\n\n const weekBuckets = new Set(\n interactions\n .map((i) => i.occurredAt ?? i.scheduledAt)\n .filter(Boolean)\n .map((d) => Math.floor(new Date(d!).getTime() / (7 * dayMs))),\n )\n let consistencyScore: number\n if (weekBuckets.size >= 8) consistencyScore = 100\n else if (weekBuckets.size >= 4) consistencyScore = 75\n else if (weekBuckets.size >= 2) consistencyScore = 50\n else consistencyScore = 25\n\n const score = Math.round(\n recencyScore * 0.4 + frequencyScore * 0.3 + diversityScore * 0.15 + consistencyScore * 0.15,\n )\n\n let label: string\n let variant: HealthVariant\n if (score >= 70) { label = 'healthy'; variant = 'success' }\n else if (score >= 40) { label = 'watchful'; variant = 'warning' }\n else { label = 'at risk'; variant = 'error' }\n\n return { score, label, variant, lastContactDays: daysSinceContact < 999 ? daysSinceContact : null }\n}\n\n/**\n * Shared health variant \u2192 semantic status token mappings.\n * Used by RelationshipHealthCard and RelationshipHealthWidget.\n */\nexport const HEALTH_ICON_CLASSES: Record<HealthVariant, string> = {\n success: 'text-status-success-icon',\n warning: 'text-status-warning-icon',\n error: 'text-status-error-icon',\n}\n\nexport const HEALTH_BADGE_CLASSES: Record<HealthVariant, string> = {\n success: 'bg-status-success-bg text-status-success-text',\n warning: 'bg-status-warning-bg text-status-warning-text',\n error: 'bg-status-error-bg text-status-error-text',\n}\n"],
5
+ "mappings": "AAcO,SAAS,mBAAmB,cAAiD;AAClF,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM,QAAQ;AAEd,QAAM,QAAQ,aACX,IAAI,CAAC,MAAM,EAAE,cAAc,EAAE,WAAW,EACxC,OAAO,OAAO,EACd,IAAI,CAAC,MAAM,IAAI,KAAK,CAAE,EAAE,QAAQ,CAAC;AACpC,QAAM,gBAAgB,MAAM,SAAS,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI;AAC9D,QAAM,mBAAmB,gBAAgB,IAAI,KAAK,OAAO,MAAM,iBAAiB,KAAK,IAAI;AAEzF,MAAI;AACJ,MAAI,oBAAoB,EAAG,gBAAe;AAAA,WACjC,oBAAoB,GAAI,gBAAe;AAAA,WACvC,oBAAoB,GAAI,gBAAe;AAAA,WACvC,oBAAoB,GAAI,gBAAe;AAAA,MAC3C,gBAAe;AAEpB,QAAM,SAAS,aAAa,OAAO,CAAC,MAAM;AACxC,UAAM,IAAI,EAAE,cAAc,EAAE;AAC5B,WAAO,KAAK,MAAM,IAAI,KAAK,CAAC,EAAE,QAAQ,IAAI,KAAK;AAAA,EACjD,CAAC,EAAE;AAEH,MAAI;AACJ,MAAI,UAAU,EAAG,kBAAiB;AAAA,WACzB,UAAU,EAAG,kBAAiB;AAAA,WAC9B,UAAU,EAAG,kBAAiB;AAAA,MAClC,kBAAiB;AAEtB,QAAM,QAAQ,IAAI,IAAI,aAAa,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC;AAChE,MAAI;AACJ,MAAI,MAAM,QAAQ,EAAG,kBAAiB;AAAA,WAC7B,MAAM,QAAQ,EAAG,kBAAiB;AAAA,WAClC,MAAM,QAAQ,EAAG,kBAAiB;AAAA,WAClC,MAAM,QAAQ,EAAG,kBAAiB;AAAA,MACtC,kBAAiB;AAEtB,QAAM,cAAc,IAAI;AAAA,IACtB,aACG,IAAI,CAAC,MAAM,EAAE,cAAc,EAAE,WAAW,EACxC,OAAO,OAAO,EACd,IAAI,CAAC,MAAM,KAAK,MAAM,IAAI,KAAK,CAAE,EAAE,QAAQ,KAAK,IAAI,MAAM,CAAC;AAAA,EAChE;AACA,MAAI;AACJ,MAAI,YAAY,QAAQ,EAAG,oBAAmB;AAAA,WACrC,YAAY,QAAQ,EAAG,oBAAmB;AAAA,WAC1C,YAAY,QAAQ,EAAG,oBAAmB;AAAA,MAC9C,oBAAmB;AAExB,QAAM,QAAQ,KAAK;AAAA,IACjB,eAAe,MAAM,iBAAiB,MAAM,iBAAiB,OAAO,mBAAmB;AAAA,EACzF;AAEA,MAAI;AACJ,MAAI;AACJ,MAAI,SAAS,IAAI;AAAE,YAAQ;AAAW,cAAU;AAAA,EAAU,WACjD,SAAS,IAAI;AAAE,YAAQ;AAAY,cAAU;AAAA,EAAU,OAC3D;AAAE,YAAQ;AAAW,cAAU;AAAA,EAAQ;AAE5C,SAAO,EAAE,OAAO,OAAO,SAAS,iBAAiB,mBAAmB,MAAM,mBAAmB,KAAK;AACpG;AAMO,MAAM,sBAAqD;AAAA,EAChE,SAAS;AAAA,EACT,SAAS;AAAA,EACT,OAAO;AACT;AAEO,MAAM,uBAAsD;AAAA,EACjE,SAAS;AAAA,EACT,SAAS;AAAA,EACT,OAAO;AACT;",
6
+ "names": []
7
+ }
@@ -18,12 +18,12 @@ async function fetchCurrencyDictionary() {
18
18
  }
19
19
  const entriesRaw = Array.isArray(payload?.entries) ? payload.entries : [];
20
20
  const entries = entriesRaw.map((entry) => {
21
- const value = typeof entry?.value === "string" ? entry.value.trim().toUpperCase() : "";
22
- const label = typeof entry?.label === "string" && entry.label.trim().length ? entry.label.trim() : value;
23
- const entryId = typeof entry?.id === "string" ? entry.id : value;
21
+ const value = typeof entry.value === "string" ? entry.value.trim().toUpperCase() : "";
22
+ const label = typeof entry.label === "string" && entry.label.trim().length ? entry.label.trim() : value;
23
+ const entryId = typeof entry.id === "string" ? entry.id : value;
24
24
  if (!value) return null;
25
- const color = typeof entry?.color === "string" && entry.color.trim().length ? entry.color.trim() : null;
26
- const icon = typeof entry?.icon === "string" && entry.icon.trim().length ? entry.icon.trim() : null;
25
+ const color = typeof entry.color === "string" && entry.color.trim().length ? entry.color.trim() : null;
26
+ const icon = typeof entry.icon === "string" && entry.icon.trim().length ? entry.icon.trim() : null;
27
27
  return { id: entryId, value, label, color, icon };
28
28
  }).filter((entry) => entry !== null);
29
29
  return { id, entries };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/modules/customers/components/detail/hooks/useCurrencyDictionary.ts"],
4
- "sourcesContent": ["\"use client\"\n\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { QueryClient } from '@tanstack/react-query'\nimport * as React from 'react'\n\nexport type CurrencyDictionaryEntry = {\n id: string\n value: string\n label: string\n color?: string | null\n icon?: string | null\n}\n\nexport type CurrencyDictionaryPayload = {\n id: string\n entries: CurrencyDictionaryEntry[]\n}\n\nconst QUERY_KEY = ['customers', 'dictionaries', 'currency'] as const\nconst STALE_TIME = 5 * 60 * 1000\n\nconst cache = new Map<string, { promise: Promise<CurrencyDictionaryPayload>; client: QueryClient }>()\nconst CACHE_KEY = JSON.stringify(QUERY_KEY)\n\nasync function fetchCurrencyDictionary(): Promise<CurrencyDictionaryPayload> {\n const payload = await readApiResultOrThrow<Record<string, unknown>>(\n '/api/customers/dictionaries/currency',\n undefined,\n { errorMessage: 'Failed to load currency dictionary.' },\n )\n const id = typeof payload?.id === 'string' ? payload.id : ''\n if (!id) {\n throw new Error('Currency dictionary is not configured yet.')\n }\n const entriesRaw = Array.isArray(payload?.entries) ? payload.entries : []\n const entries: CurrencyDictionaryEntry[] = entriesRaw\n .map((entry: any): CurrencyDictionaryEntry | null => {\n const value = typeof entry?.value === 'string' ? entry.value.trim().toUpperCase() : ''\n const label =\n typeof entry?.label === 'string' && entry.label.trim().length\n ? entry.label.trim()\n : value\n const entryId = typeof entry?.id === 'string' ? entry.id : value\n if (!value) return null\n const color = typeof entry?.color === 'string' && entry.color.trim().length ? entry.color.trim() : null\n const icon = typeof entry?.icon === 'string' && entry.icon.trim().length ? entry.icon.trim() : null\n return { id: entryId, value, label, color, icon }\n })\n .filter((entry: CurrencyDictionaryEntry | null): entry is CurrencyDictionaryEntry => entry !== null)\n return { id, entries }\n}\n\nexport function useCurrencyDictionary() {\n const [, forceRender] = React.useReducer((c) => c + 1, 0)\n const entry = cache.get(CACHE_KEY)\n const result = entry?.client.getQueryState<CurrencyDictionaryPayload>(QUERY_KEY)\n\n React.useEffect(() => {\n if (entry?.client.getQueryData(QUERY_KEY)) {\n forceRender()\n return\n }\n const client = entry?.client ?? new QueryClient()\n const promise = entry?.promise ?? client.fetchQuery({ queryKey: QUERY_KEY, queryFn: fetchCurrencyDictionary, staleTime: STALE_TIME, gcTime: STALE_TIME })\n if (!entry) cache.set(CACHE_KEY, { promise, client })\n promise.finally(() => { forceRender() })\n }, [])\n\n const data = entry?.client.getQueryData<CurrencyDictionaryPayload>(QUERY_KEY) ?? null\n const isLoading = !data && !(result && (result as any).status === 'error')\n const error = (result && (result as any).status === 'error') ? (result as any).error ?? null : null\n const refetch = React.useCallback(async () => {\n const current = cache.get(CACHE_KEY)\n const client = current?.client ?? new QueryClient()\n const promise = client.fetchQuery({ queryKey: QUERY_KEY, queryFn: fetchCurrencyDictionary, staleTime: STALE_TIME, gcTime: STALE_TIME })\n cache.set(CACHE_KEY, { promise, client })\n const payload = await promise\n forceRender()\n return payload\n }, [])\n return { data, error, isLoading, isError: Boolean(error), refetch }\n}\n\nexport async function ensureCurrencyDictionary(queryClient: QueryClient) {\n const key = JSON.stringify(QUERY_KEY)\n const existing = cache.get(key)\n if (existing) return existing.promise\n const promise = queryClient.fetchQuery({ queryKey: QUERY_KEY, queryFn: fetchCurrencyDictionary, staleTime: STALE_TIME, gcTime: STALE_TIME })\n cache.set(key, { promise, client: queryClient })\n return promise\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { QueryClient } from '@tanstack/react-query'\nimport * as React from 'react'\n\nexport type CurrencyDictionaryEntry = {\n id: string\n value: string\n label: string\n color?: string | null\n icon?: string | null\n}\n\nexport type CurrencyDictionaryPayload = {\n id: string\n entries: CurrencyDictionaryEntry[]\n}\n\nconst QUERY_KEY = ['customers', 'dictionaries', 'currency'] as const\nconst STALE_TIME = 5 * 60 * 1000\n\nconst cache = new Map<string, { promise: Promise<CurrencyDictionaryPayload>; client: QueryClient }>()\nconst CACHE_KEY = JSON.stringify(QUERY_KEY)\n\nasync function fetchCurrencyDictionary(): Promise<CurrencyDictionaryPayload> {\n const payload = await readApiResultOrThrow<Record<string, unknown>>(\n '/api/customers/dictionaries/currency',\n undefined,\n { errorMessage: 'Failed to load currency dictionary.' },\n )\n const id = typeof payload?.id === 'string' ? payload.id : ''\n if (!id) {\n throw new Error('Currency dictionary is not configured yet.')\n }\n const entriesRaw = Array.isArray(payload?.entries) ? payload.entries : []\n const entries: CurrencyDictionaryEntry[] = entriesRaw\n .map((entry: Record<string, unknown>): CurrencyDictionaryEntry | null => {\n const value = typeof entry.value === 'string' ? entry.value.trim().toUpperCase() : ''\n const label =\n typeof entry.label === 'string' && entry.label.trim().length\n ? entry.label.trim()\n : value\n const entryId = typeof entry.id === 'string' ? entry.id : value\n if (!value) return null\n const color = typeof entry.color === 'string' && entry.color.trim().length ? entry.color.trim() : null\n const icon = typeof entry.icon === 'string' && entry.icon.trim().length ? entry.icon.trim() : null\n return { id: entryId, value, label, color, icon }\n })\n .filter((entry: CurrencyDictionaryEntry | null): entry is CurrencyDictionaryEntry => entry !== null)\n return { id, entries }\n}\n\nexport function useCurrencyDictionary() {\n const [, forceRender] = React.useReducer((c) => c + 1, 0)\n const entry = cache.get(CACHE_KEY)\n const result = entry?.client.getQueryState<CurrencyDictionaryPayload>(QUERY_KEY)\n\n React.useEffect(() => {\n if (entry?.client.getQueryData(QUERY_KEY)) {\n forceRender()\n return\n }\n const client = entry?.client ?? new QueryClient()\n const promise = entry?.promise ?? client.fetchQuery({ queryKey: QUERY_KEY, queryFn: fetchCurrencyDictionary, staleTime: STALE_TIME, gcTime: STALE_TIME })\n if (!entry) cache.set(CACHE_KEY, { promise, client })\n promise.finally(() => { forceRender() })\n }, [])\n\n const data = entry?.client.getQueryData<CurrencyDictionaryPayload>(QUERY_KEY) ?? null\n const isLoading = !data && !(result && result.status === 'error')\n const error = (result && result.status === 'error') ? result.error ?? null : null\n const refetch = React.useCallback(async () => {\n const current = cache.get(CACHE_KEY)\n const client = current?.client ?? new QueryClient()\n const promise = client.fetchQuery({ queryKey: QUERY_KEY, queryFn: fetchCurrencyDictionary, staleTime: STALE_TIME, gcTime: STALE_TIME })\n cache.set(CACHE_KEY, { promise, client })\n const payload = await promise\n forceRender()\n return payload\n }, [])\n return { data, error, isLoading, isError: Boolean(error), refetch }\n}\n\nexport async function ensureCurrencyDictionary(queryClient: QueryClient) {\n const key = JSON.stringify(QUERY_KEY)\n const existing = cache.get(key)\n if (existing) return existing.promise\n const promise = queryClient.fetchQuery({ queryKey: QUERY_KEY, queryFn: fetchCurrencyDictionary, staleTime: STALE_TIME, gcTime: STALE_TIME })\n cache.set(key, { promise, client: queryClient })\n return promise\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }