@open-mercato/core 0.7.1-develop.7202.1.a52dc6707c → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (416) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/build.mjs +11 -0
  3. package/dist/modules/catalog/backend/catalog/products/[id]/page.js +23 -0
  4. package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
  5. package/dist/modules/customers/backend/customers/companies/[id]/page.js +2 -1
  6. package/dist/modules/customers/backend/customers/companies/[id]/page.js.map +2 -2
  7. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +2 -1
  8. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
  9. package/dist/modules/customers/backend/customers/people/[id]/page.js +2 -2
  10. package/dist/modules/customers/backend/customers/people/[id]/page.js.map +2 -2
  11. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +2 -1
  12. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
  13. package/dist/modules/customers/lib/detailHelpers.js +4 -0
  14. package/dist/modules/customers/lib/detailHelpers.js.map +2 -2
  15. package/dist/modules/customers/lib/todoCompatibility.js +5 -0
  16. package/dist/modules/customers/lib/todoCompatibility.js.map +2 -2
  17. package/dist/modules/design_system/backend/design-system/page.meta.js +3 -2
  18. package/dist/modules/design_system/backend/design-system/page.meta.js.map +2 -2
  19. package/dist/modules/design_system/gallery/assets/ai-prompt-image.png +0 -0
  20. package/dist/modules/design_system/gallery/assets/avatar-illustration.png +0 -0
  21. package/dist/modules/design_system/gallery/assets/avatar-memoji.png +0 -0
  22. package/dist/modules/design_system/gallery/assets/avatar-photo.png +0 -0
  23. package/dist/modules/design_system/gallery/assets/blog-photo-0.png +0 -0
  24. package/dist/modules/design_system/gallery/assets/contact-support-portrait.png +0 -0
  25. package/dist/modules/design_system/gallery/assets/crypto-ada.png +0 -0
  26. package/dist/modules/design_system/gallery/assets/crypto-avax.png +0 -0
  27. package/dist/modules/design_system/gallery/assets/crypto-bnb.png +0 -0
  28. package/dist/modules/design_system/gallery/assets/crypto-brand.png +0 -0
  29. package/dist/modules/design_system/gallery/assets/crypto-btc.png +0 -0
  30. package/dist/modules/design_system/gallery/assets/crypto-clock.svg +3 -0
  31. package/dist/modules/design_system/gallery/assets/crypto-crown.svg +3 -0
  32. package/dist/modules/design_system/gallery/assets/crypto-dot.png +0 -0
  33. package/dist/modules/design_system/gallery/assets/crypto-eth.png +0 -0
  34. package/dist/modules/design_system/gallery/assets/crypto-hbar.png +0 -0
  35. package/dist/modules/design_system/gallery/assets/crypto-history.svg +3 -0
  36. package/dist/modules/design_system/gallery/assets/crypto-link.svg +3 -0
  37. package/dist/modules/design_system/gallery/assets/crypto-menu.svg +3 -0
  38. package/dist/modules/design_system/gallery/assets/crypto-metamask.png +0 -0
  39. package/dist/modules/design_system/gallery/assets/crypto-more.svg +3 -0
  40. package/dist/modules/design_system/gallery/assets/crypto-phantom.png +0 -0
  41. package/dist/modules/design_system/gallery/assets/crypto-rewards.svg +3 -0
  42. package/dist/modules/design_system/gallery/assets/crypto-sad-face.png +0 -0
  43. package/dist/modules/design_system/gallery/assets/crypto-sol.png +0 -0
  44. package/dist/modules/design_system/gallery/assets/crypto-star.svg +3 -0
  45. package/dist/modules/design_system/gallery/assets/crypto-status-cancelled.svg +3 -0
  46. package/dist/modules/design_system/gallery/assets/crypto-status-pending.svg +3 -0
  47. package/dist/modules/design_system/gallery/assets/crypto-status-success.svg +3 -0
  48. package/dist/modules/design_system/gallery/assets/crypto-status-warning.svg +3 -0
  49. package/dist/modules/design_system/gallery/assets/crypto-trx.png +0 -0
  50. package/dist/modules/design_system/gallery/assets/crypto-usdc.png +0 -0
  51. package/dist/modules/design_system/gallery/assets/crypto-usdt.png +0 -0
  52. package/dist/modules/design_system/gallery/assets/crypto-walletconnect.png +0 -0
  53. package/dist/modules/design_system/gallery/assets/crypto-wei.png +0 -0
  54. package/dist/modules/design_system/gallery/assets/crypto-xrp.png +0 -0
  55. package/dist/modules/design_system/gallery/assets/cryptocurrency-artwork.js +67 -0
  56. package/dist/modules/design_system/gallery/assets/cryptocurrency-artwork.js.map +7 -0
  57. package/dist/modules/design_system/gallery/assets/github-logo.png +0 -0
  58. package/dist/modules/design_system/gallery/assets/images.d.js +1 -0
  59. package/dist/modules/design_system/gallery/assets/images.d.js.map +7 -0
  60. package/dist/modules/design_system/gallery/assets/input-european-union.svg +18 -0
  61. package/dist/modules/design_system/gallery/assets/landing-teams-01.png +0 -0
  62. package/dist/modules/design_system/gallery/assets/marketing-artwork.js +83 -0
  63. package/dist/modules/design_system/gallery/assets/marketing-artwork.js.map +7 -0
  64. package/dist/modules/design_system/gallery/assets/menu-apex.svg +18 -0
  65. package/dist/modules/design_system/gallery/assets/menu-mastercard.svg +7 -0
  66. package/dist/modules/design_system/gallery/assets/menu-spotify.svg +4 -0
  67. package/dist/modules/design_system/gallery/assets/menu-united-states.svg +16 -0
  68. package/dist/modules/design_system/gallery/assets/select-google.png +0 -0
  69. package/dist/modules/design_system/gallery/assets/select-poland.png +0 -0
  70. package/dist/modules/design_system/gallery/assets/selection-artwork.js +5 -0
  71. package/dist/modules/design_system/gallery/assets/selection-artwork.js.map +7 -0
  72. package/dist/modules/design_system/gallery/assets/social-apple-filled.svg +4 -0
  73. package/dist/modules/design_system/gallery/assets/social-apple-stroke.svg +4 -0
  74. package/dist/modules/design_system/gallery/assets/social-dropbox-filled.svg +5 -0
  75. package/dist/modules/design_system/gallery/assets/social-dropbox-stroke.svg +5 -0
  76. package/dist/modules/design_system/gallery/assets/social-facebook-filled.svg +4 -0
  77. package/dist/modules/design_system/gallery/assets/social-facebook-stroke.svg +10 -0
  78. package/dist/modules/design_system/gallery/assets/social-github-filled.svg +4 -0
  79. package/dist/modules/design_system/gallery/assets/social-github-stroke.svg +4 -0
  80. package/dist/modules/design_system/gallery/assets/social-google-filled.svg +7 -0
  81. package/dist/modules/design_system/gallery/assets/social-google-stroke.svg +7 -0
  82. package/dist/modules/design_system/gallery/assets/social-linkedin-filled.svg +4 -0
  83. package/dist/modules/design_system/gallery/assets/social-linkedin-stroke.svg +4 -0
  84. package/dist/modules/design_system/gallery/assets/social-x-filled.svg +4 -0
  85. package/dist/modules/design_system/gallery/assets/social-x-stroke.svg +4 -0
  86. package/dist/modules/design_system/gallery/assets/style-studio-product.png +0 -0
  87. package/dist/modules/design_system/gallery/assets/upload-images.js +8 -0
  88. package/dist/modules/design_system/gallery/assets/upload-images.js.map +7 -0
  89. package/dist/modules/design_system/gallery/components/BrandStylePreview.js +74 -0
  90. package/dist/modules/design_system/gallery/components/BrandStylePreview.js.map +7 -0
  91. package/dist/modules/design_system/gallery/components/CodeSnippet.js +31 -31
  92. package/dist/modules/design_system/gallery/components/CodeSnippet.js.map +2 -2
  93. package/dist/modules/design_system/gallery/components/ColorPlayground.js +408 -0
  94. package/dist/modules/design_system/gallery/components/ColorPlayground.js.map +7 -0
  95. package/dist/modules/design_system/gallery/components/ColorStudioCompositions.js +166 -0
  96. package/dist/modules/design_system/gallery/components/ColorStudioCompositions.js.map +7 -0
  97. package/dist/modules/design_system/gallery/components/ColorStudioSpecimen.js +182 -0
  98. package/dist/modules/design_system/gallery/components/ColorStudioSpecimen.js.map +7 -0
  99. package/dist/modules/design_system/gallery/components/CompactEntrySpecimen.js +80 -0
  100. package/dist/modules/design_system/gallery/components/CompactEntrySpecimen.js.map +7 -0
  101. package/dist/modules/design_system/gallery/components/ComponentIndex.js +42 -0
  102. package/dist/modules/design_system/gallery/components/ComponentIndex.js.map +7 -0
  103. package/dist/modules/design_system/gallery/components/DesignSystemHome.js +69 -0
  104. package/dist/modules/design_system/gallery/components/DesignSystemHome.js.map +7 -0
  105. package/dist/modules/design_system/gallery/components/EntryCard.js +47 -41
  106. package/dist/modules/design_system/gallery/components/EntryCard.js.map +2 -2
  107. package/dist/modules/design_system/gallery/components/EntryHeader.js +68 -0
  108. package/dist/modules/design_system/gallery/components/EntryHeader.js.map +7 -0
  109. package/dist/modules/design_system/gallery/components/FamilyEntryPreview.js +19 -0
  110. package/dist/modules/design_system/gallery/components/FamilyEntryPreview.js.map +7 -0
  111. package/dist/modules/design_system/gallery/components/FoundationGuide.js +46 -0
  112. package/dist/modules/design_system/gallery/components/FoundationGuide.js.map +7 -0
  113. package/dist/modules/design_system/gallery/components/GalleryLink.js +21 -0
  114. package/dist/modules/design_system/gallery/components/GalleryLink.js.map +7 -0
  115. package/dist/modules/design_system/gallery/components/GalleryNavigation.js +82 -0
  116. package/dist/modules/design_system/gallery/components/GalleryNavigation.js.map +7 -0
  117. package/dist/modules/design_system/gallery/components/GalleryShell.js +147 -67
  118. package/dist/modules/design_system/gallery/components/GalleryShell.js.map +3 -3
  119. package/dist/modules/design_system/gallery/components/IconsBrowser.js +33 -0
  120. package/dist/modules/design_system/gallery/components/IconsBrowser.js.map +7 -0
  121. package/dist/modules/design_system/gallery/components/SourceLibrary.js +93 -0
  122. package/dist/modules/design_system/gallery/components/SourceLibrary.js.map +7 -0
  123. package/dist/modules/design_system/gallery/components/StyleAgents.js +139 -0
  124. package/dist/modules/design_system/gallery/components/StyleAgents.js.map +7 -0
  125. package/dist/modules/design_system/gallery/components/ThemeTokenReference.js +101 -0
  126. package/dist/modules/design_system/gallery/components/ThemeTokenReference.js.map +7 -0
  127. package/dist/modules/design_system/gallery/components/VariantPreview.js +2 -2
  128. package/dist/modules/design_system/gallery/components/VariantPreview.js.map +2 -2
  129. package/dist/modules/design_system/gallery/components/colorPreview.js +58 -0
  130. package/dist/modules/design_system/gallery/components/colorPreview.js.map +7 -0
  131. package/dist/modules/design_system/gallery/components/colorStudio.js +218 -0
  132. package/dist/modules/design_system/gallery/components/colorStudio.js.map +7 -0
  133. package/dist/modules/design_system/gallery/components/styleAgentBranding.js +46 -0
  134. package/dist/modules/design_system/gallery/components/styleAgentBranding.js.map +7 -0
  135. package/dist/modules/design_system/gallery/components/themeTokens.js +32 -0
  136. package/dist/modules/design_system/gallery/components/themeTokens.js.map +7 -0
  137. package/dist/modules/design_system/gallery/demos/ai-product-code.generated.js +194 -0
  138. package/dist/modules/design_system/gallery/demos/ai-product-code.generated.js.map +7 -0
  139. package/dist/modules/design_system/gallery/demos/ai-product.js +423 -0
  140. package/dist/modules/design_system/gallery/demos/ai-product.js.map +7 -0
  141. package/dist/modules/design_system/gallery/demos/buttons.js +289 -0
  142. package/dist/modules/design_system/gallery/demos/buttons.js.map +7 -0
  143. package/dist/modules/design_system/gallery/demos/cryptocurrency.js +1708 -0
  144. package/dist/modules/design_system/gallery/demos/cryptocurrency.js.map +7 -0
  145. package/dist/modules/design_system/gallery/demos/feeds-code.generated.js +92 -0
  146. package/dist/modules/design_system/gallery/demos/feeds-code.generated.js.map +7 -0
  147. package/dist/modules/design_system/gallery/demos/feeds.js +148 -0
  148. package/dist/modules/design_system/gallery/demos/feeds.js.map +7 -0
  149. package/dist/modules/design_system/gallery/demos/file-upload.js +72 -0
  150. package/dist/modules/design_system/gallery/demos/file-upload.js.map +7 -0
  151. package/dist/modules/design_system/gallery/demos/foundation-reference-data.js +4875 -0
  152. package/dist/modules/design_system/gallery/demos/foundation-reference-data.js.map +7 -0
  153. package/dist/modules/design_system/gallery/demos/foundation-references.js +188 -0
  154. package/dist/modules/design_system/gallery/demos/foundation-references.js.map +7 -0
  155. package/dist/modules/design_system/gallery/demos/key-components-code.generated.js +6 -0
  156. package/dist/modules/design_system/gallery/demos/key-components-code.generated.js.map +7 -0
  157. package/dist/modules/design_system/gallery/demos/key-components.js +127 -0
  158. package/dist/modules/design_system/gallery/demos/key-components.js.map +7 -0
  159. package/dist/modules/design_system/gallery/demos/marketing-controls-code.generated.js +98 -0
  160. package/dist/modules/design_system/gallery/demos/marketing-controls-code.generated.js.map +7 -0
  161. package/dist/modules/design_system/gallery/demos/marketing-controls.js +134 -0
  162. package/dist/modules/design_system/gallery/demos/marketing-controls.js.map +7 -0
  163. package/dist/modules/design_system/gallery/demos/marketing-widgets-code.generated.js +195 -0
  164. package/dist/modules/design_system/gallery/demos/marketing-widgets-code.generated.js.map +7 -0
  165. package/dist/modules/design_system/gallery/demos/marketing-widgets.js +586 -0
  166. package/dist/modules/design_system/gallery/demos/marketing-widgets.js.map +7 -0
  167. package/dist/modules/design_system/gallery/demos/menu-fixtures.js +40 -0
  168. package/dist/modules/design_system/gallery/demos/menu-fixtures.js.map +7 -0
  169. package/dist/modules/design_system/gallery/demos/menu-sources.js +295 -0
  170. package/dist/modules/design_system/gallery/demos/menu-sources.js.map +7 -0
  171. package/dist/modules/design_system/gallery/demos/menus.js +150 -0
  172. package/dist/modules/design_system/gallery/demos/menus.js.map +7 -0
  173. package/dist/modules/design_system/gallery/demos/rating-reviews.js +53 -0
  174. package/dist/modules/design_system/gallery/demos/rating-reviews.js.map +7 -0
  175. package/dist/modules/design_system/gallery/demos/registered-icons.js +104 -0
  176. package/dist/modules/design_system/gallery/demos/registered-icons.js.map +7 -0
  177. package/dist/modules/design_system/gallery/demos/selection-cards.js +99 -0
  178. package/dist/modules/design_system/gallery/demos/selection-cards.js.map +7 -0
  179. package/dist/modules/design_system/gallery/demos/shell-code.generated.js +189 -0
  180. package/dist/modules/design_system/gallery/demos/shell-code.generated.js.map +7 -0
  181. package/dist/modules/design_system/gallery/demos/shell.js +330 -0
  182. package/dist/modules/design_system/gallery/demos/shell.js.map +7 -0
  183. package/dist/modules/design_system/gallery/demos/source-artwork.js +120 -0
  184. package/dist/modules/design_system/gallery/demos/source-artwork.js.map +7 -0
  185. package/dist/modules/design_system/gallery/demos/source-filters-code.generated.js +125 -0
  186. package/dist/modules/design_system/gallery/demos/source-filters-code.generated.js.map +7 -0
  187. package/dist/modules/design_system/gallery/demos/source-filters.js +185 -0
  188. package/dist/modules/design_system/gallery/demos/source-filters.js.map +7 -0
  189. package/dist/modules/design_system/gallery/demos/source-icons.js +69 -0
  190. package/dist/modules/design_system/gallery/demos/source-icons.js.map +7 -0
  191. package/dist/modules/design_system/gallery/demos/table-cells-code.generated.js +150 -0
  192. package/dist/modules/design_system/gallery/demos/table-cells-code.generated.js.map +7 -0
  193. package/dist/modules/design_system/gallery/demos/table-cells.js +181 -0
  194. package/dist/modules/design_system/gallery/demos/table-cells.js.map +7 -0
  195. package/dist/modules/design_system/gallery/demos/text-inputs.js +113 -0
  196. package/dist/modules/design_system/gallery/demos/text-inputs.js.map +7 -0
  197. package/dist/modules/design_system/gallery/demos/time-picker-code.generated.js +41 -0
  198. package/dist/modules/design_system/gallery/demos/time-picker-code.generated.js.map +7 -0
  199. package/dist/modules/design_system/gallery/demos/time-picker.js +41 -0
  200. package/dist/modules/design_system/gallery/demos/time-picker.js.map +7 -0
  201. package/dist/modules/design_system/gallery/entries/banners.js +123 -60
  202. package/dist/modules/design_system/gallery/entries/banners.js.map +2 -2
  203. package/dist/modules/design_system/gallery/entries/buttons-snippets.js +433 -0
  204. package/dist/modules/design_system/gallery/entries/buttons-snippets.js.map +7 -0
  205. package/dist/modules/design_system/gallery/entries/buttons.js +127 -148
  206. package/dist/modules/design_system/gallery/entries/buttons.js.map +2 -2
  207. package/dist/modules/design_system/gallery/entries/charts.js +532 -186
  208. package/dist/modules/design_system/gallery/entries/charts.js.map +2 -2
  209. package/dist/modules/design_system/gallery/entries/dates.js +191 -3
  210. package/dist/modules/design_system/gallery/entries/dates.js.map +2 -2
  211. package/dist/modules/design_system/gallery/entries/detail.js +118 -77
  212. package/dist/modules/design_system/gallery/entries/detail.js.map +2 -2
  213. package/dist/modules/design_system/gallery/entries/display.js +1449 -240
  214. package/dist/modules/design_system/gallery/entries/display.js.map +2 -2
  215. package/dist/modules/design_system/gallery/entries/feedback.js +1058 -132
  216. package/dist/modules/design_system/gallery/entries/feedback.js.map +2 -2
  217. package/dist/modules/design_system/gallery/entries/filters.js +231 -103
  218. package/dist/modules/design_system/gallery/entries/filters.js.map +2 -2
  219. package/dist/modules/design_system/gallery/entries/foundations.js +368 -57
  220. package/dist/modules/design_system/gallery/entries/foundations.js.map +2 -2
  221. package/dist/modules/design_system/gallery/entries/icons.js +29 -91
  222. package/dist/modules/design_system/gallery/entries/icons.js.map +2 -2
  223. package/dist/modules/design_system/gallery/entries/inputs-snippets.js +154 -0
  224. package/dist/modules/design_system/gallery/entries/inputs-snippets.js.map +7 -0
  225. package/dist/modules/design_system/gallery/entries/inputs.js +2043 -306
  226. package/dist/modules/design_system/gallery/entries/inputs.js.map +2 -2
  227. package/dist/modules/design_system/gallery/entries/library.js +20 -0
  228. package/dist/modules/design_system/gallery/entries/library.js.map +7 -0
  229. package/dist/modules/design_system/gallery/entries/messages.js +121 -103
  230. package/dist/modules/design_system/gallery/entries/messages.js.map +2 -2
  231. package/dist/modules/design_system/gallery/entries/navigation.js +676 -103
  232. package/dist/modules/design_system/gallery/entries/navigation.js.map +2 -2
  233. package/dist/modules/design_system/gallery/entries/notifications.js +131 -78
  234. package/dist/modules/design_system/gallery/entries/notifications.js.map +2 -2
  235. package/dist/modules/design_system/gallery/entries/overlays.js +611 -203
  236. package/dist/modules/design_system/gallery/entries/overlays.js.map +2 -2
  237. package/dist/modules/design_system/gallery/entries/scaffolding.js +1175 -120
  238. package/dist/modules/design_system/gallery/entries/scaffolding.js.map +2 -2
  239. package/dist/modules/design_system/gallery/entries/schedule.js +79 -54
  240. package/dist/modules/design_system/gallery/entries/schedule.js.map +2 -2
  241. package/dist/modules/design_system/gallery/presentation.js +108 -0
  242. package/dist/modules/design_system/gallery/presentation.js.map +7 -0
  243. package/dist/modules/design_system/gallery/registry.js +8 -5
  244. package/dist/modules/design_system/gallery/registry.js.map +2 -2
  245. package/dist/modules/design_system/gallery/source-library.generated.js +5 -0
  246. package/dist/modules/design_system/gallery/source-library.generated.js.map +7 -0
  247. package/dist/modules/design_system/i18n/de.json +7167 -0
  248. package/dist/modules/design_system/i18n/en.json +7167 -0
  249. package/dist/modules/design_system/i18n/es.json +7167 -0
  250. package/dist/modules/design_system/i18n/ko.json +7167 -0
  251. package/dist/modules/design_system/i18n/pl.json +7167 -0
  252. package/dist/modules/push_notifications/lib/queue.js +1 -31
  253. package/dist/modules/push_notifications/lib/queue.js.map +2 -2
  254. package/jest.config.cjs +1 -0
  255. package/jest.mocks/image.js +1 -0
  256. package/package.json +8 -9
  257. package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +50 -0
  258. package/src/modules/customers/backend/customers/companies/[id]/page.tsx +2 -1
  259. package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +2 -1
  260. package/src/modules/customers/backend/customers/people/[id]/page.tsx +2 -2
  261. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +2 -1
  262. package/src/modules/customers/lib/detailHelpers.ts +4 -0
  263. package/src/modules/customers/lib/todoCompatibility.ts +10 -0
  264. package/src/modules/design_system/backend/design-system/page.meta.ts +3 -2
  265. package/src/modules/design_system/gallery/assets/README.md +30 -0
  266. package/src/modules/design_system/gallery/assets/ai-prompt-image.png +0 -0
  267. package/src/modules/design_system/gallery/assets/avatar-illustration.png +0 -0
  268. package/src/modules/design_system/gallery/assets/avatar-memoji.png +0 -0
  269. package/src/modules/design_system/gallery/assets/avatar-photo.png +0 -0
  270. package/src/modules/design_system/gallery/assets/blog-photo-0.png +0 -0
  271. package/src/modules/design_system/gallery/assets/contact-support-portrait.png +0 -0
  272. package/src/modules/design_system/gallery/assets/crypto-ada.png +0 -0
  273. package/src/modules/design_system/gallery/assets/crypto-avax.png +0 -0
  274. package/src/modules/design_system/gallery/assets/crypto-bnb.png +0 -0
  275. package/src/modules/design_system/gallery/assets/crypto-brand.png +0 -0
  276. package/src/modules/design_system/gallery/assets/crypto-btc.png +0 -0
  277. package/src/modules/design_system/gallery/assets/crypto-clock.svg +3 -0
  278. package/src/modules/design_system/gallery/assets/crypto-crown.svg +3 -0
  279. package/src/modules/design_system/gallery/assets/crypto-dot.png +0 -0
  280. package/src/modules/design_system/gallery/assets/crypto-eth.png +0 -0
  281. package/src/modules/design_system/gallery/assets/crypto-hbar.png +0 -0
  282. package/src/modules/design_system/gallery/assets/crypto-history.svg +3 -0
  283. package/src/modules/design_system/gallery/assets/crypto-link.svg +3 -0
  284. package/src/modules/design_system/gallery/assets/crypto-menu.svg +3 -0
  285. package/src/modules/design_system/gallery/assets/crypto-metamask.png +0 -0
  286. package/src/modules/design_system/gallery/assets/crypto-more.svg +3 -0
  287. package/src/modules/design_system/gallery/assets/crypto-phantom.png +0 -0
  288. package/src/modules/design_system/gallery/assets/crypto-rewards.svg +3 -0
  289. package/src/modules/design_system/gallery/assets/crypto-sad-face.png +0 -0
  290. package/src/modules/design_system/gallery/assets/crypto-sol.png +0 -0
  291. package/src/modules/design_system/gallery/assets/crypto-star.svg +3 -0
  292. package/src/modules/design_system/gallery/assets/crypto-status-cancelled.svg +3 -0
  293. package/src/modules/design_system/gallery/assets/crypto-status-pending.svg +3 -0
  294. package/src/modules/design_system/gallery/assets/crypto-status-success.svg +3 -0
  295. package/src/modules/design_system/gallery/assets/crypto-status-warning.svg +3 -0
  296. package/src/modules/design_system/gallery/assets/crypto-trx.png +0 -0
  297. package/src/modules/design_system/gallery/assets/crypto-usdc.png +0 -0
  298. package/src/modules/design_system/gallery/assets/crypto-usdt.png +0 -0
  299. package/src/modules/design_system/gallery/assets/crypto-walletconnect.png +0 -0
  300. package/src/modules/design_system/gallery/assets/crypto-wei.png +0 -0
  301. package/src/modules/design_system/gallery/assets/crypto-xrp.png +0 -0
  302. package/src/modules/design_system/gallery/assets/cryptocurrency-artwork.ts +63 -0
  303. package/src/modules/design_system/gallery/assets/github-logo.png +0 -0
  304. package/src/modules/design_system/gallery/assets/images.d.ts +9 -0
  305. package/src/modules/design_system/gallery/assets/input-european-union.svg +18 -0
  306. package/src/modules/design_system/gallery/assets/landing-teams-01.png +0 -0
  307. package/src/modules/design_system/gallery/assets/marketing-artwork.ts +79 -0
  308. package/src/modules/design_system/gallery/assets/menu-apex.svg +18 -0
  309. package/src/modules/design_system/gallery/assets/menu-mastercard.svg +7 -0
  310. package/src/modules/design_system/gallery/assets/menu-spotify.svg +4 -0
  311. package/src/modules/design_system/gallery/assets/menu-united-states.svg +16 -0
  312. package/src/modules/design_system/gallery/assets/select-google.png +0 -0
  313. package/src/modules/design_system/gallery/assets/select-poland.png +0 -0
  314. package/src/modules/design_system/gallery/assets/selection-artwork.ts +1 -0
  315. package/src/modules/design_system/gallery/assets/social-apple-filled.svg +4 -0
  316. package/src/modules/design_system/gallery/assets/social-apple-stroke.svg +4 -0
  317. package/src/modules/design_system/gallery/assets/social-dropbox-filled.svg +5 -0
  318. package/src/modules/design_system/gallery/assets/social-dropbox-stroke.svg +5 -0
  319. package/src/modules/design_system/gallery/assets/social-facebook-filled.svg +4 -0
  320. package/src/modules/design_system/gallery/assets/social-facebook-stroke.svg +10 -0
  321. package/src/modules/design_system/gallery/assets/social-github-filled.svg +4 -0
  322. package/src/modules/design_system/gallery/assets/social-github-stroke.svg +4 -0
  323. package/src/modules/design_system/gallery/assets/social-google-filled.svg +7 -0
  324. package/src/modules/design_system/gallery/assets/social-google-stroke.svg +7 -0
  325. package/src/modules/design_system/gallery/assets/social-linkedin-filled.svg +4 -0
  326. package/src/modules/design_system/gallery/assets/social-linkedin-stroke.svg +4 -0
  327. package/src/modules/design_system/gallery/assets/social-x-filled.svg +4 -0
  328. package/src/modules/design_system/gallery/assets/social-x-stroke.svg +4 -0
  329. package/src/modules/design_system/gallery/assets/style-studio-product.png +0 -0
  330. package/src/modules/design_system/gallery/assets/upload-images.ts +5 -0
  331. package/src/modules/design_system/gallery/components/BrandStylePreview.tsx +94 -0
  332. package/src/modules/design_system/gallery/components/CodeSnippet.tsx +34 -34
  333. package/src/modules/design_system/gallery/components/ColorPlayground.tsx +324 -0
  334. package/src/modules/design_system/gallery/components/ColorStudioCompositions.tsx +96 -0
  335. package/src/modules/design_system/gallery/components/ColorStudioSpecimen.tsx +164 -0
  336. package/src/modules/design_system/gallery/components/CompactEntrySpecimen.tsx +65 -0
  337. package/src/modules/design_system/gallery/components/ComponentIndex.tsx +47 -0
  338. package/src/modules/design_system/gallery/components/DesignSystemHome.tsx +66 -0
  339. package/src/modules/design_system/gallery/components/EntryCard.tsx +52 -37
  340. package/src/modules/design_system/gallery/components/EntryHeader.tsx +80 -0
  341. package/src/modules/design_system/gallery/components/FamilyEntryPreview.tsx +22 -0
  342. package/src/modules/design_system/gallery/components/FoundationGuide.tsx +43 -0
  343. package/src/modules/design_system/gallery/components/GalleryLink.tsx +19 -0
  344. package/src/modules/design_system/gallery/components/GalleryNavigation.tsx +86 -0
  345. package/src/modules/design_system/gallery/components/GalleryShell.tsx +149 -63
  346. package/src/modules/design_system/gallery/components/IconsBrowser.tsx +40 -0
  347. package/src/modules/design_system/gallery/components/SourceLibrary.tsx +90 -0
  348. package/src/modules/design_system/gallery/components/StyleAgents.tsx +115 -0
  349. package/src/modules/design_system/gallery/components/ThemeTokenReference.tsx +76 -0
  350. package/src/modules/design_system/gallery/components/VariantPreview.tsx +2 -2
  351. package/src/modules/design_system/gallery/components/colorPreview.ts +63 -0
  352. package/src/modules/design_system/gallery/components/colorStudio.ts +260 -0
  353. package/src/modules/design_system/gallery/components/styleAgentBranding.ts +42 -0
  354. package/src/modules/design_system/gallery/components/themeTokens.ts +26 -0
  355. package/src/modules/design_system/gallery/demos/ai-product-code.generated.ts +3 -0
  356. package/src/modules/design_system/gallery/demos/ai-product.tsx +188 -0
  357. package/src/modules/design_system/gallery/demos/buttons.tsx +331 -0
  358. package/src/modules/design_system/gallery/demos/cryptocurrency.tsx +1943 -0
  359. package/src/modules/design_system/gallery/demos/feeds-code.generated.ts +4 -0
  360. package/src/modules/design_system/gallery/demos/feeds.tsx +82 -0
  361. package/src/modules/design_system/gallery/demos/file-upload.tsx +61 -0
  362. package/src/modules/design_system/gallery/demos/foundation-reference-data.ts +4872 -0
  363. package/src/modules/design_system/gallery/demos/foundation-references.tsx +140 -0
  364. package/src/modules/design_system/gallery/demos/key-components-code.generated.ts +3 -0
  365. package/src/modules/design_system/gallery/demos/key-components.tsx +106 -0
  366. package/src/modules/design_system/gallery/demos/marketing-controls-code.generated.ts +3 -0
  367. package/src/modules/design_system/gallery/demos/marketing-controls.tsx +92 -0
  368. package/src/modules/design_system/gallery/demos/marketing-widgets-code.generated.ts +3 -0
  369. package/src/modules/design_system/gallery/demos/marketing-widgets.tsx +189 -0
  370. package/src/modules/design_system/gallery/demos/menu-fixtures.tsx +48 -0
  371. package/src/modules/design_system/gallery/demos/menu-sources.ts +5 -0
  372. package/src/modules/design_system/gallery/demos/menus.tsx +122 -0
  373. package/src/modules/design_system/gallery/demos/rating-reviews.tsx +44 -0
  374. package/src/modules/design_system/gallery/demos/registered-icons.tsx +117 -0
  375. package/src/modules/design_system/gallery/demos/selection-cards.tsx +97 -0
  376. package/src/modules/design_system/gallery/demos/shell-code.generated.ts +3 -0
  377. package/src/modules/design_system/gallery/demos/shell.tsx +183 -0
  378. package/src/modules/design_system/gallery/demos/source-artwork.tsx +88 -0
  379. package/src/modules/design_system/gallery/demos/source-filters-code.generated.ts +3 -0
  380. package/src/modules/design_system/gallery/demos/source-filters.tsx +119 -0
  381. package/src/modules/design_system/gallery/demos/source-icons.tsx +62 -0
  382. package/src/modules/design_system/gallery/demos/table-cells-code.generated.ts +3 -0
  383. package/src/modules/design_system/gallery/demos/table-cells.tsx +144 -0
  384. package/src/modules/design_system/gallery/demos/text-inputs.tsx +90 -0
  385. package/src/modules/design_system/gallery/demos/time-picker-code.generated.ts +5 -0
  386. package/src/modules/design_system/gallery/demos/time-picker.tsx +31 -0
  387. package/src/modules/design_system/gallery/entries/banners.tsx +143 -94
  388. package/src/modules/design_system/gallery/entries/buttons-snippets.ts +432 -0
  389. package/src/modules/design_system/gallery/entries/buttons.tsx +125 -196
  390. package/src/modules/design_system/gallery/entries/charts.tsx +545 -233
  391. package/src/modules/design_system/gallery/entries/dates.tsx +171 -3
  392. package/src/modules/design_system/gallery/entries/detail.tsx +142 -115
  393. package/src/modules/design_system/gallery/entries/display.tsx +1691 -319
  394. package/src/modules/design_system/gallery/entries/feedback.tsx +1082 -169
  395. package/src/modules/design_system/gallery/entries/filters.tsx +238 -143
  396. package/src/modules/design_system/gallery/entries/foundations.tsx +404 -61
  397. package/src/modules/design_system/gallery/entries/icons.tsx +31 -117
  398. package/src/modules/design_system/gallery/entries/inputs-snippets.ts +156 -0
  399. package/src/modules/design_system/gallery/entries/inputs.tsx +2146 -503
  400. package/src/modules/design_system/gallery/entries/library.tsx +16 -0
  401. package/src/modules/design_system/gallery/entries/messages.tsx +114 -106
  402. package/src/modules/design_system/gallery/entries/navigation.tsx +782 -192
  403. package/src/modules/design_system/gallery/entries/notifications.tsx +145 -120
  404. package/src/modules/design_system/gallery/entries/overlays.tsx +696 -280
  405. package/src/modules/design_system/gallery/entries/scaffolding.tsx +1192 -158
  406. package/src/modules/design_system/gallery/entries/schedule.tsx +72 -58
  407. package/src/modules/design_system/gallery/presentation.ts +106 -0
  408. package/src/modules/design_system/gallery/registry.ts +8 -6
  409. package/src/modules/design_system/gallery/source-library.generated.ts +2 -0
  410. package/src/modules/design_system/i18n/de.json +7112 -3
  411. package/src/modules/design_system/i18n/en.json +7112 -3
  412. package/src/modules/design_system/i18n/es.json +7112 -3
  413. package/src/modules/design_system/i18n/ko.json +7112 -3
  414. package/src/modules/design_system/i18n/pl.json +7112 -3
  415. package/src/modules/push_notifications/AGENTS.md +9 -5
  416. package/src/modules/push_notifications/lib/queue.ts +15 -44
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/customers/backend/customers/people/%5Bid%5D/page.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { extensionPoints } from '@open-mercato/core/modules/customers/extension-points'\nimport Link from 'next/link'\nimport { useRouter, useSearchParams } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { apiCallOrThrow, readApiResultOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'\nimport { mapCrudServerErrorToFormErrors } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { E } from '#generated/entities.ids.generated'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport {\n ActivitiesSection,\n} from '../../../../components/detail/ActivitiesSection'\nimport {\n NotesSection,\n type CommentSummary,\n type SectionAction,\n RecordNotFoundState,\n ErrorMessage,\n} from '@open-mercato/ui/backend/detail'\nimport {\n TagsSection,\n type TagOption,\n} from '../../../../components/detail/TagsSection'\nimport { DealsSection } from '../../../../components/detail/DealsSection'\nimport { AddressesSection } from '../../../../components/detail/AddressesSection'\nimport { TasksSection } from '../../../../components/detail/TasksSection'\nimport { PersonHighlights } from '../../../../components/detail/PersonHighlights'\nimport {\n renderLinkedInDisplay,\n renderTwitterDisplay,\n renderMultilineMarkdownDisplay,\n InlineDictionaryEditor,\n} from '../../../../components/detail/InlineEditors'\nimport { DetailFieldsSection, type DetailFieldConfig } from '@open-mercato/ui/backend/detail'\nimport { isValidSocialUrl } from '@open-mercato/core/modules/customers/lib/detailHelpers'\nimport type { ActivitySummary, DealSummary, TagSummary, TodoLinkSummary } from '../../../../components/detail/types'\nimport { CustomDataSection } from '../../../../components/detail/CustomDataSection'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { normalizeCustomFieldSubmitValue } from '../../../../components/detail/customFieldUtils'\nimport { renderDictionaryColor, renderDictionaryIcon } from '@open-mercato/core/modules/dictionaries/components/dictionaryAppearance'\nimport { ICON_SUGGESTIONS } from '../../../../lib/dictionaries'\nimport { createCustomerNotesAdapter } from '../../../../components/detail/notesAdapter'\nimport { readMarkdownPreferenceCookie, writeMarkdownPreferenceCookie } from '../../../../lib/markdownPreference'\nimport { InjectionSpot, useInjectionWidgets } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { DetailTabsLayout } from '../../../../components/detail/DetailTabsLayout'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { SendObjectMessageDialog } from '@open-mercato/ui/backend/messages'\n\ntype PersonOverview = {\n person: {\n id: string\n displayName: string\n description?: string | null\n primaryEmail?: string | null\n primaryPhone?: string | null\n status?: string | null\n lifecycleStage?: string | null\n source?: string | null\n nextInteractionAt?: string | null\n nextInteractionName?: string | null\n nextInteractionRefId?: string | null\n nextInteractionIcon?: string | null\n nextInteractionColor?: string | null\n organizationId?: string | null\n updatedAt?: string | null\n }\n profile: {\n id: string\n firstName?: string | null\n lastName?: string | null\n preferredName?: string | null\n jobTitle?: string | null\n department?: string | null\n seniority?: string | null\n timezone?: string | null\n linkedInUrl?: string | null\n twitterUrl?: string | null\n companyEntityId?: string | null\n } | null\n customFields: Record<string, unknown>\n tags: TagSummary[]\n comments: CommentSummary[]\n activities: ActivitySummary[]\n deals: DealSummary[]\n todos: TodoLinkSummary[]\n viewer?: {\n userId: string | null\n name?: string | null\n email?: string | null\n } | null\n}\n\ntype SectionKey = 'notes' | 'activities' | 'deals' | 'addresses' | 'tasks' | string\n\ntype ProfileEditableField = 'firstName' | 'lastName' | 'jobTitle' | 'department' | 'linkedInUrl' | 'twitterUrl'\n\n\nexport default function CustomerPersonDetailPage({ params }: { params?: { id?: string } }) {\n const id = params?.id\n const t = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const detailTranslator = React.useMemo(() => createTranslatorWithFallback(t), [t])\n const notesAdapter = React.useMemo(() => createCustomerNotesAdapter(detailTranslator), [detailTranslator])\n const router = useRouter()\n const searchParams = useSearchParams()\n const initialTab = React.useMemo(() => {\n const raw = searchParams?.get('tab')\n if (raw === 'notes' || raw === 'activities' || raw === 'deals' || raw === 'addresses' || raw === 'tasks') {\n return raw\n }\n return 'notes'\n }, [searchParams])\n const [data, setData] = React.useState<PersonOverview | null>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [isNotFound, setIsNotFound] = React.useState(false)\n const [activeTab, setActiveTab] = React.useState<SectionKey>(initialTab)\n const [sectionAction, setSectionAction] = React.useState<SectionAction | null>(null)\n const [isDeleting, setIsDeleting] = React.useState(false)\n\n const handleSectionActionChange = React.useCallback((action: SectionAction | null) => {\n setSectionAction(action)\n }, [])\n\n const handleSectionAction = React.useCallback(() => {\n if (!sectionAction || sectionAction.disabled) return\n sectionAction.onClick()\n }, [sectionAction])\n\n React.useEffect(() => {\n setSectionAction(null)\n }, [activeTab])\n const validators = React.useMemo(() => ({\n email: (value: string) => {\n if (!value) return null\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n return emailRegex.test(value) ? null : t('customers.people.detail.inline.emailInvalid')\n },\n phone: (value: string) => {\n if (!value) return null\n return value.length >= 3 ? null : t('customers.people.detail.inline.phoneInvalid')\n },\n displayName: (value: string) => {\n const trimmed = value.trim()\n return trimmed.length ? null : t('customers.people.form.displayName.error')\n },\n linkedInUrl: (value: string) => {\n if (!value) return null\n const candidate = value.trim()\n return isValidSocialUrl(candidate, { hosts: ['linkedin.com'], pathRequired: true })\n ? null\n : t('customers.people.detail.inline.linkedInInvalid')\n },\n twitterUrl: (value: string) => {\n if (!value) return null\n const candidate = value.trim()\n return isValidSocialUrl(candidate, { hosts: ['twitter.com', 'x.com'], pathRequired: true })\n ? null\n : t('customers.people.detail.inline.twitterInvalid')\n },\n }), [t])\n\n const personId = data?.person?.id ?? null\n const mutationContextId = React.useMemo(\n () => (personId ? `customer-person:${personId}` : `customer-person:${id ?? 'pending'}`),\n [id, personId],\n )\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n personId?: string | null\n resourceKind: string\n resourceId?: string\n data: PersonOverview | null\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: mutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n const injectionContext = React.useMemo(\n () => ({\n formId: mutationContextId,\n personId,\n resourceKind: 'customers.person',\n resourceId: personId ?? (id ?? undefined),\n data,\n retryLastMutation,\n }),\n [data, id, mutationContextId, personId, retryLastMutation],\n )\n const runMutationWithContext = React.useCallback(\n async <T,>(operation: () => Promise<T>, mutationPayload?: Record<string, unknown>): Promise<T> => {\n return runMutation({\n operation,\n mutationPayload,\n context: injectionContext,\n })\n },\n [injectionContext, runMutation],\n )\n const { widgets: injectedTabWidgets } = useInjectionWidgets('customers.person.detail:tabs', {\n context: injectionContext,\n triggerOnLoad: true,\n })\n const injectedTabs = React.useMemo(\n () =>\n (injectedTabWidgets ?? [])\n .filter((widget) => (widget.placement?.kind ?? 'tab') === 'tab')\n .map((widget) => {\n const id = widget.placement?.groupId ?? widget.widgetId\n const label = widget.placement?.groupLabel ?? widget.module.metadata.title\n const priority = typeof widget.placement?.priority === 'number' ? widget.placement.priority : 0\n const render = () => (\n <widget.module.Widget\n context={injectionContext}\n data={data}\n onDataChange={(next) => setData(next as PersonOverview)}\n />\n )\n return { id, label, priority, render }\n })\n .sort((a, b) => b.priority - a.priority),\n [data, injectedTabWidgets, injectionContext],\n )\n const injectedTabMap = React.useMemo(() => new Map(injectedTabs.map((tab) => [tab.id, tab.render])), [injectedTabs])\n\n const tabs = React.useMemo(\n () => [\n { id: 'notes' as const, label: t('customers.people.detail.tabs.notes') },\n { id: 'activities' as const, label: t('customers.people.detail.tabs.activities') },\n { id: 'deals' as const, label: t('customers.people.detail.tabs.deals') },\n { id: 'addresses' as const, label: t('customers.people.detail.tabs.addresses') },\n { id: 'tasks' as const, label: t('customers.people.detail.tabs.tasks') },\n ...injectedTabs.map((tab) => ({ id: tab.id as SectionKey, label: tab.label })),\n ],\n [injectedTabs, t]\n )\n\n const personName = React.useMemo(\n () => (data?.person?.displayName ? data.person.displayName : t('customers.people.list.deleteFallbackName')),\n [data?.person?.displayName, t]\n )\n\n const dealsScope = React.useMemo(\n () => (personId ? ({ kind: 'person', entityId: personId } as const) : null),\n [personId],\n )\n const dealSelectOptions = React.useMemo(\n () =>\n Array.isArray(data?.deals)\n ? data.deals\n .map((deal) => {\n if (!deal || typeof deal !== 'object') return null\n const record = deal as Record<string, unknown>\n const id = typeof record.id === 'string' ? record.id : ''\n if (!id) return null\n const rawTitle = typeof record.title === 'string' ? record.title.trim() : ''\n const label = rawTitle.length ? rawTitle : id\n return { id, label }\n })\n .filter((option): option is { id: string; label: string } => option !== null)\n : [],\n [data?.deals],\n )\n const handleNotesLoadingChange = React.useCallback(() => {}, [])\n\n const handleActivitiesLoadingChange = React.useCallback(() => {}, [])\n\n const handleDealsLoadingChange = React.useCallback(() => {}, [])\n\n const handleAddressesLoadingChange = React.useCallback(() => {}, [])\n\n const handleTasksLoadingChange = React.useCallback(() => {}, [])\n\n const initialLoadDoneRef = React.useRef(false)\n const loadData = React.useCallback(async () => {\n if (!id) {\n setIsNotFound(true)\n setIsLoading(false)\n return\n }\n if (!initialLoadDoneRef.current) {\n setIsLoading(true)\n }\n setError(null)\n setIsNotFound(false)\n try {\n const payload = await readApiResultOrThrow<PersonOverview>(\n `/api/customers/people/${encodeURIComponent(id)}?include=todos`,\n undefined,\n { errorMessage: t('customers.people.detail.error.load') },\n )\n setData(payload as PersonOverview)\n } catch (err) {\n if ((err as { status?: number }).status === 404) {\n setIsNotFound(true)\n } else {\n const message = err instanceof Error ? err.message : t('customers.people.detail.error.load')\n setError(message)\n }\n if (!initialLoadDoneRef.current) setData(null)\n } finally {\n setIsLoading(false)\n initialLoadDoneRef.current = true\n }\n }, [id, t])\n\n React.useEffect(() => {\n loadData().catch(() => {})\n }, [loadData])\n\n const savePerson = React.useCallback(\n async (patch: Record<string, unknown>, apply: (prev: PersonOverview) => PersonOverview) => {\n if (!data) return\n const payload = { id: data.person.id, ...patch }\n const result = await runMutationWithContext(\n () => withScopedApiRequestHeaders(\n buildOptimisticLockHeader((data?.person as { updatedAt?: string } | undefined)?.updatedAt),\n () => apiCallOrThrow<{ ok?: boolean; updatedAt?: string | null }>(\n '/api/customers/people',\n {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n },\n { errorMessage: t('customers.people.detail.inline.error') },\n ),\n ),\n payload,\n )\n // Refresh the optimistic-lock token so the next sequential inline edit does not\n // send a stale updatedAt and falsely 409 (#2055, default-ON locking).\n const nextUpdatedAt = result?.result?.updatedAt ?? null\n setData((prev) => {\n if (!prev) return prev\n const applied = apply(prev)\n return nextUpdatedAt\n ? { ...applied, person: { ...applied.person, updatedAt: nextUpdatedAt } }\n : applied\n })\n },\n [data, runMutationWithContext, t]\n )\n\n const updateDisplayName = React.useCallback(\n async (next: string | null) => {\n const send = typeof next === 'string' ? next : ''\n await savePerson(\n { displayName: send },\n (prev) => ({\n ...prev,\n person: {\n ...prev.person,\n displayName: next && next.length ? next : prev.person.displayName,\n },\n })\n )\n },\n [savePerson]\n )\n\n const updateProfileField = React.useCallback(\n async (field: ProfileEditableField, next: string | null) => {\n const send = typeof next === 'string' ? next : ''\n await savePerson(\n { [field]: send },\n (prev) => {\n if (!prev.profile) return prev\n const nextValue = next && next.length ? next : null\n return {\n ...prev,\n profile: {\n ...prev.profile,\n [field]: nextValue,\n },\n }\n }\n )\n },\n [savePerson]\n )\n\n const handleDelete = React.useCallback(async () => {\n if (!personId) return\n const confirmed = await confirm({\n title: t('customers.people.list.deleteConfirm', undefined, { name: personName }),\n variant: 'destructive',\n })\n if (!confirmed) return\n setIsDeleting(true)\n try {\n await runMutationWithContext(\n () => withScopedApiRequestHeaders(\n buildOptimisticLockHeader((data?.person as { updatedAt?: string } | undefined)?.updatedAt),\n () => apiCallOrThrow(\n `/api/customers/people?id=${encodeURIComponent(personId)}`,\n {\n method: 'DELETE',\n headers: { 'content-type': 'application/json' },\n },\n { errorMessage: t('customers.people.list.deleteError') },\n ),\n ),\n { id: personId },\n )\n flash(t('customers.people.list.deleteSuccess'), 'success')\n router.push('/backend/customers/people')\n } catch (err) {\n const message = err instanceof Error ? err.message : t('customers.people.list.deleteError')\n flash(message, 'error')\n } finally {\n setIsDeleting(false)\n }\n }, [confirm, personId, personName, router, runMutationWithContext, t])\n\n const handleTagsChange = React.useCallback((nextTags: TagOption[]) => {\n setData((prev) => (prev ? { ...prev, tags: nextTags } : prev))\n }, [])\n \n const handleCustomFieldsSubmit = React.useCallback(\n async (values: Record<string, unknown>) => {\n if (!data) {\n throw new Error(t('customers.people.detail.inline.error'))\n }\n const customPayload = collectCustomFieldValues(values, {\n transform: (value) => normalizeCustomFieldSubmitValue(value),\n })\n const prefixed: Record<string, unknown> = {}\n for (const [fieldId, value] of Object.entries(customPayload)) {\n prefixed[`cf_${fieldId}`] = value\n }\n if (!Object.keys(customPayload).length) {\n flash(t('ui.forms.flash.saveSuccess'), 'success')\n return\n }\n try {\n const payload = {\n id: data.person.id,\n customFields: customPayload,\n }\n await runMutationWithContext(\n () => withScopedApiRequestHeaders(\n buildOptimisticLockHeader((data?.person as { updatedAt?: string } | undefined)?.updatedAt),\n () => apiCallOrThrow(\n '/api/customers/people',\n {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n },\n { errorMessage: t('customers.people.detail.inline.error') },\n ),\n ),\n payload,\n )\n } catch (err) {\n const { message: helperMessage, fieldErrors } = mapCrudServerErrorToFormErrors(err)\n const mappedErrors = fieldErrors\n ? Object.entries(fieldErrors).reduce<Record<string, string>>((acc, [key, value]) => {\n const formKey = key.startsWith('cf_') ? key : `cf_${key}`\n acc[formKey] = value\n return acc\n }, {})\n : undefined\n const error = new Error(helperMessage ?? t('customers.people.detail.inline.error')) as Error & {\n fieldErrors?: Record<string, string>\n }\n if (mappedErrors && Object.keys(mappedErrors).length) error.fieldErrors = mappedErrors\n throw error\n }\n setData((prev) => {\n if (!prev) return prev\n const nextCustomFields = { ...prefixed }\n return { ...prev, customFields: nextCustomFields }\n })\n flash(t('ui.forms.flash.saveSuccess'), 'success')\n },\n [data, runMutationWithContext, t]\n )\n \n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <div className=\"flex h-[50vh] flex-col items-center justify-center gap-2 text-muted-foreground\">\n <Spinner className=\"h-6 w-6\" />\n <span>{t('customers.people.detail.loading')}</span>\n </div>\n </PageBody>\n </Page>\n )\n }\n \n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('customers.people.detail.error.notFound', 'Person not found.')}\n backHref=\"/backend/customers/people\"\n backLabel={t('customers.people.detail.actions.backToList', 'Back to people')}\n />\n </PageBody>\n </Page>\n )\n }\n\n if (error || !data || !personId) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage\n label={error ?? t('customers.people.detail.error.notFound', 'Person not found.')}\n action={\n <Button asChild variant=\"outline\" size=\"sm\">\n <Link href=\"/backend/customers/people\">\n {t('customers.people.detail.actions.backToList', 'Back to people')}\n </Link>\n </Button>\n }\n />\n </PageBody>\n </Page>\n )\n }\n \n const { person, profile } = data\n \n const detailFields: DetailFieldConfig[] = [\n {\n key: 'displayName',\n kind: 'text',\n label: t('customers.people.detail.fields.displayName'),\n value: person.displayName,\n placeholder: t('customers.people.form.displayName.placeholder'),\n emptyLabel: t('customers.people.detail.noValue'),\n validator: validators.displayName,\n onSave: updateDisplayName,\n },\n {\n key: 'firstName',\n kind: 'text',\n label: t('customers.people.form.firstName'),\n value: profile?.firstName ?? null,\n placeholder: t('customers.people.form.firstName'),\n emptyLabel: t('customers.people.detail.noValue'),\n onSave: (next) => updateProfileField('firstName', next),\n },\n {\n key: 'lastName',\n kind: 'text',\n label: t('customers.people.form.lastName'),\n value: profile?.lastName ?? null,\n placeholder: t('customers.people.form.lastName'),\n emptyLabel: t('customers.people.detail.noValue'),\n onSave: (next) => updateProfileField('lastName', next),\n },\n {\n key: 'jobTitle',\n kind: 'custom',\n label: t('customers.people.form.jobTitle'),\n emptyLabel: t('customers.people.detail.noValue'),\n render: () => (\n <InlineDictionaryEditor\n label={t('customers.people.form.jobTitle')}\n value={profile?.jobTitle ?? null}\n emptyLabel={t('customers.people.detail.noValue')}\n kind=\"job-titles\"\n onSave={async (next) => updateProfileField('jobTitle', next)}\n selectClassName=\"h-9 w-full rounded border px-3 text-sm\"\n variant=\"muted\"\n activateOnClick\n />\n ),\n },\n {\n key: 'lifecycleStage',\n kind: 'custom',\n label: t('customers.people.detail.fields.lifecycleStage'),\n emptyLabel: t('customers.people.detail.noValue'),\n render: () => (\n <InlineDictionaryEditor\n label={t('customers.people.detail.fields.lifecycleStage')}\n value={person.lifecycleStage ?? null}\n emptyLabel={t('customers.people.detail.noValue')}\n kind=\"lifecycle-stages\"\n onSave={async (next) => {\n const send = typeof next === 'string' ? next : ''\n await savePerson(\n { lifecycleStage: send },\n (prev) => ({\n ...prev,\n person: { ...prev.person, lifecycleStage: next && next.length ? next : null },\n })\n )\n }}\n selectClassName=\"h-9 w-full rounded border px-3 text-sm\"\n variant=\"muted\"\n activateOnClick\n />\n ),\n },\n {\n key: 'source',\n kind: 'custom',\n label: t('customers.people.form.source'),\n emptyLabel: t('customers.people.detail.noValue'),\n render: () => (\n <InlineDictionaryEditor\n label={t('customers.people.form.source')}\n value={person.source ?? null}\n emptyLabel={t('customers.people.detail.noValue')}\n kind=\"sources\"\n onSave={async (next) => {\n const send = typeof next === 'string' ? next : ''\n await savePerson(\n { source: send },\n (prev) => ({\n ...prev,\n person: { ...prev.person, source: next && next.length ? next : null },\n })\n )\n }}\n selectClassName=\"h-9 w-full rounded border px-3 text-sm\"\n variant=\"muted\"\n activateOnClick\n />\n ),\n },\n {\n key: 'description',\n kind: 'multiline',\n label: t('customers.people.form.description'),\n value: person.description ?? null,\n placeholder: t('customers.people.form.description'),\n emptyLabel: t('customers.people.detail.noValue'),\n gridClassName: 'sm:col-span-2 xl:col-span-3',\n renderDisplay: renderMultilineMarkdownDisplay,\n onSave: async (next) => {\n const send = typeof next === 'string' ? next : ''\n await savePerson(\n { description: send },\n (prev) => ({\n ...prev,\n person: { ...prev.person, description: next && next.length ? next : null },\n })\n )\n },\n },\n {\n key: 'department',\n kind: 'text',\n label: t('customers.people.detail.fields.department'),\n value: profile?.department ?? null,\n placeholder: t('customers.people.detail.fields.department'),\n emptyLabel: t('customers.people.detail.noValue'),\n onSave: (next) => updateProfileField('department', next),\n },\n {\n key: 'linkedInUrl',\n kind: 'text',\n label: t('customers.people.detail.fields.linkedIn'),\n value: profile?.linkedInUrl ?? null,\n placeholder: t('customers.people.detail.fields.linkedIn'),\n emptyLabel: t('customers.people.detail.noValue'),\n onSave: (next) => updateProfileField('linkedInUrl', next),\n inputType: 'url',\n validator: validators.linkedInUrl,\n renderDisplay: renderLinkedInDisplay,\n },\n {\n key: 'twitterUrl',\n kind: 'text',\n label: t('customers.people.detail.fields.twitter'),\n value: profile?.twitterUrl ?? null,\n placeholder: t('customers.people.detail.fields.twitter'),\n emptyLabel: t('customers.people.detail.noValue'),\n onSave: (next) => updateProfileField('twitterUrl', next),\n inputType: 'url',\n validator: validators.twitterUrl,\n renderDisplay: renderTwitterDisplay,\n },\n ]\n \n return (\n <Page>\n <PageBody className=\"space-y-8\">\n <PersonHighlights\n person={person}\n profile={profile}\n validators={{\n email: validators.email,\n phone: validators.phone,\n displayName: validators.displayName,\n }}\n utilityActions={(\n <SendObjectMessageDialog\n object={{\n entityModule: 'customers',\n entityType: 'person',\n entityId: personId,\n previewData: {\n title: person.displayName,\n subtitle: person.primaryEmail ?? undefined,\n metadata: {\n [t('customers.people.detail.highlights.primaryPhone')]: person.primaryPhone ?? '-',\n [t('customers.people.detail.fields.jobTitle')]: profile?.jobTitle ?? '-',\n },\n },\n }}\n viewHref={`/backend/customers/people/${personId}`}\n />\n )}\n onDisplayNameSave={updateDisplayName}\n onPrimaryEmailSave={async (next) => {\n const send = typeof next === 'string' ? next : ''\n await savePerson(\n { primaryEmail: send },\n (prev) => ({\n ...prev,\n person: {\n ...prev.person,\n primaryEmail: next && next.length ? next.toLowerCase() : null,\n },\n })\n )\n }}\n onPrimaryPhoneSave={async (next) => {\n const send = typeof next === 'string' ? next : ''\n await savePerson(\n { primaryPhone: send },\n (prev) => ({\n ...prev,\n person: {\n ...prev.person,\n primaryPhone: next && next.length ? next : null,\n },\n })\n )\n }}\n onStatusSave={async (next) => {\n const send = typeof next === 'string' ? next : ''\n await savePerson(\n { status: send },\n (prev) => ({\n ...prev,\n person: {\n ...prev.person,\n status: next && next.length ? next : null,\n },\n })\n )\n }}\n onNextInteractionSave={async (next) => {\n await savePerson(\n {\n nextInteraction: next\n ? {\n at: next.at,\n name: next.name,\n refId: next.refId ?? undefined,\n icon: next.icon ?? undefined,\n color: next.color ?? undefined,\n }\n : null,\n },\n (prev) => ({\n ...prev,\n person: {\n ...prev.person,\n nextInteractionAt: next ? next.at : null,\n nextInteractionName: next ? next.name || null : null,\n nextInteractionRefId: next ? next.refId || null : null,\n nextInteractionIcon: next ? next.icon || null : null,\n nextInteractionColor: next ? next.color || null : null,\n },\n })\n )\n }}\n onDelete={handleDelete}\n isDeleting={isDeleting}\n onCompanySave={async (next) => {\n const normalized = typeof next === 'string' && next.trim().length ? next.trim() : null\n await savePerson(\n { companyEntityId: normalized },\n (prev) => {\n if (!prev.profile) return prev\n return {\n ...prev,\n profile: {\n ...prev.profile,\n companyEntityId: normalized,\n },\n }\n }\n )\n }}\n />\n \n <DetailTabsLayout\n tabs={tabs}\n activeTab={activeTab}\n onTabChange={setActiveTab}\n sectionAction={sectionAction}\n onSectionAction={handleSectionAction}\n navAriaLabel={t('customers.people.detail.tabs.label', 'Person detail sections')}\n headerClassName=\"mb-1\"\n >\n {(() => {\n const injected = injectedTabMap.get(activeTab)\n if (injected) return injected()\n if (activeTab === 'notes') {\n return (\n <NotesSection\n entityId={personId}\n dealOptions={dealSelectOptions}\n emptyLabel={t('customers.people.detail.empty.comments')}\n viewerUserId={data.viewer?.userId ?? null}\n viewerName={data.viewer?.name ?? null}\n viewerEmail={data.viewer?.email ?? null}\n addActionLabel={t('customers.people.detail.notes.addLabel')}\n emptyState={{\n title: t('customers.people.detail.emptyState.notes.title'),\n actionLabel: t('customers.people.detail.emptyState.notes.action'),\n }}\n onActionChange={handleSectionActionChange}\n translator={detailTranslator}\n onLoadingChange={handleNotesLoadingChange}\n dataAdapter={notesAdapter}\n renderIcon={renderDictionaryIcon}\n renderColor={renderDictionaryColor}\n iconSuggestions={ICON_SUGGESTIONS}\n readMarkdownPreference={readMarkdownPreferenceCookie}\n writeMarkdownPreference={writeMarkdownPreferenceCookie}\n />\n )\n }\n if (activeTab === 'activities') {\n return (\n <ActivitiesSection\n entityId={personId}\n dealOptions={dealSelectOptions}\n defaultEntityId={personId ?? undefined}\n runGuardedMutation={runMutationWithContext}\n addActionLabel={t('customers.people.detail.activities.add')}\n emptyState={{\n title: t('customers.people.detail.emptyState.activities.title'),\n actionLabel: t('customers.people.detail.emptyState.activities.action'),\n }}\n onActionChange={handleSectionActionChange}\n onLoadingChange={handleActivitiesLoadingChange}\n />\n )\n }\n if (activeTab === 'deals') {\n return (\n <DealsSection\n scope={dealsScope}\n emptyLabel={t('customers.people.detail.empty.deals')}\n addActionLabel={t('customers.people.detail.actions.addDeal')}\n emptyState={{\n title: t('customers.people.detail.emptyState.deals.title'),\n actionLabel: t('customers.people.detail.emptyState.deals.action'),\n }}\n onActionChange={handleSectionActionChange}\n onLoadingChange={handleDealsLoadingChange}\n onDataRefresh={loadData}\n translator={detailTranslator}\n runGuardedMutation={runMutationWithContext}\n />\n )\n }\n if (activeTab === 'addresses') {\n return (\n <AddressesSection\n entityId={personId}\n emptyLabel={t('customers.people.detail.empty.addresses')}\n addActionLabel={t('customers.people.detail.addresses.add')}\n emptyState={{\n title: t('customers.people.detail.emptyState.addresses.title'),\n actionLabel: t('customers.people.detail.emptyState.addresses.action'),\n }}\n onActionChange={handleSectionActionChange}\n onLoadingChange={handleAddressesLoadingChange}\n translator={detailTranslator}\n />\n )\n }\n if (activeTab === 'tasks') {\n return (\n <TasksSection\n entityId={personId}\n initialTasks={data.todos}\n runGuardedMutation={runMutationWithContext}\n emptyLabel={t('customers.people.detail.empty.todos')}\n addActionLabel={t('customers.people.detail.tasks.add')}\n emptyState={{\n title: t('customers.people.detail.emptyState.tasks.title'),\n actionLabel: t('customers.people.detail.emptyState.tasks.action'),\n }}\n onActionChange={handleSectionActionChange}\n onLoadingChange={handleTasksLoadingChange}\n translator={detailTranslator}\n entityName={personName}\n dialogContextKey=\"customers.people.detail.tasks.dialog.context\"\n dialogContextFallback=\"This task will be linked to {{name}}\"\n />\n )\n }\n return null\n })()}\n </DetailTabsLayout>\n \n <div className=\"space-y-6\">\n <div className=\"space-y-3\">\n <h2 className=\"text-sm font-semibold\">{t('customers.people.detail.sections.details')}</h2>\n <DetailFieldsSection fields={detailFields} />\n <InjectionSpot\n spotId={extensionPoints.hosts.personLegacyDetails.spotId}\n context={injectionContext}\n data={data}\n onDataChange={(next) => setData(next as PersonOverview)}\n />\n </div>\n\n <CustomDataSection\n entityIds={[E.customers.customer_entity, E.customers.customer_person_profile]}\n values={data.customFields ?? {}}\n onSubmit={handleCustomFieldsSubmit}\n title={t('customers.people.detail.sections.customFields')}\n />\n \n <TagsSection\n entityId={data.person.id}\n tags={data.tags}\n onChange={handleTagsChange}\n isSubmitting={false}\n />\n </div>\n\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n }\n \n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { extensionPoints } from '@open-mercato/core/modules/customers/extension-points'\nimport Link from 'next/link'\nimport { useRouter, useSearchParams } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { apiCallOrThrow, readApiResultOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'\nimport { mapCrudServerErrorToFormErrors } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { E } from '#generated/entities.ids.generated'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport {\n ActivitiesSection,\n} from '../../../../components/detail/ActivitiesSection'\nimport {\n NotesSection,\n type CommentSummary,\n type SectionAction,\n RecordNotFoundState,\n ErrorMessage,\n} from '@open-mercato/ui/backend/detail'\nimport {\n TagsSection,\n type TagOption,\n} from '../../../../components/detail/TagsSection'\nimport { DealsSection } from '../../../../components/detail/DealsSection'\nimport { AddressesSection } from '../../../../components/detail/AddressesSection'\nimport { TasksSection } from '../../../../components/detail/TasksSection'\nimport { PersonHighlights } from '../../../../components/detail/PersonHighlights'\nimport {\n renderLinkedInDisplay,\n renderTwitterDisplay,\n renderMultilineMarkdownDisplay,\n InlineDictionaryEditor,\n} from '../../../../components/detail/InlineEditors'\nimport { DetailFieldsSection, type DetailFieldConfig } from '@open-mercato/ui/backend/detail'\nimport { isValidSocialUrl, isDetailNotFoundStatus } from '@open-mercato/core/modules/customers/lib/detailHelpers'\nimport type { ActivitySummary, DealSummary, TagSummary, TodoLinkSummary } from '../../../../components/detail/types'\nimport { CustomDataSection } from '../../../../components/detail/CustomDataSection'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { normalizeCustomFieldSubmitValue } from '../../../../components/detail/customFieldUtils'\nimport { renderDictionaryColor, renderDictionaryIcon } from '@open-mercato/core/modules/dictionaries/components/dictionaryAppearance'\nimport { ICON_SUGGESTIONS } from '../../../../lib/dictionaries'\nimport { createCustomerNotesAdapter } from '../../../../components/detail/notesAdapter'\nimport { readMarkdownPreferenceCookie, writeMarkdownPreferenceCookie } from '../../../../lib/markdownPreference'\nimport { InjectionSpot, useInjectionWidgets } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { DetailTabsLayout } from '../../../../components/detail/DetailTabsLayout'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { SendObjectMessageDialog } from '@open-mercato/ui/backend/messages'\n\ntype PersonOverview = {\n person: {\n id: string\n displayName: string\n description?: string | null\n primaryEmail?: string | null\n primaryPhone?: string | null\n status?: string | null\n lifecycleStage?: string | null\n source?: string | null\n nextInteractionAt?: string | null\n nextInteractionName?: string | null\n nextInteractionRefId?: string | null\n nextInteractionIcon?: string | null\n nextInteractionColor?: string | null\n organizationId?: string | null\n updatedAt?: string | null\n }\n profile: {\n id: string\n firstName?: string | null\n lastName?: string | null\n preferredName?: string | null\n jobTitle?: string | null\n department?: string | null\n seniority?: string | null\n timezone?: string | null\n linkedInUrl?: string | null\n twitterUrl?: string | null\n companyEntityId?: string | null\n } | null\n customFields: Record<string, unknown>\n tags: TagSummary[]\n comments: CommentSummary[]\n activities: ActivitySummary[]\n deals: DealSummary[]\n todos: TodoLinkSummary[]\n viewer?: {\n userId: string | null\n name?: string | null\n email?: string | null\n } | null\n}\n\ntype SectionKey = 'notes' | 'activities' | 'deals' | 'addresses' | 'tasks' | string\n\ntype ProfileEditableField = 'firstName' | 'lastName' | 'jobTitle' | 'department' | 'linkedInUrl' | 'twitterUrl'\n\n\nexport default function CustomerPersonDetailPage({ params }: { params?: { id?: string } }) {\n const id = params?.id\n const t = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const detailTranslator = React.useMemo(() => createTranslatorWithFallback(t), [t])\n const notesAdapter = React.useMemo(() => createCustomerNotesAdapter(detailTranslator), [detailTranslator])\n const router = useRouter()\n const searchParams = useSearchParams()\n const initialTab = React.useMemo(() => {\n const raw = searchParams?.get('tab')\n if (raw === 'notes' || raw === 'activities' || raw === 'deals' || raw === 'addresses' || raw === 'tasks') {\n return raw\n }\n return 'notes'\n }, [searchParams])\n const [data, setData] = React.useState<PersonOverview | null>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [isNotFound, setIsNotFound] = React.useState(false)\n const [activeTab, setActiveTab] = React.useState<SectionKey>(initialTab)\n const [sectionAction, setSectionAction] = React.useState<SectionAction | null>(null)\n const [isDeleting, setIsDeleting] = React.useState(false)\n\n const handleSectionActionChange = React.useCallback((action: SectionAction | null) => {\n setSectionAction(action)\n }, [])\n\n const handleSectionAction = React.useCallback(() => {\n if (!sectionAction || sectionAction.disabled) return\n sectionAction.onClick()\n }, [sectionAction])\n\n React.useEffect(() => {\n setSectionAction(null)\n }, [activeTab])\n const validators = React.useMemo(() => ({\n email: (value: string) => {\n if (!value) return null\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n return emailRegex.test(value) ? null : t('customers.people.detail.inline.emailInvalid')\n },\n phone: (value: string) => {\n if (!value) return null\n return value.length >= 3 ? null : t('customers.people.detail.inline.phoneInvalid')\n },\n displayName: (value: string) => {\n const trimmed = value.trim()\n return trimmed.length ? null : t('customers.people.form.displayName.error')\n },\n linkedInUrl: (value: string) => {\n if (!value) return null\n const candidate = value.trim()\n return isValidSocialUrl(candidate, { hosts: ['linkedin.com'], pathRequired: true })\n ? null\n : t('customers.people.detail.inline.linkedInInvalid')\n },\n twitterUrl: (value: string) => {\n if (!value) return null\n const candidate = value.trim()\n return isValidSocialUrl(candidate, { hosts: ['twitter.com', 'x.com'], pathRequired: true })\n ? null\n : t('customers.people.detail.inline.twitterInvalid')\n },\n }), [t])\n\n const personId = data?.person?.id ?? null\n const mutationContextId = React.useMemo(\n () => (personId ? `customer-person:${personId}` : `customer-person:${id ?? 'pending'}`),\n [id, personId],\n )\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n personId?: string | null\n resourceKind: string\n resourceId?: string\n data: PersonOverview | null\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: mutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n const injectionContext = React.useMemo(\n () => ({\n formId: mutationContextId,\n personId,\n resourceKind: 'customers.person',\n resourceId: personId ?? (id ?? undefined),\n data,\n retryLastMutation,\n }),\n [data, id, mutationContextId, personId, retryLastMutation],\n )\n const runMutationWithContext = React.useCallback(\n async <T,>(operation: () => Promise<T>, mutationPayload?: Record<string, unknown>): Promise<T> => {\n return runMutation({\n operation,\n mutationPayload,\n context: injectionContext,\n })\n },\n [injectionContext, runMutation],\n )\n const { widgets: injectedTabWidgets } = useInjectionWidgets('customers.person.detail:tabs', {\n context: injectionContext,\n triggerOnLoad: true,\n })\n const injectedTabs = React.useMemo(\n () =>\n (injectedTabWidgets ?? [])\n .filter((widget) => (widget.placement?.kind ?? 'tab') === 'tab')\n .map((widget) => {\n const id = widget.placement?.groupId ?? widget.widgetId\n const label = widget.placement?.groupLabel ?? widget.module.metadata.title\n const priority = typeof widget.placement?.priority === 'number' ? widget.placement.priority : 0\n const render = () => (\n <widget.module.Widget\n context={injectionContext}\n data={data}\n onDataChange={(next) => setData(next as PersonOverview)}\n />\n )\n return { id, label, priority, render }\n })\n .sort((a, b) => b.priority - a.priority),\n [data, injectedTabWidgets, injectionContext],\n )\n const injectedTabMap = React.useMemo(() => new Map(injectedTabs.map((tab) => [tab.id, tab.render])), [injectedTabs])\n\n const tabs = React.useMemo(\n () => [\n { id: 'notes' as const, label: t('customers.people.detail.tabs.notes') },\n { id: 'activities' as const, label: t('customers.people.detail.tabs.activities') },\n { id: 'deals' as const, label: t('customers.people.detail.tabs.deals') },\n { id: 'addresses' as const, label: t('customers.people.detail.tabs.addresses') },\n { id: 'tasks' as const, label: t('customers.people.detail.tabs.tasks') },\n ...injectedTabs.map((tab) => ({ id: tab.id as SectionKey, label: tab.label })),\n ],\n [injectedTabs, t]\n )\n\n const personName = React.useMemo(\n () => (data?.person?.displayName ? data.person.displayName : t('customers.people.list.deleteFallbackName')),\n [data?.person?.displayName, t]\n )\n\n const dealsScope = React.useMemo(\n () => (personId ? ({ kind: 'person', entityId: personId } as const) : null),\n [personId],\n )\n const dealSelectOptions = React.useMemo(\n () =>\n Array.isArray(data?.deals)\n ? data.deals\n .map((deal) => {\n if (!deal || typeof deal !== 'object') return null\n const record = deal as Record<string, unknown>\n const id = typeof record.id === 'string' ? record.id : ''\n if (!id) return null\n const rawTitle = typeof record.title === 'string' ? record.title.trim() : ''\n const label = rawTitle.length ? rawTitle : id\n return { id, label }\n })\n .filter((option): option is { id: string; label: string } => option !== null)\n : [],\n [data?.deals],\n )\n const handleNotesLoadingChange = React.useCallback(() => {}, [])\n\n const handleActivitiesLoadingChange = React.useCallback(() => {}, [])\n\n const handleDealsLoadingChange = React.useCallback(() => {}, [])\n\n const handleAddressesLoadingChange = React.useCallback(() => {}, [])\n\n const handleTasksLoadingChange = React.useCallback(() => {}, [])\n\n const initialLoadDoneRef = React.useRef(false)\n const loadData = React.useCallback(async () => {\n if (!id) {\n setIsNotFound(true)\n setIsLoading(false)\n return\n }\n if (!initialLoadDoneRef.current) {\n setIsLoading(true)\n }\n setError(null)\n setIsNotFound(false)\n try {\n const payload = await readApiResultOrThrow<PersonOverview>(\n `/api/customers/people/${encodeURIComponent(id)}?include=todos`,\n undefined,\n { errorMessage: t('customers.people.detail.error.load') },\n )\n setData(payload as PersonOverview)\n } catch (err) {\n if (isDetailNotFoundStatus((err as { status?: number }).status)) {\n setIsNotFound(true)\n } else {\n const message = err instanceof Error ? err.message : t('customers.people.detail.error.load')\n setError(message)\n }\n if (!initialLoadDoneRef.current) setData(null)\n } finally {\n setIsLoading(false)\n initialLoadDoneRef.current = true\n }\n }, [id, t])\n\n React.useEffect(() => {\n loadData().catch(() => {})\n }, [loadData])\n\n const savePerson = React.useCallback(\n async (patch: Record<string, unknown>, apply: (prev: PersonOverview) => PersonOverview) => {\n if (!data) return\n const payload = { id: data.person.id, ...patch }\n const result = await runMutationWithContext(\n () => withScopedApiRequestHeaders(\n buildOptimisticLockHeader((data?.person as { updatedAt?: string } | undefined)?.updatedAt),\n () => apiCallOrThrow<{ ok?: boolean; updatedAt?: string | null }>(\n '/api/customers/people',\n {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n },\n { errorMessage: t('customers.people.detail.inline.error') },\n ),\n ),\n payload,\n )\n // Refresh the optimistic-lock token so the next sequential inline edit does not\n // send a stale updatedAt and falsely 409 (#2055, default-ON locking).\n const nextUpdatedAt = result?.result?.updatedAt ?? null\n setData((prev) => {\n if (!prev) return prev\n const applied = apply(prev)\n return nextUpdatedAt\n ? { ...applied, person: { ...applied.person, updatedAt: nextUpdatedAt } }\n : applied\n })\n },\n [data, runMutationWithContext, t]\n )\n\n const updateDisplayName = React.useCallback(\n async (next: string | null) => {\n const send = typeof next === 'string' ? next : ''\n await savePerson(\n { displayName: send },\n (prev) => ({\n ...prev,\n person: {\n ...prev.person,\n displayName: next && next.length ? next : prev.person.displayName,\n },\n })\n )\n },\n [savePerson]\n )\n\n const updateProfileField = React.useCallback(\n async (field: ProfileEditableField, next: string | null) => {\n const send = typeof next === 'string' ? next : ''\n await savePerson(\n { [field]: send },\n (prev) => {\n if (!prev.profile) return prev\n const nextValue = next && next.length ? next : null\n return {\n ...prev,\n profile: {\n ...prev.profile,\n [field]: nextValue,\n },\n }\n }\n )\n },\n [savePerson]\n )\n\n const handleDelete = React.useCallback(async () => {\n if (!personId) return\n const confirmed = await confirm({\n title: t('customers.people.list.deleteConfirm', undefined, { name: personName }),\n variant: 'destructive',\n })\n if (!confirmed) return\n setIsDeleting(true)\n try {\n await runMutationWithContext(\n () => withScopedApiRequestHeaders(\n buildOptimisticLockHeader((data?.person as { updatedAt?: string } | undefined)?.updatedAt),\n () => apiCallOrThrow(\n `/api/customers/people?id=${encodeURIComponent(personId)}`,\n {\n method: 'DELETE',\n headers: { 'content-type': 'application/json' },\n },\n { errorMessage: t('customers.people.list.deleteError') },\n ),\n ),\n { id: personId },\n )\n flash(t('customers.people.list.deleteSuccess'), 'success')\n router.push('/backend/customers/people')\n } catch (err) {\n const message = err instanceof Error ? err.message : t('customers.people.list.deleteError')\n flash(message, 'error')\n } finally {\n setIsDeleting(false)\n }\n }, [confirm, personId, personName, router, runMutationWithContext, t])\n\n const handleTagsChange = React.useCallback((nextTags: TagOption[]) => {\n setData((prev) => (prev ? { ...prev, tags: nextTags } : prev))\n }, [])\n \n const handleCustomFieldsSubmit = React.useCallback(\n async (values: Record<string, unknown>) => {\n if (!data) {\n throw new Error(t('customers.people.detail.inline.error'))\n }\n const customPayload = collectCustomFieldValues(values, {\n transform: (value) => normalizeCustomFieldSubmitValue(value),\n })\n const prefixed: Record<string, unknown> = {}\n for (const [fieldId, value] of Object.entries(customPayload)) {\n prefixed[`cf_${fieldId}`] = value\n }\n if (!Object.keys(customPayload).length) {\n flash(t('ui.forms.flash.saveSuccess'), 'success')\n return\n }\n try {\n const payload = {\n id: data.person.id,\n customFields: customPayload,\n }\n await runMutationWithContext(\n () => withScopedApiRequestHeaders(\n buildOptimisticLockHeader((data?.person as { updatedAt?: string } | undefined)?.updatedAt),\n () => apiCallOrThrow(\n '/api/customers/people',\n {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n },\n { errorMessage: t('customers.people.detail.inline.error') },\n ),\n ),\n payload,\n )\n } catch (err) {\n const { message: helperMessage, fieldErrors } = mapCrudServerErrorToFormErrors(err)\n const mappedErrors = fieldErrors\n ? Object.entries(fieldErrors).reduce<Record<string, string>>((acc, [key, value]) => {\n const formKey = key.startsWith('cf_') ? key : `cf_${key}`\n acc[formKey] = value\n return acc\n }, {})\n : undefined\n const error = new Error(helperMessage ?? t('customers.people.detail.inline.error')) as Error & {\n fieldErrors?: Record<string, string>\n }\n if (mappedErrors && Object.keys(mappedErrors).length) error.fieldErrors = mappedErrors\n throw error\n }\n setData((prev) => {\n if (!prev) return prev\n const nextCustomFields = { ...prefixed }\n return { ...prev, customFields: nextCustomFields }\n })\n flash(t('ui.forms.flash.saveSuccess'), 'success')\n },\n [data, runMutationWithContext, t]\n )\n \n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <div className=\"flex h-[50vh] flex-col items-center justify-center gap-2 text-muted-foreground\">\n <Spinner className=\"h-6 w-6\" />\n <span>{t('customers.people.detail.loading')}</span>\n </div>\n </PageBody>\n </Page>\n )\n }\n \n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('customers.people.detail.error.notFound', 'Person not found.')}\n backHref=\"/backend/customers/people\"\n backLabel={t('customers.people.detail.actions.backToList', 'Back to people')}\n />\n </PageBody>\n </Page>\n )\n }\n\n if (error || !data || !personId) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage\n label={error ?? t('customers.people.detail.error.notFound', 'Person not found.')}\n action={\n <Button asChild variant=\"outline\" size=\"sm\">\n <Link href=\"/backend/customers/people\">\n {t('customers.people.detail.actions.backToList', 'Back to people')}\n </Link>\n </Button>\n }\n />\n </PageBody>\n </Page>\n )\n }\n \n const { person, profile } = data\n \n const detailFields: DetailFieldConfig[] = [\n {\n key: 'displayName',\n kind: 'text',\n label: t('customers.people.detail.fields.displayName'),\n value: person.displayName,\n placeholder: t('customers.people.form.displayName.placeholder'),\n emptyLabel: t('customers.people.detail.noValue'),\n validator: validators.displayName,\n onSave: updateDisplayName,\n },\n {\n key: 'firstName',\n kind: 'text',\n label: t('customers.people.form.firstName'),\n value: profile?.firstName ?? null,\n placeholder: t('customers.people.form.firstName'),\n emptyLabel: t('customers.people.detail.noValue'),\n onSave: (next) => updateProfileField('firstName', next),\n },\n {\n key: 'lastName',\n kind: 'text',\n label: t('customers.people.form.lastName'),\n value: profile?.lastName ?? null,\n placeholder: t('customers.people.form.lastName'),\n emptyLabel: t('customers.people.detail.noValue'),\n onSave: (next) => updateProfileField('lastName', next),\n },\n {\n key: 'jobTitle',\n kind: 'custom',\n label: t('customers.people.form.jobTitle'),\n emptyLabel: t('customers.people.detail.noValue'),\n render: () => (\n <InlineDictionaryEditor\n label={t('customers.people.form.jobTitle')}\n value={profile?.jobTitle ?? null}\n emptyLabel={t('customers.people.detail.noValue')}\n kind=\"job-titles\"\n onSave={async (next) => updateProfileField('jobTitle', next)}\n selectClassName=\"h-9 w-full rounded border px-3 text-sm\"\n variant=\"muted\"\n activateOnClick\n />\n ),\n },\n {\n key: 'lifecycleStage',\n kind: 'custom',\n label: t('customers.people.detail.fields.lifecycleStage'),\n emptyLabel: t('customers.people.detail.noValue'),\n render: () => (\n <InlineDictionaryEditor\n label={t('customers.people.detail.fields.lifecycleStage')}\n value={person.lifecycleStage ?? null}\n emptyLabel={t('customers.people.detail.noValue')}\n kind=\"lifecycle-stages\"\n onSave={async (next) => {\n const send = typeof next === 'string' ? next : ''\n await savePerson(\n { lifecycleStage: send },\n (prev) => ({\n ...prev,\n person: { ...prev.person, lifecycleStage: next && next.length ? next : null },\n })\n )\n }}\n selectClassName=\"h-9 w-full rounded border px-3 text-sm\"\n variant=\"muted\"\n activateOnClick\n />\n ),\n },\n {\n key: 'source',\n kind: 'custom',\n label: t('customers.people.form.source'),\n emptyLabel: t('customers.people.detail.noValue'),\n render: () => (\n <InlineDictionaryEditor\n label={t('customers.people.form.source')}\n value={person.source ?? null}\n emptyLabel={t('customers.people.detail.noValue')}\n kind=\"sources\"\n onSave={async (next) => {\n const send = typeof next === 'string' ? next : ''\n await savePerson(\n { source: send },\n (prev) => ({\n ...prev,\n person: { ...prev.person, source: next && next.length ? next : null },\n })\n )\n }}\n selectClassName=\"h-9 w-full rounded border px-3 text-sm\"\n variant=\"muted\"\n activateOnClick\n />\n ),\n },\n {\n key: 'description',\n kind: 'multiline',\n label: t('customers.people.form.description'),\n value: person.description ?? null,\n placeholder: t('customers.people.form.description'),\n emptyLabel: t('customers.people.detail.noValue'),\n gridClassName: 'sm:col-span-2 xl:col-span-3',\n renderDisplay: renderMultilineMarkdownDisplay,\n onSave: async (next) => {\n const send = typeof next === 'string' ? next : ''\n await savePerson(\n { description: send },\n (prev) => ({\n ...prev,\n person: { ...prev.person, description: next && next.length ? next : null },\n })\n )\n },\n },\n {\n key: 'department',\n kind: 'text',\n label: t('customers.people.detail.fields.department'),\n value: profile?.department ?? null,\n placeholder: t('customers.people.detail.fields.department'),\n emptyLabel: t('customers.people.detail.noValue'),\n onSave: (next) => updateProfileField('department', next),\n },\n {\n key: 'linkedInUrl',\n kind: 'text',\n label: t('customers.people.detail.fields.linkedIn'),\n value: profile?.linkedInUrl ?? null,\n placeholder: t('customers.people.detail.fields.linkedIn'),\n emptyLabel: t('customers.people.detail.noValue'),\n onSave: (next) => updateProfileField('linkedInUrl', next),\n inputType: 'url',\n validator: validators.linkedInUrl,\n renderDisplay: renderLinkedInDisplay,\n },\n {\n key: 'twitterUrl',\n kind: 'text',\n label: t('customers.people.detail.fields.twitter'),\n value: profile?.twitterUrl ?? null,\n placeholder: t('customers.people.detail.fields.twitter'),\n emptyLabel: t('customers.people.detail.noValue'),\n onSave: (next) => updateProfileField('twitterUrl', next),\n inputType: 'url',\n validator: validators.twitterUrl,\n renderDisplay: renderTwitterDisplay,\n },\n ]\n \n return (\n <Page>\n <PageBody className=\"space-y-8\">\n <PersonHighlights\n person={person}\n profile={profile}\n validators={{\n email: validators.email,\n phone: validators.phone,\n displayName: validators.displayName,\n }}\n utilityActions={(\n <SendObjectMessageDialog\n object={{\n entityModule: 'customers',\n entityType: 'person',\n entityId: personId,\n previewData: {\n title: person.displayName,\n subtitle: person.primaryEmail ?? undefined,\n metadata: {\n [t('customers.people.detail.highlights.primaryPhone')]: person.primaryPhone ?? '-',\n [t('customers.people.detail.fields.jobTitle')]: profile?.jobTitle ?? '-',\n },\n },\n }}\n viewHref={`/backend/customers/people/${personId}`}\n />\n )}\n onDisplayNameSave={updateDisplayName}\n onPrimaryEmailSave={async (next) => {\n const send = typeof next === 'string' ? next : ''\n await savePerson(\n { primaryEmail: send },\n (prev) => ({\n ...prev,\n person: {\n ...prev.person,\n primaryEmail: next && next.length ? next.toLowerCase() : null,\n },\n })\n )\n }}\n onPrimaryPhoneSave={async (next) => {\n const send = typeof next === 'string' ? next : ''\n await savePerson(\n { primaryPhone: send },\n (prev) => ({\n ...prev,\n person: {\n ...prev.person,\n primaryPhone: next && next.length ? next : null,\n },\n })\n )\n }}\n onStatusSave={async (next) => {\n const send = typeof next === 'string' ? next : ''\n await savePerson(\n { status: send },\n (prev) => ({\n ...prev,\n person: {\n ...prev.person,\n status: next && next.length ? next : null,\n },\n })\n )\n }}\n onNextInteractionSave={async (next) => {\n await savePerson(\n {\n nextInteraction: next\n ? {\n at: next.at,\n name: next.name,\n refId: next.refId ?? undefined,\n icon: next.icon ?? undefined,\n color: next.color ?? undefined,\n }\n : null,\n },\n (prev) => ({\n ...prev,\n person: {\n ...prev.person,\n nextInteractionAt: next ? next.at : null,\n nextInteractionName: next ? next.name || null : null,\n nextInteractionRefId: next ? next.refId || null : null,\n nextInteractionIcon: next ? next.icon || null : null,\n nextInteractionColor: next ? next.color || null : null,\n },\n })\n )\n }}\n onDelete={handleDelete}\n isDeleting={isDeleting}\n onCompanySave={async (next) => {\n const normalized = typeof next === 'string' && next.trim().length ? next.trim() : null\n await savePerson(\n { companyEntityId: normalized },\n (prev) => {\n if (!prev.profile) return prev\n return {\n ...prev,\n profile: {\n ...prev.profile,\n companyEntityId: normalized,\n },\n }\n }\n )\n }}\n />\n \n <DetailTabsLayout\n tabs={tabs}\n activeTab={activeTab}\n onTabChange={setActiveTab}\n sectionAction={sectionAction}\n onSectionAction={handleSectionAction}\n navAriaLabel={t('customers.people.detail.tabs.label', 'Person detail sections')}\n headerClassName=\"mb-1\"\n >\n {(() => {\n const injected = injectedTabMap.get(activeTab)\n if (injected) return injected()\n if (activeTab === 'notes') {\n return (\n <NotesSection\n entityId={personId}\n dealOptions={dealSelectOptions}\n emptyLabel={t('customers.people.detail.empty.comments')}\n viewerUserId={data.viewer?.userId ?? null}\n viewerName={data.viewer?.name ?? null}\n viewerEmail={data.viewer?.email ?? null}\n addActionLabel={t('customers.people.detail.notes.addLabel')}\n emptyState={{\n title: t('customers.people.detail.emptyState.notes.title'),\n actionLabel: t('customers.people.detail.emptyState.notes.action'),\n }}\n onActionChange={handleSectionActionChange}\n translator={detailTranslator}\n onLoadingChange={handleNotesLoadingChange}\n dataAdapter={notesAdapter}\n renderIcon={renderDictionaryIcon}\n renderColor={renderDictionaryColor}\n iconSuggestions={ICON_SUGGESTIONS}\n readMarkdownPreference={readMarkdownPreferenceCookie}\n writeMarkdownPreference={writeMarkdownPreferenceCookie}\n />\n )\n }\n if (activeTab === 'activities') {\n return (\n <ActivitiesSection\n entityId={personId}\n dealOptions={dealSelectOptions}\n defaultEntityId={personId ?? undefined}\n runGuardedMutation={runMutationWithContext}\n addActionLabel={t('customers.people.detail.activities.add')}\n emptyState={{\n title: t('customers.people.detail.emptyState.activities.title'),\n actionLabel: t('customers.people.detail.emptyState.activities.action'),\n }}\n onActionChange={handleSectionActionChange}\n onLoadingChange={handleActivitiesLoadingChange}\n />\n )\n }\n if (activeTab === 'deals') {\n return (\n <DealsSection\n scope={dealsScope}\n emptyLabel={t('customers.people.detail.empty.deals')}\n addActionLabel={t('customers.people.detail.actions.addDeal')}\n emptyState={{\n title: t('customers.people.detail.emptyState.deals.title'),\n actionLabel: t('customers.people.detail.emptyState.deals.action'),\n }}\n onActionChange={handleSectionActionChange}\n onLoadingChange={handleDealsLoadingChange}\n onDataRefresh={loadData}\n translator={detailTranslator}\n runGuardedMutation={runMutationWithContext}\n />\n )\n }\n if (activeTab === 'addresses') {\n return (\n <AddressesSection\n entityId={personId}\n emptyLabel={t('customers.people.detail.empty.addresses')}\n addActionLabel={t('customers.people.detail.addresses.add')}\n emptyState={{\n title: t('customers.people.detail.emptyState.addresses.title'),\n actionLabel: t('customers.people.detail.emptyState.addresses.action'),\n }}\n onActionChange={handleSectionActionChange}\n onLoadingChange={handleAddressesLoadingChange}\n translator={detailTranslator}\n />\n )\n }\n if (activeTab === 'tasks') {\n return (\n <TasksSection\n entityId={personId}\n initialTasks={data.todos}\n runGuardedMutation={runMutationWithContext}\n emptyLabel={t('customers.people.detail.empty.todos')}\n addActionLabel={t('customers.people.detail.tasks.add')}\n emptyState={{\n title: t('customers.people.detail.emptyState.tasks.title'),\n actionLabel: t('customers.people.detail.emptyState.tasks.action'),\n }}\n onActionChange={handleSectionActionChange}\n onLoadingChange={handleTasksLoadingChange}\n translator={detailTranslator}\n entityName={personName}\n dialogContextKey=\"customers.people.detail.tasks.dialog.context\"\n dialogContextFallback=\"This task will be linked to {{name}}\"\n />\n )\n }\n return null\n })()}\n </DetailTabsLayout>\n \n <div className=\"space-y-6\">\n <div className=\"space-y-3\">\n <h2 className=\"text-sm font-semibold\">{t('customers.people.detail.sections.details')}</h2>\n <DetailFieldsSection fields={detailFields} />\n <InjectionSpot\n spotId={extensionPoints.hosts.personLegacyDetails.spotId}\n context={injectionContext}\n data={data}\n onDataChange={(next) => setData(next as PersonOverview)}\n />\n </div>\n\n <CustomDataSection\n entityIds={[E.customers.customer_entity, E.customers.customer_person_profile]}\n values={data.customFields ?? {}}\n onSubmit={handleCustomFieldsSubmit}\n title={t('customers.people.detail.sections.customFields')}\n />\n \n <TagsSection\n entityId={data.person.id}\n tags={data.tags}\n onChange={handleTagsChange}\n isSubmitting={false}\n />\n </div>\n\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n }\n \n"],
5
+ "mappings": "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",
6
6
  "names": ["id", "error"]
7
7
  }
@@ -46,6 +46,7 @@ import {
46
46
  mapPersonOverviewToFormValues
47
47
  } from "../../../../components/formConfig.js";
48
48
  import { coerceDisplayName, coerceDisplayNameOrNull } from "../../../../lib/displayName.js";
49
+ import { isDetailNotFoundStatus } from "@open-mercato/core/modules/customers/lib/detailHelpers";
49
50
  import { createLogger } from "@open-mercato/shared/lib/logger";
50
51
  const logger = createLogger("customers");
51
52
  function PersonDetailV2Page({ params }) {
@@ -122,7 +123,7 @@ function PersonDetailV2Page({ params }) {
122
123
  const next = lockTokenOverride && payload?.person ? { ...payload, person: { ...payload.person, updatedAt: lockTokenOverride, updated_at: lockTokenOverride } } : payload;
123
124
  setData(next);
124
125
  } catch (err) {
125
- if (err.status === 404) {
126
+ if (isDetailNotFoundStatus(err.status)) {
126
127
  setIsNotFound(true);
127
128
  } else {
128
129
  const message = err instanceof Error ? err.message : t("customers.people.detail.error.load", "Failed to load person.");
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/customers/backend/customers/people-v2/%5Bid%5D/page.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { extensionPoints } from '@open-mercato/core/modules/customers/extension-points'\nimport Link from 'next/link'\nimport { useRouter, useSearchParams, usePathname } from 'next/navigation'\nimport { User, Hash, Users, Building2 } from 'lucide-react'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CrudForm } from '@open-mercato/ui/backend/CrudForm'\nimport { CollapsibleZoneLayout, type ZoneSectionDescriptor } from '@open-mercato/ui/backend/crud/CollapsibleZoneLayout'\nimport { useIsMobile } from '@open-mercato/ui/hooks/useIsMobile'\nimport { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { E } from '#generated/entities.ids.generated'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useOrganizationScopeDetail } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { AttachmentsSection, ErrorMessage, LoadingMessage, RecordNotFoundState, type SectionAction } from '@open-mercato/ui/backend/detail'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { InjectionSpot, useInjectionWidgets } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { buildRecordInjectionContext, useSetCurrentRecordInjectionContext } from '@open-mercato/ui/backend/injection/recordContext'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\n\nimport { ActivitiesSection } from '../../../../components/detail/ActivitiesSection'\nimport { PersonEmailThreadsTab } from '../../../../components/detail/PersonEmailThreadsTab'\nimport { ActivitiesCard } from '../../../../components/detail/ActivitiesCard'\nimport type { ActivityKind } from '../../../../components/detail/ActivitiesAddNewMenu'\nimport { DealsSection } from '../../../../components/detail/DealsSection'\nimport { TasksSection } from '../../../../components/detail/TasksSection'\nimport type { TagSummary } from '../../../../components/detail/types'\nimport { ScheduleActivityDialog, type ScheduleActivityEditData } from '../../../../components/detail/ScheduleActivityDialog'\nimport { PersonDetailHeader } from '../../../../components/detail/PersonDetailHeader'\nimport { ChangelogTab } from '../../../../components/detail/ChangelogTab'\nimport { PersonDetailTabs, resolveLegacyTab, type PersonTabId } from '../../../../components/detail/PersonDetailTabs'\nimport { AddressesSection } from '../../../../components/detail/AddressesSection'\nimport { PersonCompaniesSection } from '../../../../components/detail/PersonCompaniesSection'\nimport { MobilePersonDetail } from '../../../../components/detail/MobilePersonDetail'\nimport type { TagsSectionController } from '@open-mercato/ui/backend/detail'\nimport {\n buildPersonEditPayload,\n createPersonEditFields,\n createPersonPersonalDataGroups,\n createPersonEditSchema,\n mapPersonOverviewToFormValues,\n type PersonEditFormValues,\n type PersonOverview,\n} from '../../../../components/formConfig'\nimport { coerceDisplayName, coerceDisplayNameOrNull } from '../../../../lib/displayName'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('customers')\n\nexport default function PersonDetailV2Page({ params }: { params?: { id?: string } }) {\n const id = params?.id\n const t = useT()\n const router = useRouter()\n const searchParams = useSearchParams()\n const pathname = usePathname()\n const { organizationId } = useOrganizationScopeDetail()\n const isMobile = useIsMobile()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n\n const detailTranslator = React.useMemo(() => createTranslatorWithFallback(t), [t])\n\n\n const formSchema = React.useMemo(() => createPersonEditSchema(), [])\n const fields = React.useMemo(() => createPersonEditFields(t), [t])\n\n const [data, setData] = React.useState<PersonOverview | null>(null)\n // Mirror the latest `data` into a ref so save handlers always read the current\n // optimistic-lock token (`person.updatedAt`) instead of the value captured in\n // their `useCallback` closure. Without this, a header-field save issued after a\n // prior in-page reload would send a stale token (or none), letting a concurrent\n // two-tab overwrite slip through without the 409 + conflict bar (#2055, Alina A7).\n const dataRef = React.useRef<PersonOverview | null>(null)\n React.useEffect(() => {\n dataRef.current = data\n }, [data])\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [isNotFound, setIsNotFound] = React.useState(false)\n\n // Form state lifted for header Save button\n const [isDirty, setIsDirty] = React.useState(false)\n const [isSaving, setIsSaving] = React.useState(false)\n const formWrapperRef = React.useRef<HTMLDivElement>(null)\n\n const [sectionAction, setSectionAction] = React.useState<SectionAction | null>(null)\n const [scheduleDialogOpen, setScheduleDialogOpen] = React.useState(false)\n const [scheduleEditData, setScheduleEditData] = React.useState<ScheduleActivityEditData | null>(null)\n const [activityRefreshKey, setActivityRefreshKey] = React.useState(0)\n const [dealCount, setDealCount] = React.useState(0)\n\n const currentPersonId = data?.person?.id ?? null\n const mutationContextId = React.useMemo(\n () => (currentPersonId ? `customer-person:${currentPersonId}` : `customer-person:${id ?? 'pending'}`),\n [currentPersonId, id],\n )\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n personId?: string | null\n resourceKind: string\n resourceId?: string\n data: PersonOverview | null\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: mutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n const personDisplayName = coerceDisplayName(data?.person?.displayName)\n const personName = personDisplayName.trim().length\n ? personDisplayName\n : t('customers.people.list.deleteFallbackName', 'this person')\n\n const personDisplayNameForGroups = personDisplayName.trim().length\n ? personDisplayName.trim()\n : null\n\n const scheduleDialogCompanyName = coerceDisplayNameOrNull(\n data?.company?.displayName ?? data?.companies?.[0]?.displayName ?? null,\n )\n\n const groups = React.useMemo(\n () => createPersonPersonalDataGroups(t, { entityName: personDisplayNameForGroups }),\n [t, personDisplayNameForGroups],\n )\n\n const zoneSections = React.useMemo<ZoneSectionDescriptor[]>(() => [\n { id: 'personalData', icon: User, label: t('customers.people.form.groups.personalData', 'Personal data') },\n { id: 'companyRole', icon: Building2, label: t('customers.people.form.groups.companyRole', 'Company & role') },\n { id: 'customFields', icon: Hash, label: t('customers.people.form.groups.customAttributes', 'Custom attributes') },\n { id: 'roles', icon: Users, label: t('customers.people.form.groups.roles', 'My roles') },\n ], [t])\n\n // Data loading\n const initialLoadDoneRef = React.useRef(false)\n const loadData = React.useCallback(async (lockTokenOverride?: string | null) => {\n if (!id) {\n setIsNotFound(true)\n setIsLoading(false)\n return\n }\n if (!initialLoadDoneRef.current) {\n setIsLoading(true)\n }\n setError(null)\n setIsNotFound(false)\n try {\n const payload = await readApiResultOrThrow<PersonOverview>(\n `/api/customers/people/${encodeURIComponent(id)}`,\n undefined,\n { errorMessage: t('customers.people.detail.error.load', 'Failed to load person.') },\n )\n // When the caller is the save handler, pin the optimistic-lock token to the\n // value the write itself returned rather than the one this GET observed \u2014 a\n // concurrent third-party bump between save and reload must stay stale so the\n // next in-page save 409s (#2055, Alina A7). Applied in the same state update\n // as the refresh to avoid a redundant second re-render.\n const next = lockTokenOverride && payload?.person\n ? { ...payload, person: { ...payload.person, updatedAt: lockTokenOverride, updated_at: lockTokenOverride } }\n : payload\n setData(next as PersonOverview)\n } catch (err) {\n if ((err as { status?: number }).status === 404) {\n setIsNotFound(true)\n } else {\n const message = err instanceof Error ? err.message : t('customers.people.detail.error.load', 'Failed to load person.')\n setError(message)\n }\n if (!initialLoadDoneRef.current) setData(null)\n } finally {\n setIsLoading(false)\n initialLoadDoneRef.current = true\n }\n }, [id, t])\n\n React.useEffect(() => {\n loadData().catch((err) => logger.warn('loadData failed', { component: 'people-v2', err }))\n }, [loadData])\n\n React.useEffect(() => {\n setDealCount(data?.counts?.deals ?? 0)\n }, [data?.counts?.deals])\n\n const handleActivityCreated = React.useCallback(() => {\n setActivityRefreshKey((k) => k + 1)\n loadData().catch((err) => logger.warn('reload after activity failed', { component: 'people-v2', err }))\n }, [loadData])\n\n const plannedActivities = React.useMemo(() => {\n return data?.plannedActivitiesPreview ?? []\n }, [data?.plannedActivitiesPreview])\n\n // Injection context for UMES\n const injectionContext = React.useMemo(\n () => ({\n formId: mutationContextId,\n personId: currentPersonId,\n resourceKind: 'customers.person',\n resourceId: currentPersonId ?? (id ?? undefined),\n data,\n retryLastMutation,\n }),\n [currentPersonId, data, id, mutationContextId, retryLastMutation],\n )\n const runMutationWithContext = React.useCallback(\n async <T,>(operation: () => Promise<T>, mutationPayload?: Record<string, unknown>): Promise<T> => {\n return runMutation({\n operation,\n mutationPayload,\n context: injectionContext,\n })\n },\n [injectionContext, runMutation],\n )\n\n // Publish page-load record context to the AppShell-owned `backend:record:current`\n // mount so the enterprise record_locks widget resolves `customers.person` + id\n // explicitly (the hardcoded path allowlist misses the `people-v2` route).\n // Presence/acquire/heartbeat run on load; the hook clears on unmount/record switch.\n useSetCurrentRecordInjectionContext(\n buildRecordInjectionContext({\n resourceKind: 'customers.person',\n resourceId: currentPersonId,\n updatedAt: data?.person?.updatedAt ?? data?.person?.updated_at ?? null,\n data: data as Record<string, unknown> | null,\n path: pathname,\n }),\n )\n\n const handleAddActivity = React.useCallback((kind: ActivityKind) => {\n setScheduleEditData({\n id: '',\n interactionType: kind,\n title: null,\n body: null,\n scheduledAt: null,\n durationMinutes: null,\n location: null,\n allDay: null,\n recurrenceRule: null,\n recurrenceEnd: null,\n participants: null,\n reminderMinutes: null,\n visibility: null,\n linkedEntities: null,\n guestPermissions: null,\n })\n setScheduleDialogOpen(true)\n }, [])\n\n const handleEditActivity = React.useCallback((activity: { id: string; interactionType?: string; title?: string | null; body?: string | null; scheduledAt?: string | null; occurredAt?: string | null; [key: string]: unknown }) => {\n const raw = activity as Record<string, unknown>\n const durationValue = typeof raw.duration === 'number'\n ? raw.duration\n : typeof raw.durationMinutes === 'number'\n ? raw.durationMinutes as number\n : null\n // Forward `customValues` so per-type chip state (callPhoneNumber, callDirection,\n // taskPriority, \u2026) round-trips on edit (#1808 phone persistence).\n // Forward `occurredAt` so historical activity edits prefill from the original\n // moment instead of \"today\" (#1807 prefill).\n const editPayload = {\n id: activity.id,\n updatedAt: typeof raw.updatedAt === 'string' ? raw.updatedAt as string : typeof raw.updated_at === 'string' ? raw.updated_at as string : null,\n interactionType: typeof activity.interactionType === 'string' ? activity.interactionType : undefined,\n title: typeof activity.title === 'string' ? activity.title : null,\n body: typeof activity.body === 'string' ? activity.body : null,\n scheduledAt: typeof activity.scheduledAt === 'string' ? activity.scheduledAt : null,\n occurredAt: typeof activity.occurredAt === 'string' ? activity.occurredAt : null,\n durationMinutes: durationValue,\n priority: typeof raw.priority === 'number' ? raw.priority as number : null,\n location: typeof raw.location === 'string' ? raw.location as string : null,\n allDay: typeof raw.allDay === 'boolean' ? raw.allDay as boolean : null,\n recurrenceRule: typeof raw.recurrenceRule === 'string' ? raw.recurrenceRule as string : null,\n recurrenceEnd: typeof raw.recurrenceEnd === 'string' ? raw.recurrenceEnd as string : null,\n participants: Array.isArray(raw.participants) ? raw.participants as ScheduleActivityEditData['participants'] : null,\n reminderMinutes: typeof raw.reminderMinutes === 'number' ? raw.reminderMinutes as number : null,\n visibility: typeof raw.visibility === 'string' ? raw.visibility as string : null,\n linkedEntities: Array.isArray(raw.linkedEntities) ? raw.linkedEntities as ScheduleActivityEditData['linkedEntities'] : null,\n guestPermissions: raw.guestPermissions && typeof raw.guestPermissions === 'object'\n ? raw.guestPermissions as ScheduleActivityEditData['guestPermissions']\n : null,\n customValues: raw.customValues && typeof raw.customValues === 'object'\n ? raw.customValues as Record<string, unknown>\n : null,\n phoneNumber: typeof raw.phoneNumber === 'string' ? raw.phoneNumber as string : null,\n } as ScheduleActivityEditData & { customValues?: Record<string, unknown> | null; phoneNumber?: string | null }\n setScheduleEditData(editPayload)\n setScheduleDialogOpen(true)\n }, [])\n\n // Injected tabs from UMES\n const { widgets: injectedTabWidgets } = useInjectionWidgets('detail:customers.person:tabs', {\n context: injectionContext,\n triggerOnLoad: true,\n })\n\n const injectedTabs = React.useMemo(\n () =>\n (injectedTabWidgets ?? [])\n .filter((widget) => (widget.placement?.kind ?? 'tab') === 'tab')\n .map((widget) => {\n const tabId = widget.placement?.groupId ?? widget.widgetId\n const label = widget.placement?.groupLabel\n ? t(widget.placement.groupLabel, widget.placement.groupLabel)\n : widget.module.metadata.title ?? tabId\n const priority = typeof widget.placement?.priority === 'number' ? widget.placement.priority : 0\n const render = () => (\n <widget.module.Widget\n context={injectionContext}\n data={data}\n onDataChange={(next: unknown) => setData(next as PersonOverview)}\n />\n )\n return { id: tabId, label, priority, render }\n })\n .sort((a, b) => b.priority - a.priority),\n [data, injectedTabWidgets, injectionContext, t],\n )\n\n const injectedTabMap = React.useMemo(() => new Map(injectedTabs.map((tab) => [tab.id, tab.render])), [injectedTabs])\n\n const injectedTabIds = React.useMemo(() => injectedTabs.map((tab) => tab.id), [injectedTabs])\n const initialTab = React.useMemo(\n () => resolveLegacyTab(searchParams?.get('tab'), injectedTabIds),\n [injectedTabIds, searchParams],\n )\n const [activeTab, setActiveTab] = React.useState<PersonTabId>(initialTab)\n\n React.useEffect(() => {\n setActiveTab(initialTab)\n }, [initialTab])\n\n const handleTabChange = React.useCallback(\n (tab: PersonTabId) => {\n setActiveTab(tab)\n if (!pathname) return\n const nextParams = new URLSearchParams(searchParams?.toString() ?? '')\n nextParams.set('tab', tab)\n router.replace(`${pathname}?${nextParams.toString()}`, { scroll: false })\n },\n [pathname, router, searchParams],\n )\n\n // Tags\n const handleTagsChange = React.useCallback((nextTags: TagSummary[]) => {\n setData((prev) => (prev ? { ...prev, tags: nextTags } : prev))\n }, [])\n const tagsSectionControllerRef = React.useRef<TagsSectionController | null>(null)\n\n // Section action (for tabs that expose add/create buttons)\n const handleSectionActionChange = React.useCallback((action: SectionAction | null) => {\n setSectionAction((prev) => (action !== null ? action : prev))\n }, [])\n\n React.useEffect(() => {\n setSectionAction(null)\n }, [activeTab])\n\n // Deals scope\n const dealsScope = React.useMemo(\n () => (currentPersonId ? ({ kind: 'person', entityId: currentPersonId } as const) : null),\n [currentPersonId],\n )\n\n const initialValues = React.useMemo(\n () => (data ? mapPersonOverviewToFormValues(data) : undefined),\n [data],\n )\n\n // Form submit/delete\n const handleFormSubmit = React.useCallback(\n async (values: PersonEditFormValues) => {\n setIsSaving(true)\n try {\n await tagsSectionControllerRef.current?.flush()\n\n let payload: Record<string, unknown>\n try {\n payload = buildPersonEditPayload(values, organizationId)\n } catch (err) {\n if (err instanceof Error && err.message === 'DISPLAY_NAME_REQUIRED') {\n const message = t('customers.people.form.displayName.error')\n throw createCrudFormError(message, { displayName: message })\n }\n throw err\n }\n\n // Attach the current optimistic-lock token directly on this write path so\n // every header-field edit (displayName/status/\u2026) carries `updatedAt`, not\n // just the fields the embedded CrudForm intercepts. Read from `dataRef` so\n // the token reflects the latest in-page reload rather than a stale closure\n // capture, and let the 409 propagate to CrudForm's surfaceRecordConflict so\n // the unified conflict bar renders (#2055, Alina A7).\n const lockedUpdatedAt = dataRef.current?.person?.updatedAt\n ?? dataRef.current?.person?.updated_at\n ?? null\n const updateResponse = await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(lockedUpdatedAt),\n () => updateCrud<{ updatedAt?: string | null }>('customers/people', payload),\n )\n flash(t('customers.people.form.updateSuccess', 'Person updated.'), 'success')\n // Refresh the view and pin the optimistic-lock token to the write's OWN\n // authoritative `updatedAt` in a single reload (see loadData) so a\n // concurrent third-party bump stays stale on the next save (#2055, Alina A7).\n const savedUpdatedAt = typeof updateResponse.result?.updatedAt === 'string'\n ? updateResponse.result.updatedAt\n : null\n await loadData(savedUpdatedAt)\n } finally {\n setIsSaving(false)\n }\n },\n [loadData, organizationId, t],\n )\n\n const handleFormDelete = React.useCallback(\n async () => {\n const personId = data?.person?.id ?? ''\n if (!personId) return\n const approved = await confirm({\n title: t('customers.people.detail.deleteConfirmTitle', 'Delete person?'),\n description: t('customers.people.detail.deleteConfirmDescription', 'This action cannot be undone.'),\n confirmText: t('customers.people.detail.actions.delete', 'Delete'),\n cancelText: t('customers.people.detail.actions.cancel', 'Cancel'),\n variant: 'destructive',\n })\n if (!approved) return\n try {\n await runMutationWithContext(\n () => withScopedApiRequestHeaders(\n buildOptimisticLockHeader(data?.person?.updatedAt ?? data?.person?.updated_at ?? null),\n () => deleteCrud('customers/people', { id: personId }),\n ),\n { id: personId, operation: 'deletePerson' },\n )\n } catch (err) {\n // The guarded mutation routes a 409 to the unified conflict bar; surface\n // any other server error (e.g. a linked-records delete guard) as a flash\n // instead of letting it crash the page.\n if (!surfaceRecordConflict(err, t)) {\n flash(\n err instanceof Error && err.message.trim().length > 0\n ? err.message\n : t('customers.people.detail.deleteError', 'Failed to delete person.'),\n 'error',\n )\n }\n return\n }\n flash(t('customers.people.list.deleteSuccess', 'Person deleted.'), 'success')\n router.push('/backend/customers/people')\n },\n [confirm, data?.person?.id, router, runMutationWithContext, t],\n )\n\n const handleHeaderSave = React.useCallback(() => {\n const form = formWrapperRef.current?.querySelector('form')\n if (form) form.requestSubmit()\n }, [])\n\n // Counts for tab badges\n const interactionCount = data?.counts?.activities ?? 0\n const todoCount = data?.counts?.todos ?? 0\n const companyCount = data?.counts?.companies ?? (data?.companies?.length ?? (data?.company ? 1 : 0))\n\n // Loading / error states\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <LoadingMessage label={t('customers.people.detail.loading', 'Loading person\u2026')} />\n </PageBody>\n </Page>\n )\n }\n\n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('customers.people.detail.error.notFound', 'Person not found.')}\n backHref=\"/backend/customers/people\"\n backLabel={t('customers.people.detail.actions.backToList', 'Back to people')}\n />\n </PageBody>\n </Page>\n )\n }\n\n if (error || !data?.person?.id || !initialValues) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage\n label={error ?? t('customers.people.detail.error.load', 'Failed to load person.')}\n action={(\n <Button asChild variant=\"outline\">\n <Link href=\"/backend/customers/people\">\n {t('customers.people.detail.actions.backToList', 'Back to people')}\n </Link>\n </Button>\n )}\n />\n </PageBody>\n </Page>\n )\n }\n\n const personId = data.person.id\n const useCanonicalInteractions = data.interactionMode === 'canonical'\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-4\">\n {/* UMES header injection (third-party extensions) */}\n <InjectionSpot spotId={extensionPoints.hosts.personHeader.spotId} context={injectionContext} data={data} />\n <InjectionSpot spotId={extensionPoints.hosts.personStatusBadges.spotId} context={injectionContext} data={data} />\n\n {/* Persistent person header */}\n <PersonDetailHeader\n data={data}\n onTagsChange={handleTagsChange}\n tagsSectionControllerRef={tagsSectionControllerRef}\n onSave={handleHeaderSave}\n onDelete={handleFormDelete}\n isDirty={isDirty}\n isSaving={isSaving}\n onOpenCompaniesTab={() => handleTabChange('companies')}\n onDataReload={() => { loadData().catch((err) => logger.warn('onDataReload failed', { component: 'people-v2', err })) }}\n onFocusField={(fieldName) => {\n const selectorMap: Record<string, string> = {\n primaryEmail: 'input[type=\"email\"]',\n primaryPhone: 'input[type=\"tel\"]',\n }\n const selector = selectorMap[fieldName]\n const input = selector ? formWrapperRef.current?.querySelector<HTMLInputElement>(selector) : null\n if (input) {\n input.scrollIntoView({ behavior: 'smooth', block: 'center' })\n requestAnimationFrame(() => input.focus())\n }\n }}\n />\n\n {/* Zone content shared between desktop (CollapsibleZoneLayout) and mobile (MobilePersonDetail). */}\n {(() => {\n const zone1Content = (\n <div ref={formWrapperRef}>\n <CrudForm<PersonEditFormValues>\n embedded\n trackDirtyWhenEmbedded\n injectionSpotId={extensionPoints.hosts.personForm.spotId}\n entityIds={[E.customers.customer_entity, E.customers.customer_person_profile]}\n schema={formSchema}\n fields={fields}\n groups={groups}\n initialValues={initialValues}\n optimisticLockUpdatedAt={data.person.updatedAt ?? data.person.updated_at ?? null}\n onSubmit={handleFormSubmit}\n onDelete={handleFormDelete}\n hideFooterActions\n collapsibleGroups={{ pageType: 'person-v2', chevronPosition: 'right' }}\n sortableGroups={{ pageType: 'person-v2' }}\n onDirtyChange={setIsDirty}\n />\n </div>\n )\n const zone2Content = (\n <PersonDetailTabs\n activeTab={activeTab}\n onTabChange={handleTabChange}\n injectedTabs={injectedTabs.map((tab) => ({ id: tab.id, label: tab.label }))}\n activitiesCount={interactionCount}\n dealsCount={dealCount}\n companiesCount={companyCount}\n addressesCount={data?.counts?.addresses ?? 0}\n tasksCount={todoCount}\n sectionAction={sectionAction}\n >\n <div className=\"min-w-0\">\n {(() => {\n // Injected tab content\n const injected = injectedTabMap.get(activeTab)\n if (injected) return injected()\n\n if (activeTab === 'activities') {\n return (\n <div className=\"space-y-4\">\n <ActivitiesCard\n entityId={personId}\n plannedActivities={plannedActivities}\n refreshKey={activityRefreshKey}\n onAddNew={handleAddActivity}\n onEditActivity={handleEditActivity}\n entityCompanyName={data.company?.displayName ?? data.companies?.[0]?.displayName ?? null}\n />\n <ActivitiesSection\n entityId={personId}\n entityName={personName}\n useCanonicalInteractions={useCanonicalInteractions}\n runGuardedMutation={runMutationWithContext}\n onDataRefresh={handleActivityCreated}\n refreshKey={activityRefreshKey}\n addActionLabel={t('customers.people.detail.activities.add', 'Log activity')}\n emptyState={{\n title: t('customers.people.detail.emptyState.activities.title', 'No activities logged yet'),\n actionLabel: t('customers.people.detail.emptyState.activities.action', 'Log activity'),\n }}\n onActionChange={handleSectionActionChange}\n onEditActivity={handleEditActivity}\n />\n </div>\n )\n }\n\n if (activeTab === 'emails') {\n return (\n <PersonEmailThreadsTab\n personId={personId}\n defaultRecipient={data.person?.primaryEmail ?? null}\n />\n )\n }\n\n if (activeTab === 'deals') {\n return (\n <DealsSection\n scope={dealsScope}\n emptyLabel={t('customers.people.detail.empty.deals', 'No deals linked to this person.')}\n addActionLabel={t('customers.people.detail.actions.addDeal', 'Add deal')}\n emptyState={{\n title: t('customers.people.detail.emptyState.deals.title', 'No deals yet'),\n actionLabel: t('customers.people.detail.emptyState.deals.action', 'Create a deal'),\n }}\n onActionChange={handleSectionActionChange}\n translator={detailTranslator}\n runGuardedMutation={runMutationWithContext}\n onCountDelta={(delta) => setDealCount((current) => Math.max(0, current + delta))}\n />\n )\n }\n\n if (activeTab === 'companies') {\n return (\n <PersonCompaniesSection\n personId={personId}\n personName={personName}\n initialLinkedCompanies={data?.companies ?? []}\n onChanged={loadData}\n runGuardedMutation={runMutationWithContext}\n />\n )\n }\n\n if (activeTab === 'addresses') {\n return (\n <AddressesSection\n entityId={personId}\n emptyLabel={t('customers.people.detail.empty.addresses', 'No addresses linked to this person.')}\n addActionLabel={t('customers.people.detail.addresses.add', 'Add address')}\n emptyState={{\n title: t('customers.people.detail.emptyState.addresses.title', 'No addresses yet'),\n actionLabel: t('customers.people.detail.emptyState.addresses.action', 'Add address'),\n }}\n onActionChange={handleSectionActionChange}\n translator={detailTranslator}\n />\n )\n }\n\n if (activeTab === 'tasks') {\n return (\n <TasksSection\n entityId={personId}\n initialTasks={[]}\n useCanonicalInteractions={useCanonicalInteractions}\n runGuardedMutation={runMutationWithContext}\n onDataRefresh={loadData}\n emptyLabel={t('customers.people.detail.empty.todos', 'No tasks linked to this person.')}\n addActionLabel={t('customers.people.detail.tasks.add', 'Add task')}\n emptyState={{\n title: t('customers.people.detail.emptyState.tasks.title', 'Plan what happens next'),\n actionLabel: t('customers.people.detail.emptyState.tasks.action', 'Create task'),\n }}\n onActionChange={handleSectionActionChange}\n translator={detailTranslator}\n entityName={personName}\n dialogContextKey=\"customers.people.detail.tasks.dialog.context\"\n dialogContextFallback=\"This task will be linked to {{name}}\"\n />\n )\n }\n\n if (activeTab === 'files') {\n return (\n <AttachmentsSection\n entityId={E.customers.customer_entity}\n recordId={personId}\n title={t('customers.people.detail.tabs.files', 'Files')}\n description={t('customers.people.detail.files.subtitle', 'Upload and manage files linked to this person.')}\n />\n )\n }\n\n if (activeTab === 'changelog') {\n return <ChangelogTab entityId={personId} entityType=\"person\" />\n }\n\n return null\n })()}\n </div>\n </PersonDetailTabs>\n )\n // Render only the layout variant that matches the viewport. Mounting\n // both the mobile and desktop layouts at once would create two\n // CrudForm instances bound to one `formWrapperRef`, so header Save\n // could submit the hidden instance's stale values and silently\n // discard the edit (#2453). `useIsMobile` is SSR-safe.\n return isMobile ? (\n <MobilePersonDetail zone1={zone1Content} zone2={zone2Content} />\n ) : (\n <CollapsibleZoneLayout\n pageType=\"person-v2\"\n entityName={personName}\n isDirty={isDirty}\n sections={zoneSections}\n zone1={zone1Content}\n zone2={zone2Content}\n />\n )\n })()}\n\n {/* UMES footer injection */}\n <InjectionSpot spotId={extensionPoints.hosts.personFooter.spotId} context={injectionContext} data={data} />\n\n {/* Schedule Activity Dialog \u2014 opened from PlannedActivities \"+ Schedule\" or other triggers */}\n <ScheduleActivityDialog\n open={scheduleDialogOpen}\n onClose={() => { setScheduleDialogOpen(false); setScheduleEditData(null) }}\n entityId={personId}\n entityName={personName}\n companyName={scheduleDialogCompanyName}\n entityType=\"person\"\n onActivityCreated={handleActivityCreated}\n editData={scheduleEditData}\n />\n {ConfirmDialogElement}\n </div>\n </PageBody>\n </Page>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { extensionPoints } from '@open-mercato/core/modules/customers/extension-points'\nimport Link from 'next/link'\nimport { useRouter, useSearchParams, usePathname } from 'next/navigation'\nimport { User, Hash, Users, Building2 } from 'lucide-react'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CrudForm } from '@open-mercato/ui/backend/CrudForm'\nimport { CollapsibleZoneLayout, type ZoneSectionDescriptor } from '@open-mercato/ui/backend/crud/CollapsibleZoneLayout'\nimport { useIsMobile } from '@open-mercato/ui/hooks/useIsMobile'\nimport { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { E } from '#generated/entities.ids.generated'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useOrganizationScopeDetail } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { AttachmentsSection, ErrorMessage, LoadingMessage, RecordNotFoundState, type SectionAction } from '@open-mercato/ui/backend/detail'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { InjectionSpot, useInjectionWidgets } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { buildRecordInjectionContext, useSetCurrentRecordInjectionContext } from '@open-mercato/ui/backend/injection/recordContext'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\n\nimport { ActivitiesSection } from '../../../../components/detail/ActivitiesSection'\nimport { PersonEmailThreadsTab } from '../../../../components/detail/PersonEmailThreadsTab'\nimport { ActivitiesCard } from '../../../../components/detail/ActivitiesCard'\nimport type { ActivityKind } from '../../../../components/detail/ActivitiesAddNewMenu'\nimport { DealsSection } from '../../../../components/detail/DealsSection'\nimport { TasksSection } from '../../../../components/detail/TasksSection'\nimport type { TagSummary } from '../../../../components/detail/types'\nimport { ScheduleActivityDialog, type ScheduleActivityEditData } from '../../../../components/detail/ScheduleActivityDialog'\nimport { PersonDetailHeader } from '../../../../components/detail/PersonDetailHeader'\nimport { ChangelogTab } from '../../../../components/detail/ChangelogTab'\nimport { PersonDetailTabs, resolveLegacyTab, type PersonTabId } from '../../../../components/detail/PersonDetailTabs'\nimport { AddressesSection } from '../../../../components/detail/AddressesSection'\nimport { PersonCompaniesSection } from '../../../../components/detail/PersonCompaniesSection'\nimport { MobilePersonDetail } from '../../../../components/detail/MobilePersonDetail'\nimport type { TagsSectionController } from '@open-mercato/ui/backend/detail'\nimport {\n buildPersonEditPayload,\n createPersonEditFields,\n createPersonPersonalDataGroups,\n createPersonEditSchema,\n mapPersonOverviewToFormValues,\n type PersonEditFormValues,\n type PersonOverview,\n} from '../../../../components/formConfig'\nimport { coerceDisplayName, coerceDisplayNameOrNull } from '../../../../lib/displayName'\nimport { isDetailNotFoundStatus } from '@open-mercato/core/modules/customers/lib/detailHelpers'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('customers')\n\nexport default function PersonDetailV2Page({ params }: { params?: { id?: string } }) {\n const id = params?.id\n const t = useT()\n const router = useRouter()\n const searchParams = useSearchParams()\n const pathname = usePathname()\n const { organizationId } = useOrganizationScopeDetail()\n const isMobile = useIsMobile()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n\n const detailTranslator = React.useMemo(() => createTranslatorWithFallback(t), [t])\n\n\n const formSchema = React.useMemo(() => createPersonEditSchema(), [])\n const fields = React.useMemo(() => createPersonEditFields(t), [t])\n\n const [data, setData] = React.useState<PersonOverview | null>(null)\n // Mirror the latest `data` into a ref so save handlers always read the current\n // optimistic-lock token (`person.updatedAt`) instead of the value captured in\n // their `useCallback` closure. Without this, a header-field save issued after a\n // prior in-page reload would send a stale token (or none), letting a concurrent\n // two-tab overwrite slip through without the 409 + conflict bar (#2055, Alina A7).\n const dataRef = React.useRef<PersonOverview | null>(null)\n React.useEffect(() => {\n dataRef.current = data\n }, [data])\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [isNotFound, setIsNotFound] = React.useState(false)\n\n // Form state lifted for header Save button\n const [isDirty, setIsDirty] = React.useState(false)\n const [isSaving, setIsSaving] = React.useState(false)\n const formWrapperRef = React.useRef<HTMLDivElement>(null)\n\n const [sectionAction, setSectionAction] = React.useState<SectionAction | null>(null)\n const [scheduleDialogOpen, setScheduleDialogOpen] = React.useState(false)\n const [scheduleEditData, setScheduleEditData] = React.useState<ScheduleActivityEditData | null>(null)\n const [activityRefreshKey, setActivityRefreshKey] = React.useState(0)\n const [dealCount, setDealCount] = React.useState(0)\n\n const currentPersonId = data?.person?.id ?? null\n const mutationContextId = React.useMemo(\n () => (currentPersonId ? `customer-person:${currentPersonId}` : `customer-person:${id ?? 'pending'}`),\n [currentPersonId, id],\n )\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n personId?: string | null\n resourceKind: string\n resourceId?: string\n data: PersonOverview | null\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: mutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n const personDisplayName = coerceDisplayName(data?.person?.displayName)\n const personName = personDisplayName.trim().length\n ? personDisplayName\n : t('customers.people.list.deleteFallbackName', 'this person')\n\n const personDisplayNameForGroups = personDisplayName.trim().length\n ? personDisplayName.trim()\n : null\n\n const scheduleDialogCompanyName = coerceDisplayNameOrNull(\n data?.company?.displayName ?? data?.companies?.[0]?.displayName ?? null,\n )\n\n const groups = React.useMemo(\n () => createPersonPersonalDataGroups(t, { entityName: personDisplayNameForGroups }),\n [t, personDisplayNameForGroups],\n )\n\n const zoneSections = React.useMemo<ZoneSectionDescriptor[]>(() => [\n { id: 'personalData', icon: User, label: t('customers.people.form.groups.personalData', 'Personal data') },\n { id: 'companyRole', icon: Building2, label: t('customers.people.form.groups.companyRole', 'Company & role') },\n { id: 'customFields', icon: Hash, label: t('customers.people.form.groups.customAttributes', 'Custom attributes') },\n { id: 'roles', icon: Users, label: t('customers.people.form.groups.roles', 'My roles') },\n ], [t])\n\n // Data loading\n const initialLoadDoneRef = React.useRef(false)\n const loadData = React.useCallback(async (lockTokenOverride?: string | null) => {\n if (!id) {\n setIsNotFound(true)\n setIsLoading(false)\n return\n }\n if (!initialLoadDoneRef.current) {\n setIsLoading(true)\n }\n setError(null)\n setIsNotFound(false)\n try {\n const payload = await readApiResultOrThrow<PersonOverview>(\n `/api/customers/people/${encodeURIComponent(id)}`,\n undefined,\n { errorMessage: t('customers.people.detail.error.load', 'Failed to load person.') },\n )\n // When the caller is the save handler, pin the optimistic-lock token to the\n // value the write itself returned rather than the one this GET observed \u2014 a\n // concurrent third-party bump between save and reload must stay stale so the\n // next in-page save 409s (#2055, Alina A7). Applied in the same state update\n // as the refresh to avoid a redundant second re-render.\n const next = lockTokenOverride && payload?.person\n ? { ...payload, person: { ...payload.person, updatedAt: lockTokenOverride, updated_at: lockTokenOverride } }\n : payload\n setData(next as PersonOverview)\n } catch (err) {\n if (isDetailNotFoundStatus((err as { status?: number }).status)) {\n setIsNotFound(true)\n } else {\n const message = err instanceof Error ? err.message : t('customers.people.detail.error.load', 'Failed to load person.')\n setError(message)\n }\n if (!initialLoadDoneRef.current) setData(null)\n } finally {\n setIsLoading(false)\n initialLoadDoneRef.current = true\n }\n }, [id, t])\n\n React.useEffect(() => {\n loadData().catch((err) => logger.warn('loadData failed', { component: 'people-v2', err }))\n }, [loadData])\n\n React.useEffect(() => {\n setDealCount(data?.counts?.deals ?? 0)\n }, [data?.counts?.deals])\n\n const handleActivityCreated = React.useCallback(() => {\n setActivityRefreshKey((k) => k + 1)\n loadData().catch((err) => logger.warn('reload after activity failed', { component: 'people-v2', err }))\n }, [loadData])\n\n const plannedActivities = React.useMemo(() => {\n return data?.plannedActivitiesPreview ?? []\n }, [data?.plannedActivitiesPreview])\n\n // Injection context for UMES\n const injectionContext = React.useMemo(\n () => ({\n formId: mutationContextId,\n personId: currentPersonId,\n resourceKind: 'customers.person',\n resourceId: currentPersonId ?? (id ?? undefined),\n data,\n retryLastMutation,\n }),\n [currentPersonId, data, id, mutationContextId, retryLastMutation],\n )\n const runMutationWithContext = React.useCallback(\n async <T,>(operation: () => Promise<T>, mutationPayload?: Record<string, unknown>): Promise<T> => {\n return runMutation({\n operation,\n mutationPayload,\n context: injectionContext,\n })\n },\n [injectionContext, runMutation],\n )\n\n // Publish page-load record context to the AppShell-owned `backend:record:current`\n // mount so the enterprise record_locks widget resolves `customers.person` + id\n // explicitly (the hardcoded path allowlist misses the `people-v2` route).\n // Presence/acquire/heartbeat run on load; the hook clears on unmount/record switch.\n useSetCurrentRecordInjectionContext(\n buildRecordInjectionContext({\n resourceKind: 'customers.person',\n resourceId: currentPersonId,\n updatedAt: data?.person?.updatedAt ?? data?.person?.updated_at ?? null,\n data: data as Record<string, unknown> | null,\n path: pathname,\n }),\n )\n\n const handleAddActivity = React.useCallback((kind: ActivityKind) => {\n setScheduleEditData({\n id: '',\n interactionType: kind,\n title: null,\n body: null,\n scheduledAt: null,\n durationMinutes: null,\n location: null,\n allDay: null,\n recurrenceRule: null,\n recurrenceEnd: null,\n participants: null,\n reminderMinutes: null,\n visibility: null,\n linkedEntities: null,\n guestPermissions: null,\n })\n setScheduleDialogOpen(true)\n }, [])\n\n const handleEditActivity = React.useCallback((activity: { id: string; interactionType?: string; title?: string | null; body?: string | null; scheduledAt?: string | null; occurredAt?: string | null; [key: string]: unknown }) => {\n const raw = activity as Record<string, unknown>\n const durationValue = typeof raw.duration === 'number'\n ? raw.duration\n : typeof raw.durationMinutes === 'number'\n ? raw.durationMinutes as number\n : null\n // Forward `customValues` so per-type chip state (callPhoneNumber, callDirection,\n // taskPriority, \u2026) round-trips on edit (#1808 phone persistence).\n // Forward `occurredAt` so historical activity edits prefill from the original\n // moment instead of \"today\" (#1807 prefill).\n const editPayload = {\n id: activity.id,\n updatedAt: typeof raw.updatedAt === 'string' ? raw.updatedAt as string : typeof raw.updated_at === 'string' ? raw.updated_at as string : null,\n interactionType: typeof activity.interactionType === 'string' ? activity.interactionType : undefined,\n title: typeof activity.title === 'string' ? activity.title : null,\n body: typeof activity.body === 'string' ? activity.body : null,\n scheduledAt: typeof activity.scheduledAt === 'string' ? activity.scheduledAt : null,\n occurredAt: typeof activity.occurredAt === 'string' ? activity.occurredAt : null,\n durationMinutes: durationValue,\n priority: typeof raw.priority === 'number' ? raw.priority as number : null,\n location: typeof raw.location === 'string' ? raw.location as string : null,\n allDay: typeof raw.allDay === 'boolean' ? raw.allDay as boolean : null,\n recurrenceRule: typeof raw.recurrenceRule === 'string' ? raw.recurrenceRule as string : null,\n recurrenceEnd: typeof raw.recurrenceEnd === 'string' ? raw.recurrenceEnd as string : null,\n participants: Array.isArray(raw.participants) ? raw.participants as ScheduleActivityEditData['participants'] : null,\n reminderMinutes: typeof raw.reminderMinutes === 'number' ? raw.reminderMinutes as number : null,\n visibility: typeof raw.visibility === 'string' ? raw.visibility as string : null,\n linkedEntities: Array.isArray(raw.linkedEntities) ? raw.linkedEntities as ScheduleActivityEditData['linkedEntities'] : null,\n guestPermissions: raw.guestPermissions && typeof raw.guestPermissions === 'object'\n ? raw.guestPermissions as ScheduleActivityEditData['guestPermissions']\n : null,\n customValues: raw.customValues && typeof raw.customValues === 'object'\n ? raw.customValues as Record<string, unknown>\n : null,\n phoneNumber: typeof raw.phoneNumber === 'string' ? raw.phoneNumber as string : null,\n } as ScheduleActivityEditData & { customValues?: Record<string, unknown> | null; phoneNumber?: string | null }\n setScheduleEditData(editPayload)\n setScheduleDialogOpen(true)\n }, [])\n\n // Injected tabs from UMES\n const { widgets: injectedTabWidgets } = useInjectionWidgets('detail:customers.person:tabs', {\n context: injectionContext,\n triggerOnLoad: true,\n })\n\n const injectedTabs = React.useMemo(\n () =>\n (injectedTabWidgets ?? [])\n .filter((widget) => (widget.placement?.kind ?? 'tab') === 'tab')\n .map((widget) => {\n const tabId = widget.placement?.groupId ?? widget.widgetId\n const label = widget.placement?.groupLabel\n ? t(widget.placement.groupLabel, widget.placement.groupLabel)\n : widget.module.metadata.title ?? tabId\n const priority = typeof widget.placement?.priority === 'number' ? widget.placement.priority : 0\n const render = () => (\n <widget.module.Widget\n context={injectionContext}\n data={data}\n onDataChange={(next: unknown) => setData(next as PersonOverview)}\n />\n )\n return { id: tabId, label, priority, render }\n })\n .sort((a, b) => b.priority - a.priority),\n [data, injectedTabWidgets, injectionContext, t],\n )\n\n const injectedTabMap = React.useMemo(() => new Map(injectedTabs.map((tab) => [tab.id, tab.render])), [injectedTabs])\n\n const injectedTabIds = React.useMemo(() => injectedTabs.map((tab) => tab.id), [injectedTabs])\n const initialTab = React.useMemo(\n () => resolveLegacyTab(searchParams?.get('tab'), injectedTabIds),\n [injectedTabIds, searchParams],\n )\n const [activeTab, setActiveTab] = React.useState<PersonTabId>(initialTab)\n\n React.useEffect(() => {\n setActiveTab(initialTab)\n }, [initialTab])\n\n const handleTabChange = React.useCallback(\n (tab: PersonTabId) => {\n setActiveTab(tab)\n if (!pathname) return\n const nextParams = new URLSearchParams(searchParams?.toString() ?? '')\n nextParams.set('tab', tab)\n router.replace(`${pathname}?${nextParams.toString()}`, { scroll: false })\n },\n [pathname, router, searchParams],\n )\n\n // Tags\n const handleTagsChange = React.useCallback((nextTags: TagSummary[]) => {\n setData((prev) => (prev ? { ...prev, tags: nextTags } : prev))\n }, [])\n const tagsSectionControllerRef = React.useRef<TagsSectionController | null>(null)\n\n // Section action (for tabs that expose add/create buttons)\n const handleSectionActionChange = React.useCallback((action: SectionAction | null) => {\n setSectionAction((prev) => (action !== null ? action : prev))\n }, [])\n\n React.useEffect(() => {\n setSectionAction(null)\n }, [activeTab])\n\n // Deals scope\n const dealsScope = React.useMemo(\n () => (currentPersonId ? ({ kind: 'person', entityId: currentPersonId } as const) : null),\n [currentPersonId],\n )\n\n const initialValues = React.useMemo(\n () => (data ? mapPersonOverviewToFormValues(data) : undefined),\n [data],\n )\n\n // Form submit/delete\n const handleFormSubmit = React.useCallback(\n async (values: PersonEditFormValues) => {\n setIsSaving(true)\n try {\n await tagsSectionControllerRef.current?.flush()\n\n let payload: Record<string, unknown>\n try {\n payload = buildPersonEditPayload(values, organizationId)\n } catch (err) {\n if (err instanceof Error && err.message === 'DISPLAY_NAME_REQUIRED') {\n const message = t('customers.people.form.displayName.error')\n throw createCrudFormError(message, { displayName: message })\n }\n throw err\n }\n\n // Attach the current optimistic-lock token directly on this write path so\n // every header-field edit (displayName/status/\u2026) carries `updatedAt`, not\n // just the fields the embedded CrudForm intercepts. Read from `dataRef` so\n // the token reflects the latest in-page reload rather than a stale closure\n // capture, and let the 409 propagate to CrudForm's surfaceRecordConflict so\n // the unified conflict bar renders (#2055, Alina A7).\n const lockedUpdatedAt = dataRef.current?.person?.updatedAt\n ?? dataRef.current?.person?.updated_at\n ?? null\n const updateResponse = await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(lockedUpdatedAt),\n () => updateCrud<{ updatedAt?: string | null }>('customers/people', payload),\n )\n flash(t('customers.people.form.updateSuccess', 'Person updated.'), 'success')\n // Refresh the view and pin the optimistic-lock token to the write's OWN\n // authoritative `updatedAt` in a single reload (see loadData) so a\n // concurrent third-party bump stays stale on the next save (#2055, Alina A7).\n const savedUpdatedAt = typeof updateResponse.result?.updatedAt === 'string'\n ? updateResponse.result.updatedAt\n : null\n await loadData(savedUpdatedAt)\n } finally {\n setIsSaving(false)\n }\n },\n [loadData, organizationId, t],\n )\n\n const handleFormDelete = React.useCallback(\n async () => {\n const personId = data?.person?.id ?? ''\n if (!personId) return\n const approved = await confirm({\n title: t('customers.people.detail.deleteConfirmTitle', 'Delete person?'),\n description: t('customers.people.detail.deleteConfirmDescription', 'This action cannot be undone.'),\n confirmText: t('customers.people.detail.actions.delete', 'Delete'),\n cancelText: t('customers.people.detail.actions.cancel', 'Cancel'),\n variant: 'destructive',\n })\n if (!approved) return\n try {\n await runMutationWithContext(\n () => withScopedApiRequestHeaders(\n buildOptimisticLockHeader(data?.person?.updatedAt ?? data?.person?.updated_at ?? null),\n () => deleteCrud('customers/people', { id: personId }),\n ),\n { id: personId, operation: 'deletePerson' },\n )\n } catch (err) {\n // The guarded mutation routes a 409 to the unified conflict bar; surface\n // any other server error (e.g. a linked-records delete guard) as a flash\n // instead of letting it crash the page.\n if (!surfaceRecordConflict(err, t)) {\n flash(\n err instanceof Error && err.message.trim().length > 0\n ? err.message\n : t('customers.people.detail.deleteError', 'Failed to delete person.'),\n 'error',\n )\n }\n return\n }\n flash(t('customers.people.list.deleteSuccess', 'Person deleted.'), 'success')\n router.push('/backend/customers/people')\n },\n [confirm, data?.person?.id, router, runMutationWithContext, t],\n )\n\n const handleHeaderSave = React.useCallback(() => {\n const form = formWrapperRef.current?.querySelector('form')\n if (form) form.requestSubmit()\n }, [])\n\n // Counts for tab badges\n const interactionCount = data?.counts?.activities ?? 0\n const todoCount = data?.counts?.todos ?? 0\n const companyCount = data?.counts?.companies ?? (data?.companies?.length ?? (data?.company ? 1 : 0))\n\n // Loading / error states\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <LoadingMessage label={t('customers.people.detail.loading', 'Loading person\u2026')} />\n </PageBody>\n </Page>\n )\n }\n\n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('customers.people.detail.error.notFound', 'Person not found.')}\n backHref=\"/backend/customers/people\"\n backLabel={t('customers.people.detail.actions.backToList', 'Back to people')}\n />\n </PageBody>\n </Page>\n )\n }\n\n if (error || !data?.person?.id || !initialValues) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage\n label={error ?? t('customers.people.detail.error.load', 'Failed to load person.')}\n action={(\n <Button asChild variant=\"outline\">\n <Link href=\"/backend/customers/people\">\n {t('customers.people.detail.actions.backToList', 'Back to people')}\n </Link>\n </Button>\n )}\n />\n </PageBody>\n </Page>\n )\n }\n\n const personId = data.person.id\n const useCanonicalInteractions = data.interactionMode === 'canonical'\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-4\">\n {/* UMES header injection (third-party extensions) */}\n <InjectionSpot spotId={extensionPoints.hosts.personHeader.spotId} context={injectionContext} data={data} />\n <InjectionSpot spotId={extensionPoints.hosts.personStatusBadges.spotId} context={injectionContext} data={data} />\n\n {/* Persistent person header */}\n <PersonDetailHeader\n data={data}\n onTagsChange={handleTagsChange}\n tagsSectionControllerRef={tagsSectionControllerRef}\n onSave={handleHeaderSave}\n onDelete={handleFormDelete}\n isDirty={isDirty}\n isSaving={isSaving}\n onOpenCompaniesTab={() => handleTabChange('companies')}\n onDataReload={() => { loadData().catch((err) => logger.warn('onDataReload failed', { component: 'people-v2', err })) }}\n onFocusField={(fieldName) => {\n const selectorMap: Record<string, string> = {\n primaryEmail: 'input[type=\"email\"]',\n primaryPhone: 'input[type=\"tel\"]',\n }\n const selector = selectorMap[fieldName]\n const input = selector ? formWrapperRef.current?.querySelector<HTMLInputElement>(selector) : null\n if (input) {\n input.scrollIntoView({ behavior: 'smooth', block: 'center' })\n requestAnimationFrame(() => input.focus())\n }\n }}\n />\n\n {/* Zone content shared between desktop (CollapsibleZoneLayout) and mobile (MobilePersonDetail). */}\n {(() => {\n const zone1Content = (\n <div ref={formWrapperRef}>\n <CrudForm<PersonEditFormValues>\n embedded\n trackDirtyWhenEmbedded\n injectionSpotId={extensionPoints.hosts.personForm.spotId}\n entityIds={[E.customers.customer_entity, E.customers.customer_person_profile]}\n schema={formSchema}\n fields={fields}\n groups={groups}\n initialValues={initialValues}\n optimisticLockUpdatedAt={data.person.updatedAt ?? data.person.updated_at ?? null}\n onSubmit={handleFormSubmit}\n onDelete={handleFormDelete}\n hideFooterActions\n collapsibleGroups={{ pageType: 'person-v2', chevronPosition: 'right' }}\n sortableGroups={{ pageType: 'person-v2' }}\n onDirtyChange={setIsDirty}\n />\n </div>\n )\n const zone2Content = (\n <PersonDetailTabs\n activeTab={activeTab}\n onTabChange={handleTabChange}\n injectedTabs={injectedTabs.map((tab) => ({ id: tab.id, label: tab.label }))}\n activitiesCount={interactionCount}\n dealsCount={dealCount}\n companiesCount={companyCount}\n addressesCount={data?.counts?.addresses ?? 0}\n tasksCount={todoCount}\n sectionAction={sectionAction}\n >\n <div className=\"min-w-0\">\n {(() => {\n // Injected tab content\n const injected = injectedTabMap.get(activeTab)\n if (injected) return injected()\n\n if (activeTab === 'activities') {\n return (\n <div className=\"space-y-4\">\n <ActivitiesCard\n entityId={personId}\n plannedActivities={plannedActivities}\n refreshKey={activityRefreshKey}\n onAddNew={handleAddActivity}\n onEditActivity={handleEditActivity}\n entityCompanyName={data.company?.displayName ?? data.companies?.[0]?.displayName ?? null}\n />\n <ActivitiesSection\n entityId={personId}\n entityName={personName}\n useCanonicalInteractions={useCanonicalInteractions}\n runGuardedMutation={runMutationWithContext}\n onDataRefresh={handleActivityCreated}\n refreshKey={activityRefreshKey}\n addActionLabel={t('customers.people.detail.activities.add', 'Log activity')}\n emptyState={{\n title: t('customers.people.detail.emptyState.activities.title', 'No activities logged yet'),\n actionLabel: t('customers.people.detail.emptyState.activities.action', 'Log activity'),\n }}\n onActionChange={handleSectionActionChange}\n onEditActivity={handleEditActivity}\n />\n </div>\n )\n }\n\n if (activeTab === 'emails') {\n return (\n <PersonEmailThreadsTab\n personId={personId}\n defaultRecipient={data.person?.primaryEmail ?? null}\n />\n )\n }\n\n if (activeTab === 'deals') {\n return (\n <DealsSection\n scope={dealsScope}\n emptyLabel={t('customers.people.detail.empty.deals', 'No deals linked to this person.')}\n addActionLabel={t('customers.people.detail.actions.addDeal', 'Add deal')}\n emptyState={{\n title: t('customers.people.detail.emptyState.deals.title', 'No deals yet'),\n actionLabel: t('customers.people.detail.emptyState.deals.action', 'Create a deal'),\n }}\n onActionChange={handleSectionActionChange}\n translator={detailTranslator}\n runGuardedMutation={runMutationWithContext}\n onCountDelta={(delta) => setDealCount((current) => Math.max(0, current + delta))}\n />\n )\n }\n\n if (activeTab === 'companies') {\n return (\n <PersonCompaniesSection\n personId={personId}\n personName={personName}\n initialLinkedCompanies={data?.companies ?? []}\n onChanged={loadData}\n runGuardedMutation={runMutationWithContext}\n />\n )\n }\n\n if (activeTab === 'addresses') {\n return (\n <AddressesSection\n entityId={personId}\n emptyLabel={t('customers.people.detail.empty.addresses', 'No addresses linked to this person.')}\n addActionLabel={t('customers.people.detail.addresses.add', 'Add address')}\n emptyState={{\n title: t('customers.people.detail.emptyState.addresses.title', 'No addresses yet'),\n actionLabel: t('customers.people.detail.emptyState.addresses.action', 'Add address'),\n }}\n onActionChange={handleSectionActionChange}\n translator={detailTranslator}\n />\n )\n }\n\n if (activeTab === 'tasks') {\n return (\n <TasksSection\n entityId={personId}\n initialTasks={[]}\n useCanonicalInteractions={useCanonicalInteractions}\n runGuardedMutation={runMutationWithContext}\n onDataRefresh={loadData}\n emptyLabel={t('customers.people.detail.empty.todos', 'No tasks linked to this person.')}\n addActionLabel={t('customers.people.detail.tasks.add', 'Add task')}\n emptyState={{\n title: t('customers.people.detail.emptyState.tasks.title', 'Plan what happens next'),\n actionLabel: t('customers.people.detail.emptyState.tasks.action', 'Create task'),\n }}\n onActionChange={handleSectionActionChange}\n translator={detailTranslator}\n entityName={personName}\n dialogContextKey=\"customers.people.detail.tasks.dialog.context\"\n dialogContextFallback=\"This task will be linked to {{name}}\"\n />\n )\n }\n\n if (activeTab === 'files') {\n return (\n <AttachmentsSection\n entityId={E.customers.customer_entity}\n recordId={personId}\n title={t('customers.people.detail.tabs.files', 'Files')}\n description={t('customers.people.detail.files.subtitle', 'Upload and manage files linked to this person.')}\n />\n )\n }\n\n if (activeTab === 'changelog') {\n return <ChangelogTab entityId={personId} entityType=\"person\" />\n }\n\n return null\n })()}\n </div>\n </PersonDetailTabs>\n )\n // Render only the layout variant that matches the viewport. Mounting\n // both the mobile and desktop layouts at once would create two\n // CrudForm instances bound to one `formWrapperRef`, so header Save\n // could submit the hidden instance's stale values and silently\n // discard the edit (#2453). `useIsMobile` is SSR-safe.\n return isMobile ? (\n <MobilePersonDetail zone1={zone1Content} zone2={zone2Content} />\n ) : (\n <CollapsibleZoneLayout\n pageType=\"person-v2\"\n entityName={personName}\n isDirty={isDirty}\n sections={zoneSections}\n zone1={zone1Content}\n zone2={zone2Content}\n />\n )\n })()}\n\n {/* UMES footer injection */}\n <InjectionSpot spotId={extensionPoints.hosts.personFooter.spotId} context={injectionContext} data={data} />\n\n {/* Schedule Activity Dialog \u2014 opened from PlannedActivities \"+ Schedule\" or other triggers */}\n <ScheduleActivityDialog\n open={scheduleDialogOpen}\n onClose={() => { setScheduleDialogOpen(false); setScheduleEditData(null) }}\n entityId={personId}\n entityName={personName}\n companyName={scheduleDialogCompanyName}\n entityType=\"person\"\n onActivityCreated={handleActivityCreated}\n editData={scheduleEditData}\n />\n {ConfirmDialogElement}\n </div>\n </PageBody>\n </Page>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["personId"]
7
7
  }
@@ -28,8 +28,12 @@ function isValidSocialUrl(rawValue, options) {
28
28
  const normalizedPath = parsed.pathname.replace(/\/+/g, "/").replace(/(?:^\/|\/$)/g, "");
29
29
  return normalizedPath.length > 0;
30
30
  }
31
+ function isDetailNotFoundStatus(status) {
32
+ return status === 404 || status === 400;
33
+ }
31
34
  export {
32
35
  generateTempId,
36
+ isDetailNotFoundStatus,
33
37
  isValidSocialUrl,
34
38
  slugifyTagLabel
35
39
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/customers/lib/detailHelpers.ts"],
4
- "sourcesContent": ["import { slugifyTagLabel } from '@open-mercato/shared/lib/utils'\n\nexport function generateTempId(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID()\n }\n return `tmp-${Math.random().toString(36).slice(2)}`\n}\n\nexport function isValidSocialUrl(\n rawValue: string,\n options: { hosts: string[]; pathRequired?: boolean },\n): boolean {\n const { hosts, pathRequired = false } = options\n let parsed: URL\n try {\n parsed = new URL(rawValue)\n } catch {\n return false\n }\n const protocol = parsed.protocol.toLowerCase()\n if (protocol !== 'https:' && protocol !== 'http:') {\n return false\n }\n const hostname = parsed.hostname.toLowerCase()\n const matchesHost = hosts.some((host) => hostname === host || hostname.endsWith(`.${host}`))\n if (!matchesHost) {\n return false\n }\n if (!pathRequired) {\n return true\n }\n const normalizedPath = parsed.pathname.replace(/\\/+/g, '/').replace(/(?:^\\/|\\/$)/g, '')\n return normalizedPath.length > 0\n}\n\nexport { slugifyTagLabel }\n"],
5
- "mappings": "AAAA,SAAS,uBAAuB;AAEzB,SAAS,iBAAyB;AACvC,MAAI,OAAO,WAAW,eAAe,OAAO,OAAO,eAAe,YAAY;AAC5E,WAAO,OAAO,WAAW;AAAA,EAC3B;AACA,SAAO,OAAO,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;AACnD;AAEO,SAAS,iBACd,UACA,SACS;AACT,QAAM,EAAE,OAAO,eAAe,MAAM,IAAI;AACxC,MAAI;AACJ,MAAI;AACF,aAAS,IAAI,IAAI,QAAQ;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACA,QAAM,WAAW,OAAO,SAAS,YAAY;AAC7C,MAAI,aAAa,YAAY,aAAa,SAAS;AACjD,WAAO;AAAA,EACT;AACA,QAAM,WAAW,OAAO,SAAS,YAAY;AAC7C,QAAM,cAAc,MAAM,KAAK,CAAC,SAAS,aAAa,QAAQ,SAAS,SAAS,IAAI,IAAI,EAAE,CAAC;AAC3F,MAAI,CAAC,aAAa;AAChB,WAAO;AAAA,EACT;AACA,MAAI,CAAC,cAAc;AACjB,WAAO;AAAA,EACT;AACA,QAAM,iBAAiB,OAAO,SAAS,QAAQ,QAAQ,GAAG,EAAE,QAAQ,gBAAgB,EAAE;AACtF,SAAO,eAAe,SAAS;AACjC;",
4
+ "sourcesContent": ["import { slugifyTagLabel } from '@open-mercato/shared/lib/utils'\n\nexport function generateTempId(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID()\n }\n return `tmp-${Math.random().toString(36).slice(2)}`\n}\n\nexport function isValidSocialUrl(\n rawValue: string,\n options: { hosts: string[]; pathRequired?: boolean },\n): boolean {\n const { hosts, pathRequired = false } = options\n let parsed: URL\n try {\n parsed = new URL(rawValue)\n } catch {\n return false\n }\n const protocol = parsed.protocol.toLowerCase()\n if (protocol !== 'https:' && protocol !== 'http:') {\n return false\n }\n const hostname = parsed.hostname.toLowerCase()\n const matchesHost = hosts.some((host) => hostname === host || hostname.endsWith(`.${host}`))\n if (!matchesHost) {\n return false\n }\n if (!pathRequired) {\n return true\n }\n const normalizedPath = parsed.pathname.replace(/\\/+/g, '/').replace(/(?:^\\/|\\/$)/g, '')\n return normalizedPath.length > 0\n}\n\nexport function isDetailNotFoundStatus(status: number | null | undefined): boolean {\n return status === 404 || status === 400\n}\n\nexport { slugifyTagLabel }\n"],
5
+ "mappings": "AAAA,SAAS,uBAAuB;AAEzB,SAAS,iBAAyB;AACvC,MAAI,OAAO,WAAW,eAAe,OAAO,OAAO,eAAe,YAAY;AAC5E,WAAO,OAAO,WAAW;AAAA,EAC3B;AACA,SAAO,OAAO,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;AACnD;AAEO,SAAS,iBACd,UACA,SACS;AACT,QAAM,EAAE,OAAO,eAAe,MAAM,IAAI;AACxC,MAAI;AACJ,MAAI;AACF,aAAS,IAAI,IAAI,QAAQ;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACA,QAAM,WAAW,OAAO,SAAS,YAAY;AAC7C,MAAI,aAAa,YAAY,aAAa,SAAS;AACjD,WAAO;AAAA,EACT;AACA,QAAM,WAAW,OAAO,SAAS,YAAY;AAC7C,QAAM,cAAc,MAAM,KAAK,CAAC,SAAS,aAAa,QAAQ,SAAS,SAAS,IAAI,IAAI,EAAE,CAAC;AAC3F,MAAI,CAAC,aAAa;AAChB,WAAO;AAAA,EACT;AACA,MAAI,CAAC,cAAc;AACjB,WAAO;AAAA,EACT;AACA,QAAM,iBAAiB,OAAO,SAAS,QAAQ,QAAQ,GAAG,EAAE,QAAQ,gBAAgB,EAAE;AACtF,SAAO,eAAe,SAAS;AACjC;AAEO,SAAS,uBAAuB,QAA4C;AACjF,SAAO,WAAW,OAAO,WAAW;AACtC;",
6
6
  "names": []
7
7
  }