@open-mercato/core 0.5.1-develop.2672.g2128128275 → 0.5.1-develop.2683.4878a05b8e

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 (714) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/generated/entities/action_log/index.js +8 -0
  3. package/dist/generated/entities/action_log/index.js.map +2 -2
  4. package/dist/generated/entities/customer_company_billing/index.js +23 -0
  5. package/dist/generated/entities/customer_company_billing/index.js.map +7 -0
  6. package/dist/generated/entities/customer_deal/index.js +8 -0
  7. package/dist/generated/entities/customer_deal/index.js.map +2 -2
  8. package/dist/generated/entities/customer_deal_stage_transition/index.js +31 -0
  9. package/dist/generated/entities/customer_deal_stage_transition/index.js.map +7 -0
  10. package/dist/generated/entities/customer_dictionary_kind_setting/index.js +21 -0
  11. package/dist/generated/entities/customer_dictionary_kind_setting/index.js.map +7 -0
  12. package/dist/generated/entities/customer_entity/index.js +8 -0
  13. package/dist/generated/entities/customer_entity/index.js.map +2 -2
  14. package/dist/generated/entities/customer_entity_role/index.js +23 -0
  15. package/dist/generated/entities/customer_entity_role/index.js.map +7 -0
  16. package/dist/generated/entities/customer_interaction/index.js +23 -1
  17. package/dist/generated/entities/customer_interaction/index.js.map +2 -2
  18. package/dist/generated/entities/customer_label/index.js +19 -0
  19. package/dist/generated/entities/customer_label/index.js.map +7 -0
  20. package/dist/generated/entities/customer_label_assignment/index.js +17 -0
  21. package/dist/generated/entities/customer_label_assignment/index.js.map +7 -0
  22. package/dist/generated/entities/customer_person_company_link/index.js +21 -0
  23. package/dist/generated/entities/customer_person_company_link/index.js.map +7 -0
  24. package/dist/generated/entities/customer_person_company_role/index.js +17 -0
  25. package/dist/generated/entities/customer_person_company_role/index.js.map +7 -0
  26. package/dist/generated/entities/dictionary_entry/index.js +4 -0
  27. package/dist/generated/entities/dictionary_entry/index.js.map +2 -2
  28. package/dist/generated/entities.ids.generated.js +9 -1
  29. package/dist/generated/entities.ids.generated.js.map +2 -2
  30. package/dist/generated/entity-fields-registry.js +116 -1
  31. package/dist/generated/entity-fields-registry.js.map +2 -2
  32. package/dist/modules/attachments/api/route.js +46 -8
  33. package/dist/modules/attachments/api/route.js.map +2 -2
  34. package/dist/modules/audit_logs/api/audit-logs/actions/export/route.js +208 -0
  35. package/dist/modules/audit_logs/api/audit-logs/actions/export/route.js.map +7 -0
  36. package/dist/modules/audit_logs/api/audit-logs/actions/route.js +52 -6
  37. package/dist/modules/audit_logs/api/audit-logs/actions/route.js.map +2 -2
  38. package/dist/modules/audit_logs/cli.js +62 -0
  39. package/dist/modules/audit_logs/cli.js.map +7 -0
  40. package/dist/modules/audit_logs/components/AuditLogsActions.js +2 -2
  41. package/dist/modules/audit_logs/components/AuditLogsActions.js.map +2 -2
  42. package/dist/modules/audit_logs/data/entities.js +21 -1
  43. package/dist/modules/audit_logs/data/entities.js.map +2 -2
  44. package/dist/modules/audit_logs/data/validators.js +9 -1
  45. package/dist/modules/audit_logs/data/validators.js.map +2 -2
  46. package/dist/modules/audit_logs/lib/changeRows.js +34 -0
  47. package/dist/modules/audit_logs/lib/changeRows.js.map +7 -0
  48. package/dist/modules/audit_logs/lib/display-helpers.js +2 -20
  49. package/dist/modules/audit_logs/lib/display-helpers.js.map +3 -3
  50. package/dist/modules/audit_logs/lib/projections.js +58 -0
  51. package/dist/modules/audit_logs/lib/projections.js.map +7 -0
  52. package/dist/modules/audit_logs/migrations/Migration20260412160533.js +21 -0
  53. package/dist/modules/audit_logs/migrations/Migration20260412160533.js.map +7 -0
  54. package/dist/modules/audit_logs/services/actionLogService.js +313 -79
  55. package/dist/modules/audit_logs/services/actionLogService.js.map +2 -2
  56. package/dist/modules/auth/frontend/login.js +5 -5
  57. package/dist/modules/auth/frontend/login.js.map +2 -2
  58. package/dist/modules/customer_accounts/api/signup.js +3 -3
  59. package/dist/modules/customer_accounts/api/signup.js.map +2 -2
  60. package/dist/modules/customers/acl.js +3 -1
  61. package/dist/modules/customers/acl.js.map +2 -2
  62. package/dist/modules/customers/api/activities/route.js +4 -0
  63. package/dist/modules/customers/api/activities/route.js.map +2 -2
  64. package/dist/modules/customers/api/assignable-staff/route.js +208 -0
  65. package/dist/modules/customers/api/assignable-staff/route.js.map +7 -0
  66. package/dist/modules/customers/api/companies/[id]/people/route.js +205 -0
  67. package/dist/modules/customers/api/companies/[id]/people/route.js.map +7 -0
  68. package/dist/modules/customers/api/companies/[id]/roles/route.js +22 -0
  69. package/dist/modules/customers/api/companies/[id]/roles/route.js.map +7 -0
  70. package/dist/modules/customers/api/companies/[id]/route.js +374 -32
  71. package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
  72. package/dist/modules/customers/api/companies/route.js +82 -7
  73. package/dist/modules/customers/api/companies/route.js.map +2 -2
  74. package/dist/modules/customers/api/deals/[id]/companies/route.js +172 -0
  75. package/dist/modules/customers/api/deals/[id]/companies/route.js.map +7 -0
  76. package/dist/modules/customers/api/deals/[id]/people/route.js +156 -0
  77. package/dist/modules/customers/api/deals/[id]/people/route.js.map +7 -0
  78. package/dist/modules/customers/api/deals/[id]/route.js +459 -53
  79. package/dist/modules/customers/api/deals/[id]/route.js.map +2 -2
  80. package/dist/modules/customers/api/deals/[id]/stats/route.js +195 -0
  81. package/dist/modules/customers/api/deals/[id]/stats/route.js.map +7 -0
  82. package/dist/modules/customers/api/deals/route.js +20 -10
  83. package/dist/modules/customers/api/deals/route.js.map +3 -3
  84. package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js +105 -4
  85. package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js.map +2 -2
  86. package/dist/modules/customers/api/dictionaries/[kind]/route.js +118 -42
  87. package/dist/modules/customers/api/dictionaries/[kind]/route.js.map +2 -2
  88. package/dist/modules/customers/api/dictionaries/context.js +30 -6
  89. package/dist/modules/customers/api/dictionaries/context.js.map +2 -2
  90. package/dist/modules/customers/api/dictionaries/kind-settings/route.js +207 -0
  91. package/dist/modules/customers/api/dictionaries/kind-settings/route.js.map +7 -0
  92. package/dist/modules/customers/api/entity-roles-factory.js +471 -0
  93. package/dist/modules/customers/api/entity-roles-factory.js.map +7 -0
  94. package/dist/modules/customers/api/interactions/conflicts/route.js +158 -0
  95. package/dist/modules/customers/api/interactions/conflicts/route.js.map +7 -0
  96. package/dist/modules/customers/api/interactions/counts/route.js +92 -0
  97. package/dist/modules/customers/api/interactions/counts/route.js.map +7 -0
  98. package/dist/modules/customers/api/interactions/route.js +83 -4
  99. package/dist/modules/customers/api/interactions/route.js.map +2 -2
  100. package/dist/modules/customers/api/labels/assign/route.js +189 -0
  101. package/dist/modules/customers/api/labels/assign/route.js.map +7 -0
  102. package/dist/modules/customers/api/labels/auth.js +17 -0
  103. package/dist/modules/customers/api/labels/auth.js.map +7 -0
  104. package/dist/modules/customers/api/labels/route.js +281 -0
  105. package/dist/modules/customers/api/labels/route.js.map +7 -0
  106. package/dist/modules/customers/api/labels/table-errors.js +38 -0
  107. package/dist/modules/customers/api/labels/table-errors.js.map +7 -0
  108. package/dist/modules/customers/api/labels/unassign/route.js +184 -0
  109. package/dist/modules/customers/api/labels/unassign/route.js.map +7 -0
  110. package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js +292 -0
  111. package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js.map +7 -0
  112. package/dist/modules/customers/api/people/[id]/companies/context.js +66 -0
  113. package/dist/modules/customers/api/people/[id]/companies/context.js.map +7 -0
  114. package/dist/modules/customers/api/people/[id]/companies/enriched/route.js +334 -0
  115. package/dist/modules/customers/api/people/[id]/companies/enriched/route.js.map +7 -0
  116. package/dist/modules/customers/api/people/[id]/companies/route.js +205 -0
  117. package/dist/modules/customers/api/people/[id]/companies/route.js.map +7 -0
  118. package/dist/modules/customers/api/people/[id]/roles/route.js +22 -0
  119. package/dist/modules/customers/api/people/[id]/roles/route.js.map +7 -0
  120. package/dist/modules/customers/api/people/[id]/route.js +134 -21
  121. package/dist/modules/customers/api/people/[id]/route.js.map +2 -2
  122. package/dist/modules/customers/api/people/route.js +122 -23
  123. package/dist/modules/customers/api/people/route.js.map +2 -2
  124. package/dist/modules/customers/api/todos/route.js +4 -0
  125. package/dist/modules/customers/api/todos/route.js.map +2 -2
  126. package/dist/modules/customers/api/utils.js +22 -0
  127. package/dist/modules/customers/api/utils.js.map +2 -2
  128. package/dist/modules/customers/backend/config/customers/page.js +2 -6
  129. package/dist/modules/customers/backend/config/customers/page.js.map +2 -2
  130. package/dist/modules/customers/backend/customers/companies/page.js +37 -26
  131. package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
  132. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +265 -262
  133. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +3 -3
  134. package/dist/modules/customers/backend/customers/deals/[id]/hooks/formatters.js +23 -0
  135. package/dist/modules/customers/backend/customers/deals/[id]/hooks/formatters.js.map +7 -0
  136. package/dist/modules/customers/backend/customers/deals/[id]/hooks/types.js +1 -0
  137. package/dist/modules/customers/backend/customers/deals/[id]/hooks/types.js.map +7 -0
  138. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.js +43 -0
  139. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.js.map +7 -0
  140. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.js +264 -0
  141. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.js.map +7 -0
  142. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealClosure.js +88 -0
  143. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealClosure.js.map +7 -0
  144. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealData.js +41 -0
  145. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealData.js.map +7 -0
  146. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.js +66 -0
  147. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.js.map +7 -0
  148. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealInjectedTabs.js +39 -0
  149. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealInjectedTabs.js.map +7 -0
  150. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealMutationContext.js +49 -0
  151. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealMutationContext.js.map +7 -0
  152. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealPipeline.js +43 -0
  153. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealPipeline.js.map +7 -0
  154. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useScheduleDialog.js +28 -0
  155. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useScheduleDialog.js.map +7 -0
  156. package/dist/modules/customers/backend/customers/deals/[id]/page.js +556 -503
  157. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +3 -3
  158. package/dist/modules/customers/backend/customers/deals/page.js +66 -21
  159. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  160. package/dist/modules/customers/backend/customers/people/page.js +36 -28
  161. package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
  162. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +318 -203
  163. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +3 -3
  164. package/dist/modules/customers/cli.js +105 -13
  165. package/dist/modules/customers/cli.js.map +2 -2
  166. package/dist/modules/customers/commands/activities.js +6 -0
  167. package/dist/modules/customers/commands/activities.js.map +2 -2
  168. package/dist/modules/customers/commands/deals.js +315 -107
  169. package/dist/modules/customers/commands/deals.js.map +2 -2
  170. package/dist/modules/customers/commands/dictionaries.js +166 -32
  171. package/dist/modules/customers/commands/dictionaries.js.map +2 -2
  172. package/dist/modules/customers/commands/dictionaryKindSettings.js +208 -0
  173. package/dist/modules/customers/commands/dictionaryKindSettings.js.map +7 -0
  174. package/dist/modules/customers/commands/entity-roles.js +415 -0
  175. package/dist/modules/customers/commands/entity-roles.js.map +7 -0
  176. package/dist/modules/customers/commands/index.js +4 -0
  177. package/dist/modules/customers/commands/index.js.map +2 -2
  178. package/dist/modules/customers/commands/interactions.js +108 -21
  179. package/dist/modules/customers/commands/interactions.js.map +2 -2
  180. package/dist/modules/customers/commands/labels.js +539 -0
  181. package/dist/modules/customers/commands/labels.js.map +7 -0
  182. package/dist/modules/customers/commands/people.js +560 -463
  183. package/dist/modules/customers/commands/people.js.map +3 -3
  184. package/dist/modules/customers/commands/personCompanyLinks.js +568 -0
  185. package/dist/modules/customers/commands/personCompanyLinks.js.map +7 -0
  186. package/dist/modules/customers/commands/shared.js +12 -4
  187. package/dist/modules/customers/commands/shared.js.map +2 -2
  188. package/dist/modules/customers/commands/todos.js +10 -1
  189. package/dist/modules/customers/commands/todos.js.map +2 -2
  190. package/dist/modules/customers/components/AddressEditor.js +1 -1
  191. package/dist/modules/customers/components/AddressEditor.js.map +2 -2
  192. package/dist/modules/customers/components/CustomersConfigurationSections.js +31 -0
  193. package/dist/modules/customers/components/CustomersConfigurationSections.js.map +7 -0
  194. package/dist/modules/customers/components/DictionarySettings.js +37 -2
  195. package/dist/modules/customers/components/DictionarySettings.js.map +2 -2
  196. package/dist/modules/customers/components/detail/ActiveDealCard.js +121 -0
  197. package/dist/modules/customers/components/detail/ActiveDealCard.js.map +7 -0
  198. package/dist/modules/customers/components/detail/ActivitiesSection.js +222 -331
  199. package/dist/modules/customers/components/detail/ActivitiesSection.js.map +3 -3
  200. package/dist/modules/customers/components/detail/ActivityAiActions.js +36 -0
  201. package/dist/modules/customers/components/detail/ActivityAiActions.js.map +7 -0
  202. package/dist/modules/customers/components/detail/ActivityCard.js +126 -0
  203. package/dist/modules/customers/components/detail/ActivityCard.js.map +7 -0
  204. package/dist/modules/customers/components/detail/ActivityHistorySection.js +340 -0
  205. package/dist/modules/customers/components/detail/ActivityHistorySection.js.map +7 -0
  206. package/dist/modules/customers/components/detail/ActivityLogTab.js +56 -0
  207. package/dist/modules/customers/components/detail/ActivityLogTab.js.map +7 -0
  208. package/dist/modules/customers/components/detail/ActivityTimeline.js +108 -0
  209. package/dist/modules/customers/components/detail/ActivityTimeline.js.map +7 -0
  210. package/dist/modules/customers/components/detail/ActivityTimelineFilters.js +139 -0
  211. package/dist/modules/customers/components/detail/ActivityTimelineFilters.js.map +7 -0
  212. package/dist/modules/customers/components/detail/ActivityTypeSelector.js +42 -0
  213. package/dist/modules/customers/components/detail/ActivityTypeSelector.js.map +7 -0
  214. package/dist/modules/customers/components/detail/AiActionChips.js +38 -0
  215. package/dist/modules/customers/components/detail/AiActionChips.js.map +7 -0
  216. package/dist/modules/customers/components/detail/AssignRoleDialog.js +534 -0
  217. package/dist/modules/customers/components/detail/AssignRoleDialog.js.map +7 -0
  218. package/dist/modules/customers/components/detail/ChangelogEntryRow.js +79 -0
  219. package/dist/modules/customers/components/detail/ChangelogEntryRow.js.map +7 -0
  220. package/dist/modules/customers/components/detail/ChangelogFilters.js +176 -0
  221. package/dist/modules/customers/components/detail/ChangelogFilters.js.map +7 -0
  222. package/dist/modules/customers/components/detail/ChangelogKpiCards.js +88 -0
  223. package/dist/modules/customers/components/detail/ChangelogKpiCards.js.map +7 -0
  224. package/dist/modules/customers/components/detail/ChangelogTab.js +470 -0
  225. package/dist/modules/customers/components/detail/ChangelogTab.js.map +7 -0
  226. package/dist/modules/customers/components/detail/ComingSoonPlaceholder.js +16 -0
  227. package/dist/modules/customers/components/detail/ComingSoonPlaceholder.js.map +7 -0
  228. package/dist/modules/customers/components/detail/CompanyCard.js +283 -0
  229. package/dist/modules/customers/components/detail/CompanyCard.js.map +7 -0
  230. package/dist/modules/customers/components/detail/CompanyDashboardTab.js +133 -0
  231. package/dist/modules/customers/components/detail/CompanyDashboardTab.js.map +7 -0
  232. package/dist/modules/customers/components/detail/CompanyDetailHeader.js +191 -0
  233. package/dist/modules/customers/components/detail/CompanyDetailHeader.js.map +7 -0
  234. package/dist/modules/customers/components/detail/CompanyDetailTabs.js +123 -0
  235. package/dist/modules/customers/components/detail/CompanyDetailTabs.js.map +7 -0
  236. package/dist/modules/customers/components/detail/CompanyKpiBar.js +174 -0
  237. package/dist/modules/customers/components/detail/CompanyKpiBar.js.map +7 -0
  238. package/dist/modules/customers/components/detail/CompanyPeopleSection.js +514 -230
  239. package/dist/modules/customers/components/detail/CompanyPeopleSection.js.map +2 -2
  240. package/dist/modules/customers/components/detail/CompanyTagsDialog.js +22 -0
  241. package/dist/modules/customers/components/detail/CompanyTagsDialog.js.map +7 -0
  242. package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js +159 -0
  243. package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js.map +7 -0
  244. package/dist/modules/customers/components/detail/CreatePersonDialog.js +135 -0
  245. package/dist/modules/customers/components/detail/CreatePersonDialog.js.map +7 -0
  246. package/dist/modules/customers/components/detail/DealClosureActionBar.js +59 -0
  247. package/dist/modules/customers/components/detail/DealClosureActionBar.js.map +7 -0
  248. package/dist/modules/customers/components/detail/DealDetailHeader.js +237 -0
  249. package/dist/modules/customers/components/detail/DealDetailHeader.js.map +7 -0
  250. package/dist/modules/customers/components/detail/DealDetailTabs.js +109 -0
  251. package/dist/modules/customers/components/detail/DealDetailTabs.js.map +7 -0
  252. package/dist/modules/customers/components/detail/DealForm.js +219 -92
  253. package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
  254. package/dist/modules/customers/components/detail/DealLinkedEntitiesTab.js +295 -0
  255. package/dist/modules/customers/components/detail/DealLinkedEntitiesTab.js.map +7 -0
  256. package/dist/modules/customers/components/detail/DealLostSummaryDialog.js +107 -0
  257. package/dist/modules/customers/components/detail/DealLostSummaryDialog.js.map +7 -0
  258. package/dist/modules/customers/components/detail/DealWonPopup.js +113 -0
  259. package/dist/modules/customers/components/detail/DealWonPopup.js.map +7 -0
  260. package/dist/modules/customers/components/detail/DealsSection.js +206 -193
  261. package/dist/modules/customers/components/detail/DealsSection.js.map +2 -2
  262. package/dist/modules/customers/components/detail/DecisionMakersFooter.js +39 -0
  263. package/dist/modules/customers/components/detail/DecisionMakersFooter.js.map +7 -0
  264. package/dist/modules/customers/components/detail/EntityTagsDialog.js +1096 -0
  265. package/dist/modules/customers/components/detail/EntityTagsDialog.js.map +7 -0
  266. package/dist/modules/customers/components/detail/InlineActivityComposer.js +197 -0
  267. package/dist/modules/customers/components/detail/InlineActivityComposer.js.map +7 -0
  268. package/dist/modules/customers/components/detail/ManageTagsDialog.js +1091 -0
  269. package/dist/modules/customers/components/detail/ManageTagsDialog.js.map +7 -0
  270. package/dist/modules/customers/components/detail/MiniWeekCalendar.js +272 -0
  271. package/dist/modules/customers/components/detail/MiniWeekCalendar.js.map +7 -0
  272. package/dist/modules/customers/components/detail/MobilePersonDetail.js +106 -0
  273. package/dist/modules/customers/components/detail/MobilePersonDetail.js.map +7 -0
  274. package/dist/modules/customers/components/detail/NextStepCard.js +72 -0
  275. package/dist/modules/customers/components/detail/NextStepCard.js.map +7 -0
  276. package/dist/modules/customers/components/detail/PersonCard.js +192 -0
  277. package/dist/modules/customers/components/detail/PersonCard.js.map +7 -0
  278. package/dist/modules/customers/components/detail/PersonCompaniesSection.js +345 -0
  279. package/dist/modules/customers/components/detail/PersonCompaniesSection.js.map +7 -0
  280. package/dist/modules/customers/components/detail/PersonDetailHeader.js +220 -0
  281. package/dist/modules/customers/components/detail/PersonDetailHeader.js.map +7 -0
  282. package/dist/modules/customers/components/detail/PersonDetailTabs.js +122 -0
  283. package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +7 -0
  284. package/dist/modules/customers/components/detail/PersonTagsDialog.js +24 -0
  285. package/dist/modules/customers/components/detail/PersonTagsDialog.js.map +7 -0
  286. package/dist/modules/customers/components/detail/PipelineStepper.js +191 -0
  287. package/dist/modules/customers/components/detail/PipelineStepper.js.map +7 -0
  288. package/dist/modules/customers/components/detail/PlannedActivitiesSection.js +222 -0
  289. package/dist/modules/customers/components/detail/PlannedActivitiesSection.js.map +7 -0
  290. package/dist/modules/customers/components/detail/RelationshipHealthCard.js +49 -0
  291. package/dist/modules/customers/components/detail/RelationshipHealthCard.js.map +7 -0
  292. package/dist/modules/customers/components/detail/RoleAssignmentRow.js +189 -0
  293. package/dist/modules/customers/components/detail/RoleAssignmentRow.js.map +7 -0
  294. package/dist/modules/customers/components/detail/RolesSection.js +234 -0
  295. package/dist/modules/customers/components/detail/RolesSection.js.map +7 -0
  296. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +410 -0
  297. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +7 -0
  298. package/dist/modules/customers/components/detail/aiActionCatalog.js +41 -0
  299. package/dist/modules/customers/components/detail/aiActionCatalog.js.map +7 -0
  300. package/dist/modules/customers/components/detail/assignableStaff.js +48 -0
  301. package/dist/modules/customers/components/detail/assignableStaff.js.map +7 -0
  302. package/dist/modules/customers/components/detail/dashboard/ActiveDealWidget.js +48 -0
  303. package/dist/modules/customers/components/detail/dashboard/ActiveDealWidget.js.map +7 -0
  304. package/dist/modules/customers/components/detail/dashboard/OpenTasksWidget.js +86 -0
  305. package/dist/modules/customers/components/detail/dashboard/OpenTasksWidget.js.map +7 -0
  306. package/dist/modules/customers/components/detail/dashboard/RecentActivityWidget.js +53 -0
  307. package/dist/modules/customers/components/detail/dashboard/RecentActivityWidget.js.map +7 -0
  308. package/dist/modules/customers/components/detail/dashboard/RelationshipHealthWidget.js +30 -0
  309. package/dist/modules/customers/components/detail/dashboard/RelationshipHealthWidget.js.map +7 -0
  310. package/dist/modules/customers/components/detail/dashboard/UpcomingMeetingsWidget.js +43 -0
  311. package/dist/modules/customers/components/detail/dashboard/UpcomingMeetingsWidget.js.map +7 -0
  312. package/dist/modules/customers/components/detail/dashboard/helpers.js +71 -0
  313. package/dist/modules/customers/components/detail/dashboard/helpers.js.map +7 -0
  314. package/dist/modules/customers/components/detail/healthScoreUtils.js +69 -0
  315. package/dist/modules/customers/components/detail/healthScoreUtils.js.map +7 -0
  316. package/dist/modules/customers/components/detail/hooks/useCurrencyDictionary.js +5 -5
  317. package/dist/modules/customers/components/detail/hooks/useCurrencyDictionary.js.map +2 -2
  318. package/dist/modules/customers/components/detail/hooks/useCustomerDictionary.js +9 -8
  319. package/dist/modules/customers/components/detail/hooks/useCustomerDictionary.js.map +3 -3
  320. package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js +65 -0
  321. package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js.map +7 -0
  322. package/dist/modules/customers/components/detail/notesAdapter.js +70 -30
  323. package/dist/modules/customers/components/detail/notesAdapter.js.map +2 -2
  324. package/dist/modules/customers/components/detail/pipelineStageUtils.js +26 -0
  325. package/dist/modules/customers/components/detail/pipelineStageUtils.js.map +7 -0
  326. package/dist/modules/customers/components/detail/schedule/DateTimeFields.js +144 -0
  327. package/dist/modules/customers/components/detail/schedule/DateTimeFields.js.map +7 -0
  328. package/dist/modules/customers/components/detail/schedule/FooterFields.js +60 -0
  329. package/dist/modules/customers/components/detail/schedule/FooterFields.js.map +7 -0
  330. package/dist/modules/customers/components/detail/schedule/LinkedEntitiesField.js +216 -0
  331. package/dist/modules/customers/components/detail/schedule/LinkedEntitiesField.js.map +7 -0
  332. package/dist/modules/customers/components/detail/schedule/LocationField.js +34 -0
  333. package/dist/modules/customers/components/detail/schedule/LocationField.js.map +7 -0
  334. package/dist/modules/customers/components/detail/schedule/ParticipantsField.js +226 -0
  335. package/dist/modules/customers/components/detail/schedule/ParticipantsField.js.map +7 -0
  336. package/dist/modules/customers/components/detail/schedule/fieldConfig.js +69 -0
  337. package/dist/modules/customers/components/detail/schedule/fieldConfig.js.map +7 -0
  338. package/dist/modules/customers/components/detail/schedule/index.js +21 -0
  339. package/dist/modules/customers/components/detail/schedule/index.js.map +7 -0
  340. package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js +172 -0
  341. package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +7 -0
  342. package/dist/modules/customers/components/detail/utils.js +23 -0
  343. package/dist/modules/customers/components/detail/utils.js.map +2 -2
  344. package/dist/modules/customers/components/formConfig.js +144 -22
  345. package/dist/modules/customers/components/formConfig.js.map +2 -2
  346. package/dist/modules/customers/components/linking/LinkEntityDialog.js +661 -0
  347. package/dist/modules/customers/components/linking/LinkEntityDialog.js.map +7 -0
  348. package/dist/modules/customers/components/linking/adapters/companyAdapter.js +252 -0
  349. package/dist/modules/customers/components/linking/adapters/companyAdapter.js.map +7 -0
  350. package/dist/modules/customers/components/linking/adapters/dealAdapter.js +384 -0
  351. package/dist/modules/customers/components/linking/adapters/dealAdapter.js.map +7 -0
  352. package/dist/modules/customers/components/linking/adapters/personAdapter.js +324 -0
  353. package/dist/modules/customers/components/linking/adapters/personAdapter.js.map +7 -0
  354. package/dist/modules/customers/components/list/CollectionPreviewCell.js +53 -0
  355. package/dist/modules/customers/components/list/CollectionPreviewCell.js.map +7 -0
  356. package/dist/modules/customers/data/entities.js +407 -1
  357. package/dist/modules/customers/data/entities.js.map +2 -2
  358. package/dist/modules/customers/data/validators.js +139 -21
  359. package/dist/modules/customers/data/validators.js.map +2 -2
  360. package/dist/modules/customers/events.js +19 -1
  361. package/dist/modules/customers/events.js.map +2 -2
  362. package/dist/modules/customers/lib/customerRoleTypes.js +19 -0
  363. package/dist/modules/customers/lib/customerRoleTypes.js.map +7 -0
  364. package/dist/modules/customers/lib/dealClosureNotification.js +39 -0
  365. package/dist/modules/customers/lib/dealClosureNotification.js.map +7 -0
  366. package/dist/modules/customers/lib/dealStageTransitionTable.js +29 -0
  367. package/dist/modules/customers/lib/dealStageTransitionTable.js.map +7 -0
  368. package/dist/modules/customers/lib/dictionaries.js +25 -0
  369. package/dist/modules/customers/lib/dictionaries.js.map +2 -2
  370. package/dist/modules/customers/lib/interactionReadModel.js +10 -0
  371. package/dist/modules/customers/lib/interactionReadModel.js.map +2 -2
  372. package/dist/modules/customers/lib/personCompanies.js +235 -0
  373. package/dist/modules/customers/lib/personCompanies.js.map +7 -0
  374. package/dist/modules/customers/lib/personCompanyLinkTable.js +42 -0
  375. package/dist/modules/customers/lib/personCompanyLinkTable.js.map +7 -0
  376. package/dist/modules/customers/lib/roleTypeUsage.js +104 -0
  377. package/dist/modules/customers/lib/roleTypeUsage.js.map +7 -0
  378. package/dist/modules/customers/migrations/Migration20260406214502.js +18 -0
  379. package/dist/modules/customers/migrations/Migration20260406214502.js.map +7 -0
  380. package/dist/modules/customers/migrations/Migration20260408135736.js +17 -0
  381. package/dist/modules/customers/migrations/Migration20260408135736.js.map +7 -0
  382. package/dist/modules/customers/migrations/Migration20260408225345.js +21 -0
  383. package/dist/modules/customers/migrations/Migration20260408225345.js.map +7 -0
  384. package/dist/modules/customers/migrations/Migration20260411075533.js +27 -0
  385. package/dist/modules/customers/migrations/Migration20260411075533.js.map +7 -0
  386. package/dist/modules/customers/migrations/Migration20260411103551.js +13 -0
  387. package/dist/modules/customers/migrations/Migration20260411103551.js.map +7 -0
  388. package/dist/modules/customers/migrations/Migration20260411130944.js +26 -0
  389. package/dist/modules/customers/migrations/Migration20260411130944.js.map +7 -0
  390. package/dist/modules/customers/migrations/Migration20260415095203.js +13 -0
  391. package/dist/modules/customers/migrations/Migration20260415095203.js.map +7 -0
  392. package/dist/modules/customers/migrations/Migration20260415135056.js +20 -0
  393. package/dist/modules/customers/migrations/Migration20260415135056.js.map +7 -0
  394. package/dist/modules/customers/migrations/Migration20260417140000.js +15 -0
  395. package/dist/modules/customers/migrations/Migration20260417140000.js.map +7 -0
  396. package/dist/modules/customers/migrations/Migration20260417160000.js +17 -0
  397. package/dist/modules/customers/migrations/Migration20260417160000.js.map +7 -0
  398. package/dist/modules/customers/migrations/Migration20260417235407.js +13 -0
  399. package/dist/modules/customers/migrations/Migration20260417235407.js.map +7 -0
  400. package/dist/modules/customers/setup.js +16 -1
  401. package/dist/modules/customers/setup.js.map +2 -2
  402. package/dist/modules/customers/subscribers/deal-closure-notification.js +16 -0
  403. package/dist/modules/customers/subscribers/deal-closure-notification.js.map +7 -0
  404. package/dist/modules/customers/subscribers/deal-lost-notification.js +16 -0
  405. package/dist/modules/customers/subscribers/deal-lost-notification.js.map +7 -0
  406. package/dist/modules/data_sync/backend/data-sync/page.js +3 -3
  407. package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
  408. package/dist/modules/data_sync/components/IntegrationScheduleTab.js +5 -5
  409. package/dist/modules/data_sync/components/IntegrationScheduleTab.js.map +2 -2
  410. package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js +2 -0
  411. package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js.map +2 -2
  412. package/dist/modules/dictionaries/api/[dictionaryId]/entries/reorder/route.js +154 -0
  413. package/dist/modules/dictionaries/api/[dictionaryId]/entries/reorder/route.js.map +7 -0
  414. package/dist/modules/dictionaries/api/[dictionaryId]/entries/route.js +6 -2
  415. package/dist/modules/dictionaries/api/[dictionaryId]/entries/route.js.map +2 -2
  416. package/dist/modules/dictionaries/api/[dictionaryId]/entries/set-default/route.js +154 -0
  417. package/dist/modules/dictionaries/api/[dictionaryId]/entries/set-default/route.js.map +7 -0
  418. package/dist/modules/dictionaries/api/context.js +8 -1
  419. package/dist/modules/dictionaries/api/context.js.map +2 -2
  420. package/dist/modules/dictionaries/api/openapi.js +18 -1
  421. package/dist/modules/dictionaries/api/openapi.js.map +2 -2
  422. package/dist/modules/dictionaries/commands/entry-operations.js +388 -0
  423. package/dist/modules/dictionaries/commands/entry-operations.js.map +7 -0
  424. package/dist/modules/dictionaries/commands/factory.js +24 -3
  425. package/dist/modules/dictionaries/commands/factory.js.map +2 -2
  426. package/dist/modules/dictionaries/commands/index.js +1 -0
  427. package/dist/modules/dictionaries/commands/index.js.map +2 -2
  428. package/dist/modules/dictionaries/components/DictionaryTable.js +6 -3
  429. package/dist/modules/dictionaries/components/DictionaryTable.js.map +2 -2
  430. package/dist/modules/dictionaries/data/entities.js +11 -1
  431. package/dist/modules/dictionaries/data/entities.js.map +2 -2
  432. package/dist/modules/dictionaries/data/validators.js +28 -2
  433. package/dist/modules/dictionaries/data/validators.js.map +2 -2
  434. package/dist/modules/dictionaries/events.js +18 -0
  435. package/dist/modules/dictionaries/events.js.map +7 -0
  436. package/dist/modules/dictionaries/lib/clientEntries.js +43 -0
  437. package/dist/modules/dictionaries/lib/clientEntries.js.map +7 -0
  438. package/dist/modules/dictionaries/migrations/Migration20260410171544.js +45 -0
  439. package/dist/modules/dictionaries/migrations/Migration20260410171544.js.map +7 -0
  440. package/dist/modules/inbox_ops/api/proposals/[id]/route.js +4 -1
  441. package/dist/modules/inbox_ops/api/proposals/[id]/route.js.map +2 -2
  442. package/dist/modules/portal/frontend/[orgSlug]/portal/login/page.js +3 -3
  443. package/dist/modules/portal/frontend/[orgSlug]/portal/login/page.js.map +2 -2
  444. package/dist/modules/portal/frontend/[orgSlug]/portal/page.js +2 -2
  445. package/dist/modules/portal/frontend/[orgSlug]/portal/page.js.map +2 -2
  446. package/dist/modules/portal/frontend/[orgSlug]/portal/signup/page.js +3 -3
  447. package/dist/modules/portal/frontend/[orgSlug]/portal/signup/page.js.map +2 -2
  448. package/dist/modules/portal/frontend/[orgSlug]/portal/verify/page.js +2 -2
  449. package/dist/modules/portal/frontend/[orgSlug]/portal/verify/page.js.map +2 -2
  450. package/dist/modules/query_index/lib/engine.js +1 -1
  451. package/dist/modules/query_index/lib/engine.js.map +2 -2
  452. package/dist/modules/sales/components/documents/AddressesSection.js +82 -42
  453. package/dist/modules/sales/components/documents/AddressesSection.js.map +2 -2
  454. package/dist/modules/sales/lib/dictionaries.js +16 -0
  455. package/dist/modules/sales/lib/dictionaries.js.map +2 -2
  456. package/dist/modules/sales/widgets/injection-table.js +5 -1
  457. package/dist/modules/sales/widgets/injection-table.js.map +2 -2
  458. package/generated/entities/action_log/index.ts +4 -0
  459. package/generated/entities/customer_company_billing/index.ts +10 -0
  460. package/generated/entities/customer_deal/index.ts +4 -0
  461. package/generated/entities/customer_deal_stage_transition/index.ts +14 -0
  462. package/generated/entities/customer_dictionary_kind_setting/index.ts +9 -0
  463. package/generated/entities/customer_entity/index.ts +4 -0
  464. package/generated/entities/customer_entity_role/index.ts +10 -0
  465. package/generated/entities/customer_interaction/index.ts +11 -0
  466. package/generated/entities/customer_label/index.ts +8 -0
  467. package/generated/entities/customer_label_assignment/index.ts +7 -0
  468. package/generated/entities/customer_person_company_link/index.ts +9 -0
  469. package/generated/entities/customer_person_company_role/index.ts +7 -0
  470. package/generated/entities/dictionary_entry/index.ts +2 -0
  471. package/generated/entities.ids.generated.ts +9 -1
  472. package/generated/entity-fields-registry.ts +116 -1
  473. package/package.json +3 -3
  474. package/src/modules/attachments/api/route.ts +48 -6
  475. package/src/modules/attachments/i18n/de.json +4 -0
  476. package/src/modules/attachments/i18n/en.json +4 -0
  477. package/src/modules/attachments/i18n/es.json +4 -0
  478. package/src/modules/attachments/i18n/pl.json +4 -0
  479. package/src/modules/audit_logs/api/audit-logs/actions/export/route.ts +260 -0
  480. package/src/modules/audit_logs/api/audit-logs/actions/route.ts +81 -6
  481. package/src/modules/audit_logs/cli.ts +79 -0
  482. package/src/modules/audit_logs/components/AuditLogsActions.tsx +6 -4
  483. package/src/modules/audit_logs/data/entities.ts +17 -0
  484. package/src/modules/audit_logs/data/validators.ts +9 -1
  485. package/src/modules/audit_logs/lib/changeRows.ts +47 -0
  486. package/src/modules/audit_logs/lib/display-helpers.tsx +4 -30
  487. package/src/modules/audit_logs/lib/projections.ts +110 -0
  488. package/src/modules/audit_logs/migrations/.snapshot-open-mercato.json +325 -2
  489. package/src/modules/audit_logs/migrations/Migration20260412160533.ts +21 -0
  490. package/src/modules/audit_logs/services/actionLogService.ts +455 -85
  491. package/src/modules/auth/frontend/login.tsx +19 -15
  492. package/src/modules/catalog/i18n/de.json +1 -0
  493. package/src/modules/catalog/i18n/en.json +1 -0
  494. package/src/modules/catalog/i18n/es.json +1 -0
  495. package/src/modules/catalog/i18n/pl.json +1 -0
  496. package/src/modules/customer_accounts/api/signup.ts +3 -4
  497. package/src/modules/customer_accounts/i18n/de.json +2 -0
  498. package/src/modules/customer_accounts/i18n/en.json +2 -0
  499. package/src/modules/customer_accounts/i18n/es.json +2 -0
  500. package/src/modules/customer_accounts/i18n/pl.json +2 -0
  501. package/src/modules/customers/acl.ts +2 -0
  502. package/src/modules/customers/api/activities/route.ts +4 -0
  503. package/src/modules/customers/api/assignable-staff/route.ts +250 -0
  504. package/src/modules/customers/api/companies/[id]/people/route.ts +244 -0
  505. package/src/modules/customers/api/companies/[id]/roles/route.ts +15 -0
  506. package/src/modules/customers/api/companies/[id]/route.ts +458 -40
  507. package/src/modules/customers/api/companies/route.ts +93 -15
  508. package/src/modules/customers/api/deals/[id]/companies/route.ts +203 -0
  509. package/src/modules/customers/api/deals/[id]/people/route.ts +182 -0
  510. package/src/modules/customers/api/deals/[id]/route.ts +554 -57
  511. package/src/modules/customers/api/deals/[id]/stats/route.ts +221 -0
  512. package/src/modules/customers/api/deals/route.ts +35 -46
  513. package/src/modules/customers/api/dictionaries/[kind]/[id]/route.ts +105 -3
  514. package/src/modules/customers/api/dictionaries/[kind]/route.ts +143 -44
  515. package/src/modules/customers/api/dictionaries/context.ts +45 -16
  516. package/src/modules/customers/api/dictionaries/kind-settings/route.ts +232 -0
  517. package/src/modules/customers/api/entity-roles-factory.ts +520 -0
  518. package/src/modules/customers/api/interactions/conflicts/route.ts +196 -0
  519. package/src/modules/customers/api/interactions/counts/route.ts +112 -0
  520. package/src/modules/customers/api/interactions/route.ts +95 -2
  521. package/src/modules/customers/api/labels/assign/route.ts +202 -0
  522. package/src/modules/customers/api/labels/auth.ts +19 -0
  523. package/src/modules/customers/api/labels/route.ts +310 -0
  524. package/src/modules/customers/api/labels/table-errors.ts +36 -0
  525. package/src/modules/customers/api/labels/unassign/route.ts +197 -0
  526. package/src/modules/customers/api/people/[id]/companies/[linkId]/route.ts +331 -0
  527. package/src/modules/customers/api/people/[id]/companies/context.ts +70 -0
  528. package/src/modules/customers/api/people/[id]/companies/enriched/route.ts +384 -0
  529. package/src/modules/customers/api/people/[id]/companies/route.ts +215 -0
  530. package/src/modules/customers/api/people/[id]/roles/route.ts +15 -0
  531. package/src/modules/customers/api/people/[id]/route.ts +153 -26
  532. package/src/modules/customers/api/people/route.ts +134 -31
  533. package/src/modules/customers/api/todos/route.ts +4 -0
  534. package/src/modules/customers/api/utils.ts +36 -0
  535. package/src/modules/customers/backend/config/customers/page.tsx +2 -6
  536. package/src/modules/customers/backend/customers/companies/page.tsx +36 -26
  537. package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +277 -262
  538. package/src/modules/customers/backend/customers/deals/[id]/hooks/formatters.ts +19 -0
  539. package/src/modules/customers/backend/customers/deals/[id]/hooks/types.ts +104 -0
  540. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.ts +60 -0
  541. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.ts +362 -0
  542. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealClosure.ts +113 -0
  543. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealData.ts +52 -0
  544. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.ts +86 -0
  545. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealInjectedTabs.tsx +60 -0
  546. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealMutationContext.ts +76 -0
  547. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealPipeline.ts +56 -0
  548. package/src/modules/customers/backend/customers/deals/[id]/hooks/useScheduleDialog.ts +38 -0
  549. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +587 -624
  550. package/src/modules/customers/backend/customers/deals/page.tsx +71 -28
  551. package/src/modules/customers/backend/customers/people/page.tsx +35 -29
  552. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +343 -209
  553. package/src/modules/customers/cli.ts +107 -12
  554. package/src/modules/customers/commands/activities.ts +13 -0
  555. package/src/modules/customers/commands/deals.ts +386 -114
  556. package/src/modules/customers/commands/dictionaries.ts +175 -32
  557. package/src/modules/customers/commands/dictionaryKindSettings.ts +268 -0
  558. package/src/modules/customers/commands/entity-roles.ts +494 -0
  559. package/src/modules/customers/commands/index.ts +4 -0
  560. package/src/modules/customers/commands/interactions.ts +125 -21
  561. package/src/modules/customers/commands/labels.ts +626 -0
  562. package/src/modules/customers/commands/people.ts +373 -259
  563. package/src/modules/customers/commands/personCompanyLinks.ts +654 -0
  564. package/src/modules/customers/commands/shared.ts +16 -15
  565. package/src/modules/customers/commands/todos.ts +17 -1
  566. package/src/modules/customers/components/AddressEditor.tsx +1 -1
  567. package/src/modules/customers/components/CustomersConfigurationSections.tsx +36 -0
  568. package/src/modules/customers/components/DictionarySettings.tsx +43 -2
  569. package/src/modules/customers/components/detail/ActiveDealCard.tsx +175 -0
  570. package/src/modules/customers/components/detail/ActivitiesSection.tsx +267 -361
  571. package/src/modules/customers/components/detail/ActivityAiActions.tsx +49 -0
  572. package/src/modules/customers/components/detail/ActivityCard.tsx +154 -0
  573. package/src/modules/customers/components/detail/ActivityHistorySection.tsx +412 -0
  574. package/src/modules/customers/components/detail/ActivityLogTab.tsx +67 -0
  575. package/src/modules/customers/components/detail/ActivityTimeline.tsx +158 -0
  576. package/src/modules/customers/components/detail/ActivityTimelineFilters.tsx +163 -0
  577. package/src/modules/customers/components/detail/ActivityTypeSelector.tsx +53 -0
  578. package/src/modules/customers/components/detail/AiActionChips.tsx +48 -0
  579. package/src/modules/customers/components/detail/AssignRoleDialog.tsx +672 -0
  580. package/src/modules/customers/components/detail/ChangelogEntryRow.tsx +132 -0
  581. package/src/modules/customers/components/detail/ChangelogFilters.tsx +193 -0
  582. package/src/modules/customers/components/detail/ChangelogKpiCards.tsx +107 -0
  583. package/src/modules/customers/components/detail/ChangelogTab.tsx +629 -0
  584. package/src/modules/customers/components/detail/ComingSoonPlaceholder.tsx +21 -0
  585. package/src/modules/customers/components/detail/CompanyCard.tsx +419 -0
  586. package/src/modules/customers/components/detail/CompanyDashboardTab.tsx +161 -0
  587. package/src/modules/customers/components/detail/CompanyDetailHeader.tsx +243 -0
  588. package/src/modules/customers/components/detail/CompanyDetailTabs.tsx +172 -0
  589. package/src/modules/customers/components/detail/CompanyKpiBar.tsx +206 -0
  590. package/src/modules/customers/components/detail/CompanyPeopleSection.tsx +582 -288
  591. package/src/modules/customers/components/detail/CompanyTagsDialog.tsx +23 -0
  592. package/src/modules/customers/components/detail/ConfirmDealLostDialog.tsx +210 -0
  593. package/src/modules/customers/components/detail/CreatePersonDialog.tsx +178 -0
  594. package/src/modules/customers/components/detail/DealClosureActionBar.tsx +63 -0
  595. package/src/modules/customers/components/detail/DealDetailHeader.tsx +335 -0
  596. package/src/modules/customers/components/detail/DealDetailTabs.tsx +154 -0
  597. package/src/modules/customers/components/detail/DealForm.tsx +253 -101
  598. package/src/modules/customers/components/detail/DealLinkedEntitiesTab.tsx +349 -0
  599. package/src/modules/customers/components/detail/DealLostSummaryDialog.tsx +156 -0
  600. package/src/modules/customers/components/detail/DealWonPopup.tsx +164 -0
  601. package/src/modules/customers/components/detail/DealsSection.tsx +276 -221
  602. package/src/modules/customers/components/detail/DecisionMakersFooter.tsx +56 -0
  603. package/src/modules/customers/components/detail/EntityTagsDialog.tsx +1372 -0
  604. package/src/modules/customers/components/detail/InlineActivityComposer.tsx +239 -0
  605. package/src/modules/customers/components/detail/ManageTagsDialog.tsx +1331 -0
  606. package/src/modules/customers/components/detail/MiniWeekCalendar.tsx +338 -0
  607. package/src/modules/customers/components/detail/MobilePersonDetail.tsx +124 -0
  608. package/src/modules/customers/components/detail/NextStepCard.tsx +104 -0
  609. package/src/modules/customers/components/detail/PersonCard.tsx +238 -0
  610. package/src/modules/customers/components/detail/PersonCompaniesSection.tsx +426 -0
  611. package/src/modules/customers/components/detail/PersonDetailHeader.tsx +294 -0
  612. package/src/modules/customers/components/detail/PersonDetailTabs.tsx +172 -0
  613. package/src/modules/customers/components/detail/PersonTagsDialog.tsx +26 -0
  614. package/src/modules/customers/components/detail/PipelineStepper.tsx +245 -0
  615. package/src/modules/customers/components/detail/PlannedActivitiesSection.tsx +255 -0
  616. package/src/modules/customers/components/detail/RelationshipHealthCard.tsx +63 -0
  617. package/src/modules/customers/components/detail/RoleAssignmentRow.tsx +248 -0
  618. package/src/modules/customers/components/detail/RolesSection.tsx +311 -0
  619. package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +481 -0
  620. package/src/modules/customers/components/detail/aiActionCatalog.ts +77 -0
  621. package/src/modules/customers/components/detail/assignableStaff.ts +124 -0
  622. package/src/modules/customers/components/detail/dashboard/ActiveDealWidget.tsx +63 -0
  623. package/src/modules/customers/components/detail/dashboard/OpenTasksWidget.tsx +114 -0
  624. package/src/modules/customers/components/detail/dashboard/RecentActivityWidget.tsx +69 -0
  625. package/src/modules/customers/components/detail/dashboard/RelationshipHealthWidget.tsx +40 -0
  626. package/src/modules/customers/components/detail/dashboard/UpcomingMeetingsWidget.tsx +64 -0
  627. package/src/modules/customers/components/detail/dashboard/helpers.ts +78 -0
  628. package/src/modules/customers/components/detail/healthScoreUtils.ts +91 -0
  629. package/src/modules/customers/components/detail/hooks/useCurrencyDictionary.ts +8 -8
  630. package/src/modules/customers/components/detail/hooks/useCustomerDictionary.ts +10 -6
  631. package/src/modules/customers/components/detail/hooks/useInteractionMutations.ts +91 -0
  632. package/src/modules/customers/components/detail/notesAdapter.ts +91 -30
  633. package/src/modules/customers/components/detail/pipelineStageUtils.ts +29 -0
  634. package/src/modules/customers/components/detail/schedule/DateTimeFields.tsx +187 -0
  635. package/src/modules/customers/components/detail/schedule/FooterFields.tsx +79 -0
  636. package/src/modules/customers/components/detail/schedule/LinkedEntitiesField.tsx +277 -0
  637. package/src/modules/customers/components/detail/schedule/LocationField.tsx +42 -0
  638. package/src/modules/customers/components/detail/schedule/ParticipantsField.tsx +255 -0
  639. package/src/modules/customers/components/detail/schedule/fieldConfig.ts +70 -0
  640. package/src/modules/customers/components/detail/schedule/index.ts +9 -0
  641. package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +221 -0
  642. package/src/modules/customers/components/detail/types.ts +16 -0
  643. package/src/modules/customers/components/detail/utils.ts +25 -0
  644. package/src/modules/customers/components/formConfig.tsx +223 -28
  645. package/src/modules/customers/components/linking/LinkEntityDialog.tsx +920 -0
  646. package/src/modules/customers/components/linking/adapters/companyAdapter.tsx +398 -0
  647. package/src/modules/customers/components/linking/adapters/dealAdapter.tsx +578 -0
  648. package/src/modules/customers/components/linking/adapters/personAdapter.tsx +512 -0
  649. package/src/modules/customers/components/list/CollectionPreviewCell.tsx +66 -0
  650. package/src/modules/customers/data/entities.ts +353 -1
  651. package/src/modules/customers/data/validators.ts +170 -19
  652. package/src/modules/customers/events.ts +22 -0
  653. package/src/modules/customers/i18n/de.json +841 -2
  654. package/src/modules/customers/i18n/en.json +841 -2
  655. package/src/modules/customers/i18n/es.json +840 -1
  656. package/src/modules/customers/i18n/pl.json +841 -2
  657. package/src/modules/customers/lib/customerRoleTypes.ts +24 -0
  658. package/src/modules/customers/lib/dealClosureNotification.ts +64 -0
  659. package/src/modules/customers/lib/dealStageTransitionTable.ts +32 -0
  660. package/src/modules/customers/lib/dictionaries.ts +26 -10
  661. package/src/modules/customers/lib/interactionReadModel.ts +10 -0
  662. package/src/modules/customers/lib/personCompanies.ts +317 -0
  663. package/src/modules/customers/lib/personCompanyLinkTable.ts +58 -0
  664. package/src/modules/customers/lib/roleTypeUsage.ts +146 -0
  665. package/src/modules/customers/migrations/.snapshot-open-mercato.json +2747 -798
  666. package/src/modules/customers/migrations/Migration20260406214502.ts +19 -0
  667. package/src/modules/customers/migrations/Migration20260408135736.ts +15 -0
  668. package/src/modules/customers/migrations/Migration20260408225345.ts +23 -0
  669. package/src/modules/customers/migrations/Migration20260411075533.ts +30 -0
  670. package/src/modules/customers/migrations/Migration20260411103551.ts +13 -0
  671. package/src/modules/customers/migrations/Migration20260411130944.ts +30 -0
  672. package/src/modules/customers/migrations/Migration20260415095203.ts +13 -0
  673. package/src/modules/customers/migrations/Migration20260415135056.ts +22 -0
  674. package/src/modules/customers/migrations/Migration20260417140000.ts +15 -0
  675. package/src/modules/customers/migrations/Migration20260417160000.ts +17 -0
  676. package/src/modules/customers/migrations/Migration20260417235407.ts +13 -0
  677. package/src/modules/customers/setup.ts +15 -0
  678. package/src/modules/customers/subscribers/deal-closure-notification.ts +22 -0
  679. package/src/modules/customers/subscribers/deal-lost-notification.ts +22 -0
  680. package/src/modules/data_sync/backend/data-sync/page.tsx +9 -9
  681. package/src/modules/data_sync/components/IntegrationScheduleTab.tsx +21 -13
  682. package/src/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.ts +2 -0
  683. package/src/modules/dictionaries/api/[dictionaryId]/entries/reorder/route.ts +162 -0
  684. package/src/modules/dictionaries/api/[dictionaryId]/entries/route.ts +6 -2
  685. package/src/modules/dictionaries/api/[dictionaryId]/entries/set-default/route.ts +162 -0
  686. package/src/modules/dictionaries/api/context.ts +9 -0
  687. package/src/modules/dictionaries/api/openapi.ts +17 -0
  688. package/src/modules/dictionaries/commands/entry-operations.ts +457 -0
  689. package/src/modules/dictionaries/commands/factory.ts +31 -3
  690. package/src/modules/dictionaries/commands/index.ts +1 -0
  691. package/src/modules/dictionaries/components/DictionaryTable.tsx +15 -6
  692. package/src/modules/dictionaries/data/entities.ts +9 -0
  693. package/src/modules/dictionaries/data/validators.ts +34 -0
  694. package/src/modules/dictionaries/events.ts +20 -0
  695. package/src/modules/dictionaries/i18n/de.json +2 -0
  696. package/src/modules/dictionaries/i18n/en.json +2 -0
  697. package/src/modules/dictionaries/i18n/es.json +2 -0
  698. package/src/modules/dictionaries/i18n/pl.json +2 -0
  699. package/src/modules/dictionaries/lib/clientEntries.ts +66 -0
  700. package/src/modules/dictionaries/migrations/.snapshot-open-mercato.json +185 -3
  701. package/src/modules/dictionaries/migrations/Migration20260410171544.ts +49 -0
  702. package/src/modules/inbox_ops/api/proposals/[id]/route.ts +4 -1
  703. package/src/modules/portal/frontend/[orgSlug]/portal/login/page.tsx +9 -3
  704. package/src/modules/portal/frontend/[orgSlug]/portal/page.tsx +4 -2
  705. package/src/modules/portal/frontend/[orgSlug]/portal/signup/page.tsx +9 -3
  706. package/src/modules/portal/frontend/[orgSlug]/portal/verify/page.tsx +4 -2
  707. package/src/modules/query_index/lib/engine.ts +9 -1
  708. package/src/modules/sales/components/documents/AddressesSection.tsx +92 -42
  709. package/src/modules/sales/i18n/de.json +28 -0
  710. package/src/modules/sales/i18n/en.json +28 -0
  711. package/src/modules/sales/i18n/es.json +28 -0
  712. package/src/modules/sales/i18n/pl.json +28 -0
  713. package/src/modules/sales/lib/dictionaries.ts +18 -0
  714. package/src/modules/sales/widgets/injection-table.ts +4 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/data_sync/backend/data-sync/page.tsx"],
4
- "sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport type { ColumnDef } from '@tanstack/react-table'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { Badge, type BadgeProps } from '@open-mercato/ui/primitives/badge'\nimport { Card, CardContent, CardHeader, CardTitle } from '@open-mercato/ui/primitives/card'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport { Notice } from '@open-mercato/ui/primitives/Notice'\nimport { Separator } from '@open-mercato/ui/primitives/separator'\nimport { Switch } from '@open-mercato/ui/primitives/switch'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport {\n ArrowRightLeft,\n Boxes,\n CalendarClock,\n CircleAlert,\n Clock3,\n Gauge,\n Play,\n PlugZap,\n Repeat,\n Settings2,\n ShieldCheck,\n} from 'lucide-react'\n\ntype SyncRunRow = {\n id: string\n integrationId: string\n entityType: string\n direction: 'import' | 'export'\n status: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled' | 'paused'\n createdCount: number\n updatedCount: number\n failedCount: number\n createdAt: string\n}\n\ntype ResponsePayload = {\n items: SyncRunRow[]\n total: number\n page: number\n totalPages: number\n}\n\ntype SyncOption = {\n integrationId: string\n title: string\n description?: string | null\n providerKey?: string | null\n direction: 'import' | 'export' | 'bidirectional'\n supportedEntities: string[]\n hasCredentials: boolean\n isEnabled: boolean\n settingsPath: string\n}\n\ntype SyncOptionsResponse = {\n items: SyncOption[]\n}\n\ntype SyncScheduleRecord = {\n id: string\n integrationId: string\n entityType: string\n direction: 'import' | 'export'\n scheduleType: 'cron' | 'interval'\n scheduleValue: string\n timezone: string\n fullSync: boolean\n isEnabled: boolean\n lastRunAt: string | null\n}\n\ntype SyncSchedulesResponse = {\n items?: SyncScheduleRecord[]\n}\n\ntype SyncScheduleEditorState = {\n id?: string\n scheduleType: 'cron' | 'interval'\n scheduleValue: string\n timezone: string\n fullSync: boolean\n isEnabled: boolean\n lastRunAt: string | null\n}\n\nconst STATUS_STYLES: Record<string, string> = {\n pending: 'bg-gray-100 text-gray-800',\n running: 'bg-blue-100 text-blue-800',\n completed: 'bg-green-100 text-green-800',\n failed: 'bg-red-100 text-red-800',\n cancelled: 'bg-yellow-100 text-yellow-800',\n paused: 'bg-orange-100 text-orange-800',\n}\n\nconst DEFAULT_TIMEZONE = Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC'\n\ntype SummaryBadgeStyle = {\n variant: BadgeProps['variant']\n className?: string\n}\n\nfunction getSummaryBadgeStyle(kind: 'enabled' | 'disabled' | 'ready' | 'missing' | 'scheduled' | 'paused' | 'none'): SummaryBadgeStyle {\n if (kind === 'enabled' || kind === 'ready') {\n return {\n variant: 'outline',\n className: 'border-emerald-500/30 bg-emerald-500/15 text-emerald-200',\n }\n }\n\n if (kind === 'disabled' || kind === 'missing') {\n return {\n variant: 'outline',\n className: 'border-red-500/30 bg-red-500/15 text-red-200',\n }\n }\n\n if (kind === 'paused') {\n return {\n variant: 'outline',\n className: 'border-amber-500/30 bg-amber-500/15 text-amber-200',\n }\n }\n\n if (kind === 'scheduled') {\n return {\n variant: 'outline',\n className: 'border-sky-500/30 bg-sky-500/15 text-sky-200',\n }\n }\n\n return {\n variant: 'outline',\n className: 'border-muted-foreground/20 bg-muted/40 text-muted-foreground',\n }\n}\n\nfunction formatEntityTypeLabel(entityType: string): string {\n return entityType\n .replace(/[_-]+/g, ' ')\n .replace(/\\b\\w/g, (letter) => letter.toUpperCase())\n}\n\nfunction buildDefaultScheduleState(entityType: string): SyncScheduleEditorState {\n const normalized = entityType.trim().toLowerCase()\n const longerInterval = normalized === 'categories' || normalized === 'attributes'\n return {\n scheduleType: 'interval',\n scheduleValue: longerInterval ? '6h' : '1h',\n timezone: DEFAULT_TIMEZONE,\n fullSync: normalized !== 'products',\n isEnabled: true,\n lastRunAt: null,\n }\n}\n\nexport default function SyncRunsDashboardPage() {\n const router = useRouter()\n const [rows, setRows] = React.useState<SyncRunRow[]>([])\n const [options, setOptions] = React.useState<SyncOption[]>([])\n const [page, setPage] = React.useState(1)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [search, setSearch] = React.useState('')\n const [filterValues, setFilterValues] = React.useState<FilterValues>({})\n const [isLoading, setIsLoading] = React.useState(true)\n const [isLoadingOptions, setIsLoadingOptions] = React.useState(true)\n const [selectedIntegrationId, setSelectedIntegrationId] = React.useState('')\n const [selectedEntityType, setSelectedEntityType] = React.useState('')\n const [selectedDirection, setSelectedDirection] = React.useState<'import' | 'export'>('import')\n const [batchSize, setBatchSize] = React.useState('100')\n const [fullSync, setFullSync] = React.useState(false)\n const [scheduleEditor, setScheduleEditor] = React.useState<SyncScheduleEditorState>(() => buildDefaultScheduleState(''))\n const [isLoadingSchedule, setIsLoadingSchedule] = React.useState(false)\n const [isSavingSchedule, setIsSavingSchedule] = React.useState(false)\n const [isDeletingSchedule, setIsDeletingSchedule] = React.useState(false)\n const [reloadToken, setReloadToken] = React.useState(0)\n const scopeVersion = useOrganizationScopeVersion()\n const t = useT()\n const { runMutation } = useGuardedMutation<Record<string, unknown>>({\n contextId: 'data_sync.dashboard',\n })\n\n React.useEffect(() => {\n let cancelled = false\n async function load() {\n setIsLoading(true)\n const params = new URLSearchParams()\n params.set('page', String(page))\n params.set('pageSize', '20')\n if (filterValues.status) params.set('status', filterValues.status as string)\n if (filterValues.direction) params.set('direction', filterValues.direction as string)\n const fallback: ResponsePayload = { items: [], total: 0, page, totalPages: 1 }\n const call = await apiCall<ResponsePayload>(\n `/api/data_sync/runs?${params.toString()}`,\n undefined,\n { fallback },\n )\n if (!call.ok) {\n flash(t('data_sync.dashboard.loadError'), 'error')\n if (!cancelled) setIsLoading(false)\n return\n }\n const payload = call.result ?? fallback\n if (!cancelled) {\n setRows(Array.isArray(payload.items) ? payload.items : [])\n setTotal(payload.total || 0)\n setTotalPages(payload.totalPages || 1)\n setIsLoading(false)\n }\n }\n load()\n return () => { cancelled = true }\n }, [page, filterValues, reloadToken, scopeVersion, t])\n\n React.useEffect(() => {\n let cancelled = false\n async function loadOptions() {\n setIsLoadingOptions(true)\n const fallback: SyncOptionsResponse = { items: [] }\n const call = await apiCall<SyncOptionsResponse>('/api/data_sync/options', undefined, { fallback })\n if (!cancelled) {\n if (!call.ok) {\n flash(t('data_sync.dashboard.loadError'), 'error')\n setOptions([])\n setIsLoadingOptions(false)\n return\n }\n\n const nextItems = Array.isArray(call.result?.items) ? call.result.items : []\n setOptions(nextItems)\n setSelectedIntegrationId((current) => {\n if (current && nextItems.some((item) => item.integrationId === current)) return current\n return nextItems[0]?.integrationId ?? ''\n })\n setIsLoadingOptions(false)\n }\n }\n\n void loadOptions()\n return () => { cancelled = true }\n }, [scopeVersion, t])\n\n const selectedIntegration = React.useMemo(\n () => options.find((item) => item.integrationId === selectedIntegrationId) ?? null,\n [options, selectedIntegrationId],\n )\n\n const entityOptions = React.useMemo(\n () => selectedIntegration?.supportedEntities ?? [],\n [selectedIntegration],\n )\n\n React.useEffect(() => {\n if (!selectedIntegration) {\n setSelectedEntityType('')\n return\n }\n setSelectedEntityType((current) => (\n current && selectedIntegration.supportedEntities.includes(current)\n ? current\n : (selectedIntegration.supportedEntities[0] ?? '')\n ))\n setSelectedDirection(selectedIntegration.direction === 'export' ? 'export' : 'import')\n }, [selectedIntegration])\n\n React.useEffect(() => {\n if (!selectedIntegration || !selectedEntityType) {\n setScheduleEditor(buildDefaultScheduleState(selectedEntityType))\n return\n }\n\n const currentIntegration = selectedIntegration\n let cancelled = false\n async function loadSchedule() {\n setIsLoadingSchedule(true)\n const integrationId = currentIntegration.integrationId\n const params = new URLSearchParams({\n integrationId,\n entityType: selectedEntityType,\n direction: selectedDirection,\n page: '1',\n pageSize: '1',\n })\n const fallback: SyncSchedulesResponse = { items: [] }\n const call = await apiCall<SyncSchedulesResponse>(`/api/data_sync/schedules?${params.toString()}`, undefined, { fallback })\n\n if (cancelled) return\n\n if (!call.ok) {\n setScheduleEditor(buildDefaultScheduleState(selectedEntityType))\n setIsLoadingSchedule(false)\n return\n }\n\n const record = Array.isArray(call.result?.items) ? call.result?.items[0] : undefined\n if (!record) {\n setScheduleEditor(buildDefaultScheduleState(selectedEntityType))\n setIsLoadingSchedule(false)\n return\n }\n\n setScheduleEditor({\n id: record.id,\n scheduleType: record.scheduleType,\n scheduleValue: record.scheduleValue,\n timezone: record.timezone,\n fullSync: record.fullSync,\n isEnabled: record.isEnabled,\n lastRunAt: record.lastRunAt,\n })\n setIsLoadingSchedule(false)\n }\n\n void loadSchedule()\n return () => { cancelled = true }\n }, [selectedDirection, selectedEntityType, selectedIntegration, scopeVersion])\n\n const updateScheduleEditor = React.useCallback((changes: Partial<SyncScheduleEditorState>) => {\n setScheduleEditor((current) => ({ ...current, ...changes }))\n }, [])\n\n const handleCancel = React.useCallback(async (row: SyncRunRow) => {\n const call = await apiCall(`/api/data_sync/runs/${encodeURIComponent(row.id)}/cancel`, {\n method: 'POST',\n }, { fallback: null })\n if (call.ok) {\n flash(t('data_sync.runs.detail.cancelSuccess'), 'success')\n setReloadToken((token) => token + 1)\n } else {\n flash(t('data_sync.runs.detail.cancelError'), 'error')\n }\n }, [t])\n\n const handleRetry = React.useCallback(async (row: SyncRunRow) => {\n const call = await apiCall(`/api/data_sync/runs/${encodeURIComponent(row.id)}/retry`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ fromBeginning: false }),\n }, { fallback: null })\n if (call.ok) {\n flash(t('data_sync.runs.detail.retrySuccess'), 'success')\n setReloadToken((token) => token + 1)\n } else {\n flash(t('data_sync.runs.detail.retryError'), 'error')\n }\n }, [t])\n\n const handleFiltersApply = React.useCallback((values: FilterValues) => {\n const next: FilterValues = {}\n Object.entries(values).forEach(([key, value]) => {\n if (value !== undefined && value !== '') next[key] = value\n })\n setFilterValues(next)\n setPage(1)\n }, [])\n\n const handleFiltersClear = React.useCallback(() => {\n setFilterValues({})\n setPage(1)\n }, [])\n\n const handleStartSync = React.useCallback(async () => {\n if (!selectedIntegration || !selectedEntityType) return\n\n const parsedBatchSize = Number.parseInt(batchSize, 10)\n if (!Number.isFinite(parsedBatchSize) || parsedBatchSize < 1 || parsedBatchSize > 1000) {\n flash(t('data_sync.dashboard.start.invalidBatchSize', 'Batch size must be between 1 and 1000.'), 'error')\n return\n }\n\n try {\n const call = await runMutation({\n operation: () => apiCall<{ id: string }>('/api/data_sync/run', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n integrationId: selectedIntegration.integrationId,\n entityType: selectedEntityType,\n direction: selectedDirection,\n batchSize: parsedBatchSize,\n fullSync,\n }),\n }, { fallback: null }),\n mutationPayload: {\n integrationId: selectedIntegration.integrationId,\n entityType: selectedEntityType,\n direction: selectedDirection,\n batchSize: parsedBatchSize,\n fullSync,\n },\n context: {\n operation: 'create',\n actionId: 'start-sync-run',\n integrationId: selectedIntegration.integrationId,\n },\n })\n\n if (!call.ok || !call.result?.id) {\n flash((call.result as { error?: string } | null)?.error ?? t('data_sync.dashboard.start.error', 'Failed to start sync run'), 'error')\n return\n }\n\n flash(t('data_sync.dashboard.start.success', 'Sync run started'), 'success')\n setReloadToken((token) => token + 1)\n router.push(`/backend/data-sync/runs/${encodeURIComponent(call.result.id)}`)\n } catch (error) {\n const message = error instanceof Error ? error.message : t('data_sync.dashboard.start.error', 'Failed to start sync run')\n flash(message, 'error')\n }\n }, [batchSize, fullSync, router, runMutation, selectedDirection, selectedEntityType, selectedIntegration, t])\n\n const handleSaveSchedule = React.useCallback(async () => {\n if (!selectedIntegration || !selectedEntityType) return\n if (scheduleEditor.scheduleValue.trim().length === 0) {\n flash(t('data_sync.dashboard.schedule.invalidValue', 'Provide a schedule value before saving.'), 'error')\n return\n }\n\n setIsSavingSchedule(true)\n try {\n const call = await runMutation({\n operation: () => apiCall<SyncScheduleRecord>('/api/data_sync/schedules', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n integrationId: selectedIntegration.integrationId,\n entityType: selectedEntityType,\n direction: selectedDirection,\n scheduleType: scheduleEditor.scheduleType,\n scheduleValue: scheduleEditor.scheduleValue.trim(),\n timezone: scheduleEditor.timezone.trim() || DEFAULT_TIMEZONE,\n fullSync: scheduleEditor.fullSync,\n isEnabled: scheduleEditor.isEnabled,\n }),\n }, { fallback: null }),\n mutationPayload: {\n integrationId: selectedIntegration.integrationId,\n entityType: selectedEntityType,\n direction: selectedDirection,\n scheduleType: scheduleEditor.scheduleType,\n scheduleValue: scheduleEditor.scheduleValue.trim(),\n timezone: scheduleEditor.timezone.trim() || DEFAULT_TIMEZONE,\n fullSync: scheduleEditor.fullSync,\n isEnabled: scheduleEditor.isEnabled,\n },\n context: {\n operation: 'update',\n actionId: 'save-sync-schedule',\n integrationId: selectedIntegration.integrationId,\n },\n })\n\n if (!call.ok || !call.result) {\n flash((call.result as { error?: string } | null)?.error ?? t('data_sync.dashboard.schedule.error', 'Failed to save recurring schedule'), 'error')\n return\n }\n\n setScheduleEditor({\n id: call.result.id,\n scheduleType: call.result.scheduleType,\n scheduleValue: call.result.scheduleValue,\n timezone: call.result.timezone,\n fullSync: call.result.fullSync,\n isEnabled: call.result.isEnabled,\n lastRunAt: call.result.lastRunAt,\n })\n flash(t('data_sync.dashboard.schedule.success', 'Recurring schedule saved'), 'success')\n } catch (error) {\n const message = error instanceof Error ? error.message : t('data_sync.dashboard.schedule.error', 'Failed to save recurring schedule')\n flash(message, 'error')\n } finally {\n setIsSavingSchedule(false)\n }\n }, [runMutation, scheduleEditor, selectedDirection, selectedEntityType, selectedIntegration, t])\n\n const handleDeleteSchedule = React.useCallback(async () => {\n if (!scheduleEditor.id) return\n\n setIsDeletingSchedule(true)\n try {\n const call = await runMutation({\n operation: () => apiCall(`/api/data_sync/schedules/${encodeURIComponent(scheduleEditor.id as string)}`, {\n method: 'DELETE',\n }, { fallback: null }),\n mutationPayload: {\n scheduleId: scheduleEditor.id,\n },\n context: {\n operation: 'delete',\n actionId: 'delete-sync-schedule',\n },\n })\n\n if (!call.ok) {\n flash((call.result as { error?: string } | null)?.error ?? t('data_sync.dashboard.schedule.deleteError', 'Failed to remove recurring schedule'), 'error')\n return\n }\n\n setScheduleEditor(buildDefaultScheduleState(selectedEntityType))\n flash(t('data_sync.dashboard.schedule.deleteSuccess', 'Recurring schedule removed'), 'success')\n } catch (error) {\n const message = error instanceof Error ? error.message : t('data_sync.dashboard.schedule.deleteError', 'Failed to remove recurring schedule')\n flash(message, 'error')\n } finally {\n setIsDeletingSchedule(false)\n }\n }, [runMutation, scheduleEditor.id, selectedEntityType, t])\n\n const filters: FilterDef[] = [\n {\n id: 'status',\n type: 'select',\n label: t('data_sync.dashboard.filters.status'),\n options: [\n { label: t('data_sync.dashboard.filters.allStatuses'), value: '' },\n { label: t('data_sync.dashboard.status.pending'), value: 'pending' },\n { label: t('data_sync.dashboard.status.running'), value: 'running' },\n { label: t('data_sync.dashboard.status.completed'), value: 'completed' },\n { label: t('data_sync.dashboard.status.failed'), value: 'failed' },\n { label: t('data_sync.dashboard.status.cancelled'), value: 'cancelled' },\n ],\n },\n {\n id: 'direction',\n type: 'select',\n label: t('data_sync.dashboard.columns.direction'),\n options: [\n { label: t('data_sync.dashboard.filters.allDirections'), value: '' },\n { label: t('data_sync.dashboard.direction.import'), value: 'import' },\n { label: t('data_sync.dashboard.direction.export'), value: 'export' },\n ],\n },\n ]\n\n const columns = React.useMemo<ColumnDef<SyncRunRow>[]>(() => [\n {\n accessorKey: 'integrationId',\n header: t('data_sync.dashboard.columns.integration'),\n cell: ({ row }) => <span className=\"font-medium text-sm\">{row.original.integrationId}</span>,\n },\n {\n accessorKey: 'entityType',\n header: t('data_sync.dashboard.columns.entityType'),\n },\n {\n accessorKey: 'direction',\n header: t('data_sync.dashboard.columns.direction'),\n cell: ({ row }) => (\n <Badge variant=\"outline\">\n {t(`data_sync.dashboard.direction.${row.original.direction}`)}\n </Badge>\n ),\n },\n {\n accessorKey: 'status',\n header: t('data_sync.dashboard.columns.status'),\n cell: ({ row }) => (\n <Badge variant=\"secondary\" className={STATUS_STYLES[row.original.status] ?? ''}>\n {t(`data_sync.dashboard.status.${row.original.status}`)}\n </Badge>\n ),\n },\n {\n accessorKey: 'createdCount',\n header: t('data_sync.dashboard.columns.created'),\n },\n {\n accessorKey: 'updatedCount',\n header: t('data_sync.dashboard.columns.updated'),\n },\n {\n accessorKey: 'failedCount',\n header: t('data_sync.dashboard.columns.failed'),\n },\n {\n accessorKey: 'createdAt',\n header: t('data_sync.dashboard.columns.createdAt'),\n cell: ({ row }) => new Date(row.original.createdAt).toLocaleString(),\n },\n ], [t])\n\n const canStartSelectedIntegration = Boolean(\n selectedIntegration\n && selectedEntityType\n && selectedIntegration.isEnabled\n && selectedIntegration.hasCredentials,\n )\n const hasSavedSchedule = Boolean(scheduleEditor.id)\n const selectedEntityLabel = selectedEntityType ? formatEntityTypeLabel(selectedEntityType) : t('data_sync.dashboard.columns.entityType')\n const integrationStateBadge = getSummaryBadgeStyle(selectedIntegration?.isEnabled ? 'enabled' : 'disabled')\n const credentialsBadge = getSummaryBadgeStyle(selectedIntegration?.hasCredentials ? 'ready' : 'missing')\n const scheduleBadge = getSummaryBadgeStyle(\n hasSavedSchedule\n ? (scheduleEditor.isEnabled ? 'scheduled' : 'paused')\n : 'none',\n )\n\n return (\n <Page>\n <PageBody className=\"space-y-6\">\n <Card>\n <CardHeader className=\"space-y-4\">\n <div className=\"flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between\">\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-2 text-xs font-medium uppercase tracking-[0.14em] text-muted-foreground\">\n <Repeat className=\"size-4\" />\n <span>{t('data_sync.dashboard.start.eyebrow', 'Run once or keep it recurring')}</span>\n </div>\n <div className=\"space-y-1\">\n <CardTitle>{t('data_sync.dashboard.start.title', 'Start or schedule a sync')}</CardTitle>\n <p className=\"max-w-3xl text-sm text-muted-foreground\">\n {t('data_sync.dashboard.start.description', 'Pick a sync target, launch an ad-hoc run, or save a recurring schedule for the same entity and direction from this page.')}\n </p>\n </div>\n </div>\n {selectedIntegration ? (\n <Button asChild variant=\"outline\">\n <Link href={selectedIntegration.settingsPath}>\n <Settings2 className=\"mr-2 size-4\" />\n {t('integrations.marketplace.configure')}\n </Link>\n </Button>\n ) : null}\n </div>\n\n {selectedIntegration ? (\n <div className=\"flex flex-wrap gap-2\">\n <Badge variant=\"outline\" className=\"gap-1.5\">\n <PlugZap className=\"size-3.5\" />\n {selectedIntegration.title}\n </Badge>\n <Badge variant=\"outline\" className=\"gap-1.5\">\n <ArrowRightLeft className=\"size-3.5\" />\n {t(`data_sync.dashboard.direction.${selectedDirection}`)}\n </Badge>\n <Badge variant={integrationStateBadge.variant} className={`gap-1.5 ${integrationStateBadge.className ?? ''}`}>\n <ShieldCheck className=\"size-3.5\" />\n {selectedIntegration.isEnabled\n ? t('data_sync.dashboard.start.status.enabled', 'Integration enabled')\n : t('data_sync.dashboard.start.status.disabled', 'Integration disabled')}\n </Badge>\n <Badge variant={credentialsBadge.variant} className={`gap-1.5 ${credentialsBadge.className ?? ''}`}>\n <PlugZap className=\"size-3.5\" />\n {selectedIntegration.hasCredentials\n ? t('data_sync.dashboard.start.status.credentialsReady', 'Credentials ready')\n : t('data_sync.dashboard.start.status.credentialsMissing', 'Credentials missing')}\n </Badge>\n <Badge variant={scheduleBadge.variant} className={`gap-1.5 ${scheduleBadge.className ?? ''}`}>\n <CalendarClock className=\"size-3.5\" />\n {hasSavedSchedule\n ? (scheduleEditor.isEnabled\n ? t('data_sync.dashboard.schedule.status.enabled', 'Recurring schedule active')\n : t('data_sync.dashboard.schedule.status.disabled', 'Recurring schedule paused'))\n : t('data_sync.dashboard.schedule.status.none', 'No recurring schedule')}\n </Badge>\n </div>\n ) : null}\n </CardHeader>\n <CardContent className=\"space-y-6\">\n <div className=\"grid gap-4 xl:grid-cols-3\">\n <div className=\"space-y-2 xl:col-span-1\">\n <Label className=\"flex items-center gap-2 text-sm font-medium\">\n <PlugZap className=\"size-4 text-muted-foreground\" />\n <span>{t('data_sync.dashboard.columns.integration')}</span>\n </Label>\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={selectedIntegrationId}\n onChange={(event) => setSelectedIntegrationId(event.target.value)}\n disabled={isLoadingOptions || options.length === 0}\n >\n {options.length === 0 ? (\n <option value=\"\">{t('integrations.marketplace.noResults', 'No integrations found')}</option>\n ) : null}\n {options.map((item) => (\n <option key={item.integrationId} value={item.integrationId}>\n {item.title}\n </option>\n ))}\n </select>\n </div>\n <div className=\"space-y-2\">\n <Label className=\"flex items-center gap-2 text-sm font-medium\">\n <Boxes className=\"size-4 text-muted-foreground\" />\n <span>{t('data_sync.dashboard.columns.entityType')}</span>\n </Label>\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={selectedEntityType}\n onChange={(event) => setSelectedEntityType(event.target.value)}\n disabled={entityOptions.length === 0}\n >\n {entityOptions.map((entityType) => (\n <option key={entityType} value={entityType}>\n {formatEntityTypeLabel(entityType)}\n </option>\n ))}\n </select>\n </div>\n <div className=\"space-y-2\">\n <Label className=\"flex items-center gap-2 text-sm font-medium\">\n <ArrowRightLeft className=\"size-4 text-muted-foreground\" />\n <span>{t('data_sync.dashboard.columns.direction')}</span>\n </Label>\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={selectedDirection}\n onChange={(event) => setSelectedDirection(event.target.value === 'export' ? 'export' : 'import')}\n disabled={selectedIntegration?.direction !== 'bidirectional'}\n >\n <option value=\"import\">{t('data_sync.dashboard.direction.import')}</option>\n {(selectedIntegration?.direction === 'bidirectional' || selectedIntegration?.direction === 'export') ? (\n <option value=\"export\">{t('data_sync.dashboard.direction.export')}</option>\n ) : null}\n </select>\n </div>\n </div>\n\n {selectedIntegration?.description ? (\n <p className=\"text-sm text-muted-foreground\">{selectedIntegration.description}</p>\n ) : null}\n\n <div className=\"grid gap-4 xl:grid-cols-2\">\n <div className=\"rounded-xl border bg-muted/20 p-4\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"space-y-1\">\n <div className=\"flex items-center gap-2\">\n <Play className=\"size-4 text-primary\" />\n <h3 className=\"text-sm font-semibold\">{t('data_sync.dashboard.start.runNowTitle', 'Run once now')}</h3>\n </div>\n <p className=\"text-sm text-muted-foreground\">\n {t('data_sync.dashboard.start.runNowDescription', 'Use this for the next immediate sync. Batch size and full-sync mode apply only to this manual run.')}\n </p>\n </div>\n <Badge variant=\"outline\">{selectedEntityLabel}</Badge>\n </div>\n\n <Separator className=\"my-4\" />\n\n <div className=\"grid gap-4 sm:grid-cols-[minmax(0,180px)_1fr]\">\n <div className=\"space-y-2\">\n <Label className=\"flex items-center gap-2 text-sm font-medium\">\n <Gauge className=\"size-4 text-muted-foreground\" />\n <span>{t('data_sync.dashboard.start.batchSize', 'Batch size')}</span>\n </Label>\n <Input\n value={batchSize}\n onChange={(event) => setBatchSize(event.target.value)}\n inputMode=\"numeric\"\n />\n </div>\n <div className=\"rounded-lg border bg-background p-3\">\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"space-y-1\">\n <Label className=\"text-sm font-medium\">{t('data_sync.dashboard.start.fullSync', 'Run as full sync')}</Label>\n <p className=\"text-xs text-muted-foreground\">\n {t('data_sync.dashboard.start.fullSyncHelp', 'Ignore the saved cursor and process the entire source again for this run.')}\n </p>\n </div>\n <Switch checked={fullSync} onCheckedChange={setFullSync} />\n </div>\n </div>\n </div>\n\n <div className=\"mt-4 flex flex-wrap items-center justify-between gap-3\">\n <p className=\"text-xs text-muted-foreground\">\n {t('data_sync.dashboard.start.runNowFootnote', 'Manual runs show progress immediately and land on the run detail page after launch.')}\n </p>\n <Button\n type=\"button\"\n onClick={() => void handleStartSync()}\n disabled={!canStartSelectedIntegration}\n >\n <Play className=\"mr-2 size-4\" />\n {t('data_sync.dashboard.start.submit', 'Start sync')}\n </Button>\n </div>\n </div>\n\n <div className=\"rounded-xl border bg-muted/20 p-4\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"space-y-1\">\n <div className=\"flex items-center gap-2\">\n <CalendarClock className=\"size-4 text-primary\" />\n <h3 className=\"text-sm font-semibold\">{t('data_sync.dashboard.schedule.title', 'Recurring schedule')}</h3>\n </div>\n <p className=\"text-sm text-muted-foreground\">\n {t('data_sync.dashboard.schedule.description', 'Save a repeating schedule for the selected integration, entity, and direction without leaving this dashboard.')}\n </p>\n </div>\n <Badge variant=\"outline\">\n {hasSavedSchedule\n ? (scheduleEditor.isEnabled\n ? t('data_sync.dashboard.schedule.status.shortEnabled', 'Scheduled')\n : t('data_sync.dashboard.schedule.status.shortDisabled', 'Paused'))\n : t('data_sync.dashboard.schedule.status.shortNone', 'One-time only')}\n </Badge>\n </div>\n\n <Separator className=\"my-4\" />\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label className=\"flex items-center gap-2 text-sm font-medium\">\n <Clock3 className=\"size-4 text-muted-foreground\" />\n <span>{t('data_sync.dashboard.schedule.type', 'Schedule type')}</span>\n </Label>\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={scheduleEditor.scheduleType}\n onChange={(event) => updateScheduleEditor({\n scheduleType: event.target.value === 'cron' ? 'cron' : 'interval',\n })}\n disabled={isLoadingSchedule || isSavingSchedule || isDeletingSchedule || !selectedIntegration || !selectedEntityType}\n >\n <option value=\"interval\">{t('data_sync.dashboard.schedule.interval', 'Interval')}</option>\n <option value=\"cron\">{t('data_sync.dashboard.schedule.cron', 'Cron')}</option>\n </select>\n </div>\n <div className=\"space-y-2\">\n <Label className=\"flex items-center gap-2 text-sm font-medium\">\n <CalendarClock className=\"size-4 text-muted-foreground\" />\n <span>\n {scheduleEditor.scheduleType === 'cron'\n ? t('data_sync.dashboard.schedule.cronValue', 'Cron expression')\n : t('data_sync.dashboard.schedule.intervalValue', 'Interval')}\n </span>\n </Label>\n <Input\n value={scheduleEditor.scheduleValue}\n onChange={(event) => updateScheduleEditor({ scheduleValue: event.target.value })}\n disabled={isLoadingSchedule || isSavingSchedule || isDeletingSchedule || !selectedIntegration || !selectedEntityType}\n placeholder={scheduleEditor.scheduleType === 'cron' ? '0 * * * *' : '1h'}\n />\n <p className=\"text-xs text-muted-foreground\">\n {scheduleEditor.scheduleType === 'cron'\n ? t('data_sync.dashboard.schedule.cronHelp', 'Example: `0 * * * *` runs at the start of every hour.')\n : t('data_sync.dashboard.schedule.intervalHelp', 'Example: `1h`, `6h`, or `24h` for repeating intervals.')}\n </p>\n </div>\n <div className=\"space-y-2 sm:col-span-2\">\n <Label className=\"flex items-center gap-2 text-sm font-medium\">\n <Clock3 className=\"size-4 text-muted-foreground\" />\n <span>{t('data_sync.dashboard.schedule.timezone', 'Timezone')}</span>\n </Label>\n <Input\n value={scheduleEditor.timezone}\n onChange={(event) => updateScheduleEditor({ timezone: event.target.value })}\n disabled={isLoadingSchedule || isSavingSchedule || isDeletingSchedule || !selectedIntegration || !selectedEntityType}\n />\n </div>\n </div>\n\n <div className=\"mt-4 grid gap-3\">\n <div className=\"rounded-lg border bg-background p-3\">\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"space-y-1\">\n <Label className=\"text-sm font-medium\">{t('data_sync.dashboard.schedule.fullSync', 'Run scheduled jobs as full sync')}</Label>\n <p className=\"text-xs text-muted-foreground\">\n {t('data_sync.dashboard.schedule.fullSyncHelp', 'When enabled, every recurring run starts from the beginning instead of the saved cursor.')}\n </p>\n </div>\n <Switch\n checked={scheduleEditor.fullSync}\n onCheckedChange={(checked) => updateScheduleEditor({ fullSync: checked })}\n disabled={isLoadingSchedule || isSavingSchedule || isDeletingSchedule || !selectedIntegration || !selectedEntityType}\n />\n </div>\n </div>\n <div className=\"rounded-lg border bg-background p-3\">\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"space-y-1\">\n <Label className=\"text-sm font-medium\">{t('data_sync.dashboard.schedule.enabled', 'Schedule enabled')}</Label>\n <p className=\"text-xs text-muted-foreground\">\n {t('data_sync.dashboard.schedule.enabledHelp', 'Pause the recurring job without deleting the schedule definition.')}\n </p>\n </div>\n <Switch\n checked={scheduleEditor.isEnabled}\n onCheckedChange={(checked) => updateScheduleEditor({ isEnabled: checked })}\n disabled={isLoadingSchedule || isSavingSchedule || isDeletingSchedule || !selectedIntegration || !selectedEntityType}\n />\n </div>\n </div>\n </div>\n\n <div className=\"mt-4 flex flex-wrap items-center justify-between gap-3\">\n <div className=\"space-y-1 text-xs text-muted-foreground\">\n <div>\n {hasSavedSchedule\n ? (scheduleEditor.lastRunAt\n ? t('data_sync.dashboard.schedule.lastRun', 'Last scheduled run: {value}', {\n value: new Date(scheduleEditor.lastRunAt).toLocaleString(),\n })\n : t('data_sync.dashboard.schedule.neverRun', 'Saved, but no scheduled execution has completed yet.'))\n : t('data_sync.dashboard.schedule.none', 'No recurring schedule saved for this target yet.')}\n </div>\n </div>\n <div className=\"flex flex-wrap gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => void handleDeleteSchedule()}\n disabled={!hasSavedSchedule || isDeletingSchedule}\n >\n {isDeletingSchedule\n ? t('data_sync.dashboard.schedule.deleting', 'Removing...')\n : t('data_sync.dashboard.schedule.delete', 'Remove schedule')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => void handleSaveSchedule()}\n disabled={isSavingSchedule || !selectedIntegration || !selectedEntityType}\n >\n <CalendarClock className=\"mr-2 size-4\" />\n {isSavingSchedule\n ? t('data_sync.dashboard.schedule.saving', 'Saving...')\n : t('data_sync.dashboard.schedule.save', 'Save recurring schedule')}\n </Button>\n </div>\n </div>\n </div>\n </div>\n\n {selectedIntegration && !selectedIntegration.isEnabled ? (\n <Notice compact variant=\"warning\">\n <span className=\"inline-flex items-center gap-2\">\n <CircleAlert className=\"size-4\" />\n <span>{t('integrations.detail.state.disabled', 'This integration is disabled. Enable it on the integration settings page before starting a sync.')}</span>\n </span>\n </Notice>\n ) : null}\n {selectedIntegration && !selectedIntegration.hasCredentials ? (\n <Notice compact variant=\"warning\">\n <span className=\"inline-flex items-center gap-2\">\n <CircleAlert className=\"size-4\" />\n <span>{t('integrations.detail.credentials.notConfigured', 'Credentials are not configured yet. Save the integration credentials before starting a sync.')}</span>\n </span>\n </Notice>\n ) : null}\n </CardContent>\n </Card>\n\n <DataTable\n stickyActionsColumn\n title={t('data_sync.dashboard.title')}\n columns={columns}\n data={rows}\n filters={filters}\n filterValues={filterValues}\n onFiltersApply={handleFiltersApply}\n onFiltersClear={handleFiltersClear}\n searchValue={search}\n onSearchChange={(value) => { setSearch(value); setPage(1) }}\n perspective={{ tableId: 'data_sync.runs' }}\n onRowClick={(row) => {\n router.push(`/backend/data-sync/runs/${encodeURIComponent(row.id)}`)\n }}\n rowActions={(row) => (\n <RowActions items={[\n {\n id: 'view',\n label: t('data_sync.dashboard.actions.view'),\n onSelect: () => { router.push(`/backend/data-sync/runs/${encodeURIComponent(row.id)}`) },\n },\n ...(row.status === 'running' ? [{\n id: 'cancel',\n label: t('data_sync.runs.detail.cancel'),\n destructive: true,\n onSelect: () => { void handleCancel(row) },\n }] : []),\n ...(row.status === 'failed' ? [{\n id: 'retry',\n label: t('data_sync.runs.detail.retry'),\n onSelect: () => { void handleRetry(row) },\n }] : []),\n ]} />\n )}\n pagination={{ page, pageSize: 20, total, totalPages, onPageChange: setPage }}\n isLoading={isLoading}\n />\n </PageBody>\n </Page>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport type { ColumnDef } from '@tanstack/react-table'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { Badge, type BadgeProps } from '@open-mercato/ui/primitives/badge'\nimport { Card, CardContent, CardHeader, CardTitle } from '@open-mercato/ui/primitives/card'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport { Alert, AlertDescription } from '@open-mercato/ui/primitives/alert'\nimport { Separator } from '@open-mercato/ui/primitives/separator'\nimport { Switch } from '@open-mercato/ui/primitives/switch'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport {\n ArrowRightLeft,\n Boxes,\n CalendarClock,\n CircleAlert,\n Clock3,\n Gauge,\n Play,\n PlugZap,\n Repeat,\n Settings2,\n ShieldCheck,\n} from 'lucide-react'\n\ntype SyncRunRow = {\n id: string\n integrationId: string\n entityType: string\n direction: 'import' | 'export'\n status: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled' | 'paused'\n createdCount: number\n updatedCount: number\n failedCount: number\n createdAt: string\n}\n\ntype ResponsePayload = {\n items: SyncRunRow[]\n total: number\n page: number\n totalPages: number\n}\n\ntype SyncOption = {\n integrationId: string\n title: string\n description?: string | null\n providerKey?: string | null\n direction: 'import' | 'export' | 'bidirectional'\n supportedEntities: string[]\n hasCredentials: boolean\n isEnabled: boolean\n settingsPath: string\n}\n\ntype SyncOptionsResponse = {\n items: SyncOption[]\n}\n\ntype SyncScheduleRecord = {\n id: string\n integrationId: string\n entityType: string\n direction: 'import' | 'export'\n scheduleType: 'cron' | 'interval'\n scheduleValue: string\n timezone: string\n fullSync: boolean\n isEnabled: boolean\n lastRunAt: string | null\n}\n\ntype SyncSchedulesResponse = {\n items?: SyncScheduleRecord[]\n}\n\ntype SyncScheduleEditorState = {\n id?: string\n scheduleType: 'cron' | 'interval'\n scheduleValue: string\n timezone: string\n fullSync: boolean\n isEnabled: boolean\n lastRunAt: string | null\n}\n\nconst STATUS_STYLES: Record<string, string> = {\n pending: 'bg-gray-100 text-gray-800',\n running: 'bg-blue-100 text-blue-800',\n completed: 'bg-green-100 text-green-800',\n failed: 'bg-red-100 text-red-800',\n cancelled: 'bg-yellow-100 text-yellow-800',\n paused: 'bg-orange-100 text-orange-800',\n}\n\nconst DEFAULT_TIMEZONE = Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC'\n\ntype SummaryBadgeStyle = {\n variant: BadgeProps['variant']\n className?: string\n}\n\nfunction getSummaryBadgeStyle(kind: 'enabled' | 'disabled' | 'ready' | 'missing' | 'scheduled' | 'paused' | 'none'): SummaryBadgeStyle {\n if (kind === 'enabled' || kind === 'ready') {\n return {\n variant: 'outline',\n className: 'border-emerald-500/30 bg-emerald-500/15 text-emerald-200',\n }\n }\n\n if (kind === 'disabled' || kind === 'missing') {\n return {\n variant: 'outline',\n className: 'border-red-500/30 bg-red-500/15 text-red-200',\n }\n }\n\n if (kind === 'paused') {\n return {\n variant: 'outline',\n className: 'border-amber-500/30 bg-amber-500/15 text-amber-200',\n }\n }\n\n if (kind === 'scheduled') {\n return {\n variant: 'outline',\n className: 'border-sky-500/30 bg-sky-500/15 text-sky-200',\n }\n }\n\n return {\n variant: 'outline',\n className: 'border-muted-foreground/20 bg-muted/40 text-muted-foreground',\n }\n}\n\nfunction formatEntityTypeLabel(entityType: string): string {\n return entityType\n .replace(/[_-]+/g, ' ')\n .replace(/\\b\\w/g, (letter) => letter.toUpperCase())\n}\n\nfunction buildDefaultScheduleState(entityType: string): SyncScheduleEditorState {\n const normalized = entityType.trim().toLowerCase()\n const longerInterval = normalized === 'categories' || normalized === 'attributes'\n return {\n scheduleType: 'interval',\n scheduleValue: longerInterval ? '6h' : '1h',\n timezone: DEFAULT_TIMEZONE,\n fullSync: normalized !== 'products',\n isEnabled: true,\n lastRunAt: null,\n }\n}\n\nexport default function SyncRunsDashboardPage() {\n const router = useRouter()\n const [rows, setRows] = React.useState<SyncRunRow[]>([])\n const [options, setOptions] = React.useState<SyncOption[]>([])\n const [page, setPage] = React.useState(1)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [search, setSearch] = React.useState('')\n const [filterValues, setFilterValues] = React.useState<FilterValues>({})\n const [isLoading, setIsLoading] = React.useState(true)\n const [isLoadingOptions, setIsLoadingOptions] = React.useState(true)\n const [selectedIntegrationId, setSelectedIntegrationId] = React.useState('')\n const [selectedEntityType, setSelectedEntityType] = React.useState('')\n const [selectedDirection, setSelectedDirection] = React.useState<'import' | 'export'>('import')\n const [batchSize, setBatchSize] = React.useState('100')\n const [fullSync, setFullSync] = React.useState(false)\n const [scheduleEditor, setScheduleEditor] = React.useState<SyncScheduleEditorState>(() => buildDefaultScheduleState(''))\n const [isLoadingSchedule, setIsLoadingSchedule] = React.useState(false)\n const [isSavingSchedule, setIsSavingSchedule] = React.useState(false)\n const [isDeletingSchedule, setIsDeletingSchedule] = React.useState(false)\n const [reloadToken, setReloadToken] = React.useState(0)\n const scopeVersion = useOrganizationScopeVersion()\n const t = useT()\n const { runMutation } = useGuardedMutation<Record<string, unknown>>({\n contextId: 'data_sync.dashboard',\n })\n\n React.useEffect(() => {\n let cancelled = false\n async function load() {\n setIsLoading(true)\n const params = new URLSearchParams()\n params.set('page', String(page))\n params.set('pageSize', '20')\n if (filterValues.status) params.set('status', filterValues.status as string)\n if (filterValues.direction) params.set('direction', filterValues.direction as string)\n const fallback: ResponsePayload = { items: [], total: 0, page, totalPages: 1 }\n const call = await apiCall<ResponsePayload>(\n `/api/data_sync/runs?${params.toString()}`,\n undefined,\n { fallback },\n )\n if (!call.ok) {\n flash(t('data_sync.dashboard.loadError'), 'error')\n if (!cancelled) setIsLoading(false)\n return\n }\n const payload = call.result ?? fallback\n if (!cancelled) {\n setRows(Array.isArray(payload.items) ? payload.items : [])\n setTotal(payload.total || 0)\n setTotalPages(payload.totalPages || 1)\n setIsLoading(false)\n }\n }\n load()\n return () => { cancelled = true }\n }, [page, filterValues, reloadToken, scopeVersion, t])\n\n React.useEffect(() => {\n let cancelled = false\n async function loadOptions() {\n setIsLoadingOptions(true)\n const fallback: SyncOptionsResponse = { items: [] }\n const call = await apiCall<SyncOptionsResponse>('/api/data_sync/options', undefined, { fallback })\n if (!cancelled) {\n if (!call.ok) {\n flash(t('data_sync.dashboard.loadError'), 'error')\n setOptions([])\n setIsLoadingOptions(false)\n return\n }\n\n const nextItems = Array.isArray(call.result?.items) ? call.result.items : []\n setOptions(nextItems)\n setSelectedIntegrationId((current) => {\n if (current && nextItems.some((item) => item.integrationId === current)) return current\n return nextItems[0]?.integrationId ?? ''\n })\n setIsLoadingOptions(false)\n }\n }\n\n void loadOptions()\n return () => { cancelled = true }\n }, [scopeVersion, t])\n\n const selectedIntegration = React.useMemo(\n () => options.find((item) => item.integrationId === selectedIntegrationId) ?? null,\n [options, selectedIntegrationId],\n )\n\n const entityOptions = React.useMemo(\n () => selectedIntegration?.supportedEntities ?? [],\n [selectedIntegration],\n )\n\n React.useEffect(() => {\n if (!selectedIntegration) {\n setSelectedEntityType('')\n return\n }\n setSelectedEntityType((current) => (\n current && selectedIntegration.supportedEntities.includes(current)\n ? current\n : (selectedIntegration.supportedEntities[0] ?? '')\n ))\n setSelectedDirection(selectedIntegration.direction === 'export' ? 'export' : 'import')\n }, [selectedIntegration])\n\n React.useEffect(() => {\n if (!selectedIntegration || !selectedEntityType) {\n setScheduleEditor(buildDefaultScheduleState(selectedEntityType))\n return\n }\n\n const currentIntegration = selectedIntegration\n let cancelled = false\n async function loadSchedule() {\n setIsLoadingSchedule(true)\n const integrationId = currentIntegration.integrationId\n const params = new URLSearchParams({\n integrationId,\n entityType: selectedEntityType,\n direction: selectedDirection,\n page: '1',\n pageSize: '1',\n })\n const fallback: SyncSchedulesResponse = { items: [] }\n const call = await apiCall<SyncSchedulesResponse>(`/api/data_sync/schedules?${params.toString()}`, undefined, { fallback })\n\n if (cancelled) return\n\n if (!call.ok) {\n setScheduleEditor(buildDefaultScheduleState(selectedEntityType))\n setIsLoadingSchedule(false)\n return\n }\n\n const record = Array.isArray(call.result?.items) ? call.result?.items[0] : undefined\n if (!record) {\n setScheduleEditor(buildDefaultScheduleState(selectedEntityType))\n setIsLoadingSchedule(false)\n return\n }\n\n setScheduleEditor({\n id: record.id,\n scheduleType: record.scheduleType,\n scheduleValue: record.scheduleValue,\n timezone: record.timezone,\n fullSync: record.fullSync,\n isEnabled: record.isEnabled,\n lastRunAt: record.lastRunAt,\n })\n setIsLoadingSchedule(false)\n }\n\n void loadSchedule()\n return () => { cancelled = true }\n }, [selectedDirection, selectedEntityType, selectedIntegration, scopeVersion])\n\n const updateScheduleEditor = React.useCallback((changes: Partial<SyncScheduleEditorState>) => {\n setScheduleEditor((current) => ({ ...current, ...changes }))\n }, [])\n\n const handleCancel = React.useCallback(async (row: SyncRunRow) => {\n const call = await apiCall(`/api/data_sync/runs/${encodeURIComponent(row.id)}/cancel`, {\n method: 'POST',\n }, { fallback: null })\n if (call.ok) {\n flash(t('data_sync.runs.detail.cancelSuccess'), 'success')\n setReloadToken((token) => token + 1)\n } else {\n flash(t('data_sync.runs.detail.cancelError'), 'error')\n }\n }, [t])\n\n const handleRetry = React.useCallback(async (row: SyncRunRow) => {\n const call = await apiCall(`/api/data_sync/runs/${encodeURIComponent(row.id)}/retry`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ fromBeginning: false }),\n }, { fallback: null })\n if (call.ok) {\n flash(t('data_sync.runs.detail.retrySuccess'), 'success')\n setReloadToken((token) => token + 1)\n } else {\n flash(t('data_sync.runs.detail.retryError'), 'error')\n }\n }, [t])\n\n const handleFiltersApply = React.useCallback((values: FilterValues) => {\n const next: FilterValues = {}\n Object.entries(values).forEach(([key, value]) => {\n if (value !== undefined && value !== '') next[key] = value\n })\n setFilterValues(next)\n setPage(1)\n }, [])\n\n const handleFiltersClear = React.useCallback(() => {\n setFilterValues({})\n setPage(1)\n }, [])\n\n const handleStartSync = React.useCallback(async () => {\n if (!selectedIntegration || !selectedEntityType) return\n\n const parsedBatchSize = Number.parseInt(batchSize, 10)\n if (!Number.isFinite(parsedBatchSize) || parsedBatchSize < 1 || parsedBatchSize > 1000) {\n flash(t('data_sync.dashboard.start.invalidBatchSize', 'Batch size must be between 1 and 1000.'), 'error')\n return\n }\n\n try {\n const call = await runMutation({\n operation: () => apiCall<{ id: string }>('/api/data_sync/run', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n integrationId: selectedIntegration.integrationId,\n entityType: selectedEntityType,\n direction: selectedDirection,\n batchSize: parsedBatchSize,\n fullSync,\n }),\n }, { fallback: null }),\n mutationPayload: {\n integrationId: selectedIntegration.integrationId,\n entityType: selectedEntityType,\n direction: selectedDirection,\n batchSize: parsedBatchSize,\n fullSync,\n },\n context: {\n operation: 'create',\n actionId: 'start-sync-run',\n integrationId: selectedIntegration.integrationId,\n },\n })\n\n if (!call.ok || !call.result?.id) {\n flash((call.result as { error?: string } | null)?.error ?? t('data_sync.dashboard.start.error', 'Failed to start sync run'), 'error')\n return\n }\n\n flash(t('data_sync.dashboard.start.success', 'Sync run started'), 'success')\n setReloadToken((token) => token + 1)\n router.push(`/backend/data-sync/runs/${encodeURIComponent(call.result.id)}`)\n } catch (error) {\n const message = error instanceof Error ? error.message : t('data_sync.dashboard.start.error', 'Failed to start sync run')\n flash(message, 'error')\n }\n }, [batchSize, fullSync, router, runMutation, selectedDirection, selectedEntityType, selectedIntegration, t])\n\n const handleSaveSchedule = React.useCallback(async () => {\n if (!selectedIntegration || !selectedEntityType) return\n if (scheduleEditor.scheduleValue.trim().length === 0) {\n flash(t('data_sync.dashboard.schedule.invalidValue', 'Provide a schedule value before saving.'), 'error')\n return\n }\n\n setIsSavingSchedule(true)\n try {\n const call = await runMutation({\n operation: () => apiCall<SyncScheduleRecord>('/api/data_sync/schedules', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n integrationId: selectedIntegration.integrationId,\n entityType: selectedEntityType,\n direction: selectedDirection,\n scheduleType: scheduleEditor.scheduleType,\n scheduleValue: scheduleEditor.scheduleValue.trim(),\n timezone: scheduleEditor.timezone.trim() || DEFAULT_TIMEZONE,\n fullSync: scheduleEditor.fullSync,\n isEnabled: scheduleEditor.isEnabled,\n }),\n }, { fallback: null }),\n mutationPayload: {\n integrationId: selectedIntegration.integrationId,\n entityType: selectedEntityType,\n direction: selectedDirection,\n scheduleType: scheduleEditor.scheduleType,\n scheduleValue: scheduleEditor.scheduleValue.trim(),\n timezone: scheduleEditor.timezone.trim() || DEFAULT_TIMEZONE,\n fullSync: scheduleEditor.fullSync,\n isEnabled: scheduleEditor.isEnabled,\n },\n context: {\n operation: 'update',\n actionId: 'save-sync-schedule',\n integrationId: selectedIntegration.integrationId,\n },\n })\n\n if (!call.ok || !call.result) {\n flash((call.result as { error?: string } | null)?.error ?? t('data_sync.dashboard.schedule.error', 'Failed to save recurring schedule'), 'error')\n return\n }\n\n setScheduleEditor({\n id: call.result.id,\n scheduleType: call.result.scheduleType,\n scheduleValue: call.result.scheduleValue,\n timezone: call.result.timezone,\n fullSync: call.result.fullSync,\n isEnabled: call.result.isEnabled,\n lastRunAt: call.result.lastRunAt,\n })\n flash(t('data_sync.dashboard.schedule.success', 'Recurring schedule saved'), 'success')\n } catch (error) {\n const message = error instanceof Error ? error.message : t('data_sync.dashboard.schedule.error', 'Failed to save recurring schedule')\n flash(message, 'error')\n } finally {\n setIsSavingSchedule(false)\n }\n }, [runMutation, scheduleEditor, selectedDirection, selectedEntityType, selectedIntegration, t])\n\n const handleDeleteSchedule = React.useCallback(async () => {\n if (!scheduleEditor.id) return\n\n setIsDeletingSchedule(true)\n try {\n const call = await runMutation({\n operation: () => apiCall(`/api/data_sync/schedules/${encodeURIComponent(scheduleEditor.id as string)}`, {\n method: 'DELETE',\n }, { fallback: null }),\n mutationPayload: {\n scheduleId: scheduleEditor.id,\n },\n context: {\n operation: 'delete',\n actionId: 'delete-sync-schedule',\n },\n })\n\n if (!call.ok) {\n flash((call.result as { error?: string } | null)?.error ?? t('data_sync.dashboard.schedule.deleteError', 'Failed to remove recurring schedule'), 'error')\n return\n }\n\n setScheduleEditor(buildDefaultScheduleState(selectedEntityType))\n flash(t('data_sync.dashboard.schedule.deleteSuccess', 'Recurring schedule removed'), 'success')\n } catch (error) {\n const message = error instanceof Error ? error.message : t('data_sync.dashboard.schedule.deleteError', 'Failed to remove recurring schedule')\n flash(message, 'error')\n } finally {\n setIsDeletingSchedule(false)\n }\n }, [runMutation, scheduleEditor.id, selectedEntityType, t])\n\n const filters: FilterDef[] = [\n {\n id: 'status',\n type: 'select',\n label: t('data_sync.dashboard.filters.status'),\n options: [\n { label: t('data_sync.dashboard.filters.allStatuses'), value: '' },\n { label: t('data_sync.dashboard.status.pending'), value: 'pending' },\n { label: t('data_sync.dashboard.status.running'), value: 'running' },\n { label: t('data_sync.dashboard.status.completed'), value: 'completed' },\n { label: t('data_sync.dashboard.status.failed'), value: 'failed' },\n { label: t('data_sync.dashboard.status.cancelled'), value: 'cancelled' },\n ],\n },\n {\n id: 'direction',\n type: 'select',\n label: t('data_sync.dashboard.columns.direction'),\n options: [\n { label: t('data_sync.dashboard.filters.allDirections'), value: '' },\n { label: t('data_sync.dashboard.direction.import'), value: 'import' },\n { label: t('data_sync.dashboard.direction.export'), value: 'export' },\n ],\n },\n ]\n\n const columns = React.useMemo<ColumnDef<SyncRunRow>[]>(() => [\n {\n accessorKey: 'integrationId',\n header: t('data_sync.dashboard.columns.integration'),\n cell: ({ row }) => <span className=\"font-medium text-sm\">{row.original.integrationId}</span>,\n },\n {\n accessorKey: 'entityType',\n header: t('data_sync.dashboard.columns.entityType'),\n },\n {\n accessorKey: 'direction',\n header: t('data_sync.dashboard.columns.direction'),\n cell: ({ row }) => (\n <Badge variant=\"outline\">\n {t(`data_sync.dashboard.direction.${row.original.direction}`)}\n </Badge>\n ),\n },\n {\n accessorKey: 'status',\n header: t('data_sync.dashboard.columns.status'),\n cell: ({ row }) => (\n <Badge variant=\"secondary\" className={STATUS_STYLES[row.original.status] ?? ''}>\n {t(`data_sync.dashboard.status.${row.original.status}`)}\n </Badge>\n ),\n },\n {\n accessorKey: 'createdCount',\n header: t('data_sync.dashboard.columns.created'),\n },\n {\n accessorKey: 'updatedCount',\n header: t('data_sync.dashboard.columns.updated'),\n },\n {\n accessorKey: 'failedCount',\n header: t('data_sync.dashboard.columns.failed'),\n },\n {\n accessorKey: 'createdAt',\n header: t('data_sync.dashboard.columns.createdAt'),\n cell: ({ row }) => new Date(row.original.createdAt).toLocaleString(),\n },\n ], [t])\n\n const canStartSelectedIntegration = Boolean(\n selectedIntegration\n && selectedEntityType\n && selectedIntegration.isEnabled\n && selectedIntegration.hasCredentials,\n )\n const hasSavedSchedule = Boolean(scheduleEditor.id)\n const selectedEntityLabel = selectedEntityType ? formatEntityTypeLabel(selectedEntityType) : t('data_sync.dashboard.columns.entityType')\n const integrationStateBadge = getSummaryBadgeStyle(selectedIntegration?.isEnabled ? 'enabled' : 'disabled')\n const credentialsBadge = getSummaryBadgeStyle(selectedIntegration?.hasCredentials ? 'ready' : 'missing')\n const scheduleBadge = getSummaryBadgeStyle(\n hasSavedSchedule\n ? (scheduleEditor.isEnabled ? 'scheduled' : 'paused')\n : 'none',\n )\n\n return (\n <Page>\n <PageBody className=\"space-y-6\">\n <Card>\n <CardHeader className=\"space-y-4\">\n <div className=\"flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between\">\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-2 text-xs font-medium uppercase tracking-[0.14em] text-muted-foreground\">\n <Repeat className=\"size-4\" />\n <span>{t('data_sync.dashboard.start.eyebrow', 'Run once or keep it recurring')}</span>\n </div>\n <div className=\"space-y-1\">\n <CardTitle>{t('data_sync.dashboard.start.title', 'Start or schedule a sync')}</CardTitle>\n <p className=\"max-w-3xl text-sm text-muted-foreground\">\n {t('data_sync.dashboard.start.description', 'Pick a sync target, launch an ad-hoc run, or save a recurring schedule for the same entity and direction from this page.')}\n </p>\n </div>\n </div>\n {selectedIntegration ? (\n <Button asChild variant=\"outline\">\n <Link href={selectedIntegration.settingsPath}>\n <Settings2 className=\"mr-2 size-4\" />\n {t('integrations.marketplace.configure')}\n </Link>\n </Button>\n ) : null}\n </div>\n\n {selectedIntegration ? (\n <div className=\"flex flex-wrap gap-2\">\n <Badge variant=\"outline\" className=\"gap-1.5\">\n <PlugZap className=\"size-3.5\" />\n {selectedIntegration.title}\n </Badge>\n <Badge variant=\"outline\" className=\"gap-1.5\">\n <ArrowRightLeft className=\"size-3.5\" />\n {t(`data_sync.dashboard.direction.${selectedDirection}`)}\n </Badge>\n <Badge variant={integrationStateBadge.variant} className={`gap-1.5 ${integrationStateBadge.className ?? ''}`}>\n <ShieldCheck className=\"size-3.5\" />\n {selectedIntegration.isEnabled\n ? t('data_sync.dashboard.start.status.enabled', 'Integration enabled')\n : t('data_sync.dashboard.start.status.disabled', 'Integration disabled')}\n </Badge>\n <Badge variant={credentialsBadge.variant} className={`gap-1.5 ${credentialsBadge.className ?? ''}`}>\n <PlugZap className=\"size-3.5\" />\n {selectedIntegration.hasCredentials\n ? t('data_sync.dashboard.start.status.credentialsReady', 'Credentials ready')\n : t('data_sync.dashboard.start.status.credentialsMissing', 'Credentials missing')}\n </Badge>\n <Badge variant={scheduleBadge.variant} className={`gap-1.5 ${scheduleBadge.className ?? ''}`}>\n <CalendarClock className=\"size-3.5\" />\n {hasSavedSchedule\n ? (scheduleEditor.isEnabled\n ? t('data_sync.dashboard.schedule.status.enabled', 'Recurring schedule active')\n : t('data_sync.dashboard.schedule.status.disabled', 'Recurring schedule paused'))\n : t('data_sync.dashboard.schedule.status.none', 'No recurring schedule')}\n </Badge>\n </div>\n ) : null}\n </CardHeader>\n <CardContent className=\"space-y-6\">\n <div className=\"grid gap-4 xl:grid-cols-3\">\n <div className=\"space-y-2 xl:col-span-1\">\n <Label className=\"flex items-center gap-2 text-sm font-medium\">\n <PlugZap className=\"size-4 text-muted-foreground\" />\n <span>{t('data_sync.dashboard.columns.integration')}</span>\n </Label>\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={selectedIntegrationId}\n onChange={(event) => setSelectedIntegrationId(event.target.value)}\n disabled={isLoadingOptions || options.length === 0}\n >\n {options.length === 0 ? (\n <option value=\"\">{t('integrations.marketplace.noResults', 'No integrations found')}</option>\n ) : null}\n {options.map((item) => (\n <option key={item.integrationId} value={item.integrationId}>\n {item.title}\n </option>\n ))}\n </select>\n </div>\n <div className=\"space-y-2\">\n <Label className=\"flex items-center gap-2 text-sm font-medium\">\n <Boxes className=\"size-4 text-muted-foreground\" />\n <span>{t('data_sync.dashboard.columns.entityType')}</span>\n </Label>\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={selectedEntityType}\n onChange={(event) => setSelectedEntityType(event.target.value)}\n disabled={entityOptions.length === 0}\n >\n {entityOptions.map((entityType) => (\n <option key={entityType} value={entityType}>\n {formatEntityTypeLabel(entityType)}\n </option>\n ))}\n </select>\n </div>\n <div className=\"space-y-2\">\n <Label className=\"flex items-center gap-2 text-sm font-medium\">\n <ArrowRightLeft className=\"size-4 text-muted-foreground\" />\n <span>{t('data_sync.dashboard.columns.direction')}</span>\n </Label>\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={selectedDirection}\n onChange={(event) => setSelectedDirection(event.target.value === 'export' ? 'export' : 'import')}\n disabled={selectedIntegration?.direction !== 'bidirectional'}\n >\n <option value=\"import\">{t('data_sync.dashboard.direction.import')}</option>\n {(selectedIntegration?.direction === 'bidirectional' || selectedIntegration?.direction === 'export') ? (\n <option value=\"export\">{t('data_sync.dashboard.direction.export')}</option>\n ) : null}\n </select>\n </div>\n </div>\n\n {selectedIntegration?.description ? (\n <p className=\"text-sm text-muted-foreground\">{selectedIntegration.description}</p>\n ) : null}\n\n <div className=\"grid gap-4 xl:grid-cols-2\">\n <div className=\"rounded-xl border bg-muted/20 p-4\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"space-y-1\">\n <div className=\"flex items-center gap-2\">\n <Play className=\"size-4 text-primary\" />\n <h3 className=\"text-sm font-semibold\">{t('data_sync.dashboard.start.runNowTitle', 'Run once now')}</h3>\n </div>\n <p className=\"text-sm text-muted-foreground\">\n {t('data_sync.dashboard.start.runNowDescription', 'Use this for the next immediate sync. Batch size and full-sync mode apply only to this manual run.')}\n </p>\n </div>\n <Badge variant=\"outline\">{selectedEntityLabel}</Badge>\n </div>\n\n <Separator className=\"my-4\" />\n\n <div className=\"grid gap-4 sm:grid-cols-[minmax(0,180px)_1fr]\">\n <div className=\"space-y-2\">\n <Label className=\"flex items-center gap-2 text-sm font-medium\">\n <Gauge className=\"size-4 text-muted-foreground\" />\n <span>{t('data_sync.dashboard.start.batchSize', 'Batch size')}</span>\n </Label>\n <Input\n value={batchSize}\n onChange={(event) => setBatchSize(event.target.value)}\n inputMode=\"numeric\"\n />\n </div>\n <div className=\"rounded-lg border bg-background p-3\">\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"space-y-1\">\n <Label className=\"text-sm font-medium\">{t('data_sync.dashboard.start.fullSync', 'Run as full sync')}</Label>\n <p className=\"text-xs text-muted-foreground\">\n {t('data_sync.dashboard.start.fullSyncHelp', 'Ignore the saved cursor and process the entire source again for this run.')}\n </p>\n </div>\n <Switch checked={fullSync} onCheckedChange={setFullSync} />\n </div>\n </div>\n </div>\n\n <div className=\"mt-4 flex flex-wrap items-center justify-between gap-3\">\n <p className=\"text-xs text-muted-foreground\">\n {t('data_sync.dashboard.start.runNowFootnote', 'Manual runs show progress immediately and land on the run detail page after launch.')}\n </p>\n <Button\n type=\"button\"\n onClick={() => void handleStartSync()}\n disabled={!canStartSelectedIntegration}\n >\n <Play className=\"mr-2 size-4\" />\n {t('data_sync.dashboard.start.submit', 'Start sync')}\n </Button>\n </div>\n </div>\n\n <div className=\"rounded-xl border bg-muted/20 p-4\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"space-y-1\">\n <div className=\"flex items-center gap-2\">\n <CalendarClock className=\"size-4 text-primary\" />\n <h3 className=\"text-sm font-semibold\">{t('data_sync.dashboard.schedule.title', 'Recurring schedule')}</h3>\n </div>\n <p className=\"text-sm text-muted-foreground\">\n {t('data_sync.dashboard.schedule.description', 'Save a repeating schedule for the selected integration, entity, and direction without leaving this dashboard.')}\n </p>\n </div>\n <Badge variant=\"outline\">\n {hasSavedSchedule\n ? (scheduleEditor.isEnabled\n ? t('data_sync.dashboard.schedule.status.shortEnabled', 'Scheduled')\n : t('data_sync.dashboard.schedule.status.shortDisabled', 'Paused'))\n : t('data_sync.dashboard.schedule.status.shortNone', 'One-time only')}\n </Badge>\n </div>\n\n <Separator className=\"my-4\" />\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label className=\"flex items-center gap-2 text-sm font-medium\">\n <Clock3 className=\"size-4 text-muted-foreground\" />\n <span>{t('data_sync.dashboard.schedule.type', 'Schedule type')}</span>\n </Label>\n <select\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={scheduleEditor.scheduleType}\n onChange={(event) => updateScheduleEditor({\n scheduleType: event.target.value === 'cron' ? 'cron' : 'interval',\n })}\n disabled={isLoadingSchedule || isSavingSchedule || isDeletingSchedule || !selectedIntegration || !selectedEntityType}\n >\n <option value=\"interval\">{t('data_sync.dashboard.schedule.interval', 'Interval')}</option>\n <option value=\"cron\">{t('data_sync.dashboard.schedule.cron', 'Cron')}</option>\n </select>\n </div>\n <div className=\"space-y-2\">\n <Label className=\"flex items-center gap-2 text-sm font-medium\">\n <CalendarClock className=\"size-4 text-muted-foreground\" />\n <span>\n {scheduleEditor.scheduleType === 'cron'\n ? t('data_sync.dashboard.schedule.cronValue', 'Cron expression')\n : t('data_sync.dashboard.schedule.intervalValue', 'Interval')}\n </span>\n </Label>\n <Input\n value={scheduleEditor.scheduleValue}\n onChange={(event) => updateScheduleEditor({ scheduleValue: event.target.value })}\n disabled={isLoadingSchedule || isSavingSchedule || isDeletingSchedule || !selectedIntegration || !selectedEntityType}\n placeholder={scheduleEditor.scheduleType === 'cron' ? '0 * * * *' : '1h'}\n />\n <p className=\"text-xs text-muted-foreground\">\n {scheduleEditor.scheduleType === 'cron'\n ? t('data_sync.dashboard.schedule.cronHelp', 'Example: `0 * * * *` runs at the start of every hour.')\n : t('data_sync.dashboard.schedule.intervalHelp', 'Example: `1h`, `6h`, or `24h` for repeating intervals.')}\n </p>\n </div>\n <div className=\"space-y-2 sm:col-span-2\">\n <Label className=\"flex items-center gap-2 text-sm font-medium\">\n <Clock3 className=\"size-4 text-muted-foreground\" />\n <span>{t('data_sync.dashboard.schedule.timezone', 'Timezone')}</span>\n </Label>\n <Input\n value={scheduleEditor.timezone}\n onChange={(event) => updateScheduleEditor({ timezone: event.target.value })}\n disabled={isLoadingSchedule || isSavingSchedule || isDeletingSchedule || !selectedIntegration || !selectedEntityType}\n />\n </div>\n </div>\n\n <div className=\"mt-4 grid gap-3\">\n <div className=\"rounded-lg border bg-background p-3\">\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"space-y-1\">\n <Label className=\"text-sm font-medium\">{t('data_sync.dashboard.schedule.fullSync', 'Run scheduled jobs as full sync')}</Label>\n <p className=\"text-xs text-muted-foreground\">\n {t('data_sync.dashboard.schedule.fullSyncHelp', 'When enabled, every recurring run starts from the beginning instead of the saved cursor.')}\n </p>\n </div>\n <Switch\n checked={scheduleEditor.fullSync}\n onCheckedChange={(checked) => updateScheduleEditor({ fullSync: checked })}\n disabled={isLoadingSchedule || isSavingSchedule || isDeletingSchedule || !selectedIntegration || !selectedEntityType}\n />\n </div>\n </div>\n <div className=\"rounded-lg border bg-background p-3\">\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"space-y-1\">\n <Label className=\"text-sm font-medium\">{t('data_sync.dashboard.schedule.enabled', 'Schedule enabled')}</Label>\n <p className=\"text-xs text-muted-foreground\">\n {t('data_sync.dashboard.schedule.enabledHelp', 'Pause the recurring job without deleting the schedule definition.')}\n </p>\n </div>\n <Switch\n checked={scheduleEditor.isEnabled}\n onCheckedChange={(checked) => updateScheduleEditor({ isEnabled: checked })}\n disabled={isLoadingSchedule || isSavingSchedule || isDeletingSchedule || !selectedIntegration || !selectedEntityType}\n />\n </div>\n </div>\n </div>\n\n <div className=\"mt-4 flex flex-wrap items-center justify-between gap-3\">\n <div className=\"space-y-1 text-xs text-muted-foreground\">\n <div>\n {hasSavedSchedule\n ? (scheduleEditor.lastRunAt\n ? t('data_sync.dashboard.schedule.lastRun', 'Last scheduled run: {value}', {\n value: new Date(scheduleEditor.lastRunAt).toLocaleString(),\n })\n : t('data_sync.dashboard.schedule.neverRun', 'Saved, but no scheduled execution has completed yet.'))\n : t('data_sync.dashboard.schedule.none', 'No recurring schedule saved for this target yet.')}\n </div>\n </div>\n <div className=\"flex flex-wrap gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => void handleDeleteSchedule()}\n disabled={!hasSavedSchedule || isDeletingSchedule}\n >\n {isDeletingSchedule\n ? t('data_sync.dashboard.schedule.deleting', 'Removing...')\n : t('data_sync.dashboard.schedule.delete', 'Remove schedule')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => void handleSaveSchedule()}\n disabled={isSavingSchedule || !selectedIntegration || !selectedEntityType}\n >\n <CalendarClock className=\"mr-2 size-4\" />\n {isSavingSchedule\n ? t('data_sync.dashboard.schedule.saving', 'Saving...')\n : t('data_sync.dashboard.schedule.save', 'Save recurring schedule')}\n </Button>\n </div>\n </div>\n </div>\n </div>\n\n {selectedIntegration && !selectedIntegration.isEnabled ? (\n <Alert variant=\"warning\">\n <AlertDescription className=\"inline-flex items-center gap-2\">\n <CircleAlert className=\"size-4\" />\n <span>{t('integrations.detail.state.disabled', 'This integration is disabled. Enable it on the integration settings page before starting a sync.')}</span>\n </AlertDescription>\n </Alert>\n ) : null}\n {selectedIntegration && !selectedIntegration.hasCredentials ? (\n <Alert variant=\"warning\">\n <AlertDescription className=\"inline-flex items-center gap-2\">\n <CircleAlert className=\"size-4\" />\n <span>{t('integrations.detail.credentials.notConfigured', 'Credentials are not configured yet. Save the integration credentials before starting a sync.')}</span>\n </AlertDescription>\n </Alert>\n ) : null}\n </CardContent>\n </Card>\n\n <DataTable\n stickyActionsColumn\n title={t('data_sync.dashboard.title')}\n columns={columns}\n data={rows}\n filters={filters}\n filterValues={filterValues}\n onFiltersApply={handleFiltersApply}\n onFiltersClear={handleFiltersClear}\n searchValue={search}\n onSearchChange={(value) => { setSearch(value); setPage(1) }}\n perspective={{ tableId: 'data_sync.runs' }}\n onRowClick={(row) => {\n router.push(`/backend/data-sync/runs/${encodeURIComponent(row.id)}`)\n }}\n rowActions={(row) => (\n <RowActions items={[\n {\n id: 'view',\n label: t('data_sync.dashboard.actions.view'),\n onSelect: () => { router.push(`/backend/data-sync/runs/${encodeURIComponent(row.id)}`) },\n },\n ...(row.status === 'running' ? [{\n id: 'cancel',\n label: t('data_sync.runs.detail.cancel'),\n destructive: true,\n onSelect: () => { void handleCancel(row) },\n }] : []),\n ...(row.status === 'failed' ? [{\n id: 'retry',\n label: t('data_sync.runs.detail.retry'),\n onSelect: () => { void handleRetry(row) },\n }] : []),\n ]} />\n )}\n pagination={{ page, pageSize: 20, total, totalPages, onPageChange: setPage }}\n isLoading={isLoading}\n />\n </PageBody>\n </Page>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -7,7 +7,7 @@ import { Badge } from "@open-mercato/ui/primitives/badge";
7
7
  import { Button } from "@open-mercato/ui/primitives/button";
8
8
  import { Input } from "@open-mercato/ui/primitives/input";
9
9
  import { Label } from "@open-mercato/ui/primitives/label";
10
- import { Notice } from "@open-mercato/ui/primitives/Notice";
10
+ import { Alert, AlertDescription } from "@open-mercato/ui/primitives/alert";
11
11
  import { Spinner } from "@open-mercato/ui/primitives/spinner";
12
12
  import { useOrganizationScopeVersion } from "@open-mercato/shared/lib/frontend/useOrganizationScope";
13
13
  import { useT } from "@open-mercato/shared/lib/i18n/context";
@@ -219,7 +219,7 @@ function IntegrationScheduleTab(props) {
219
219
  return /* @__PURE__ */ jsx("div", { className: "flex min-h-40 items-center justify-center rounded-lg border bg-card", children: /* @__PURE__ */ jsx(Spinner, {}) });
220
220
  }
221
221
  if (!option) {
222
- return /* @__PURE__ */ jsx(Notice, { compact: true, variant: "warning", children: t("data_sync.integrationTab.notAvailable", "This integration is not registered as a data sync provider.") });
222
+ return /* @__PURE__ */ jsx(Alert, { variant: "warning", children: /* @__PURE__ */ jsx(AlertDescription, { children: t("data_sync.integrationTab.notAvailable", "This integration is not registered as a data sync provider.") }) });
223
223
  }
224
224
  return /* @__PURE__ */ jsxs("section", { className: "space-y-4 rounded-lg border bg-card p-6", children: [
225
225
  /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [
@@ -244,9 +244,9 @@ function IntegrationScheduleTab(props) {
244
244
  t("data_sync.integrationTab.refresh", "Refresh")
245
245
  ] })
246
246
  ] }),
247
- !props.isEnabled ? /* @__PURE__ */ jsx(Notice, { compact: true, variant: "warning", children: t("data_sync.integrationTab.integrationDisabledNotice", "The integration is disabled. You can save schedules now, but runs will stay blocked until the integration is enabled.") }) : null,
248
- !props.hasCredentials ? /* @__PURE__ */ jsx(Notice, { compact: true, variant: "warning", children: t("data_sync.integrationTab.credentialsMissingNotice", "Credentials are still missing. Save schedules first if you want, but manual and scheduled runs will fail until credentials are configured.") }) : null,
249
- rows.length === 0 ? /* @__PURE__ */ jsx(Notice, { compact: true, children: t("data_sync.integrationTab.empty", "This provider does not expose any schedulable sync entities yet.") }) : /* @__PURE__ */ jsx("div", { className: "overflow-x-auto rounded-lg border", children: /* @__PURE__ */ jsxs("table", { className: "w-full min-w-[1080px] text-sm", children: [
247
+ !props.isEnabled ? /* @__PURE__ */ jsx(Alert, { variant: "warning", children: /* @__PURE__ */ jsx(AlertDescription, { children: t("data_sync.integrationTab.integrationDisabledNotice", "The integration is disabled. You can save schedules now, but runs will stay blocked until the integration is enabled.") }) }) : null,
248
+ !props.hasCredentials ? /* @__PURE__ */ jsx(Alert, { variant: "warning", children: /* @__PURE__ */ jsx(AlertDescription, { children: t("data_sync.integrationTab.credentialsMissingNotice", "Credentials are still missing. Save schedules first if you want, but manual and scheduled runs will fail until credentials are configured.") }) }) : null,
249
+ rows.length === 0 ? /* @__PURE__ */ jsx(Alert, { variant: "info", children: /* @__PURE__ */ jsx(AlertDescription, { children: t("data_sync.integrationTab.empty", "This provider does not expose any schedulable sync entities yet.") }) }) : /* @__PURE__ */ jsx("div", { className: "overflow-x-auto rounded-lg border", children: /* @__PURE__ */ jsxs("table", { className: "w-full min-w-[1080px] text-sm", children: [
250
250
  /* @__PURE__ */ jsx("thead", { className: "bg-muted/50 text-left", children: /* @__PURE__ */ jsxs("tr", { children: [
251
251
  /* @__PURE__ */ jsx("th", { className: "px-3 py-2 font-medium", children: t("data_sync.dashboard.columns.entityType", "Entity Type") }),
252
252
  /* @__PURE__ */ jsx("th", { className: "px-3 py-2 font-medium", children: t("data_sync.dashboard.columns.direction", "Direction") }),
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/data_sync/components/IntegrationScheduleTab.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport { Notice } from '@open-mercato/ui/primitives/Notice'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport {\n CalendarClock,\n Play,\n RefreshCw,\n Save,\n ShieldAlert,\n ShieldCheck,\n Trash2,\n} from 'lucide-react'\n\ntype SyncOption = {\n integrationId: string\n title: string\n direction: 'import' | 'export' | 'bidirectional'\n supportedEntities: string[]\n hasCredentials: boolean\n isEnabled: boolean\n}\n\ntype SyncOptionsResponse = {\n items?: SyncOption[]\n}\n\ntype SyncScheduleRecord = {\n id: string\n integrationId: string\n entityType: string\n direction: 'import' | 'export'\n scheduleType: 'cron' | 'interval'\n scheduleValue: string\n timezone: string\n fullSync: boolean\n isEnabled: boolean\n lastRunAt: string | null\n}\n\ntype SyncSchedulesResponse = {\n items?: SyncScheduleRecord[]\n}\n\ntype SyncScheduleEditorState = {\n id?: string\n scheduleType: 'cron' | 'interval'\n scheduleValue: string\n timezone: string\n fullSync: boolean\n isEnabled: boolean\n lastRunAt: string | null\n}\n\ntype IntegrationScheduleTabProps = {\n integrationId: string\n hasCredentials: boolean\n isEnabled: boolean\n}\n\nconst DEFAULT_TIMEZONE = Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC'\n\nfunction formatEntityTypeLabel(entityType: string): string {\n return entityType\n .replace(/[_-]+/g, ' ')\n .replace(/\\b\\w/g, (letter) => letter.toUpperCase())\n}\n\nfunction buildDefaultScheduleState(entityType: string): SyncScheduleEditorState {\n const normalized = entityType.trim().toLowerCase()\n const longerInterval = normalized === 'categories' || normalized === 'attributes'\n return {\n scheduleType: 'interval',\n scheduleValue: longerInterval ? '6h' : '1h',\n timezone: DEFAULT_TIMEZONE,\n fullSync: normalized !== 'products',\n isEnabled: true,\n lastRunAt: null,\n }\n}\n\nfunction getSupportedDirections(direction: SyncOption['direction'] | null | undefined): Array<'import' | 'export'> {\n if (direction === 'export') return ['export']\n if (direction === 'bidirectional') return ['import', 'export']\n return ['import']\n}\n\nfunction buildScheduleKey(entityType: string, direction: 'import' | 'export'): string {\n return `${entityType}:${direction}`\n}\n\nfunction buildScheduleEditors(\n entityTypes: string[],\n directions: Array<'import' | 'export'>,\n records: SyncScheduleRecord[],\n): Record<string, SyncScheduleEditorState> {\n const nextEntries: Array<[string, SyncScheduleEditorState]> = []\n for (const entityType of entityTypes) {\n for (const direction of directions) {\n const record = records.find((item) => item.entityType === entityType && item.direction === direction)\n nextEntries.push([\n buildScheduleKey(entityType, direction),\n record\n ? {\n id: record.id,\n scheduleType: record.scheduleType,\n scheduleValue: record.scheduleValue,\n timezone: record.timezone,\n fullSync: record.fullSync,\n isEnabled: record.isEnabled,\n lastRunAt: record.lastRunAt,\n }\n : buildDefaultScheduleState(entityType),\n ])\n }\n }\n return Object.fromEntries(nextEntries)\n}\n\nexport function IntegrationScheduleTab(props: IntegrationScheduleTabProps) {\n const t = useT()\n const scopeVersion = useOrganizationScopeVersion()\n const [option, setOption] = React.useState<SyncOption | null>(null)\n const [schedules, setSchedules] = React.useState<Record<string, SyncScheduleEditorState>>({})\n const [isLoading, setIsLoading] = React.useState(true)\n const [runningKey, setRunningKey] = React.useState<string | null>(null)\n const [savingKey, setSavingKey] = React.useState<string | null>(null)\n const [deletingKey, setDeletingKey] = React.useState<string | null>(null)\n\n const load = React.useCallback(async () => {\n setIsLoading(true)\n try {\n const [optionsCall, schedulesCall] = await Promise.all([\n apiCall<SyncOptionsResponse>('/api/data_sync/options', undefined, { fallback: { items: [] } }),\n apiCall<SyncSchedulesResponse>(`/api/data_sync/schedules?integrationId=${encodeURIComponent(props.integrationId)}&page=1&pageSize=100`, undefined, { fallback: { items: [] } }),\n ])\n\n const resolvedOption = (optionsCall.result?.items ?? []).find((item) => item.integrationId === props.integrationId) ?? null\n setOption(resolvedOption)\n\n const supportedEntities = resolvedOption?.supportedEntities ?? []\n const supportedDirections = getSupportedDirections(resolvedOption?.direction)\n setSchedules(buildScheduleEditors(supportedEntities, supportedDirections, schedulesCall.result?.items ?? []))\n } catch (error) {\n const message = error instanceof Error ? error.message : t('data_sync.integrationTab.loadError', 'Failed to load sync schedules.')\n flash(message, 'error')\n } finally {\n setIsLoading(false)\n }\n }, [props.integrationId, t])\n\n React.useEffect(() => {\n void load()\n }, [load, scopeVersion])\n\n const supportedDirections = React.useMemo(\n () => getSupportedDirections(option?.direction),\n [option?.direction],\n )\n\n const rows = React.useMemo(\n () => (option?.supportedEntities ?? []).flatMap((entityType) => (\n supportedDirections.map((direction) => ({\n entityType,\n direction,\n key: buildScheduleKey(entityType, direction),\n }))\n )),\n [option?.supportedEntities, supportedDirections],\n )\n\n const updateScheduleEditor = React.useCallback((key: string, patch: Partial<SyncScheduleEditorState>, entityType: string) => {\n setSchedules((current) => ({\n ...current,\n [key]: {\n ...(current[key] ?? buildDefaultScheduleState(entityType)),\n ...patch,\n },\n }))\n }, [])\n\n const handleStartSync = React.useCallback(async (entityType: string, direction: 'import' | 'export', scheduleKey: string) => {\n if (!props.isEnabled) {\n flash(t('data_sync.integrationTab.integrationDisabled', 'Enable the integration before starting a sync.'), 'error')\n return\n }\n if (!props.hasCredentials) {\n flash(t('data_sync.integrationTab.credentialsMissing', 'Configure credentials before starting a sync.'), 'error')\n return\n }\n\n setRunningKey(scheduleKey)\n try {\n const scheduleState = schedules[scheduleKey] ?? buildDefaultScheduleState(entityType)\n const call = await apiCall<{ id: string }>('/api/data_sync/run', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n integrationId: props.integrationId,\n entityType,\n direction,\n fullSync: scheduleState.fullSync,\n batchSize: 100,\n }),\n }, { fallback: null })\n\n if (!call.ok) {\n throw new Error((call.result as { error?: string } | null)?.error ?? 'Failed to start sync')\n }\n\n flash(t('data_sync.integrationTab.runStarted', 'Sync run started.'), 'success')\n } catch (error) {\n const message = error instanceof Error ? error.message : t('data_sync.integrationTab.runError', 'Failed to start sync.')\n flash(message, 'error')\n } finally {\n setRunningKey(null)\n }\n }, [props.hasCredentials, props.integrationId, props.isEnabled, schedules, t])\n\n const handleSaveSchedule = React.useCallback(async (entityType: string, direction: 'import' | 'export', scheduleKey: string) => {\n const scheduleState = schedules[scheduleKey] ?? buildDefaultScheduleState(entityType)\n setSavingKey(scheduleKey)\n try {\n const call = await apiCall<SyncScheduleRecord>('/api/data_sync/schedules', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n integrationId: props.integrationId,\n entityType,\n direction,\n scheduleType: scheduleState.scheduleType,\n scheduleValue: scheduleState.scheduleValue,\n timezone: scheduleState.timezone,\n fullSync: scheduleState.fullSync,\n isEnabled: scheduleState.isEnabled,\n }),\n }, { fallback: null })\n\n if (!call.ok || !call.result) {\n throw new Error((call.result as { error?: string } | null)?.error ?? 'Failed to save schedule')\n }\n\n updateScheduleEditor(scheduleKey, {\n id: call.result.id,\n scheduleType: call.result.scheduleType,\n scheduleValue: call.result.scheduleValue,\n timezone: call.result.timezone,\n fullSync: call.result.fullSync,\n isEnabled: call.result.isEnabled,\n lastRunAt: call.result.lastRunAt,\n }, entityType)\n flash(t('data_sync.dashboard.schedule.success', 'Recurring schedule saved'), 'success')\n } catch (error) {\n const message = error instanceof Error ? error.message : t('data_sync.dashboard.schedule.error', 'Failed to save recurring schedule')\n flash(message, 'error')\n } finally {\n setSavingKey(null)\n }\n }, [props.integrationId, schedules, t, updateScheduleEditor])\n\n const handleDeleteSchedule = React.useCallback(async (entityType: string, scheduleKey: string) => {\n const scheduleState = schedules[scheduleKey]\n if (!scheduleState?.id) {\n updateScheduleEditor(scheduleKey, buildDefaultScheduleState(entityType), entityType)\n return\n }\n\n setDeletingKey(scheduleKey)\n try {\n const call = await apiCall(`/api/data_sync/schedules/${encodeURIComponent(scheduleState.id)}`, {\n method: 'DELETE',\n }, { fallback: null })\n\n if (!call.ok) {\n throw new Error((call.result as { error?: string } | null)?.error ?? 'Failed to delete schedule')\n }\n\n setSchedules((current) => ({\n ...current,\n [scheduleKey]: buildDefaultScheduleState(entityType),\n }))\n flash(t('data_sync.dashboard.schedule.deleteSuccess', 'Recurring schedule removed'), 'success')\n } catch (error) {\n const message = error instanceof Error ? error.message : t('data_sync.dashboard.schedule.deleteError', 'Failed to remove recurring schedule')\n flash(message, 'error')\n } finally {\n setDeletingKey(null)\n }\n }, [schedules, t, updateScheduleEditor])\n\n if (isLoading) {\n return (\n <div className=\"flex min-h-40 items-center justify-center rounded-lg border bg-card\">\n <Spinner />\n </div>\n )\n }\n\n if (!option) {\n return (\n <Notice compact variant=\"warning\">\n {t('data_sync.integrationTab.notAvailable', 'This integration is not registered as a data sync provider.')}\n </Notice>\n )\n }\n\n return (\n <section className=\"space-y-4 rounded-lg border bg-card p-6\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div className=\"space-y-2\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <Badge variant=\"outline\" className={props.isEnabled ? 'border-emerald-300 text-emerald-700' : 'border-amber-300 text-amber-700'}>\n {props.isEnabled ? <ShieldCheck className=\"mr-2 h-3.5 w-3.5\" /> : <ShieldAlert className=\"mr-2 h-3.5 w-3.5\" />}\n {props.isEnabled\n ? t('data_sync.dashboard.start.status.enabled', 'Integration enabled')\n : t('data_sync.dashboard.start.status.disabled', 'Integration disabled')}\n </Badge>\n <Badge variant=\"outline\" className={props.hasCredentials ? 'border-sky-300 text-sky-700' : 'border-amber-300 text-amber-700'}>\n <CalendarClock className=\"mr-2 h-3.5 w-3.5\" />\n {props.hasCredentials\n ? t('data_sync.dashboard.start.status.credentialsReady', 'Credentials ready')\n : t('data_sync.dashboard.start.status.credentialsMissing', 'Credentials missing')}\n </Badge>\n </div>\n <div>\n <h3 className=\"text-base font-semibold\">{t('data_sync.integrationTab.title', 'Sync schedules')}</h3>\n <p className=\"text-sm text-muted-foreground\">\n {t('data_sync.integrationTab.description', 'Run one-off syncs or save recurring schedules for every supported entity directly from the integration detail page.')}\n </p>\n </div>\n </div>\n <Button type=\"button\" variant=\"outline\" onClick={() => void load()} disabled={isLoading}>\n <RefreshCw className=\"mr-2 h-4 w-4\" />\n {t('data_sync.integrationTab.refresh', 'Refresh')}\n </Button>\n </div>\n\n {!props.isEnabled ? (\n <Notice compact variant=\"warning\">\n {t('data_sync.integrationTab.integrationDisabledNotice', 'The integration is disabled. You can save schedules now, but runs will stay blocked until the integration is enabled.')}\n </Notice>\n ) : null}\n\n {!props.hasCredentials ? (\n <Notice compact variant=\"warning\">\n {t('data_sync.integrationTab.credentialsMissingNotice', 'Credentials are still missing. Save schedules first if you want, but manual and scheduled runs will fail until credentials are configured.')}\n </Notice>\n ) : null}\n\n {rows.length === 0 ? (\n <Notice compact>\n {t('data_sync.integrationTab.empty', 'This provider does not expose any schedulable sync entities yet.')}\n </Notice>\n ) : (\n <div className=\"overflow-x-auto rounded-lg border\">\n <table className=\"w-full min-w-[1080px] text-sm\">\n <thead className=\"bg-muted/50 text-left\">\n <tr>\n <th className=\"px-3 py-2 font-medium\">{t('data_sync.dashboard.columns.entityType', 'Entity Type')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('data_sync.dashboard.columns.direction', 'Direction')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('data_sync.dashboard.schedule.type', 'Schedule type')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('data_sync.integrationTab.columns.value', 'Value')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('data_sync.dashboard.schedule.timezone', 'Timezone')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('data_sync.dashboard.start.fullSync', 'Run as full sync')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('data_sync.dashboard.schedule.enabled', 'Schedule enabled')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('data_sync.integrationTab.columns.lastRun', 'Last run')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('data_sync.integrationTab.columns.actions', 'Actions')}</th>\n </tr>\n </thead>\n <tbody>\n {rows.map((row) => {\n const scheduleState = schedules[row.key] ?? buildDefaultScheduleState(row.entityType)\n const isRunning = runningKey === row.key\n const isSaving = savingKey === row.key\n const isDeleting = deletingKey === row.key\n const controlsDisabled = isRunning || isSaving || isDeleting\n return (\n <tr key={row.key} className=\"border-t align-top\">\n <td className=\"px-3 py-3 font-medium\">{formatEntityTypeLabel(row.entityType)}</td>\n <td className=\"px-3 py-3\">{t(`data_sync.dashboard.direction.${row.direction}`, row.direction === 'import' ? 'Import' : 'Export')}</td>\n <td className=\"px-3 py-3\">\n <select\n className=\"flex h-10 w-full min-w-32 rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={scheduleState.scheduleType}\n onChange={(event) => updateScheduleEditor(row.key, {\n scheduleType: event.target.value === 'cron' ? 'cron' : 'interval',\n }, row.entityType)}\n disabled={controlsDisabled}\n >\n <option value=\"interval\">{t('data_sync.dashboard.schedule.interval', 'Interval')}</option>\n <option value=\"cron\">{t('data_sync.dashboard.schedule.cron', 'Cron')}</option>\n </select>\n </td>\n <td className=\"px-3 py-3\">\n <Input\n value={scheduleState.scheduleValue}\n onChange={(event) => updateScheduleEditor(row.key, { scheduleValue: event.target.value }, row.entityType)}\n disabled={controlsDisabled}\n placeholder={scheduleState.scheduleType === 'cron' ? '0 * * * *' : '1h'}\n />\n </td>\n <td className=\"px-3 py-3\">\n <Input\n value={scheduleState.timezone}\n onChange={(event) => updateScheduleEditor(row.key, { timezone: event.target.value }, row.entityType)}\n disabled={controlsDisabled}\n />\n </td>\n <td className=\"px-3 py-3\">\n <label className=\"flex min-h-10 items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={scheduleState.fullSync}\n onChange={(event) => updateScheduleEditor(row.key, { fullSync: event.target.checked }, row.entityType)}\n disabled={controlsDisabled}\n />\n <span>{t('data_sync.integrationTab.fullSyncShort', 'Full')}</span>\n </label>\n </td>\n <td className=\"px-3 py-3\">\n <label className=\"flex min-h-10 items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={scheduleState.isEnabled}\n onChange={(event) => updateScheduleEditor(row.key, { isEnabled: event.target.checked }, row.entityType)}\n disabled={controlsDisabled}\n />\n <span>{scheduleState.isEnabled ? t('data_sync.dashboard.schedule.status.shortEnabled', 'Scheduled') : t('data_sync.dashboard.schedule.status.shortDisabled', 'Paused')}</span>\n </label>\n </td>\n <td className=\"px-3 py-3 text-muted-foreground\">\n {scheduleState.lastRunAt\n ? new Date(scheduleState.lastRunAt).toLocaleString()\n : scheduleState.id\n ? t('data_sync.dashboard.schedule.neverRun', 'Saved, but no scheduled execution has completed yet.')\n : t('data_sync.dashboard.schedule.none', 'No recurring schedule saved for this target yet.')}\n </td>\n <td className=\"px-3 py-3\">\n <div className=\"flex flex-wrap gap-2\">\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={() => void handleStartSync(row.entityType, row.direction, row.key)}\n disabled={controlsDisabled || !props.isEnabled || !props.hasCredentials}\n >\n {isRunning ? <Spinner className=\"mr-2 h-4 w-4\" /> : <Play className=\"mr-2 h-4 w-4\" />}\n {isRunning\n ? t('data_sync.integrationTab.starting', 'Starting...')\n : t('data_sync.integrationTab.start', 'Run now')}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n onClick={() => void handleSaveSchedule(row.entityType, row.direction, row.key)}\n disabled={controlsDisabled}\n >\n {isSaving ? <Spinner className=\"mr-2 h-4 w-4\" /> : <Save className=\"mr-2 h-4 w-4\" />}\n {isSaving\n ? t('data_sync.dashboard.schedule.saving', 'Saving...')\n : t('data_sync.dashboard.schedule.save', 'Save recurring schedule')}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n onClick={() => void handleDeleteSchedule(row.entityType, row.key)}\n disabled={controlsDisabled || !scheduleState.id}\n >\n {isDeleting ? <Spinner className=\"mr-2 h-4 w-4\" /> : <Trash2 className=\"mr-2 h-4 w-4\" />}\n {isDeleting\n ? t('data_sync.dashboard.schedule.deleting', 'Removing...')\n : t('data_sync.dashboard.schedule.delete', 'Remove schedule')}\n </Button>\n </div>\n </td>\n </tr>\n )\n })}\n </tbody>\n </table>\n </div>\n )}\n\n <div className=\"grid gap-3 rounded-lg border border-dashed p-4 text-sm text-muted-foreground md:grid-cols-3\">\n <div className=\"space-y-1\">\n <Label>{t('data_sync.dashboard.schedule.interval', 'Interval')}</Label>\n <p>{t('data_sync.dashboard.schedule.intervalHelp', 'Example: `1h`, `6h`, or `24h` for repeating intervals.')}</p>\n </div>\n <div className=\"space-y-1\">\n <Label>{t('data_sync.dashboard.schedule.cron', 'Cron')}</Label>\n <p>{t('data_sync.dashboard.schedule.cronHelp', 'Example: `0 * * * *` runs at the start of every hour.')}</p>\n </div>\n <div className=\"space-y-1\">\n <Label>{t('data_sync.integrationTab.runNowTitle', 'Manual runs')}</Label>\n <p>{t('data_sync.integrationTab.runNowHelp', 'Run now uses the full-sync checkbox from the same row and starts progress tracking immediately in Data Sync.')}</p>\n </div>\n </div>\n </section>\n )\n}\n\nexport default IntegrationScheduleTab\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport { Alert, AlertDescription } from '@open-mercato/ui/primitives/alert'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport {\n CalendarClock,\n Play,\n RefreshCw,\n Save,\n ShieldAlert,\n ShieldCheck,\n Trash2,\n} from 'lucide-react'\n\ntype SyncOption = {\n integrationId: string\n title: string\n direction: 'import' | 'export' | 'bidirectional'\n supportedEntities: string[]\n hasCredentials: boolean\n isEnabled: boolean\n}\n\ntype SyncOptionsResponse = {\n items?: SyncOption[]\n}\n\ntype SyncScheduleRecord = {\n id: string\n integrationId: string\n entityType: string\n direction: 'import' | 'export'\n scheduleType: 'cron' | 'interval'\n scheduleValue: string\n timezone: string\n fullSync: boolean\n isEnabled: boolean\n lastRunAt: string | null\n}\n\ntype SyncSchedulesResponse = {\n items?: SyncScheduleRecord[]\n}\n\ntype SyncScheduleEditorState = {\n id?: string\n scheduleType: 'cron' | 'interval'\n scheduleValue: string\n timezone: string\n fullSync: boolean\n isEnabled: boolean\n lastRunAt: string | null\n}\n\ntype IntegrationScheduleTabProps = {\n integrationId: string\n hasCredentials: boolean\n isEnabled: boolean\n}\n\nconst DEFAULT_TIMEZONE = Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC'\n\nfunction formatEntityTypeLabel(entityType: string): string {\n return entityType\n .replace(/[_-]+/g, ' ')\n .replace(/\\b\\w/g, (letter) => letter.toUpperCase())\n}\n\nfunction buildDefaultScheduleState(entityType: string): SyncScheduleEditorState {\n const normalized = entityType.trim().toLowerCase()\n const longerInterval = normalized === 'categories' || normalized === 'attributes'\n return {\n scheduleType: 'interval',\n scheduleValue: longerInterval ? '6h' : '1h',\n timezone: DEFAULT_TIMEZONE,\n fullSync: normalized !== 'products',\n isEnabled: true,\n lastRunAt: null,\n }\n}\n\nfunction getSupportedDirections(direction: SyncOption['direction'] | null | undefined): Array<'import' | 'export'> {\n if (direction === 'export') return ['export']\n if (direction === 'bidirectional') return ['import', 'export']\n return ['import']\n}\n\nfunction buildScheduleKey(entityType: string, direction: 'import' | 'export'): string {\n return `${entityType}:${direction}`\n}\n\nfunction buildScheduleEditors(\n entityTypes: string[],\n directions: Array<'import' | 'export'>,\n records: SyncScheduleRecord[],\n): Record<string, SyncScheduleEditorState> {\n const nextEntries: Array<[string, SyncScheduleEditorState]> = []\n for (const entityType of entityTypes) {\n for (const direction of directions) {\n const record = records.find((item) => item.entityType === entityType && item.direction === direction)\n nextEntries.push([\n buildScheduleKey(entityType, direction),\n record\n ? {\n id: record.id,\n scheduleType: record.scheduleType,\n scheduleValue: record.scheduleValue,\n timezone: record.timezone,\n fullSync: record.fullSync,\n isEnabled: record.isEnabled,\n lastRunAt: record.lastRunAt,\n }\n : buildDefaultScheduleState(entityType),\n ])\n }\n }\n return Object.fromEntries(nextEntries)\n}\n\nexport function IntegrationScheduleTab(props: IntegrationScheduleTabProps) {\n const t = useT()\n const scopeVersion = useOrganizationScopeVersion()\n const [option, setOption] = React.useState<SyncOption | null>(null)\n const [schedules, setSchedules] = React.useState<Record<string, SyncScheduleEditorState>>({})\n const [isLoading, setIsLoading] = React.useState(true)\n const [runningKey, setRunningKey] = React.useState<string | null>(null)\n const [savingKey, setSavingKey] = React.useState<string | null>(null)\n const [deletingKey, setDeletingKey] = React.useState<string | null>(null)\n\n const load = React.useCallback(async () => {\n setIsLoading(true)\n try {\n const [optionsCall, schedulesCall] = await Promise.all([\n apiCall<SyncOptionsResponse>('/api/data_sync/options', undefined, { fallback: { items: [] } }),\n apiCall<SyncSchedulesResponse>(`/api/data_sync/schedules?integrationId=${encodeURIComponent(props.integrationId)}&page=1&pageSize=100`, undefined, { fallback: { items: [] } }),\n ])\n\n const resolvedOption = (optionsCall.result?.items ?? []).find((item) => item.integrationId === props.integrationId) ?? null\n setOption(resolvedOption)\n\n const supportedEntities = resolvedOption?.supportedEntities ?? []\n const supportedDirections = getSupportedDirections(resolvedOption?.direction)\n setSchedules(buildScheduleEditors(supportedEntities, supportedDirections, schedulesCall.result?.items ?? []))\n } catch (error) {\n const message = error instanceof Error ? error.message : t('data_sync.integrationTab.loadError', 'Failed to load sync schedules.')\n flash(message, 'error')\n } finally {\n setIsLoading(false)\n }\n }, [props.integrationId, t])\n\n React.useEffect(() => {\n void load()\n }, [load, scopeVersion])\n\n const supportedDirections = React.useMemo(\n () => getSupportedDirections(option?.direction),\n [option?.direction],\n )\n\n const rows = React.useMemo(\n () => (option?.supportedEntities ?? []).flatMap((entityType) => (\n supportedDirections.map((direction) => ({\n entityType,\n direction,\n key: buildScheduleKey(entityType, direction),\n }))\n )),\n [option?.supportedEntities, supportedDirections],\n )\n\n const updateScheduleEditor = React.useCallback((key: string, patch: Partial<SyncScheduleEditorState>, entityType: string) => {\n setSchedules((current) => ({\n ...current,\n [key]: {\n ...(current[key] ?? buildDefaultScheduleState(entityType)),\n ...patch,\n },\n }))\n }, [])\n\n const handleStartSync = React.useCallback(async (entityType: string, direction: 'import' | 'export', scheduleKey: string) => {\n if (!props.isEnabled) {\n flash(t('data_sync.integrationTab.integrationDisabled', 'Enable the integration before starting a sync.'), 'error')\n return\n }\n if (!props.hasCredentials) {\n flash(t('data_sync.integrationTab.credentialsMissing', 'Configure credentials before starting a sync.'), 'error')\n return\n }\n\n setRunningKey(scheduleKey)\n try {\n const scheduleState = schedules[scheduleKey] ?? buildDefaultScheduleState(entityType)\n const call = await apiCall<{ id: string }>('/api/data_sync/run', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n integrationId: props.integrationId,\n entityType,\n direction,\n fullSync: scheduleState.fullSync,\n batchSize: 100,\n }),\n }, { fallback: null })\n\n if (!call.ok) {\n throw new Error((call.result as { error?: string } | null)?.error ?? 'Failed to start sync')\n }\n\n flash(t('data_sync.integrationTab.runStarted', 'Sync run started.'), 'success')\n } catch (error) {\n const message = error instanceof Error ? error.message : t('data_sync.integrationTab.runError', 'Failed to start sync.')\n flash(message, 'error')\n } finally {\n setRunningKey(null)\n }\n }, [props.hasCredentials, props.integrationId, props.isEnabled, schedules, t])\n\n const handleSaveSchedule = React.useCallback(async (entityType: string, direction: 'import' | 'export', scheduleKey: string) => {\n const scheduleState = schedules[scheduleKey] ?? buildDefaultScheduleState(entityType)\n setSavingKey(scheduleKey)\n try {\n const call = await apiCall<SyncScheduleRecord>('/api/data_sync/schedules', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n integrationId: props.integrationId,\n entityType,\n direction,\n scheduleType: scheduleState.scheduleType,\n scheduleValue: scheduleState.scheduleValue,\n timezone: scheduleState.timezone,\n fullSync: scheduleState.fullSync,\n isEnabled: scheduleState.isEnabled,\n }),\n }, { fallback: null })\n\n if (!call.ok || !call.result) {\n throw new Error((call.result as { error?: string } | null)?.error ?? 'Failed to save schedule')\n }\n\n updateScheduleEditor(scheduleKey, {\n id: call.result.id,\n scheduleType: call.result.scheduleType,\n scheduleValue: call.result.scheduleValue,\n timezone: call.result.timezone,\n fullSync: call.result.fullSync,\n isEnabled: call.result.isEnabled,\n lastRunAt: call.result.lastRunAt,\n }, entityType)\n flash(t('data_sync.dashboard.schedule.success', 'Recurring schedule saved'), 'success')\n } catch (error) {\n const message = error instanceof Error ? error.message : t('data_sync.dashboard.schedule.error', 'Failed to save recurring schedule')\n flash(message, 'error')\n } finally {\n setSavingKey(null)\n }\n }, [props.integrationId, schedules, t, updateScheduleEditor])\n\n const handleDeleteSchedule = React.useCallback(async (entityType: string, scheduleKey: string) => {\n const scheduleState = schedules[scheduleKey]\n if (!scheduleState?.id) {\n updateScheduleEditor(scheduleKey, buildDefaultScheduleState(entityType), entityType)\n return\n }\n\n setDeletingKey(scheduleKey)\n try {\n const call = await apiCall(`/api/data_sync/schedules/${encodeURIComponent(scheduleState.id)}`, {\n method: 'DELETE',\n }, { fallback: null })\n\n if (!call.ok) {\n throw new Error((call.result as { error?: string } | null)?.error ?? 'Failed to delete schedule')\n }\n\n setSchedules((current) => ({\n ...current,\n [scheduleKey]: buildDefaultScheduleState(entityType),\n }))\n flash(t('data_sync.dashboard.schedule.deleteSuccess', 'Recurring schedule removed'), 'success')\n } catch (error) {\n const message = error instanceof Error ? error.message : t('data_sync.dashboard.schedule.deleteError', 'Failed to remove recurring schedule')\n flash(message, 'error')\n } finally {\n setDeletingKey(null)\n }\n }, [schedules, t, updateScheduleEditor])\n\n if (isLoading) {\n return (\n <div className=\"flex min-h-40 items-center justify-center rounded-lg border bg-card\">\n <Spinner />\n </div>\n )\n }\n\n if (!option) {\n return (\n <Alert variant=\"warning\">\n <AlertDescription>\n {t('data_sync.integrationTab.notAvailable', 'This integration is not registered as a data sync provider.')}\n </AlertDescription>\n </Alert>\n )\n }\n\n return (\n <section className=\"space-y-4 rounded-lg border bg-card p-6\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div className=\"space-y-2\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <Badge variant=\"outline\" className={props.isEnabled ? 'border-emerald-300 text-emerald-700' : 'border-amber-300 text-amber-700'}>\n {props.isEnabled ? <ShieldCheck className=\"mr-2 h-3.5 w-3.5\" /> : <ShieldAlert className=\"mr-2 h-3.5 w-3.5\" />}\n {props.isEnabled\n ? t('data_sync.dashboard.start.status.enabled', 'Integration enabled')\n : t('data_sync.dashboard.start.status.disabled', 'Integration disabled')}\n </Badge>\n <Badge variant=\"outline\" className={props.hasCredentials ? 'border-sky-300 text-sky-700' : 'border-amber-300 text-amber-700'}>\n <CalendarClock className=\"mr-2 h-3.5 w-3.5\" />\n {props.hasCredentials\n ? t('data_sync.dashboard.start.status.credentialsReady', 'Credentials ready')\n : t('data_sync.dashboard.start.status.credentialsMissing', 'Credentials missing')}\n </Badge>\n </div>\n <div>\n <h3 className=\"text-base font-semibold\">{t('data_sync.integrationTab.title', 'Sync schedules')}</h3>\n <p className=\"text-sm text-muted-foreground\">\n {t('data_sync.integrationTab.description', 'Run one-off syncs or save recurring schedules for every supported entity directly from the integration detail page.')}\n </p>\n </div>\n </div>\n <Button type=\"button\" variant=\"outline\" onClick={() => void load()} disabled={isLoading}>\n <RefreshCw className=\"mr-2 h-4 w-4\" />\n {t('data_sync.integrationTab.refresh', 'Refresh')}\n </Button>\n </div>\n\n {!props.isEnabled ? (\n <Alert variant=\"warning\">\n <AlertDescription>\n {t('data_sync.integrationTab.integrationDisabledNotice', 'The integration is disabled. You can save schedules now, but runs will stay blocked until the integration is enabled.')}\n </AlertDescription>\n </Alert>\n ) : null}\n\n {!props.hasCredentials ? (\n <Alert variant=\"warning\">\n <AlertDescription>\n {t('data_sync.integrationTab.credentialsMissingNotice', 'Credentials are still missing. Save schedules first if you want, but manual and scheduled runs will fail until credentials are configured.')}\n </AlertDescription>\n </Alert>\n ) : null}\n\n {rows.length === 0 ? (\n <Alert variant=\"info\">\n <AlertDescription>\n {t('data_sync.integrationTab.empty', 'This provider does not expose any schedulable sync entities yet.')}\n </AlertDescription>\n </Alert>\n ) : (\n <div className=\"overflow-x-auto rounded-lg border\">\n <table className=\"w-full min-w-[1080px] text-sm\">\n <thead className=\"bg-muted/50 text-left\">\n <tr>\n <th className=\"px-3 py-2 font-medium\">{t('data_sync.dashboard.columns.entityType', 'Entity Type')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('data_sync.dashboard.columns.direction', 'Direction')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('data_sync.dashboard.schedule.type', 'Schedule type')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('data_sync.integrationTab.columns.value', 'Value')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('data_sync.dashboard.schedule.timezone', 'Timezone')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('data_sync.dashboard.start.fullSync', 'Run as full sync')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('data_sync.dashboard.schedule.enabled', 'Schedule enabled')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('data_sync.integrationTab.columns.lastRun', 'Last run')}</th>\n <th className=\"px-3 py-2 font-medium\">{t('data_sync.integrationTab.columns.actions', 'Actions')}</th>\n </tr>\n </thead>\n <tbody>\n {rows.map((row) => {\n const scheduleState = schedules[row.key] ?? buildDefaultScheduleState(row.entityType)\n const isRunning = runningKey === row.key\n const isSaving = savingKey === row.key\n const isDeleting = deletingKey === row.key\n const controlsDisabled = isRunning || isSaving || isDeleting\n return (\n <tr key={row.key} className=\"border-t align-top\">\n <td className=\"px-3 py-3 font-medium\">{formatEntityTypeLabel(row.entityType)}</td>\n <td className=\"px-3 py-3\">{t(`data_sync.dashboard.direction.${row.direction}`, row.direction === 'import' ? 'Import' : 'Export')}</td>\n <td className=\"px-3 py-3\">\n <select\n className=\"flex h-10 w-full min-w-32 rounded-md border border-input bg-background px-3 py-2 text-sm\"\n value={scheduleState.scheduleType}\n onChange={(event) => updateScheduleEditor(row.key, {\n scheduleType: event.target.value === 'cron' ? 'cron' : 'interval',\n }, row.entityType)}\n disabled={controlsDisabled}\n >\n <option value=\"interval\">{t('data_sync.dashboard.schedule.interval', 'Interval')}</option>\n <option value=\"cron\">{t('data_sync.dashboard.schedule.cron', 'Cron')}</option>\n </select>\n </td>\n <td className=\"px-3 py-3\">\n <Input\n value={scheduleState.scheduleValue}\n onChange={(event) => updateScheduleEditor(row.key, { scheduleValue: event.target.value }, row.entityType)}\n disabled={controlsDisabled}\n placeholder={scheduleState.scheduleType === 'cron' ? '0 * * * *' : '1h'}\n />\n </td>\n <td className=\"px-3 py-3\">\n <Input\n value={scheduleState.timezone}\n onChange={(event) => updateScheduleEditor(row.key, { timezone: event.target.value }, row.entityType)}\n disabled={controlsDisabled}\n />\n </td>\n <td className=\"px-3 py-3\">\n <label className=\"flex min-h-10 items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={scheduleState.fullSync}\n onChange={(event) => updateScheduleEditor(row.key, { fullSync: event.target.checked }, row.entityType)}\n disabled={controlsDisabled}\n />\n <span>{t('data_sync.integrationTab.fullSyncShort', 'Full')}</span>\n </label>\n </td>\n <td className=\"px-3 py-3\">\n <label className=\"flex min-h-10 items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={scheduleState.isEnabled}\n onChange={(event) => updateScheduleEditor(row.key, { isEnabled: event.target.checked }, row.entityType)}\n disabled={controlsDisabled}\n />\n <span>{scheduleState.isEnabled ? t('data_sync.dashboard.schedule.status.shortEnabled', 'Scheduled') : t('data_sync.dashboard.schedule.status.shortDisabled', 'Paused')}</span>\n </label>\n </td>\n <td className=\"px-3 py-3 text-muted-foreground\">\n {scheduleState.lastRunAt\n ? new Date(scheduleState.lastRunAt).toLocaleString()\n : scheduleState.id\n ? t('data_sync.dashboard.schedule.neverRun', 'Saved, but no scheduled execution has completed yet.')\n : t('data_sync.dashboard.schedule.none', 'No recurring schedule saved for this target yet.')}\n </td>\n <td className=\"px-3 py-3\">\n <div className=\"flex flex-wrap gap-2\">\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={() => void handleStartSync(row.entityType, row.direction, row.key)}\n disabled={controlsDisabled || !props.isEnabled || !props.hasCredentials}\n >\n {isRunning ? <Spinner className=\"mr-2 h-4 w-4\" /> : <Play className=\"mr-2 h-4 w-4\" />}\n {isRunning\n ? t('data_sync.integrationTab.starting', 'Starting...')\n : t('data_sync.integrationTab.start', 'Run now')}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n onClick={() => void handleSaveSchedule(row.entityType, row.direction, row.key)}\n disabled={controlsDisabled}\n >\n {isSaving ? <Spinner className=\"mr-2 h-4 w-4\" /> : <Save className=\"mr-2 h-4 w-4\" />}\n {isSaving\n ? t('data_sync.dashboard.schedule.saving', 'Saving...')\n : t('data_sync.dashboard.schedule.save', 'Save recurring schedule')}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n onClick={() => void handleDeleteSchedule(row.entityType, row.key)}\n disabled={controlsDisabled || !scheduleState.id}\n >\n {isDeleting ? <Spinner className=\"mr-2 h-4 w-4\" /> : <Trash2 className=\"mr-2 h-4 w-4\" />}\n {isDeleting\n ? t('data_sync.dashboard.schedule.deleting', 'Removing...')\n : t('data_sync.dashboard.schedule.delete', 'Remove schedule')}\n </Button>\n </div>\n </td>\n </tr>\n )\n })}\n </tbody>\n </table>\n </div>\n )}\n\n <div className=\"grid gap-3 rounded-lg border border-dashed p-4 text-sm text-muted-foreground md:grid-cols-3\">\n <div className=\"space-y-1\">\n <Label>{t('data_sync.dashboard.schedule.interval', 'Interval')}</Label>\n <p>{t('data_sync.dashboard.schedule.intervalHelp', 'Example: `1h`, `6h`, or `24h` for repeating intervals.')}</p>\n </div>\n <div className=\"space-y-1\">\n <Label>{t('data_sync.dashboard.schedule.cron', 'Cron')}</Label>\n <p>{t('data_sync.dashboard.schedule.cronHelp', 'Example: `0 * * * *` runs at the start of every hour.')}</p>\n </div>\n <div className=\"space-y-1\">\n <Label>{t('data_sync.integrationTab.runNowTitle', 'Manual runs')}</Label>\n <p>{t('data_sync.integrationTab.runNowHelp', 'Run now uses the full-sync checkbox from the same row and starts progress tracking immediately in Data Sync.')}</p>\n </div>\n </div>\n </section>\n )\n}\n\nexport default IntegrationScheduleTab\n"],
5
+ "mappings": "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",
6
6
  "names": ["supportedDirections"]
7
7
  }
@@ -90,6 +90,8 @@ async function PATCH(req, ctx) {
90
90
  label: updated.label,
91
91
  color: updated.color,
92
92
  icon: updated.icon,
93
+ position: updated.position ?? 0,
94
+ isDefault: updated.isDefault ?? false,
93
95
  createdAt: updated.createdAt,
94
96
  updatedAt: updated.updatedAt
95
97
  });