@open-mercato/core 0.6.6-develop.6551.1.1511bfa890 → 0.6.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (304) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/dist/generated/entities.ids.generated.js +0 -1
  3. package/dist/generated/entities.ids.generated.js.map +2 -2
  4. package/dist/generated/entity-fields-registry.js +0 -12
  5. package/dist/generated/entity-fields-registry.js.map +2 -2
  6. package/dist/modules/api_keys/api/keys/route.js +13 -30
  7. package/dist/modules/api_keys/api/keys/route.js.map +2 -2
  8. package/dist/modules/api_keys/cli.js +1 -2
  9. package/dist/modules/api_keys/cli.js.map +2 -2
  10. package/dist/modules/attachments/api/file/[id]/route.js +7 -9
  11. package/dist/modules/attachments/api/file/[id]/route.js.map +2 -2
  12. package/dist/modules/attachments/api/image/[id]/[[...slug]]/route.js +7 -9
  13. package/dist/modules/attachments/api/image/[id]/[[...slug]]/route.js.map +2 -2
  14. package/dist/modules/attachments/api/route.js +17 -21
  15. package/dist/modules/attachments/api/route.js.map +2 -2
  16. package/dist/modules/attachments/components/AttachmentContentPreview.js +35 -6
  17. package/dist/modules/attachments/components/AttachmentContentPreview.js.map +2 -2
  18. package/dist/modules/audit_logs/backend/audit-logs/page.js +24 -14
  19. package/dist/modules/audit_logs/backend/audit-logs/page.js.map +2 -2
  20. package/dist/modules/auth/api/users/route.js +2 -6
  21. package/dist/modules/auth/api/users/route.js.map +2 -2
  22. package/dist/modules/auth/cli.js +2 -3
  23. package/dist/modules/auth/cli.js.map +2 -2
  24. package/dist/modules/configs/lib/upgrade-actions.js +0 -22
  25. package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
  26. package/dist/modules/customer_accounts/api/admin/roles/[id]/acl.js +0 -1
  27. package/dist/modules/customer_accounts/api/admin/roles/[id]/acl.js.map +2 -2
  28. package/dist/modules/customer_accounts/api/admin/roles/[id].js +3 -17
  29. package/dist/modules/customer_accounts/api/admin/roles/[id].js.map +2 -2
  30. package/dist/modules/customer_accounts/api/portal/users/[id]/roles.js +1 -6
  31. package/dist/modules/customer_accounts/api/portal/users/[id]/roles.js.map +2 -2
  32. package/dist/modules/customer_accounts/api/portal/users-invite.js +1 -6
  33. package/dist/modules/customer_accounts/api/portal/users-invite.js.map +2 -2
  34. package/dist/modules/customer_accounts/services/customerInvitationService.js +0 -1
  35. package/dist/modules/customer_accounts/services/customerInvitationService.js.map +2 -2
  36. package/dist/modules/customer_accounts/services/customerRbacService.js +1 -6
  37. package/dist/modules/customer_accounts/services/customerRbacService.js.map +2 -2
  38. package/dist/modules/customer_accounts/widgets/injection-table.js +2 -0
  39. package/dist/modules/customer_accounts/widgets/injection-table.js.map +2 -2
  40. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +1 -7
  41. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
  42. package/dist/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.js +2 -2
  43. package/dist/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.js.map +2 -2
  44. package/dist/modules/customers/components/detail/CompanyDetailTabs.js +43 -37
  45. package/dist/modules/customers/components/detail/CompanyDetailTabs.js.map +2 -2
  46. package/dist/modules/customers/components/detail/DealDetailTabs.js +35 -23
  47. package/dist/modules/customers/components/detail/DealDetailTabs.js.map +2 -2
  48. package/dist/modules/customers/components/detail/DetailTabsLayout.js +21 -6
  49. package/dist/modules/customers/components/detail/DetailTabsLayout.js.map +2 -2
  50. package/dist/modules/customers/components/detail/MobilePersonDetail.js +32 -26
  51. package/dist/modules/customers/components/detail/MobilePersonDetail.js.map +2 -2
  52. package/dist/modules/customers/components/detail/PersonDetailTabs.js +39 -29
  53. package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +2 -2
  54. package/dist/modules/dashboards/api/roles/widgets/route.js +3 -22
  55. package/dist/modules/dashboards/api/roles/widgets/route.js.map +2 -2
  56. package/dist/modules/dashboards/api/users/widgets/route.js +3 -22
  57. package/dist/modules/dashboards/api/users/widgets/route.js.map +2 -2
  58. package/dist/modules/dashboards/cli.js +3 -4
  59. package/dist/modules/dashboards/cli.js.map +2 -2
  60. package/dist/modules/dashboards/lib/widgetAssignmentScope.js +1 -9
  61. package/dist/modules/dashboards/lib/widgetAssignmentScope.js.map +2 -2
  62. package/dist/modules/dictionaries/commands/entries.js +14 -7
  63. package/dist/modules/dictionaries/commands/entries.js.map +2 -2
  64. package/dist/modules/dictionaries/commands/entry-operations.js +16 -7
  65. package/dist/modules/dictionaries/commands/entry-operations.js.map +2 -2
  66. package/dist/modules/dictionaries/commands/factory.js +3 -9
  67. package/dist/modules/dictionaries/commands/factory.js.map +2 -2
  68. package/dist/modules/dictionaries/fields/dictionary.js +41 -56
  69. package/dist/modules/dictionaries/fields/dictionary.js.map +2 -2
  70. package/dist/modules/directory/utils/organizationScope.js +3 -10
  71. package/dist/modules/directory/utils/organizationScope.js.map +2 -2
  72. package/dist/modules/entities/api/records.js +4 -5
  73. package/dist/modules/entities/api/records.js.map +2 -2
  74. package/dist/modules/entities/backend/entities/system/[entityId]/page.meta.js +0 -1
  75. package/dist/modules/entities/backend/entities/system/[entityId]/page.meta.js.map +2 -2
  76. package/dist/modules/entities/backend/entities/user/[entityId]/page.js +49 -49
  77. package/dist/modules/entities/backend/entities/user/[entityId]/page.js.map +2 -2
  78. package/dist/modules/entities/backend/entities/user/[entityId]/page.meta.js +0 -1
  79. package/dist/modules/entities/backend/entities/user/[entityId]/page.meta.js.map +2 -2
  80. package/dist/modules/entities/cli.js +1 -2
  81. package/dist/modules/entities/cli.js.map +2 -2
  82. package/dist/modules/feature_toggles/api/check/boolean/route.js +14 -0
  83. package/dist/modules/feature_toggles/api/check/boolean/route.js.map +2 -2
  84. package/dist/modules/feature_toggles/defaults.json +0 -8
  85. package/dist/modules/integrations/backend/integrations/[id]/page.js +80 -9
  86. package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
  87. package/dist/modules/payment_gateways/data/entities.js +0 -45
  88. package/dist/modules/payment_gateways/data/entities.js.map +2 -2
  89. package/dist/modules/payment_gateways/lib/gateway-service.js +38 -173
  90. package/dist/modules/payment_gateways/lib/gateway-service.js.map +3 -3
  91. package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js +14 -16
  92. package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js.map +2 -2
  93. package/dist/modules/planner/components/AvailabilityRulesEditor.js +30 -18
  94. package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
  95. package/dist/modules/query_index/api/status.js +8 -2
  96. package/dist/modules/query_index/api/status.js.map +2 -2
  97. package/dist/modules/resources/backend/resources/resources/[id]/page.js +24 -24
  98. package/dist/modules/resources/backend/resources/resources/[id]/page.js.map +2 -2
  99. package/dist/modules/sales/backend/sales/channels/create/page.js +0 -6
  100. package/dist/modules/sales/backend/sales/channels/create/page.js.map +2 -2
  101. package/dist/modules/sales/backend/sales/channels/create/page.meta.js +0 -2
  102. package/dist/modules/sales/backend/sales/channels/create/page.meta.js.map +2 -2
  103. package/dist/modules/sales/backend/sales/channels/offers/page.js +0 -6
  104. package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
  105. package/dist/modules/sales/backend/sales/channels/offers/page.meta.js +0 -2
  106. package/dist/modules/sales/backend/sales/channels/offers/page.meta.js.map +2 -2
  107. package/dist/modules/sales/backend/sales/channels/page.js +0 -6
  108. package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
  109. package/dist/modules/sales/backend/sales/channels/page.meta.js +0 -2
  110. package/dist/modules/sales/backend/sales/channels/page.meta.js.map +2 -2
  111. package/dist/modules/sales/backend/sales/documents/[id]/page.js +4 -6
  112. package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
  113. package/dist/modules/sales/commands/documents.js +0 -44
  114. package/dist/modules/sales/commands/documents.js.map +2 -2
  115. package/dist/modules/sales/commands/returns.js +27 -2
  116. package/dist/modules/sales/commands/returns.js.map +2 -2
  117. package/dist/modules/sales/components/documents/AddressesSection.js +2 -6
  118. package/dist/modules/sales/components/documents/AddressesSection.js.map +2 -2
  119. package/dist/modules/sales/components/documents/ItemsSection.js +0 -1
  120. package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
  121. package/dist/modules/sales/components/documents/LineItemDialog.js +0 -9
  122. package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
  123. package/dist/modules/sales/components/documents/SalesDocumentForm.js +3 -51
  124. package/dist/modules/sales/components/documents/SalesDocumentForm.js.map +2 -2
  125. package/dist/modules/sales/components/documents/SalesDocumentsTable.js +8 -10
  126. package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
  127. package/dist/modules/sales/components/documents/ShipmentDialog.js +38 -59
  128. package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
  129. package/dist/modules/sales/lib/shipments/snapshots.js +1 -27
  130. package/dist/modules/sales/lib/shipments/snapshots.js.map +2 -2
  131. package/dist/modules/staff/backend/staff/team-members/[id]/page.js +25 -22
  132. package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
  133. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +14 -12
  134. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
  135. package/dist/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.js +29 -10
  136. package/dist/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.js.map +2 -2
  137. package/dist/modules/sync_excel/lib/adapters/customers.js +20 -19
  138. package/dist/modules/sync_excel/lib/adapters/customers.js.map +2 -2
  139. package/dist/modules/sync_excel/lib/parser.js +0 -185
  140. package/dist/modules/sync_excel/lib/parser.js.map +2 -2
  141. package/dist/modules/sync_excel/lib/upload-storage.js +1 -20
  142. package/dist/modules/sync_excel/lib/upload-storage.js.map +2 -2
  143. package/dist/modules/workflows/frontend/checkout-demo/page.js +8 -1
  144. package/dist/modules/workflows/frontend/checkout-demo/page.js.map +2 -2
  145. package/dist/modules/workflows/lib/activity-executor.js +1 -1
  146. package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
  147. package/dist/modules/workflows/lib/find-definition.js +18 -2
  148. package/dist/modules/workflows/lib/find-definition.js.map +2 -2
  149. package/dist/modules/workflows/lib/signal-handler.js +3 -2
  150. package/dist/modules/workflows/lib/signal-handler.js.map +2 -2
  151. package/dist/modules/workflows/lib/step-handler.js +4 -8
  152. package/dist/modules/workflows/lib/step-handler.js.map +2 -2
  153. package/dist/modules/workflows/lib/task-handler.js +3 -5
  154. package/dist/modules/workflows/lib/task-handler.js.map +2 -2
  155. package/dist/modules/workflows/lib/timer-handler.js +2 -1
  156. package/dist/modules/workflows/lib/timer-handler.js.map +2 -2
  157. package/dist/modules/workflows/lib/transition-handler.js +5 -13
  158. package/dist/modules/workflows/lib/transition-handler.js.map +2 -2
  159. package/dist/modules/workflows/lib/workflow-executor.js +11 -9
  160. package/dist/modules/workflows/lib/workflow-executor.js.map +2 -2
  161. package/dist/modules/workflows/migrations/Migration20260715120000.js +68 -0
  162. package/dist/modules/workflows/migrations/Migration20260715120000.js.map +7 -0
  163. package/dist/modules/workflows/migrations/Migration20260716120000.js +24 -0
  164. package/dist/modules/workflows/migrations/Migration20260716120000.js.map +7 -0
  165. package/dist/modules/workflows/workflows.js +2 -0
  166. package/dist/modules/workflows/workflows.js.map +2 -2
  167. package/generated/entities.ids.generated.ts +0 -1
  168. package/generated/entity-fields-registry.ts +0 -12
  169. package/package.json +8 -9
  170. package/src/modules/api_keys/api/keys/route.ts +13 -36
  171. package/src/modules/api_keys/cli.ts +3 -2
  172. package/src/modules/attachments/api/file/[id]/route.ts +7 -11
  173. package/src/modules/attachments/api/image/[id]/[[...slug]]/route.ts +7 -11
  174. package/src/modules/attachments/api/route.ts +21 -26
  175. package/src/modules/attachments/components/AttachmentContentPreview.tsx +44 -9
  176. package/src/modules/audit_logs/backend/audit-logs/page.tsx +22 -12
  177. package/src/modules/auth/api/users/route.ts +2 -11
  178. package/src/modules/auth/cli.ts +2 -3
  179. package/src/modules/configs/i18n/de.json +1 -5
  180. package/src/modules/configs/i18n/en.json +1 -5
  181. package/src/modules/configs/i18n/es.json +1 -5
  182. package/src/modules/configs/i18n/pl.json +1 -5
  183. package/src/modules/configs/lib/upgrade-actions.ts +0 -24
  184. package/src/modules/customer_accounts/AGENTS.md +6 -8
  185. package/src/modules/customer_accounts/api/admin/roles/[id]/acl.ts +0 -1
  186. package/src/modules/customer_accounts/api/admin/roles/[id].ts +3 -17
  187. package/src/modules/customer_accounts/api/portal/users/[id]/roles.ts +1 -6
  188. package/src/modules/customer_accounts/api/portal/users-invite.ts +1 -6
  189. package/src/modules/customer_accounts/services/customerInvitationService.ts +0 -1
  190. package/src/modules/customer_accounts/services/customerRbacService.ts +2 -9
  191. package/src/modules/customer_accounts/widgets/injection-table.ts +2 -0
  192. package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +1 -11
  193. package/src/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.tsx +2 -6
  194. package/src/modules/customers/components/detail/CompanyDetailTabs.tsx +55 -39
  195. package/src/modules/customers/components/detail/DealDetailTabs.tsx +49 -24
  196. package/src/modules/customers/components/detail/DetailTabsLayout.tsx +24 -13
  197. package/src/modules/customers/components/detail/MobilePersonDetail.tsx +31 -25
  198. package/src/modules/customers/components/detail/PersonDetailTabs.tsx +50 -29
  199. package/src/modules/dashboards/api/roles/widgets/route.ts +3 -22
  200. package/src/modules/dashboards/api/users/widgets/route.ts +3 -22
  201. package/src/modules/dashboards/cli.ts +9 -4
  202. package/src/modules/dashboards/lib/widgetAssignmentScope.ts +0 -18
  203. package/src/modules/dictionaries/commands/entries.ts +16 -7
  204. package/src/modules/dictionaries/commands/entry-operations.ts +18 -8
  205. package/src/modules/dictionaries/commands/factory.ts +2 -8
  206. package/src/modules/dictionaries/fields/dictionary.tsx +32 -55
  207. package/src/modules/dictionaries/i18n/de.json +0 -2
  208. package/src/modules/dictionaries/i18n/en.json +0 -2
  209. package/src/modules/dictionaries/i18n/es.json +0 -2
  210. package/src/modules/dictionaries/i18n/pl.json +0 -2
  211. package/src/modules/directory/utils/organizationScope.ts +2 -36
  212. package/src/modules/entities/api/records.ts +7 -5
  213. package/src/modules/entities/backend/entities/system/[entityId]/page.meta.ts +0 -1
  214. package/src/modules/entities/backend/entities/user/[entityId]/page.meta.ts +0 -1
  215. package/src/modules/entities/backend/entities/user/[entityId]/page.tsx +49 -51
  216. package/src/modules/entities/cli.ts +1 -2
  217. package/src/modules/entities/i18n/de.json +0 -34
  218. package/src/modules/entities/i18n/en.json +0 -34
  219. package/src/modules/entities/i18n/es.json +0 -34
  220. package/src/modules/entities/i18n/pl.json +0 -34
  221. package/src/modules/feature_toggles/api/check/boolean/route.ts +15 -0
  222. package/src/modules/feature_toggles/defaults.json +0 -8
  223. package/src/modules/integrations/backend/integrations/[id]/page.tsx +59 -16
  224. package/src/modules/payment_gateways/data/entities.ts +0 -39
  225. package/src/modules/payment_gateways/lib/gateway-service.ts +40 -211
  226. package/src/modules/payment_gateways/migrations/.snapshot-open-mercato.json +0 -236
  227. package/src/modules/planner/backend/planner/availability-rulesets/[id]/page.tsx +20 -14
  228. package/src/modules/planner/components/AvailabilityRulesEditor.tsx +34 -16
  229. package/src/modules/query_index/api/status.ts +8 -2
  230. package/src/modules/resources/backend/resources/resources/[id]/page.tsx +37 -27
  231. package/src/modules/sales/backend/sales/channels/create/page.meta.ts +0 -3
  232. package/src/modules/sales/backend/sales/channels/create/page.tsx +0 -7
  233. package/src/modules/sales/backend/sales/channels/offers/page.meta.ts +0 -3
  234. package/src/modules/sales/backend/sales/channels/offers/page.tsx +0 -7
  235. package/src/modules/sales/backend/sales/channels/page.meta.ts +0 -4
  236. package/src/modules/sales/backend/sales/channels/page.tsx +0 -7
  237. package/src/modules/sales/backend/sales/documents/[id]/page.tsx +5 -7
  238. package/src/modules/sales/commands/documents.ts +0 -65
  239. package/src/modules/sales/commands/returns.ts +32 -2
  240. package/src/modules/sales/components/documents/AddressesSection.tsx +2 -6
  241. package/src/modules/sales/components/documents/ItemsSection.tsx +0 -5
  242. package/src/modules/sales/components/documents/LineItemDialog.tsx +0 -10
  243. package/src/modules/sales/components/documents/SalesDocumentForm.tsx +3 -53
  244. package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +8 -10
  245. package/src/modules/sales/components/documents/ShipmentDialog.tsx +40 -65
  246. package/src/modules/sales/i18n/de.json +0 -5
  247. package/src/modules/sales/i18n/en.json +0 -5
  248. package/src/modules/sales/i18n/es.json +0 -5
  249. package/src/modules/sales/i18n/pl.json +0 -5
  250. package/src/modules/sales/lib/shipments/snapshots.ts +0 -30
  251. package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +34 -25
  252. package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +17 -11
  253. package/src/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.tsx +28 -11
  254. package/src/modules/sync_excel/lib/adapters/customers.ts +22 -20
  255. package/src/modules/sync_excel/lib/parser.ts +0 -245
  256. package/src/modules/sync_excel/lib/upload-storage.ts +1 -23
  257. package/src/modules/workflows/frontend/checkout-demo/page.tsx +12 -1
  258. package/src/modules/workflows/lib/activity-executor.ts +22 -2
  259. package/src/modules/workflows/lib/find-definition.ts +53 -1
  260. package/src/modules/workflows/lib/signal-handler.ts +5 -4
  261. package/src/modules/workflows/lib/step-handler.ts +4 -8
  262. package/src/modules/workflows/lib/task-handler.ts +2 -4
  263. package/src/modules/workflows/lib/timer-handler.ts +3 -2
  264. package/src/modules/workflows/lib/transition-handler.ts +5 -13
  265. package/src/modules/workflows/lib/workflow-executor.ts +11 -8
  266. package/src/modules/workflows/migrations/Migration20260715120000.ts +114 -0
  267. package/src/modules/workflows/migrations/Migration20260716120000.ts +57 -0
  268. package/src/modules/workflows/workflows.ts +2 -0
  269. package/dist/generated/entities/gateway_session_initialization/index.js +0 -23
  270. package/dist/generated/entities/gateway_session_initialization/index.js.map +0 -7
  271. package/dist/modules/attachments/lib/reconcileOrganization.js +0 -110
  272. package/dist/modules/attachments/lib/reconcileOrganization.js.map +0 -7
  273. package/dist/modules/attachments/lib/requestScope.js +0 -10
  274. package/dist/modules/attachments/lib/requestScope.js.map +0 -7
  275. package/dist/modules/auth/api/autologin.js +0 -85
  276. package/dist/modules/auth/api/autologin.js.map +0 -7
  277. package/dist/modules/auth/lib/autologin.js +0 -19
  278. package/dist/modules/auth/lib/autologin.js.map +0 -7
  279. package/dist/modules/customers/components/detail/useDealsAccess.js +0 -16
  280. package/dist/modules/customers/components/detail/useDealsAccess.js.map +0 -7
  281. package/dist/modules/payment_gateways/lib/session-idempotency.js +0 -104
  282. package/dist/modules/payment_gateways/lib/session-idempotency.js.map +0 -7
  283. package/dist/modules/payment_gateways/migrations/Migration20260709220938_payment_gateways.js +0 -11
  284. package/dist/modules/payment_gateways/migrations/Migration20260709220938_payment_gateways.js.map +0 -7
  285. package/dist/modules/sales/components/SalesChannelsDisabledNotice.js +0 -15
  286. package/dist/modules/sales/components/SalesChannelsDisabledNotice.js.map +0 -7
  287. package/dist/modules/sales/components/useSalesChannelsEnabled.js +0 -44
  288. package/dist/modules/sales/components/useSalesChannelsEnabled.js.map +0 -7
  289. package/dist/modules/sales/lib/salesChannelsToggle.js +0 -18
  290. package/dist/modules/sales/lib/salesChannelsToggle.js.map +0 -7
  291. package/dist/modules/sales/lib/salesChannelsToggleId.js +0 -5
  292. package/dist/modules/sales/lib/salesChannelsToggleId.js.map +0 -7
  293. package/generated/entities/gateway_session_initialization/index.ts +0 -10
  294. package/src/modules/attachments/lib/reconcileOrganization.ts +0 -188
  295. package/src/modules/attachments/lib/requestScope.ts +0 -27
  296. package/src/modules/auth/api/autologin.ts +0 -100
  297. package/src/modules/auth/lib/autologin.ts +0 -36
  298. package/src/modules/customers/components/detail/useDealsAccess.ts +0 -19
  299. package/src/modules/payment_gateways/lib/session-idempotency.ts +0 -142
  300. package/src/modules/payment_gateways/migrations/Migration20260709220938_payment_gateways.ts +0 -10
  301. package/src/modules/sales/components/SalesChannelsDisabledNotice.tsx +0 -21
  302. package/src/modules/sales/components/useSalesChannelsEnabled.ts +0 -59
  303. package/src/modules/sales/lib/salesChannelsToggle.ts +0 -26
  304. package/src/modules/sales/lib/salesChannelsToggleId.ts +0 -1
@@ -296,13 +296,6 @@ export function ShipmentDialog({
296
296
  const [addressOptions, setAddressOptions] = React.useState<ShipmentAddressOption[]>([])
297
297
  const [addressLoading, setAddressLoading] = React.useState(false)
298
298
  const [addressError, setAddressError] = React.useState<string | null>(null)
299
- const addressLoadPromiseRef = React.useRef<{
300
- orderId: string
301
- promise: Promise<ShipmentAddressOption[]>
302
- } | null>(null)
303
- const currentAddressOrderIdRef = React.useRef(orderId)
304
- currentAddressOrderIdRef.current = orderId
305
- const initializedDialogKeyRef = React.useRef<string | null>(null)
306
299
  const [documentStatuses, setDocumentStatuses] = React.useState<StatusOption[]>([])
307
300
  const [lineStatuses, setLineStatuses] = React.useState<StatusOption[]>([])
308
301
  const [shipmentStatuses, setShipmentStatuses] = React.useState<StatusOption[]>([])
@@ -486,52 +479,37 @@ export function ShipmentDialog({
486
479
  [],
487
480
  )
488
481
 
489
- const loadAddressOptions = React.useCallback((): Promise<ShipmentAddressOption[]> => {
490
- const activeRequest = addressLoadPromiseRef.current
491
- if (activeRequest?.orderId === orderId) return activeRequest.promise
492
-
482
+ const loadAddressOptions = React.useCallback(async () => {
493
483
  setAddressLoading(true)
494
- const request = (async () => {
495
- try {
496
- const params = new URLSearchParams({
497
- page: '1',
498
- pageSize: '100',
499
- documentId: orderId,
500
- documentKind: 'order',
501
- })
502
- const response = await apiCall<{ items?: Array<Record<string, unknown>> }>(
503
- `/api/sales/document-addresses?${params.toString()}`,
504
- undefined,
505
- { fallback: { items: [] } },
506
- )
507
- const items = Array.isArray(response.result?.items) ? response.result.items : []
508
- const mapped = items
509
- .map((item) => mapDocumentAddressOption(item))
510
- .filter((entry): entry is ShipmentAddressOption => Boolean(entry))
511
- const loadedOptions = dedupeAddressOptions([...baseAddressOptions, ...mapped])
512
- if (currentAddressOrderIdRef.current !== orderId) return baseAddressOptions
513
- mergeAddressOptions(loadedOptions)
514
- setAddressError(null)
515
- return loadedOptions
516
- } catch (err) {
517
- logger.error('sales.shipments.addresses.load', { err })
518
- if (currentAddressOrderIdRef.current === orderId) {
519
- setAddressError(
520
- t('sales.documents.shipments.addressLoadError', 'Failed to load addresses.'),
521
- )
522
- }
523
- return baseAddressOptions
524
- }
525
- })()
526
- addressLoadPromiseRef.current = { orderId, promise: request }
527
- void request.then(() => {
528
- if (addressLoadPromiseRef.current?.promise === request) {
529
- addressLoadPromiseRef.current = null
530
- setAddressLoading(false)
531
- }
532
- })
533
- return request
534
- }, [baseAddressOptions, mapDocumentAddressOption, mergeAddressOptions, orderId, t])
484
+ try {
485
+ const params = new URLSearchParams({
486
+ page: '1',
487
+ pageSize: '100',
488
+ documentId: orderId,
489
+ documentKind: 'order',
490
+ })
491
+ const response = await apiCall<{ items?: Array<Record<string, unknown>> }>(
492
+ `/api/sales/document-addresses?${params.toString()}`,
493
+ undefined,
494
+ { fallback: { items: [] } },
495
+ )
496
+ const items = Array.isArray(response.result?.items) ? response.result.items : []
497
+ const mapped = items
498
+ .map((item) => mapDocumentAddressOption(item))
499
+ .filter((entry): entry is ShipmentAddressOption => Boolean(entry))
500
+ mergeAddressOptions(mapped)
501
+ setAddressError(null)
502
+ return mapped
503
+ } catch (err) {
504
+ logger.error('sales.shipments.addresses.load', { err })
505
+ setAddressError(
506
+ t('sales.documents.shipments.addressLoadError', 'Failed to load addresses.'),
507
+ )
508
+ return []
509
+ } finally {
510
+ setAddressLoading(false)
511
+ }
512
+ }, [mapDocumentAddressOption, mergeAddressOptions, orderId, t])
535
513
 
536
514
  const buildPriceSubtitle = React.useCallback(
537
515
  (option: ShippingMethodOption): string | undefined => {
@@ -873,20 +851,16 @@ export function ShipmentDialog({
873
851
  )
874
852
 
875
853
  React.useEffect(() => {
876
- if (!open) {
877
- initializedDialogKeyRef.current = null
878
- return
879
- }
880
- const dialogKey = `${orderId}:${mode}:${shipment?.id ?? 'new'}`
881
- if (initializedDialogKeyRef.current === dialogKey) return
882
- initializedDialogKeyRef.current = dialogKey
854
+ if (!open) return
883
855
  setFormResetKey((prev) => prev + 1)
884
856
  if (!shippingMethods.length) {
885
857
  void loadShippingMethods()
886
858
  }
887
859
  setAddressOptions(baseAddressOptions)
888
860
  setAddressError(null)
889
- void loadAddressOptions()
861
+ if (!addressOptions.length) {
862
+ void loadAddressOptions()
863
+ }
890
864
  if (!shipmentStatuses.length) {
891
865
  void loadShipmentStatuses()
892
866
  }
@@ -897,6 +871,7 @@ export function ShipmentDialog({
897
871
  void loadLineStatuses()
898
872
  }
899
873
  }, [
874
+ addressOptions.length,
900
875
  baseAddressOptions,
901
876
  documentStatuses.length,
902
877
  loadAddressOptions,
@@ -906,8 +881,6 @@ export function ShipmentDialog({
906
881
  loadShippingMethods,
907
882
  mode,
908
883
  open,
909
- orderId,
910
- shipment?.id,
911
884
  lineStatuses.length,
912
885
  shipmentStatuses.length,
913
886
  shippingMethods.length,
@@ -966,9 +939,11 @@ export function ShipmentDialog({
966
939
 
967
940
  const fetchAddressItems = React.useCallback(
968
941
  async (query?: string): Promise<LookupSelectItem[]> => {
969
- const options = addressOptions.length ? addressOptions : await loadAddressOptions()
942
+ if (!addressOptions.length && !addressLoading) {
943
+ await loadAddressOptions()
944
+ }
970
945
  const needle = query?.trim().toLowerCase() ?? ''
971
- return options
946
+ return addressOptions
972
947
  .filter((option) => {
973
948
  if (!needle) return true
974
949
  return (
@@ -987,7 +962,7 @@ export function ShipmentDialog({
987
962
  ),
988
963
  }))
989
964
  },
990
- [addressOptions, loadAddressOptions],
965
+ [addressLoading, addressOptions, loadAddressOptions],
991
966
  )
992
967
 
993
968
  const validateItems = React.useCallback(
@@ -60,7 +60,6 @@
60
60
  "sales.channels.actions.backToList": "Zurück zu Kanälen",
61
61
  "sales.channels.actions.create": "Kanal hinzufügen",
62
62
  "sales.channels.create": "Vertriebskanal erstellen",
63
- "sales.channels.disabledNotice": "Vertriebskanäle sind für diesen Mandanten deaktiviert. Aktivieren Sie das Feature-Toggle \"Sales Channels\", um sie zu verwalten.",
64
63
  "sales.channels.form.address1": "Adresszeile 1",
65
64
  "sales.channels.form.address2": "Adresszeile 2",
66
65
  "sales.channels.form.city": "Stadt",
@@ -639,10 +638,8 @@
639
638
  "sales.documents.detail.items.errorDelete": "Position konnte nicht gelöscht werden.",
640
639
  "sales.documents.detail.items.errorDeleteShipped": "Positionen mit versandten Artikeln können nicht gelöscht werden.",
641
640
  "sales.documents.detail.items.errorLoad": "Positionen konnten nicht geladen werden.",
642
- "sales.documents.detail.items.errorPriceShipped": "Preis oder Einheit einer Position mit versandten Artikeln können nicht geändert werden.",
643
641
  "sales.documents.detail.items.errorProductRequired": "Wähle ein Produkt aus, um fortzufahren.",
644
642
  "sales.documents.detail.items.errorQuantity": "Die Menge muss größer als 0 sein.",
645
- "sales.documents.detail.items.errorQuantityBelowShipped": "Die Menge kann nicht unter die bereits versandten {{shipped}} gesenkt werden.",
646
643
  "sales.documents.detail.items.errorSave": "Position konnte nicht gespeichert werden.",
647
644
  "sales.documents.detail.items.errorUnitPrice": "Der Stückpreis muss größer als 0 sein.",
648
645
  "sales.documents.detail.items.errorVariantRequired": "Wähle eine Variante aus, um fortzufahren.",
@@ -953,10 +950,8 @@
953
950
  "sales.documents.items.errorDeleteShipped": "Positionen mit versandten Artikeln können nicht gelöscht werden.",
954
951
  "sales.documents.items.errorLoad": "Positionen konnten nicht geladen werden.",
955
952
  "sales.documents.items.errorNameRequired": "Name ist für benutzerdefinierte Positionen erforderlich.",
956
- "sales.documents.items.errorPriceShipped": "Preis oder Einheit einer Position mit versandten Artikeln können nicht geändert werden.",
957
953
  "sales.documents.items.errorProductRequired": "Wähle ein Produkt aus, um fortzufahren.",
958
954
  "sales.documents.items.errorQuantity": "Die Menge muss größer als 0 sein.",
959
- "sales.documents.items.errorQuantityBelowShipped": "Die Menge kann nicht unter die bereits versandten {{shipped}} gesenkt werden.",
960
955
  "sales.documents.items.errorSave": "Position konnte nicht gespeichert werden.",
961
956
  "sales.documents.items.errorScope": "Organisation und Mandant sind erforderlich.",
962
957
  "sales.documents.items.errorUnitPrice": "Der Stückpreis muss größer als 0 sein.",
@@ -60,7 +60,6 @@
60
60
  "sales.channels.actions.backToList": "Back to channels",
61
61
  "sales.channels.actions.create": "Add channel",
62
62
  "sales.channels.create": "Create sales channel",
63
- "sales.channels.disabledNotice": "Sales channels are disabled for this tenant. Enable the \"Sales Channels\" feature toggle to manage them.",
64
63
  "sales.channels.form.address1": "Address line 1",
65
64
  "sales.channels.form.address2": "Address line 2",
66
65
  "sales.channels.form.city": "City",
@@ -639,10 +638,8 @@
639
638
  "sales.documents.detail.items.errorDelete": "Failed to delete line.",
640
639
  "sales.documents.detail.items.errorDeleteShipped": "You cannot delete a line that has shipped items.",
641
640
  "sales.documents.detail.items.errorLoad": "Failed to load items.",
642
- "sales.documents.detail.items.errorPriceShipped": "You cannot change the price or unit of a line that has shipped items.",
643
641
  "sales.documents.detail.items.errorProductRequired": "Select a product to continue.",
644
642
  "sales.documents.detail.items.errorQuantity": "Quantity must be greater than 0.",
645
- "sales.documents.detail.items.errorQuantityBelowShipped": "You cannot lower the quantity below the {{shipped}} already shipped.",
646
643
  "sales.documents.detail.items.errorSave": "Failed to save line.",
647
644
  "sales.documents.detail.items.errorUnitPrice": "Unit price must be greater than 0.",
648
645
  "sales.documents.detail.items.errorVariantRequired": "Select a variant to continue.",
@@ -953,10 +950,8 @@
953
950
  "sales.documents.items.errorDeleteShipped": "You cannot delete a line that has shipped items.",
954
951
  "sales.documents.items.errorLoad": "Failed to load items.",
955
952
  "sales.documents.items.errorNameRequired": "Name is required for custom lines.",
956
- "sales.documents.items.errorPriceShipped": "You cannot change the price or unit of a line that has shipped items.",
957
953
  "sales.documents.items.errorProductRequired": "Select a product to continue.",
958
954
  "sales.documents.items.errorQuantity": "Quantity must be greater than 0.",
959
- "sales.documents.items.errorQuantityBelowShipped": "You cannot lower the quantity below the {{shipped}} already shipped.",
960
955
  "sales.documents.items.errorSave": "Failed to save line.",
961
956
  "sales.documents.items.errorScope": "Organization and tenant are required.",
962
957
  "sales.documents.items.errorUnitPrice": "Unit price must be greater than 0.",
@@ -60,7 +60,6 @@
60
60
  "sales.channels.actions.backToList": "Volver a canales",
61
61
  "sales.channels.actions.create": "Añadir canal",
62
62
  "sales.channels.create": "Crear canal de ventas",
63
- "sales.channels.disabledNotice": "Los canales de venta están desactivados para este inquilino. Active el conmutador de función \"Sales Channels\" para gestionarlos.",
64
63
  "sales.channels.form.address1": "Línea de dirección 1",
65
64
  "sales.channels.form.address2": "Línea de dirección 2",
66
65
  "sales.channels.form.city": "Ciudad",
@@ -639,10 +638,8 @@
639
638
  "sales.documents.detail.items.errorDelete": "No se pudo eliminar la línea.",
640
639
  "sales.documents.detail.items.errorDeleteShipped": "No puedes eliminar una línea que ya tiene envíos.",
641
640
  "sales.documents.detail.items.errorLoad": "No se pudieron cargar los artículos.",
642
- "sales.documents.detail.items.errorPriceShipped": "No puedes cambiar el precio ni la unidad de una línea que ya tiene envíos.",
643
641
  "sales.documents.detail.items.errorProductRequired": "Selecciona un producto para continuar.",
644
642
  "sales.documents.detail.items.errorQuantity": "La cantidad debe ser mayor que 0.",
645
- "sales.documents.detail.items.errorQuantityBelowShipped": "No puedes reducir la cantidad por debajo de las {{shipped}} ya enviadas.",
646
643
  "sales.documents.detail.items.errorSave": "No se pudo guardar la línea.",
647
644
  "sales.documents.detail.items.errorUnitPrice": "El precio unitario debe ser mayor que 0.",
648
645
  "sales.documents.detail.items.errorVariantRequired": "Selecciona una variante para continuar.",
@@ -953,10 +950,8 @@
953
950
  "sales.documents.items.errorDeleteShipped": "No puedes eliminar una línea que ya tiene envíos.",
954
951
  "sales.documents.items.errorLoad": "No se pudieron cargar los artículos.",
955
952
  "sales.documents.items.errorNameRequired": "El nombre es obligatorio para líneas personalizadas.",
956
- "sales.documents.items.errorPriceShipped": "No puedes cambiar el precio ni la unidad de una línea que ya tiene envíos.",
957
953
  "sales.documents.items.errorProductRequired": "Selecciona un producto para continuar.",
958
954
  "sales.documents.items.errorQuantity": "La cantidad debe ser mayor que 0.",
959
- "sales.documents.items.errorQuantityBelowShipped": "No puedes reducir la cantidad por debajo de las {{shipped}} ya enviadas.",
960
955
  "sales.documents.items.errorSave": "No se pudo guardar la línea.",
961
956
  "sales.documents.items.errorScope": "Se requieren organización e inquilino.",
962
957
  "sales.documents.items.errorUnitPrice": "El precio unitario debe ser mayor que 0.",
@@ -60,7 +60,6 @@
60
60
  "sales.channels.actions.backToList": "Powrót do kanałów",
61
61
  "sales.channels.actions.create": "Dodaj kanał",
62
62
  "sales.channels.create": "Utwórz kanał sprzedaży",
63
- "sales.channels.disabledNotice": "Kanały sprzedaży są wyłączone dla tego najemcy. Włącz przełącznik funkcji \"Sales Channels\", aby nimi zarządzać.",
64
63
  "sales.channels.form.address1": "Adres linia 1",
65
64
  "sales.channels.form.address2": "Adres linia 2",
66
65
  "sales.channels.form.city": "Miasto",
@@ -639,10 +638,8 @@
639
638
  "sales.documents.detail.items.errorDelete": "Nie udało się usunąć pozycji.",
640
639
  "sales.documents.detail.items.errorDeleteShipped": "Nie można usunąć pozycji, która ma wysłane sztuki.",
641
640
  "sales.documents.detail.items.errorLoad": "Nie udało się wczytać pozycji.",
642
- "sales.documents.detail.items.errorPriceShipped": "Nie można zmienić ceny ani jednostki pozycji, która ma wysłane sztuki.",
643
641
  "sales.documents.detail.items.errorProductRequired": "Wybierz produkt, aby kontynuować.",
644
642
  "sales.documents.detail.items.errorQuantity": "Ilość musi być większa niż 0.",
645
- "sales.documents.detail.items.errorQuantityBelowShipped": "Nie można obniżyć ilości poniżej {{shipped}} już wysłanych.",
646
643
  "sales.documents.detail.items.errorSave": "Nie udało się zapisać pozycji.",
647
644
  "sales.documents.detail.items.errorUnitPrice": "Cena jednostkowa musi być większa niż 0.",
648
645
  "sales.documents.detail.items.errorVariantRequired": "Wybierz wariant, aby kontynuować.",
@@ -953,10 +950,8 @@
953
950
  "sales.documents.items.errorDeleteShipped": "Nie można usunąć pozycji, która ma wysłane sztuki.",
954
951
  "sales.documents.items.errorLoad": "Nie udało się załadować pozycji.",
955
952
  "sales.documents.items.errorNameRequired": "Nazwa jest wymagana dla niestandardowych pozycji.",
956
- "sales.documents.items.errorPriceShipped": "Nie można zmienić ceny ani jednostki pozycji, która ma wysłane sztuki.",
957
953
  "sales.documents.items.errorProductRequired": "Wybierz produkt, aby kontynuować.",
958
954
  "sales.documents.items.errorQuantity": "Ilość musi być większa niż 0.",
959
- "sales.documents.items.errorQuantityBelowShipped": "Nie można obniżyć ilości poniżej {{shipped}} już wysłanych.",
960
955
  "sales.documents.items.errorSave": "Nie udało się zapisać pozycji.",
961
956
  "sales.documents.items.errorScope": "Wymagane są organizacja i najemca.",
962
957
  "sales.documents.items.errorUnitPrice": "Cena jednostkowa musi być większa niż 0.",
@@ -136,34 +136,4 @@ export const refreshShipmentItemsSnapshot = async (
136
136
  return snapshot
137
137
  }
138
138
 
139
- export const loadShippedQuantityByLine = async (
140
- em: EntityManager,
141
- orderId: string,
142
- scope: { tenantId: string; organizationId: string },
143
- ): Promise<Map<string, number>> => {
144
- const shipments = await findWithDecryption(
145
- em,
146
- SalesShipment,
147
- { order: orderId, deletedAt: null },
148
- {},
149
- scope,
150
- )
151
- const shippedByLine = new Map<string, number>()
152
- if (!shipments.length) return shippedByLine
153
- const items = await findWithDecryption(
154
- em,
155
- SalesShipmentItem,
156
- { shipment: { $in: shipments.map((shipment) => shipment.id) } },
157
- {},
158
- scope,
159
- )
160
- items.forEach((item) => {
161
- const orderLineId = typeof item.orderLine === 'string' ? item.orderLine : (item.orderLine?.id ?? null)
162
- if (!orderLineId) return
163
- const next = (shippedByLine.get(orderLineId) ?? 0) + coerceShipmentQuantity(item.quantity)
164
- shippedByLine.set(orderLineId, next)
165
- })
166
- return shippedByLine
167
- }
168
-
169
139
  export type { ShipmentItemSnapshot } from './types'
@@ -5,7 +5,6 @@ import Link from 'next/link'
5
5
  import { usePathname, useRouter, useSearchParams } from 'next/navigation'
6
6
  import { Page, PageBody } from '@open-mercato/ui/backend/Page'
7
7
  import { Button } from '@open-mercato/ui/primitives/button'
8
- import { Tabs, TabsList, TabsTrigger } from '@open-mercato/ui/primitives/tabs'
9
8
  import { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
10
9
  import { extractCustomFieldEntries } from '@open-mercato/shared/lib/crud/custom-fields-client'
11
10
  import { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'
@@ -433,22 +432,29 @@ export default function StaffTeamMemberDetailPage({ params }: { params?: { id?:
433
432
  </div>
434
433
  </div>
435
434
 
436
- <Tabs
437
- value={activePanel}
438
- onValueChange={(value) => setActivePanel(value as 'details' | 'availability' | 'jobHistory')}
439
- variant="underline"
440
- >
441
- <TabsList
442
- className="w-full flex-wrap"
435
+ <div className="border-b">
436
+ <nav
437
+ className="flex flex-wrap items-center gap-5 text-sm"
443
438
  aria-label={t('staff.teamMembers.detail.tabs.label', 'Team member sections')}
444
439
  >
445
440
  {panelTabs.map((tab) => (
446
- <TabsTrigger key={tab.id} value={tab.id}>
441
+ <button
442
+ key={tab.id}
443
+ type="button"
444
+ role="tab"
445
+ aria-selected={activePanel === tab.id}
446
+ onClick={() => setActivePanel(tab.id)}
447
+ className={`relative -mb-px border-b-2 px-0 py-2 text-sm font-medium transition-colors ${
448
+ activePanel === tab.id
449
+ ? 'border-accent-indigo text-foreground'
450
+ : 'border-transparent text-muted-foreground hover:text-foreground'
451
+ }`}
452
+ >
447
453
  {tab.label}
448
- </TabsTrigger>
454
+ </button>
449
455
  ))}
450
- </TabsList>
451
- </Tabs>
456
+ </nav>
457
+ </div>
452
458
 
453
459
  {activePanel === 'details' ? (
454
460
  <>
@@ -494,19 +500,22 @@ export default function StaffTeamMemberDetailPage({ params }: { params?: { id?:
494
500
 
495
501
  <div className="rounded-lg border bg-card p-4">
496
502
  <div className="flex flex-wrap items-center justify-between gap-3">
497
- <Tabs
498
- value={activeTab}
499
- onValueChange={(value) => setActiveTab(value as 'notes' | 'activities' | 'addresses')}
500
- variant="underline"
501
- >
502
- <TabsList className="h-auto flex-wrap border-b-0">
503
- {tabs.map((tab) => (
504
- <TabsTrigger key={tab.id} value={tab.id}>
505
- {tab.label}
506
- </TabsTrigger>
507
- ))}
508
- </TabsList>
509
- </Tabs>
503
+ <div className="flex gap-2">
504
+ {tabs.map((tab) => (
505
+ <button
506
+ key={tab.id}
507
+ type="button"
508
+ onClick={() => setActiveTab(tab.id)}
509
+ className={`relative -mb-px border-b-2 px-0 py-1 text-sm font-medium transition-colors ${
510
+ activeTab === tab.id
511
+ ? 'border-accent-indigo text-foreground'
512
+ : 'border-transparent text-muted-foreground hover:text-foreground'
513
+ }`}
514
+ >
515
+ {tab.label}
516
+ </button>
517
+ ))}
518
+ </div>
510
519
  {sectionAction ? (
511
520
  <Button
512
521
  type="button"
@@ -12,7 +12,6 @@ import { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimi
12
12
  import { DataTable, withDataTableNamespaces } from '@open-mercato/ui/backend/DataTable'
13
13
  import { RowActions } from '@open-mercato/ui/backend/RowActions'
14
14
  import { Button } from '@open-mercato/ui/primitives/button'
15
- import { Tabs, TabsList, TabsTrigger } from '@open-mercato/ui/primitives/tabs'
16
15
  import { BooleanIcon } from '@open-mercato/ui/backend/ValueIcons'
17
16
  import { flash } from '@open-mercato/ui/backend/FlashMessages'
18
17
  import { useT } from '@open-mercato/shared/lib/i18n/context'
@@ -363,22 +362,29 @@ export default function StaffTeamEditPage({ params }: { params?: { id?: string }
363
362
  <Page>
364
363
  <PageBody>
365
364
  <div className="space-y-6">
366
- <Tabs
367
- value={activeTab}
368
- onValueChange={(value) => setActiveTab(value as 'details' | 'members')}
369
- variant="underline"
370
- >
371
- <TabsList className="w-full flex-wrap" aria-label={memberLabels.tabs.label}>
365
+ <div className="border-b">
366
+ <nav className="flex flex-wrap items-center gap-5 text-sm" aria-label={memberLabels.tabs.label}>
372
367
  {[
373
368
  { id: 'details', label: memberLabels.tabs.details },
374
369
  { id: 'members', label: memberLabels.tabs.members },
375
370
  ].map((tab) => (
376
- <TabsTrigger key={tab.id} value={tab.id}>
371
+ <button
372
+ key={tab.id}
373
+ type="button"
374
+ role="tab"
375
+ aria-selected={activeTab === tab.id}
376
+ onClick={() => setActiveTab(tab.id as 'details' | 'members')}
377
+ className={`relative -mb-px border-b-2 px-0 py-2 text-sm font-medium transition-colors ${
378
+ activeTab === tab.id
379
+ ? 'border-accent-indigo text-foreground'
380
+ : 'border-transparent text-muted-foreground hover:text-foreground'
381
+ }`}
382
+ >
377
383
  {tab.label}
378
- </TabsTrigger>
384
+ </button>
379
385
  ))}
380
- </TabsList>
381
- </Tabs>
386
+ </nav>
387
+ </div>
382
388
 
383
389
  {activeTab === 'details' ? (
384
390
  <TeamForm
@@ -1,7 +1,7 @@
1
1
  "use client"
2
2
 
3
3
  import * as React from 'react'
4
- import { Tabs, TabsList, TabsTrigger } from '@open-mercato/ui/primitives/tabs'
4
+ import { Button } from '@open-mercato/ui/primitives/button'
5
5
 
6
6
  export type SavedViewTab = {
7
7
  id: string
@@ -19,18 +19,35 @@ export type SavedViewTabsProps = {
19
19
 
20
20
  export function SavedViewTabs({ tabs, activeId, onSelect, className, ariaLabel }: SavedViewTabsProps) {
21
21
  return (
22
- <Tabs value={activeId} onValueChange={onSelect} variant="underline" className={className}>
23
- <TabsList className="w-full flex-wrap" aria-label={ariaLabel ?? 'Saved views'}>
24
- {tabs.map((tab) => (
25
- <TabsTrigger
22
+ <div
23
+ role="tablist"
24
+ aria-label={ariaLabel ?? 'Saved views'}
25
+ className={`flex items-center gap-1 border-b border-border ${className ?? ''}`}
26
+ >
27
+ {tabs.map((tab) => {
28
+ const isActive = tab.id === activeId
29
+ return (
30
+ <Button
26
31
  key={tab.id}
27
- value={tab.id}
28
- count={typeof tab.count === 'number' ? tab.count : undefined}
32
+ type="button"
33
+ variant="ghost"
34
+ size="sm"
35
+ role="tab"
36
+ aria-selected={isActive}
37
+ className={`h-auto rounded-none px-3 py-2 text-sm hover:bg-transparent ${
38
+ isActive
39
+ ? 'border-b-2 border-foreground font-medium text-foreground'
40
+ : 'border-b-2 border-transparent text-muted-foreground hover:text-foreground'
41
+ }`}
42
+ onClick={() => onSelect(tab.id)}
29
43
  >
30
44
  {tab.label}
31
- </TabsTrigger>
32
- ))}
33
- </TabsList>
34
- </Tabs>
45
+ {typeof tab.count === 'number' ? (
46
+ <span className="ml-1.5 text-xs text-muted-foreground/70 tabular-nums">{tab.count}</span>
47
+ ) : null}
48
+ </Button>
49
+ )
50
+ })}
51
+ </div>
35
52
  )
36
53
  }
@@ -17,8 +17,8 @@ import { CustomerAddress, CustomerEntity } from '../../../customers/data/entitie
17
17
  import { Attachment } from '../../../attachments/data/entities'
18
18
  import { CustomFieldDef } from '../../../entities/data/entities'
19
19
  import { SyncExcelUpload } from '../../data/entities'
20
- import { parseCsvDocumentBatches, parseCsvStreamMetadata, type CsvPreviewRow } from '../parser'
21
- import { createSyncExcelUploadReadStream } from '../upload-storage'
20
+ import { parseCsvDocument, type CsvPreviewRow } from '../parser'
21
+ import { readSyncExcelUploadBuffer } from '../upload-storage'
22
22
  import { E } from '#generated/entities.ids.generated'
23
23
 
24
24
  type SyncExcelCursor = {
@@ -785,16 +785,20 @@ async function resolveExistingPersonId(params: {
785
785
  return params.emailDedupeIndex.get(params.email) ?? null
786
786
  }
787
787
 
788
- function mappingHasEmailField(mapping: DataMapping): boolean {
789
- return mapping.fields.some((field) => field.localField === 'person.primaryEmail')
790
- }
791
-
792
788
  async function buildEmailDedupeIndex(params: {
793
789
  em: EntityManager
790
+ rows: CsvPreviewRow[]
794
791
  mapping: DataMapping
795
792
  scope: TenantScope
796
793
  }): Promise<EmailDedupeIndex> {
797
- if (!mappingHasEmailField(params.mapping)) return new Map()
794
+ const emails = new Set<string>()
795
+ for (const row of params.rows) {
796
+ const rowValues = mapRowValues(row, params.mapping.fields)
797
+ const email = rowValues.values.primaryEmail
798
+ if (email) emails.add(email)
799
+ }
800
+
801
+ if (emails.size === 0) return new Map()
798
802
 
799
803
  const candidates = await findWithDecryption(
800
804
  params.em,
@@ -817,7 +821,7 @@ async function buildEmailDedupeIndex(params: {
817
821
  const index: EmailDedupeIndex = new Map()
818
822
  for (const candidate of candidates) {
819
823
  const email = normalizeEmail(candidate.primaryEmail)
820
- if (!email || index.has(email)) continue
824
+ if (!email || !emails.has(email) || index.has(email)) continue
821
825
  index.set(email, candidate.id)
822
826
  }
823
827
  return index
@@ -1039,28 +1043,26 @@ export const syncExcelCustomersAdapter: DataSyncAdapter = {
1039
1043
  throw new Error('CSV upload attachment could not be found.')
1040
1044
  }
1041
1045
 
1042
- const document = await parseCsvStreamMetadata(await createSyncExcelUploadReadStream(attachment))
1046
+ const fileBuffer = await readSyncExcelUploadBuffer(attachment)
1047
+ const document = parseCsvDocument(fileBuffer)
1043
1048
  const startOffset = cursor?.uploadId === upload.id ? cursor.offset : 0
1044
1049
  const commandContext = buildCommandContext(container, input.scope)
1045
1050
  const customFieldDefinitions = await loadImportCustomFieldDefinitions(em, input.scope)
1046
1051
  const emailDedupeIndex = await buildEmailDedupeIndex({
1047
1052
  em,
1053
+ rows: document.rows.slice(startOffset),
1048
1054
  mapping: input.mapping,
1049
1055
  scope: input.scope,
1050
1056
  })
1051
- let batchIndex = 0
1052
1057
 
1053
- for await (const batch of parseCsvDocumentBatches(await createSyncExcelUploadReadStream(attachment), {
1054
- batchSize: input.batchSize,
1055
- startOffset,
1056
- })) {
1057
- const batchRows = batch.rows
1058
+ for (let offset = startOffset, batchIndex = 0; offset < document.rows.length; offset += input.batchSize, batchIndex += 1) {
1059
+ const batchRows = document.rows.slice(offset, offset + input.batchSize)
1058
1060
  const items: ImportItem[] = []
1059
1061
 
1060
1062
  for (let index = 0; index < batchRows.length; index += 1) {
1061
1063
  items.push(await processRow({
1062
1064
  row: batchRows[index],
1063
- rowNumber: batch.rowStart + index + 1,
1065
+ rowNumber: offset + index + 1,
1064
1066
  mapping: input.mapping,
1065
1067
  scope: input.scope,
1066
1068
  commandBus,
@@ -1072,17 +1074,17 @@ export const syncExcelCustomersAdapter: DataSyncAdapter = {
1072
1074
  }))
1073
1075
  }
1074
1076
 
1077
+ const nextOffset = offset + batchRows.length
1075
1078
  yield {
1076
1079
  items,
1077
- cursor: createCursor(upload.id, batch.nextOffset),
1078
- hasMore: batch.nextOffset < document.totalRows,
1080
+ cursor: createCursor(upload.id, nextOffset),
1081
+ hasMore: nextOffset < document.rows.length,
1079
1082
  totalEstimate: document.totalRows,
1080
1083
  processedCount: batchRows.length,
1081
1084
  refreshCoverageEntityTypes: CUSTOMER_IMPORT_COVERAGE_ENTITY_TYPES,
1082
1085
  batchIndex,
1083
- message: `Processed ${batch.nextOffset} of ${document.totalRows} CSV rows`,
1086
+ message: `Processed ${nextOffset} of ${document.totalRows} CSV rows`,
1084
1087
  }
1085
- batchIndex += 1
1086
1088
  }
1087
1089
 
1088
1090
  upload.status = 'completed'