@open-mercato/core 0.6.8-develop.7029.1.a1bb3363af → 0.6.8-develop.7031.1.005201cd70

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 (236) hide show
  1. package/dist/modules/api_keys/backend/api-keys/page.js +3 -1
  2. package/dist/modules/api_keys/backend/api-keys/page.js.map +2 -2
  3. package/dist/modules/attachments/components/AttachmentLibrary.js +2 -0
  4. package/dist/modules/attachments/components/AttachmentLibrary.js.map +2 -2
  5. package/dist/modules/audit_logs/backend/audit-logs/page.js +6 -0
  6. package/dist/modules/audit_logs/backend/audit-logs/page.js.map +2 -2
  7. package/dist/modules/auth/backend/roles/page.js +3 -1
  8. package/dist/modules/auth/backend/roles/page.js.map +2 -2
  9. package/dist/modules/auth/backend/users/page.js +2 -1
  10. package/dist/modules/auth/backend/users/page.js.map +2 -2
  11. package/dist/modules/business_rules/backend/logs/page.js +3 -1
  12. package/dist/modules/business_rules/backend/logs/page.js.map +2 -2
  13. package/dist/modules/business_rules/backend/rules/page.js +3 -1
  14. package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
  15. package/dist/modules/business_rules/backend/sets/page.js +3 -1
  16. package/dist/modules/business_rules/backend/sets/page.js.map +2 -2
  17. package/dist/modules/catalog/ai-agents.js +1 -1
  18. package/dist/modules/catalog/ai-agents.js.map +1 -1
  19. package/dist/modules/catalog/ai-tools/merchandising-pack.js +2 -2
  20. package/dist/modules/catalog/ai-tools/merchandising-pack.js.map +2 -2
  21. package/dist/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.js +5 -2
  22. package/dist/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.js.map +2 -2
  23. package/dist/modules/catalog/components/categories/CategoriesDataTable.js +2 -0
  24. package/dist/modules/catalog/components/categories/CategoriesDataTable.js.map +2 -2
  25. package/dist/modules/catalog/components/products/ProductsDataTable.js +7 -1
  26. package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
  27. package/dist/modules/catalog/widgets/injection/merchandising-assistant-trigger/widget.client.js +2 -0
  28. package/dist/modules/catalog/widgets/injection/merchandising-assistant-trigger/widget.client.js.map +2 -2
  29. package/dist/modules/communication_channels/backend/communication_channels/channels/page.js +3 -0
  30. package/dist/modules/communication_channels/backend/communication_channels/channels/page.js.map +2 -2
  31. package/dist/modules/configs/lib/system-status.js +9 -0
  32. package/dist/modules/configs/lib/system-status.js.map +2 -2
  33. package/dist/modules/currencies/backend/currencies/page.js +3 -1
  34. package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
  35. package/dist/modules/currencies/backend/exchange-rates/page.js +3 -1
  36. package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
  37. package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js +3 -1
  38. package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js.map +2 -2
  39. package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js +3 -1
  40. package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js.map +2 -2
  41. package/dist/modules/customers/ai-tools/companies-pack.js +4 -1
  42. package/dist/modules/customers/ai-tools/companies-pack.js.map +2 -2
  43. package/dist/modules/customers/ai-tools/deals-pack.js +4 -1
  44. package/dist/modules/customers/ai-tools/deals-pack.js.map +2 -2
  45. package/dist/modules/customers/ai-tools/people-pack.js +4 -1
  46. package/dist/modules/customers/ai-tools/people-pack.js.map +2 -2
  47. package/dist/modules/customers/api/deals/map/route.js +2 -1
  48. package/dist/modules/customers/api/deals/map/route.js.map +2 -2
  49. package/dist/modules/customers/backend/customers/companies/page.js +3 -1
  50. package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
  51. package/dist/modules/customers/backend/customers/deals/page.js +5 -2
  52. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  53. package/dist/modules/customers/backend/customers/people/page.js +3 -1
  54. package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
  55. package/dist/modules/customers/components/CustomerTodosTable.js +1 -0
  56. package/dist/modules/customers/components/CustomerTodosTable.js.map +2 -2
  57. package/dist/modules/data_sync/backend/data-sync/page.js +3 -1
  58. package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
  59. package/dist/modules/devices/backend/devices/page.js +3 -1
  60. package/dist/modules/devices/backend/devices/page.js.map +2 -2
  61. package/dist/modules/directory/backend/directory/organizations/page.js +2 -1
  62. package/dist/modules/directory/backend/directory/organizations/page.js.map +2 -2
  63. package/dist/modules/directory/backend/directory/tenants/page.js +2 -1
  64. package/dist/modules/directory/backend/directory/tenants/page.js.map +2 -2
  65. package/dist/modules/entities/api/records.js +4 -2
  66. package/dist/modules/entities/api/records.js.map +2 -2
  67. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +3 -1
  68. package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
  69. package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js +3 -0
  70. package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js.map +2 -2
  71. package/dist/modules/eudr/backend/eudr/plots/page.js +3 -0
  72. package/dist/modules/eudr/backend/eudr/plots/page.js.map +2 -2
  73. package/dist/modules/eudr/backend/eudr/product-mappings/page.js +3 -0
  74. package/dist/modules/eudr/backend/eudr/product-mappings/page.js.map +2 -2
  75. package/dist/modules/eudr/backend/eudr/risk-assessments/page.js +3 -0
  76. package/dist/modules/eudr/backend/eudr/risk-assessments/page.js.map +2 -2
  77. package/dist/modules/eudr/backend/eudr/statements/page.js +3 -0
  78. package/dist/modules/eudr/backend/eudr/statements/page.js.map +2 -2
  79. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js +1 -0
  80. package/dist/modules/feature_toggles/components/FeatureTogglesTable.js.map +2 -2
  81. package/dist/modules/feature_toggles/components/OverridesTable.js +1 -0
  82. package/dist/modules/feature_toggles/components/OverridesTable.js.map +2 -2
  83. package/dist/modules/inbox_ops/backend/inbox-ops/log/page.js +3 -0
  84. package/dist/modules/inbox_ops/backend/inbox-ops/log/page.js.map +2 -2
  85. package/dist/modules/inbox_ops/backend/inbox-ops/page.js +3 -0
  86. package/dist/modules/inbox_ops/backend/inbox-ops/page.js.map +2 -2
  87. package/dist/modules/messages/components/MessagesInboxPageClient.js +4 -1
  88. package/dist/modules/messages/components/MessagesInboxPageClient.js.map +2 -2
  89. package/dist/modules/payment_gateways/backend/payment-gateways/page.js +3 -1
  90. package/dist/modules/payment_gateways/backend/payment-gateways/page.js.map +2 -2
  91. package/dist/modules/planner/backend/planner/availability-rulesets/page.js +3 -0
  92. package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
  93. package/dist/modules/push_notifications/backend/push_notifications/page.js +3 -1
  94. package/dist/modules/push_notifications/backend/push_notifications/page.js.map +2 -2
  95. package/dist/modules/query_index/lib/engine.js +108 -48
  96. package/dist/modules/query_index/lib/engine.js.map +2 -2
  97. package/dist/modules/resources/backend/resources/resource-types/page.js +3 -1
  98. package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
  99. package/dist/modules/resources/backend/resources/resources/page.js +3 -1
  100. package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
  101. package/dist/modules/sales/backend/sales/channels/offers/page.js +3 -0
  102. package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
  103. package/dist/modules/sales/backend/sales/channels/page.js +3 -0
  104. package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
  105. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +3 -0
  106. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
  107. package/dist/modules/sales/components/documents/SalesDocumentsTable.js +4 -0
  108. package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
  109. package/dist/modules/staff/backend/staff/leave-requests/page.js +3 -0
  110. package/dist/modules/staff/backend/staff/leave-requests/page.js.map +2 -2
  111. package/dist/modules/staff/backend/staff/my-leave-requests/page.js +3 -0
  112. package/dist/modules/staff/backend/staff/my-leave-requests/page.js.map +2 -2
  113. package/dist/modules/staff/backend/staff/team-members/page.js +3 -0
  114. package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
  115. package/dist/modules/staff/backend/staff/team-roles/page.js +3 -0
  116. package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
  117. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +3 -0
  118. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
  119. package/dist/modules/staff/backend/staff/teams/page.js +3 -0
  120. package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
  121. package/dist/modules/staff/backend/staff/timesheets/projects/page.js +3 -0
  122. package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +2 -2
  123. package/dist/modules/warranty_claims/backend/page.js +3 -0
  124. package/dist/modules/warranty_claims/backend/page.js.map +2 -2
  125. package/dist/modules/warranty_claims/backend/warranty_claims/registrations/page.js +3 -0
  126. package/dist/modules/warranty_claims/backend/warranty_claims/registrations/page.js.map +2 -2
  127. package/dist/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/page.js +3 -0
  128. package/dist/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/page.js.map +2 -2
  129. package/dist/modules/warranty_claims/backend/warranty_claims/vendor-policies/page.js +3 -0
  130. package/dist/modules/warranty_claims/backend/warranty_claims/vendor-policies/page.js.map +2 -2
  131. package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.js +3 -0
  132. package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.js.map +2 -2
  133. package/dist/modules/wms/commands/inventory-actions.js +3 -0
  134. package/dist/modules/wms/commands/inventory-actions.js.map +2 -2
  135. package/dist/modules/wms/components/backend/WmsConfigurationPage.js +4 -0
  136. package/dist/modules/wms/components/backend/WmsConfigurationPage.js.map +2 -2
  137. package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js +1 -0
  138. package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js.map +2 -2
  139. package/dist/modules/wms/components/backend/WmsLotsListPage.js +1 -0
  140. package/dist/modules/wms/components/backend/WmsLotsListPage.js.map +2 -2
  141. package/dist/modules/wms/components/backend/inventoryMutationLoaders.js +27 -20
  142. package/dist/modules/wms/components/backend/inventoryMutationLoaders.js.map +2 -2
  143. package/dist/modules/workflows/backend/definitions/page.js +3 -1
  144. package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
  145. package/dist/modules/workflows/backend/events/page.js +3 -1
  146. package/dist/modules/workflows/backend/events/page.js.map +2 -2
  147. package/dist/modules/workflows/backend/instances/page.js +3 -1
  148. package/dist/modules/workflows/backend/instances/page.js.map +2 -2
  149. package/dist/modules/workflows/backend/tasks/page.js +3 -1
  150. package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
  151. package/package.json +7 -7
  152. package/src/modules/api_keys/backend/api-keys/page.tsx +4 -1
  153. package/src/modules/attachments/components/AttachmentLibrary.tsx +3 -0
  154. package/src/modules/audit_logs/backend/audit-logs/page.tsx +8 -0
  155. package/src/modules/auth/backend/roles/page.tsx +4 -2
  156. package/src/modules/auth/backend/users/page.tsx +3 -2
  157. package/src/modules/business_rules/backend/logs/page.tsx +4 -1
  158. package/src/modules/business_rules/backend/rules/page.tsx +4 -1
  159. package/src/modules/business_rules/backend/sets/page.tsx +4 -1
  160. package/src/modules/catalog/ai-agents.ts +1 -1
  161. package/src/modules/catalog/ai-tools/merchandising-pack.ts +2 -2
  162. package/src/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.tsx +12 -5
  163. package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +3 -0
  164. package/src/modules/catalog/components/products/ProductsDataTable.tsx +7 -0
  165. package/src/modules/catalog/i18n/de.json +1 -0
  166. package/src/modules/catalog/i18n/en.json +1 -0
  167. package/src/modules/catalog/i18n/es.json +1 -0
  168. package/src/modules/catalog/i18n/ko.json +1 -0
  169. package/src/modules/catalog/i18n/pl.json +1 -0
  170. package/src/modules/catalog/widgets/injection/merchandising-assistant-trigger/widget.client.tsx +4 -0
  171. package/src/modules/communication_channels/backend/communication_channels/channels/page.tsx +4 -0
  172. package/src/modules/configs/i18n/de.json +2 -0
  173. package/src/modules/configs/i18n/en.json +2 -0
  174. package/src/modules/configs/i18n/es.json +2 -0
  175. package/src/modules/configs/i18n/ko.json +2 -0
  176. package/src/modules/configs/i18n/pl.json +2 -0
  177. package/src/modules/configs/lib/system-status.ts +9 -0
  178. package/src/modules/currencies/backend/currencies/page.tsx +4 -1
  179. package/src/modules/currencies/backend/exchange-rates/page.tsx +4 -1
  180. package/src/modules/customer_accounts/backend/customer_accounts/roles/page.tsx +4 -1
  181. package/src/modules/customer_accounts/backend/customer_accounts/users/page.tsx +4 -1
  182. package/src/modules/customers/ai-tools/companies-pack.ts +4 -1
  183. package/src/modules/customers/ai-tools/deals-pack.ts +4 -1
  184. package/src/modules/customers/ai-tools/people-pack.ts +4 -1
  185. package/src/modules/customers/api/deals/map/route.ts +1 -0
  186. package/src/modules/customers/backend/customers/companies/page.tsx +4 -1
  187. package/src/modules/customers/backend/customers/deals/page.tsx +8 -2
  188. package/src/modules/customers/backend/customers/people/page.tsx +4 -1
  189. package/src/modules/customers/components/CustomerTodosTable.tsx +2 -0
  190. package/src/modules/data_sync/backend/data-sync/page.tsx +4 -1
  191. package/src/modules/devices/backend/devices/page.tsx +4 -1
  192. package/src/modules/directory/backend/directory/organizations/page.tsx +3 -1
  193. package/src/modules/directory/backend/directory/tenants/page.tsx +3 -1
  194. package/src/modules/entities/api/records.ts +2 -0
  195. package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +4 -1
  196. package/src/modules/eudr/backend/eudr/evidence-submissions/page.tsx +4 -0
  197. package/src/modules/eudr/backend/eudr/plots/page.tsx +4 -0
  198. package/src/modules/eudr/backend/eudr/product-mappings/page.tsx +4 -0
  199. package/src/modules/eudr/backend/eudr/risk-assessments/page.tsx +4 -0
  200. package/src/modules/eudr/backend/eudr/statements/page.tsx +4 -0
  201. package/src/modules/feature_toggles/components/FeatureTogglesTable.tsx +2 -1
  202. package/src/modules/feature_toggles/components/OverridesTable.tsx +2 -1
  203. package/src/modules/inbox_ops/backend/inbox-ops/log/page.tsx +4 -0
  204. package/src/modules/inbox_ops/backend/inbox-ops/page.tsx +4 -0
  205. package/src/modules/messages/components/MessagesInboxPageClient.tsx +4 -0
  206. package/src/modules/payment_gateways/backend/payment-gateways/page.tsx +4 -1
  207. package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +4 -0
  208. package/src/modules/push_notifications/backend/push_notifications/page.tsx +4 -1
  209. package/src/modules/query_index/lib/engine.ts +156 -53
  210. package/src/modules/resources/backend/resources/resource-types/page.tsx +4 -1
  211. package/src/modules/resources/backend/resources/resources/page.tsx +4 -1
  212. package/src/modules/sales/backend/sales/channels/offers/page.tsx +4 -0
  213. package/src/modules/sales/backend/sales/channels/page.tsx +4 -0
  214. package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +4 -0
  215. package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +5 -0
  216. package/src/modules/staff/backend/staff/leave-requests/page.tsx +4 -0
  217. package/src/modules/staff/backend/staff/my-leave-requests/page.tsx +4 -0
  218. package/src/modules/staff/backend/staff/team-members/page.tsx +6 -0
  219. package/src/modules/staff/backend/staff/team-roles/page.tsx +4 -0
  220. package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +4 -0
  221. package/src/modules/staff/backend/staff/teams/page.tsx +4 -0
  222. package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +4 -0
  223. package/src/modules/warranty_claims/backend/page.tsx +4 -0
  224. package/src/modules/warranty_claims/backend/warranty_claims/registrations/page.tsx +4 -0
  225. package/src/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/page.tsx +4 -0
  226. package/src/modules/warranty_claims/backend/warranty_claims/vendor-policies/page.tsx +4 -0
  227. package/src/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.tsx +4 -0
  228. package/src/modules/wms/commands/inventory-actions.ts +3 -0
  229. package/src/modules/wms/components/backend/WmsConfigurationPage.tsx +5 -0
  230. package/src/modules/wms/components/backend/WmsInventoryConsolePage.tsx +2 -0
  231. package/src/modules/wms/components/backend/WmsLotsListPage.tsx +2 -0
  232. package/src/modules/wms/components/backend/inventoryMutationLoaders.ts +36 -20
  233. package/src/modules/workflows/backend/definitions/page.tsx +4 -1
  234. package/src/modules/workflows/backend/events/page.tsx +4 -1
  235. package/src/modules/workflows/backend/instances/page.tsx +4 -1
  236. package/src/modules/workflows/backend/tasks/page.tsx +4 -1
@@ -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 { extensionPoints } from '@open-mercato/core/modules/data_sync/extension-points'\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 { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { StatusBadge } from '@open-mercato/ui/primitives/status-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 {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\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, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'\nimport { 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 Clock3,\n Gauge,\n Play,\n PlugZap,\n Repeat,\n Settings2,\n ShieldCheck,\n} from 'lucide-react'\nimport { getSyncRunStatusVariant, getSyncSummaryVariant } from '../../lib/syncRunStatus'\nimport type { RunParameter } from '../../lib/adapter'\nimport { getApplicableRunParameters } from '../../lib/run-parameters'\nimport {\n RunParameterFields,\n buildDefaultRunParameterValues,\n buildRetryFailureMessage,\n buildRunFailureMessage,\n buildRunParametersPayload,\n type RetryFailureBody,\n type RunFailureBody,\n type RunParameterFormValue,\n} from '../../components/RunParameterFields'\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 runMode?: 'generic' | 'provider'\n canStartRun?: boolean\n supportedEntities: string[]\n runParameters?: RunParameter[]\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 updatedAt?: 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 updatedAt?: string | null\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 updatedAt: 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 [paramValues, setParamValues] = React.useState<Record<string, RunParameterFormValue>>({})\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 if (search.trim()) params.set('search', search.trim())\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, search, 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 const runParameters = React.useMemo(\n () => getApplicableRunParameters(\n selectedIntegration?.runParameters,\n selectedDirection,\n // Pass the state through as-is. Before an entity is chosen it is '',\n // which matches no `entityType` and so hides scoped parameters \u2014 the\n // wanted outcome. Mapping '' to `undefined` would mean \"skip entity\n // scoping\" and show every scoped parameter instead.\n selectedEntityType,\n ),\n [selectedIntegration, selectedDirection, selectedEntityType],\n )\n\n React.useEffect(() => {\n setParamValues(buildDefaultRunParameterValues(runParameters))\n }, [runParameters])\n\n const updateParamValue = React.useCallback((key: string, value: RunParameterFormValue) => {\n setParamValues((current) => ({ ...current, [key]: value }))\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 updatedAt: record.updatedAt ?? null,\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 // optimistic-lock-exempt: run lifecycle action endpoint (cancel), not a concurrent record edit\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 // optimistic-lock-exempt: run lifecycle action endpoint (retry), not a concurrent record edit\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(buildRetryFailureMessage(call.result as RetryFailureBody | null, t), '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 const parameters = buildRunParametersPayload(runParameters, paramValues)\n const requestBody: Record<string, unknown> = {\n integrationId: selectedIntegration.integrationId,\n entityType: selectedEntityType,\n direction: selectedDirection,\n batchSize: parsedBatchSize,\n fullSync,\n }\n if (runParameters.length > 0) requestBody.parameters = parameters\n\n try {\n const call = await runMutation({\n // optimistic-lock-exempt: starts a new sync run (create), not a concurrent record edit\n operation: () => apiCall<{ id: string }>('/api/data_sync/run', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(requestBody),\n }, { fallback: null }),\n mutationPayload: requestBody,\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(buildRunFailureMessage(\n call.result as RunFailureBody | null,\n t('data_sync.dashboard.start.error', 'Failed to start sync run'),\n t,\n ), '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, paramValues, router, runMutation, runParameters, 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 // Keyed upsert (POST). When the editor holds an existing schedule's\n // `updatedAt`, the lock header version-checks the resolved row on the\n // server; a brand-new schedule has a null `updatedAt`, so the header is\n // empty and the create path stays unaffected.\n operation: () => withScopedApiRequestHeaders(\n buildOptimisticLockHeader(scheduleEditor.updatedAt),\n () => 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 ),\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 const conflictError = Object.assign(\n new Error((call.result as { error?: string } | null)?.error ?? t('data_sync.dashboard.schedule.error', 'Failed to save recurring schedule')),\n {\n status: call.status,\n ...(call.result && typeof call.result === 'object' ? call.result : {}),\n },\n )\n if (surfaceRecordConflict(conflictError, t)) {\n return\n }\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 updatedAt: call.result.updatedAt ?? null,\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: () => withScopedApiRequestHeaders(\n buildOptimisticLockHeader(scheduleEditor.updatedAt),\n () => apiCall(`/api/data_sync/schedules/${encodeURIComponent(scheduleEditor.id as string)}`, {\n method: 'DELETE',\n }, { fallback: null }),\n ),\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, scheduleEditor.updatedAt, 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 <StatusBadge variant={getSyncRunStatusVariant(row.original.status)}>\n {t(`data_sync.dashboard.status.${row.original.status}`)}\n </StatusBadge>\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.canStartRun !== false\n && selectedIntegration.hasCredentials,\n )\n const hasSavedSchedule = Boolean(scheduleEditor.id)\n const selectedEntityLabel = selectedEntityType ? formatEntityTypeLabel(selectedEntityType) : t('data_sync.dashboard.columns.entityType')\n const integrationStateVariant = getSyncSummaryVariant(selectedIntegration?.isEnabled ? 'enabled' : 'disabled')\n const credentialsVariant = getSyncSummaryVariant(selectedIntegration?.hasCredentials ? 'ready' : 'missing')\n const scheduleVariant = getSyncSummaryVariant(\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-widest 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={integrationStateVariant} className=\"gap-1.5\">\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={credentialsVariant} className=\"gap-1.5\">\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={scheduleVariant} className=\"gap-1.5\">\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 value={selectedIntegrationId || undefined}\n onValueChange={(value) => setSelectedIntegrationId(value ?? '')}\n disabled={isLoadingOptions || options.length === 0}\n >\n <SelectTrigger size=\"lg\">\n <SelectValue\n placeholder={\n options.length === 0\n ? t('integrations.marketplace.noResults', 'No integrations found')\n : undefined\n }\n />\n </SelectTrigger>\n <SelectContent>\n {options.map((item) => (\n <SelectItem key={item.integrationId} value={item.integrationId}>\n {item.title}\n </SelectItem>\n ))}\n </SelectContent>\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 value={selectedEntityType || undefined}\n onValueChange={(value) => setSelectedEntityType(value ?? '')}\n disabled={entityOptions.length === 0}\n >\n <SelectTrigger size=\"lg\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {entityOptions.map((entityType) => (\n <SelectItem key={entityType} value={entityType}>\n {formatEntityTypeLabel(entityType)}\n </SelectItem>\n ))}\n </SelectContent>\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 value={selectedDirection}\n onValueChange={(value) => setSelectedDirection(value === 'export' ? 'export' : 'import')}\n disabled={selectedIntegration?.direction !== 'bidirectional'}\n >\n <SelectTrigger size=\"lg\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"import\">{t('data_sync.dashboard.direction.import')}</SelectItem>\n {(selectedIntegration?.direction === 'bidirectional' || selectedIntegration?.direction === 'export') ? (\n <SelectItem value=\"export\">{t('data_sync.dashboard.direction.export')}</SelectItem>\n ) : null}\n </SelectContent>\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/30 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 {runParameters.length > 0 ? (\n <div className=\"mt-4 space-y-3\">\n <div className=\"flex items-center gap-2\">\n <Settings2 className=\"size-4 text-muted-foreground\" />\n <h4 className=\"text-sm font-semibold\">\n {t('data_sync.dashboard.start.parameters', 'Run parameters')}\n </h4>\n </div>\n <p className=\"text-xs text-muted-foreground\">\n {t('data_sync.dashboard.start.parametersHelp', 'Optional values this integration accepts for the manual run.')}\n </p>\n <RunParameterFields\n params={runParameters}\n values={paramValues}\n onChange={updateParamValue}\n />\n </div>\n ) : null}\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/30 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 value={scheduleEditor.scheduleType}\n onValueChange={(value) => updateScheduleEditor({\n scheduleType: value === 'cron' ? 'cron' : 'interval',\n })}\n disabled={isLoadingSchedule || isSavingSchedule || isDeletingSchedule || !selectedIntegration || !selectedEntityType}\n >\n <SelectTrigger size=\"lg\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"interval\">{t('data_sync.dashboard.schedule.interval', 'Interval')}</SelectItem>\n <SelectItem value=\"cron\">{t('data_sync.dashboard.schedule.cron', 'Cron')}</SelectItem>\n </SelectContent>\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 status=\"warning\">\n <AlertDescription>\n {t('integrations.detail.state.disabled', 'This integration is disabled. Enable it on the integration settings page before starting a sync.')}\n </AlertDescription>\n </Alert>\n ) : null}\n {selectedIntegration && !selectedIntegration.hasCredentials ? (\n <Alert status=\"warning\">\n <AlertDescription>\n {t('integrations.detail.credentials.notConfigured', 'Credentials are not configured yet. Save the integration credentials before starting a sync.')}\n </AlertDescription>\n </Alert>\n ) : null}\n {selectedIntegration && selectedIntegration.canStartRun === false ? (\n <Alert status=\"information\">\n <AlertDescription>\n {t('data_sync.dashboard.start.providerManaged', 'This integration starts sync runs from its own setup flow. Open the integration settings page to continue.')}\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 searchPlaceholder={t('data_sync.dashboard.searchPlaceholder')}\n perspective={{ tableId: extensionPoints.hosts.runsTable.tableId }}\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 { extensionPoints } from '@open-mercato/core/modules/data_sync/extension-points'\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 { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { StatusBadge } from '@open-mercato/ui/primitives/status-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 {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\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, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'\nimport { 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 Clock3,\n Gauge,\n Play,\n PlugZap,\n Repeat,\n Settings2,\n ShieldCheck,\n} from 'lucide-react'\nimport { getSyncRunStatusVariant, getSyncSummaryVariant } from '../../lib/syncRunStatus'\nimport type { RunParameter } from '../../lib/adapter'\nimport { getApplicableRunParameters } from '../../lib/run-parameters'\nimport {\n RunParameterFields,\n buildDefaultRunParameterValues,\n buildRetryFailureMessage,\n buildRunFailureMessage,\n buildRunParametersPayload,\n type RetryFailureBody,\n type RunFailureBody,\n type RunParameterFormValue,\n} from '../../components/RunParameterFields'\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 totalIsCapped?: boolean\n}\n\ntype SyncOption = {\n integrationId: string\n title: string\n description?: string | null\n providerKey?: string | null\n direction: 'import' | 'export' | 'bidirectional'\n runMode?: 'generic' | 'provider'\n canStartRun?: boolean\n supportedEntities: string[]\n runParameters?: RunParameter[]\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 updatedAt?: 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 updatedAt?: string | null\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 updatedAt: 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 [totalIsCapped, setTotalIsCapped] = React.useState(false)\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 [paramValues, setParamValues] = React.useState<Record<string, RunParameterFormValue>>({})\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 if (search.trim()) params.set('search', search.trim())\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 setTotalIsCapped(payload?.totalIsCapped === true)\n setIsLoading(false)\n }\n }\n load()\n return () => { cancelled = true }\n }, [page, filterValues, search, 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 const runParameters = React.useMemo(\n () => getApplicableRunParameters(\n selectedIntegration?.runParameters,\n selectedDirection,\n // Pass the state through as-is. Before an entity is chosen it is '',\n // which matches no `entityType` and so hides scoped parameters \u2014 the\n // wanted outcome. Mapping '' to `undefined` would mean \"skip entity\n // scoping\" and show every scoped parameter instead.\n selectedEntityType,\n ),\n [selectedIntegration, selectedDirection, selectedEntityType],\n )\n\n React.useEffect(() => {\n setParamValues(buildDefaultRunParameterValues(runParameters))\n }, [runParameters])\n\n const updateParamValue = React.useCallback((key: string, value: RunParameterFormValue) => {\n setParamValues((current) => ({ ...current, [key]: value }))\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 updatedAt: record.updatedAt ?? null,\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 // optimistic-lock-exempt: run lifecycle action endpoint (cancel), not a concurrent record edit\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 // optimistic-lock-exempt: run lifecycle action endpoint (retry), not a concurrent record edit\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(buildRetryFailureMessage(call.result as RetryFailureBody | null, t), '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 const parameters = buildRunParametersPayload(runParameters, paramValues)\n const requestBody: Record<string, unknown> = {\n integrationId: selectedIntegration.integrationId,\n entityType: selectedEntityType,\n direction: selectedDirection,\n batchSize: parsedBatchSize,\n fullSync,\n }\n if (runParameters.length > 0) requestBody.parameters = parameters\n\n try {\n const call = await runMutation({\n // optimistic-lock-exempt: starts a new sync run (create), not a concurrent record edit\n operation: () => apiCall<{ id: string }>('/api/data_sync/run', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(requestBody),\n }, { fallback: null }),\n mutationPayload: requestBody,\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(buildRunFailureMessage(\n call.result as RunFailureBody | null,\n t('data_sync.dashboard.start.error', 'Failed to start sync run'),\n t,\n ), '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, paramValues, router, runMutation, runParameters, 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 // Keyed upsert (POST). When the editor holds an existing schedule's\n // `updatedAt`, the lock header version-checks the resolved row on the\n // server; a brand-new schedule has a null `updatedAt`, so the header is\n // empty and the create path stays unaffected.\n operation: () => withScopedApiRequestHeaders(\n buildOptimisticLockHeader(scheduleEditor.updatedAt),\n () => 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 ),\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 const conflictError = Object.assign(\n new Error((call.result as { error?: string } | null)?.error ?? t('data_sync.dashboard.schedule.error', 'Failed to save recurring schedule')),\n {\n status: call.status,\n ...(call.result && typeof call.result === 'object' ? call.result : {}),\n },\n )\n if (surfaceRecordConflict(conflictError, t)) {\n return\n }\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 updatedAt: call.result.updatedAt ?? null,\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: () => withScopedApiRequestHeaders(\n buildOptimisticLockHeader(scheduleEditor.updatedAt),\n () => apiCall(`/api/data_sync/schedules/${encodeURIComponent(scheduleEditor.id as string)}`, {\n method: 'DELETE',\n }, { fallback: null }),\n ),\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, scheduleEditor.updatedAt, 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 <StatusBadge variant={getSyncRunStatusVariant(row.original.status)}>\n {t(`data_sync.dashboard.status.${row.original.status}`)}\n </StatusBadge>\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.canStartRun !== false\n && selectedIntegration.hasCredentials,\n )\n const hasSavedSchedule = Boolean(scheduleEditor.id)\n const selectedEntityLabel = selectedEntityType ? formatEntityTypeLabel(selectedEntityType) : t('data_sync.dashboard.columns.entityType')\n const integrationStateVariant = getSyncSummaryVariant(selectedIntegration?.isEnabled ? 'enabled' : 'disabled')\n const credentialsVariant = getSyncSummaryVariant(selectedIntegration?.hasCredentials ? 'ready' : 'missing')\n const scheduleVariant = getSyncSummaryVariant(\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-widest 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={integrationStateVariant} className=\"gap-1.5\">\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={credentialsVariant} className=\"gap-1.5\">\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={scheduleVariant} className=\"gap-1.5\">\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 value={selectedIntegrationId || undefined}\n onValueChange={(value) => setSelectedIntegrationId(value ?? '')}\n disabled={isLoadingOptions || options.length === 0}\n >\n <SelectTrigger size=\"lg\">\n <SelectValue\n placeholder={\n options.length === 0\n ? t('integrations.marketplace.noResults', 'No integrations found')\n : undefined\n }\n />\n </SelectTrigger>\n <SelectContent>\n {options.map((item) => (\n <SelectItem key={item.integrationId} value={item.integrationId}>\n {item.title}\n </SelectItem>\n ))}\n </SelectContent>\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 value={selectedEntityType || undefined}\n onValueChange={(value) => setSelectedEntityType(value ?? '')}\n disabled={entityOptions.length === 0}\n >\n <SelectTrigger size=\"lg\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {entityOptions.map((entityType) => (\n <SelectItem key={entityType} value={entityType}>\n {formatEntityTypeLabel(entityType)}\n </SelectItem>\n ))}\n </SelectContent>\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 value={selectedDirection}\n onValueChange={(value) => setSelectedDirection(value === 'export' ? 'export' : 'import')}\n disabled={selectedIntegration?.direction !== 'bidirectional'}\n >\n <SelectTrigger size=\"lg\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"import\">{t('data_sync.dashboard.direction.import')}</SelectItem>\n {(selectedIntegration?.direction === 'bidirectional' || selectedIntegration?.direction === 'export') ? (\n <SelectItem value=\"export\">{t('data_sync.dashboard.direction.export')}</SelectItem>\n ) : null}\n </SelectContent>\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/30 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 {runParameters.length > 0 ? (\n <div className=\"mt-4 space-y-3\">\n <div className=\"flex items-center gap-2\">\n <Settings2 className=\"size-4 text-muted-foreground\" />\n <h4 className=\"text-sm font-semibold\">\n {t('data_sync.dashboard.start.parameters', 'Run parameters')}\n </h4>\n </div>\n <p className=\"text-xs text-muted-foreground\">\n {t('data_sync.dashboard.start.parametersHelp', 'Optional values this integration accepts for the manual run.')}\n </p>\n <RunParameterFields\n params={runParameters}\n values={paramValues}\n onChange={updateParamValue}\n />\n </div>\n ) : null}\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/30 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 value={scheduleEditor.scheduleType}\n onValueChange={(value) => updateScheduleEditor({\n scheduleType: value === 'cron' ? 'cron' : 'interval',\n })}\n disabled={isLoadingSchedule || isSavingSchedule || isDeletingSchedule || !selectedIntegration || !selectedEntityType}\n >\n <SelectTrigger size=\"lg\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"interval\">{t('data_sync.dashboard.schedule.interval', 'Interval')}</SelectItem>\n <SelectItem value=\"cron\">{t('data_sync.dashboard.schedule.cron', 'Cron')}</SelectItem>\n </SelectContent>\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 status=\"warning\">\n <AlertDescription>\n {t('integrations.detail.state.disabled', 'This integration is disabled. Enable it on the integration settings page before starting a sync.')}\n </AlertDescription>\n </Alert>\n ) : null}\n {selectedIntegration && !selectedIntegration.hasCredentials ? (\n <Alert status=\"warning\">\n <AlertDescription>\n {t('integrations.detail.credentials.notConfigured', 'Credentials are not configured yet. Save the integration credentials before starting a sync.')}\n </AlertDescription>\n </Alert>\n ) : null}\n {selectedIntegration && selectedIntegration.canStartRun === false ? (\n <Alert status=\"information\">\n <AlertDescription>\n {t('data_sync.dashboard.start.providerManaged', 'This integration starts sync runs from its own setup flow. Open the integration settings page to continue.')}\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 searchPlaceholder={t('data_sync.dashboard.searchPlaceholder')}\n perspective={{ tableId: extensionPoints.hosts.runsTable.tableId }}\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, totalIsCapped, onPageChange: setPage }}\n isLoading={isLoading}\n />\n </PageBody>\n </Page>\n )\n}\n"],
5
+ "mappings": ";AAwkByB,cAmET,YAnES;AAvkBzB,YAAY,WAAW;AACvB,SAAS,uBAAuB;AAChC,OAAO,UAAU;AACjB,SAAS,iBAAiB;AAC1B,SAAS,MAAM,gBAAgB;AAC/B,SAAS,iBAAiB;AAG1B,SAAS,0BAA0B;AACnC,SAAS,aAAa;AACtB,SAAS,mBAAmB;AAC5B,SAAS,MAAM,aAAa,YAAY,iBAAiB;AACzD,SAAS,cAAc;AACvB,SAAS,aAAa;AACtB,SAAS,aAAa;AACtB,SAAS,OAAO,wBAAwB;AACxC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,iBAAiB;AAC1B,SAAS,cAAc;AACvB,SAAS,kBAAkB;AAC3B,SAAS,SAAS,mCAAmC;AACrD,SAAS,iCAAiC;AAC1C,SAAS,6BAA6B;AACtC,SAAS,aAAa;AACtB,SAAS,mCAAmC;AAC5C,SAAS,YAAY;AACrB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,yBAAyB,6BAA6B;AAE/D,SAAS,kCAAkC;AAC3C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AAsEP,MAAM,mBAAmB,KAAK,eAAe,EAAE,gBAAgB,EAAE,YAAY;AAE7E,SAAS,sBAAsB,YAA4B;AACzD,SAAO,WACJ,QAAQ,UAAU,GAAG,EACrB,QAAQ,SAAS,CAAC,WAAW,OAAO,YAAY,CAAC;AACtD;AAEA,SAAS,0BAA0B,YAA6C;AAC9E,QAAM,aAAa,WAAW,KAAK,EAAE,YAAY;AACjD,QAAM,iBAAiB,eAAe,gBAAgB,eAAe;AACrE,SAAO;AAAA,IACL,cAAc;AAAA,IACd,eAAe,iBAAiB,OAAO;AAAA,IACvC,UAAU;AAAA,IACV,UAAU,eAAe;AAAA,IACzB,WAAW;AAAA,IACX,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AACF;AAEe,SAAR,wBAAyC;AAC9C,QAAM,SAAS,UAAU;AACzB,QAAM,CAAC,MAAM,OAAO,IAAI,MAAM,SAAuB,CAAC,CAAC;AACvD,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAuB,CAAC,CAAC;AAC7D,QAAM,CAAC,MAAM,OAAO,IAAI,MAAM,SAAS,CAAC;AACxC,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAS,CAAC;AAC1C,QAAM,CAAC,YAAY,aAAa,IAAI,MAAM,SAAS,CAAC;AACpD,QAAM,CAAC,eAAe,gBAAgB,IAAI,MAAM,SAAS,KAAK;AAC9D,QAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,SAAS,EAAE;AAC7C,QAAM,CAAC,cAAc,eAAe,IAAI,MAAM,SAAuB,CAAC,CAAC;AACvE,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,SAAS,IAAI;AACrD,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,MAAM,SAAS,IAAI;AACnE,QAAM,CAAC,uBAAuB,wBAAwB,IAAI,MAAM,SAAS,EAAE;AAC3E,QAAM,CAAC,oBAAoB,qBAAqB,IAAI,MAAM,SAAS,EAAE;AACrE,QAAM,CAAC,mBAAmB,oBAAoB,IAAI,MAAM,SAA8B,QAAQ;AAC9F,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,SAAS,KAAK;AACtD,QAAM,CAAC,UAAU,WAAW,IAAI,MAAM,SAAS,KAAK;AACpD,QAAM,CAAC,aAAa,cAAc,IAAI,MAAM,SAAgD,CAAC,CAAC;AAC9F,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,MAAM,SAAkC,MAAM,0BAA0B,EAAE,CAAC;AACvH,QAAM,CAAC,mBAAmB,oBAAoB,IAAI,MAAM,SAAS,KAAK;AACtE,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,MAAM,SAAS,KAAK;AACpE,QAAM,CAAC,oBAAoB,qBAAqB,IAAI,MAAM,SAAS,KAAK;AACxE,QAAM,CAAC,aAAa,cAAc,IAAI,MAAM,SAAS,CAAC;AACtD,QAAM,eAAe,4BAA4B;AACjD,QAAM,IAAI,KAAK;AACf,QAAM,EAAE,YAAY,IAAI,mBAA4C;AAAA,IAClE,WAAW;AAAA,EACb,CAAC;AAED,QAAM,UAAU,MAAM;AACpB,QAAI,YAAY;AAChB,mBAAe,OAAO;AACpB,mBAAa,IAAI;AACjB,YAAM,SAAS,IAAI,gBAAgB;AACnC,aAAO,IAAI,QAAQ,OAAO,IAAI,CAAC;AAC/B,aAAO,IAAI,YAAY,IAAI;AAC3B,UAAI,aAAa,OAAQ,QAAO,IAAI,UAAU,aAAa,MAAgB;AAC3E,UAAI,aAAa,UAAW,QAAO,IAAI,aAAa,aAAa,SAAmB;AACpF,UAAI,OAAO,KAAK,EAAG,QAAO,IAAI,UAAU,OAAO,KAAK,CAAC;AACrD,YAAM,WAA4B,EAAE,OAAO,CAAC,GAAG,OAAO,GAAG,MAAM,YAAY,EAAE;AAC7E,YAAM,OAAO,MAAM;AAAA,QACjB,uBAAuB,OAAO,SAAS,CAAC;AAAA,QACxC;AAAA,QACA,EAAE,SAAS;AAAA,MACb;AACA,UAAI,CAAC,KAAK,IAAI;AACZ,cAAM,EAAE,+BAA+B,GAAG,OAAO;AACjD,YAAI,CAAC,UAAW,cAAa,KAAK;AAClC;AAAA,MACF;AACA,YAAM,UAAU,KAAK,UAAU;AAC/B,UAAI,CAAC,WAAW;AACd,gBAAQ,MAAM,QAAQ,QAAQ,KAAK,IAAI,QAAQ,QAAQ,CAAC,CAAC;AACzD,iBAAS,QAAQ,SAAS,CAAC;AAC3B,sBAAc,QAAQ,cAAc,CAAC;AACrC,yBAAiB,SAAS,kBAAkB,IAAI;AAChD,qBAAa,KAAK;AAAA,MACpB;AAAA,IACF;AACA,SAAK;AACL,WAAO,MAAM;AAAE,kBAAY;AAAA,IAAK;AAAA,EAClC,GAAG,CAAC,MAAM,cAAc,QAAQ,aAAa,cAAc,CAAC,CAAC;AAE7D,QAAM,UAAU,MAAM;AACpB,QAAI,YAAY;AAChB,mBAAe,cAAc;AAC3B,0BAAoB,IAAI;AACxB,YAAM,WAAgC,EAAE,OAAO,CAAC,EAAE;AAClD,YAAM,OAAO,MAAM,QAA6B,0BAA0B,QAAW,EAAE,SAAS,CAAC;AACjG,UAAI,CAAC,WAAW;AACd,YAAI,CAAC,KAAK,IAAI;AACZ,gBAAM,EAAE,+BAA+B,GAAG,OAAO;AACjD,qBAAW,CAAC,CAAC;AACb,8BAAoB,KAAK;AACzB;AAAA,QACF;AAEA,cAAM,YAAY,MAAM,QAAQ,KAAK,QAAQ,KAAK,IAAI,KAAK,OAAO,QAAQ,CAAC;AAC3E,mBAAW,SAAS;AACpB,iCAAyB,CAAC,YAAY;AACpC,cAAI,WAAW,UAAU,KAAK,CAAC,SAAS,KAAK,kBAAkB,OAAO,EAAG,QAAO;AAChF,iBAAO,UAAU,CAAC,GAAG,iBAAiB;AAAA,QACxC,CAAC;AACD,4BAAoB,KAAK;AAAA,MAC3B;AAAA,IACF;AAEA,SAAK,YAAY;AACjB,WAAO,MAAM;AAAE,kBAAY;AAAA,IAAK;AAAA,EAClC,GAAG,CAAC,cAAc,CAAC,CAAC;AAEpB,QAAM,sBAAsB,MAAM;AAAA,IAChC,MAAM,QAAQ,KAAK,CAAC,SAAS,KAAK,kBAAkB,qBAAqB,KAAK;AAAA,IAC9E,CAAC,SAAS,qBAAqB;AAAA,EACjC;AAEA,QAAM,gBAAgB,MAAM;AAAA,IAC1B,MAAM,qBAAqB,qBAAqB,CAAC;AAAA,IACjD,CAAC,mBAAmB;AAAA,EACtB;AAEA,QAAM,gBAAgB,MAAM;AAAA,IAC1B,MAAM;AAAA,MACJ,qBAAqB;AAAA,MACrB;AAAA;AAAA;AAAA;AAAA;AAAA,MAKA;AAAA,IACF;AAAA,IACA,CAAC,qBAAqB,mBAAmB,kBAAkB;AAAA,EAC7D;AAEA,QAAM,UAAU,MAAM;AACpB,mBAAe,+BAA+B,aAAa,CAAC;AAAA,EAC9D,GAAG,CAAC,aAAa,CAAC;AAElB,QAAM,mBAAmB,MAAM,YAAY,CAAC,KAAa,UAAiC;AACxF,mBAAe,CAAC,aAAa,EAAE,GAAG,SAAS,CAAC,GAAG,GAAG,MAAM,EAAE;AAAA,EAC5D,GAAG,CAAC,CAAC;AAEL,QAAM,UAAU,MAAM;AACpB,QAAI,CAAC,qBAAqB;AACxB,4BAAsB,EAAE;AACxB;AAAA,IACF;AACA,0BAAsB,CAAC,YACrB,WAAW,oBAAoB,kBAAkB,SAAS,OAAO,IAC7D,UACC,oBAAoB,kBAAkB,CAAC,KAAK,EAClD;AACD,yBAAqB,oBAAoB,cAAc,WAAW,WAAW,QAAQ;AAAA,EACvF,GAAG,CAAC,mBAAmB,CAAC;AAExB,QAAM,UAAU,MAAM;AACpB,QAAI,CAAC,uBAAuB,CAAC,oBAAoB;AAC/C,wBAAkB,0BAA0B,kBAAkB,CAAC;AAC/D;AAAA,IACF;AAEA,UAAM,qBAAqB;AAC3B,QAAI,YAAY;AAChB,mBAAe,eAAe;AAC5B,2BAAqB,IAAI;AACzB,YAAM,gBAAgB,mBAAmB;AACzC,YAAM,SAAS,IAAI,gBAAgB;AAAA,QACjC;AAAA,QACA,YAAY;AAAA,QACZ,WAAW;AAAA,QACX,MAAM;AAAA,QACN,UAAU;AAAA,MACZ,CAAC;AACD,YAAM,WAAkC,EAAE,OAAO,CAAC,EAAE;AACpD,YAAM,OAAO,MAAM,QAA+B,4BAA4B,OAAO,SAAS,CAAC,IAAI,QAAW,EAAE,SAAS,CAAC;AAE1H,UAAI,UAAW;AAEf,UAAI,CAAC,KAAK,IAAI;AACZ,0BAAkB,0BAA0B,kBAAkB,CAAC;AAC/D,6BAAqB,KAAK;AAC1B;AAAA,MACF;AAEA,YAAM,SAAS,MAAM,QAAQ,KAAK,QAAQ,KAAK,IAAI,KAAK,QAAQ,MAAM,CAAC,IAAI;AAC3E,UAAI,CAAC,QAAQ;AACX,0BAAkB,0BAA0B,kBAAkB,CAAC;AAC/D,6BAAqB,KAAK;AAC1B;AAAA,MACF;AAEA,wBAAkB;AAAA,QAChB,IAAI,OAAO;AAAA,QACX,cAAc,OAAO;AAAA,QACrB,eAAe,OAAO;AAAA,QACtB,UAAU,OAAO;AAAA,QACjB,UAAU,OAAO;AAAA,QACjB,WAAW,OAAO;AAAA,QAClB,WAAW,OAAO;AAAA,QAClB,WAAW,OAAO,aAAa;AAAA,MACjC,CAAC;AACD,2BAAqB,KAAK;AAAA,IAC5B;AAEA,SAAK,aAAa;AAClB,WAAO,MAAM;AAAE,kBAAY;AAAA,IAAK;AAAA,EAClC,GAAG,CAAC,mBAAmB,oBAAoB,qBAAqB,YAAY,CAAC;AAE7E,QAAM,uBAAuB,MAAM,YAAY,CAAC,YAA8C;AAC5F,sBAAkB,CAAC,aAAa,EAAE,GAAG,SAAS,GAAG,QAAQ,EAAE;AAAA,EAC7D,GAAG,CAAC,CAAC;AAEL,QAAM,eAAe,MAAM,YAAY,OAAO,QAAoB;AAEhE,UAAM,OAAO,MAAM,QAAQ,uBAAuB,mBAAmB,IAAI,EAAE,CAAC,WAAW;AAAA,MACrF,QAAQ;AAAA,IACV,GAAG,EAAE,UAAU,KAAK,CAAC;AACrB,QAAI,KAAK,IAAI;AACX,YAAM,EAAE,qCAAqC,GAAG,SAAS;AACzD,qBAAe,CAAC,UAAU,QAAQ,CAAC;AAAA,IACrC,OAAO;AACL,YAAM,EAAE,mCAAmC,GAAG,OAAO;AAAA,IACvD;AAAA,EACF,GAAG,CAAC,CAAC,CAAC;AAEN,QAAM,cAAc,MAAM,YAAY,OAAO,QAAoB;AAE/D,UAAM,OAAO,MAAM,QAAQ,uBAAuB,mBAAmB,IAAI,EAAE,CAAC,UAAU;AAAA,MACpF,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,EAAE,eAAe,MAAM,CAAC;AAAA,IAC/C,GAAG,EAAE,UAAU,KAAK,CAAC;AACrB,QAAI,KAAK,IAAI;AACX,YAAM,EAAE,oCAAoC,GAAG,SAAS;AACxD,qBAAe,CAAC,UAAU,QAAQ,CAAC;AAAA,IACrC,OAAO;AACL,YAAM,yBAAyB,KAAK,QAAmC,CAAC,GAAG,OAAO;AAAA,IACpF;AAAA,EACF,GAAG,CAAC,CAAC,CAAC;AAEN,QAAM,qBAAqB,MAAM,YAAY,CAAC,WAAyB;AACrE,UAAM,OAAqB,CAAC;AAC5B,WAAO,QAAQ,MAAM,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAC/C,UAAI,UAAU,UAAa,UAAU,GAAI,MAAK,GAAG,IAAI;AAAA,IACvD,CAAC;AACD,oBAAgB,IAAI;AACpB,YAAQ,CAAC;AAAA,EACX,GAAG,CAAC,CAAC;AAEL,QAAM,qBAAqB,MAAM,YAAY,MAAM;AACjD,oBAAgB,CAAC,CAAC;AAClB,YAAQ,CAAC;AAAA,EACX,GAAG,CAAC,CAAC;AAEL,QAAM,kBAAkB,MAAM,YAAY,YAAY;AACpD,QAAI,CAAC,uBAAuB,CAAC,mBAAoB;AAEjD,UAAM,kBAAkB,OAAO,SAAS,WAAW,EAAE;AACrD,QAAI,CAAC,OAAO,SAAS,eAAe,KAAK,kBAAkB,KAAK,kBAAkB,KAAM;AACtF,YAAM,EAAE,8CAA8C,wCAAwC,GAAG,OAAO;AACxG;AAAA,IACF;AAEA,UAAM,aAAa,0BAA0B,eAAe,WAAW;AACvE,UAAM,cAAuC;AAAA,MAC3C,eAAe,oBAAoB;AAAA,MACnC,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,WAAW;AAAA,MACX;AAAA,IACF;AACA,QAAI,cAAc,SAAS,EAAG,aAAY,aAAa;AAEvD,QAAI;AACF,YAAM,OAAO,MAAM,YAAY;AAAA;AAAA,QAE7B,WAAW,MAAM,QAAwB,sBAAsB;AAAA,UAC7D,QAAQ;AAAA,UACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,UAC9C,MAAM,KAAK,UAAU,WAAW;AAAA,QAClC,GAAG,EAAE,UAAU,KAAK,CAAC;AAAA,QACrB,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,WAAW;AAAA,UACX,UAAU;AAAA,UACV,eAAe,oBAAoB;AAAA,QACrC;AAAA,MACF,CAAC;AAED,UAAI,CAAC,KAAK,MAAM,CAAC,KAAK,QAAQ,IAAI;AAChC,cAAM;AAAA,UACJ,KAAK;AAAA,UACL,EAAE,mCAAmC,0BAA0B;AAAA,UAC/D;AAAA,QACF,GAAG,OAAO;AACV;AAAA,MACF;AAEA,YAAM,EAAE,qCAAqC,kBAAkB,GAAG,SAAS;AAC3E,qBAAe,CAAC,UAAU,QAAQ,CAAC;AACnC,aAAO,KAAK,2BAA2B,mBAAmB,KAAK,OAAO,EAAE,CAAC,EAAE;AAAA,IAC7E,SAAS,OAAO;AACd,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,EAAE,mCAAmC,0BAA0B;AACxH,YAAM,SAAS,OAAO;AAAA,IACxB;AAAA,EACF,GAAG,CAAC,WAAW,UAAU,aAAa,QAAQ,aAAa,eAAe,mBAAmB,oBAAoB,qBAAqB,CAAC,CAAC;AAExI,QAAM,qBAAqB,MAAM,YAAY,YAAY;AACvD,QAAI,CAAC,uBAAuB,CAAC,mBAAoB;AACjD,QAAI,eAAe,cAAc,KAAK,EAAE,WAAW,GAAG;AACpD,YAAM,EAAE,6CAA6C,yCAAyC,GAAG,OAAO;AACxG;AAAA,IACF;AAEA,wBAAoB,IAAI;AACxB,QAAI;AACF,YAAM,OAAO,MAAM,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA,QAK7B,WAAW,MAAM;AAAA,UACf,0BAA0B,eAAe,SAAS;AAAA,UAClD,MAAM,QAA4B,4BAA4B;AAAA,YAC5D,QAAQ;AAAA,YACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,YAC9C,MAAM,KAAK,UAAU;AAAA,cACnB,eAAe,oBAAoB;AAAA,cACnC,YAAY;AAAA,cACZ,WAAW;AAAA,cACX,cAAc,eAAe;AAAA,cAC7B,eAAe,eAAe,cAAc,KAAK;AAAA,cACjD,UAAU,eAAe,SAAS,KAAK,KAAK;AAAA,cAC5C,UAAU,eAAe;AAAA,cACzB,WAAW,eAAe;AAAA,YAC5B,CAAC;AAAA,UACH,GAAG,EAAE,UAAU,KAAK,CAAC;AAAA,QACvB;AAAA,QACA,iBAAiB;AAAA,UACf,eAAe,oBAAoB;AAAA,UACnC,YAAY;AAAA,UACZ,WAAW;AAAA,UACX,cAAc,eAAe;AAAA,UAC7B,eAAe,eAAe,cAAc,KAAK;AAAA,UACjD,UAAU,eAAe,SAAS,KAAK,KAAK;AAAA,UAC5C,UAAU,eAAe;AAAA,UACzB,WAAW,eAAe;AAAA,QAC5B;AAAA,QACA,SAAS;AAAA,UACP,WAAW;AAAA,UACX,UAAU;AAAA,UACV,eAAe,oBAAoB;AAAA,QACrC;AAAA,MACF,CAAC;AAED,UAAI,CAAC,KAAK,MAAM,CAAC,KAAK,QAAQ;AAC5B,cAAM,gBAAgB,OAAO;AAAA,UAC3B,IAAI,MAAO,KAAK,QAAsC,SAAS,EAAE,sCAAsC,mCAAmC,CAAC;AAAA,UAC3I;AAAA,YACE,QAAQ,KAAK;AAAA,YACb,GAAI,KAAK,UAAU,OAAO,KAAK,WAAW,WAAW,KAAK,SAAS,CAAC;AAAA,UACtE;AAAA,QACF;AACA,YAAI,sBAAsB,eAAe,CAAC,GAAG;AAC3C;AAAA,QACF;AACA,cAAO,KAAK,QAAsC,SAAS,EAAE,sCAAsC,mCAAmC,GAAG,OAAO;AAChJ;AAAA,MACF;AAEA,wBAAkB;AAAA,QAChB,IAAI,KAAK,OAAO;AAAA,QAChB,cAAc,KAAK,OAAO;AAAA,QAC1B,eAAe,KAAK,OAAO;AAAA,QAC3B,UAAU,KAAK,OAAO;AAAA,QACtB,UAAU,KAAK,OAAO;AAAA,QACtB,WAAW,KAAK,OAAO;AAAA,QACvB,WAAW,KAAK,OAAO;AAAA,QACvB,WAAW,KAAK,OAAO,aAAa;AAAA,MACtC,CAAC;AACD,YAAM,EAAE,wCAAwC,0BAA0B,GAAG,SAAS;AAAA,IACxF,SAAS,OAAO;AACd,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,EAAE,sCAAsC,mCAAmC;AACpI,YAAM,SAAS,OAAO;AAAA,IACxB,UAAE;AACA,0BAAoB,KAAK;AAAA,IAC3B;AAAA,EACF,GAAG,CAAC,aAAa,gBAAgB,mBAAmB,oBAAoB,qBAAqB,CAAC,CAAC;AAE/F,QAAM,uBAAuB,MAAM,YAAY,YAAY;AACzD,QAAI,CAAC,eAAe,GAAI;AAExB,0BAAsB,IAAI;AAC1B,QAAI;AACF,YAAM,OAAO,MAAM,YAAY;AAAA,QAC7B,WAAW,MAAM;AAAA,UACf,0BAA0B,eAAe,SAAS;AAAA,UAClD,MAAM,QAAQ,4BAA4B,mBAAmB,eAAe,EAAY,CAAC,IAAI;AAAA,YAC3F,QAAQ;AAAA,UACV,GAAG,EAAE,UAAU,KAAK,CAAC;AAAA,QACvB;AAAA,QACA,iBAAiB;AAAA,UACf,YAAY,eAAe;AAAA,QAC7B;AAAA,QACA,SAAS;AAAA,UACP,WAAW;AAAA,UACX,UAAU;AAAA,QACZ;AAAA,MACF,CAAC;AAED,UAAI,CAAC,KAAK,IAAI;AACZ,cAAO,KAAK,QAAsC,SAAS,EAAE,4CAA4C,qCAAqC,GAAG,OAAO;AACxJ;AAAA,MACF;AAEA,wBAAkB,0BAA0B,kBAAkB,CAAC;AAC/D,YAAM,EAAE,8CAA8C,4BAA4B,GAAG,SAAS;AAAA,IAChG,SAAS,OAAO;AACd,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,EAAE,4CAA4C,qCAAqC;AAC5I,YAAM,SAAS,OAAO;AAAA,IACxB,UAAE;AACA,4BAAsB,KAAK;AAAA,IAC7B;AAAA,EACF,GAAG,CAAC,aAAa,eAAe,IAAI,eAAe,WAAW,oBAAoB,CAAC,CAAC;AAEpF,QAAM,UAAuB;AAAA,IAC3B;AAAA,MACE,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,OAAO,EAAE,oCAAoC;AAAA,MAC7C,SAAS;AAAA,QACP,EAAE,OAAO,EAAE,yCAAyC,GAAG,OAAO,GAAG;AAAA,QACjE,EAAE,OAAO,EAAE,oCAAoC,GAAG,OAAO,UAAU;AAAA,QACnE,EAAE,OAAO,EAAE,oCAAoC,GAAG,OAAO,UAAU;AAAA,QACnE,EAAE,OAAO,EAAE,sCAAsC,GAAG,OAAO,YAAY;AAAA,QACvE,EAAE,OAAO,EAAE,mCAAmC,GAAG,OAAO,SAAS;AAAA,QACjE,EAAE,OAAO,EAAE,sCAAsC,GAAG,OAAO,YAAY;AAAA,MACzE;AAAA,IACF;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,OAAO,EAAE,uCAAuC;AAAA,MAChD,SAAS;AAAA,QACP,EAAE,OAAO,EAAE,2CAA2C,GAAG,OAAO,GAAG;AAAA,QACnE,EAAE,OAAO,EAAE,sCAAsC,GAAG,OAAO,SAAS;AAAA,QACpE,EAAE,OAAO,EAAE,sCAAsC,GAAG,OAAO,SAAS;AAAA,MACtE;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU,MAAM,QAAiC,MAAM;AAAA,IAC3D;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,EAAE,yCAAyC;AAAA,MACnD,MAAM,CAAC,EAAE,IAAI,MAAM,oBAAC,UAAK,WAAU,uBAAuB,cAAI,SAAS,eAAc;AAAA,IACvF;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,EAAE,wCAAwC;AAAA,IACpD;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,EAAE,uCAAuC;AAAA,MACjD,MAAM,CAAC,EAAE,IAAI,MACX,oBAAC,SAAM,SAAQ,WACZ,YAAE,iCAAiC,IAAI,SAAS,SAAS,EAAE,GAC9D;AAAA,IAEJ;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,EAAE,oCAAoC;AAAA,MAC9C,MAAM,CAAC,EAAE,IAAI,MACX,oBAAC,eAAY,SAAS,wBAAwB,IAAI,SAAS,MAAM,GAC9D,YAAE,8BAA8B,IAAI,SAAS,MAAM,EAAE,GACxD;AAAA,IAEJ;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,EAAE,qCAAqC;AAAA,IACjD;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,EAAE,qCAAqC;AAAA,IACjD;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,EAAE,oCAAoC;AAAA,IAChD;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,EAAE,uCAAuC;AAAA,MACjD,MAAM,CAAC,EAAE,IAAI,MAAM,IAAI,KAAK,IAAI,SAAS,SAAS,EAAE,eAAe;AAAA,IACrE;AAAA,EACF,GAAG,CAAC,CAAC,CAAC;AAEN,QAAM,8BAA8B;AAAA,IAClC,uBACG,sBACA,oBAAoB,aACpB,oBAAoB,gBAAgB,SACpC,oBAAoB;AAAA,EACzB;AACA,QAAM,mBAAmB,QAAQ,eAAe,EAAE;AAClD,QAAM,sBAAsB,qBAAqB,sBAAsB,kBAAkB,IAAI,EAAE,wCAAwC;AACvI,QAAM,0BAA0B,sBAAsB,qBAAqB,YAAY,YAAY,UAAU;AAC7G,QAAM,qBAAqB,sBAAsB,qBAAqB,iBAAiB,UAAU,SAAS;AAC1G,QAAM,kBAAkB;AAAA,IACtB,mBACK,eAAe,YAAY,cAAc,WAC1C;AAAA,EACN;AAEA,SACE,oBAAC,QACC,+BAAC,YAAS,WAAU,aAClB;AAAA,yBAAC,QACC;AAAA,2BAAC,cAAW,WAAU,aACpB;AAAA,6BAAC,SAAI,WAAU,qEACb;AAAA,+BAAC,SAAI,WAAU,aACb;AAAA,iCAAC,SAAI,WAAU,+FACb;AAAA,kCAAC,UAAO,WAAU,UAAS;AAAA,cAC3B,oBAAC,UAAM,YAAE,qCAAqC,+BAA+B,GAAE;AAAA,eACjF;AAAA,YACA,qBAAC,SAAI,WAAU,aACb;AAAA,kCAAC,aAAW,YAAE,mCAAmC,0BAA0B,GAAE;AAAA,cAC7E,oBAAC,OAAE,WAAU,2CACV,YAAE,yCAAyC,0HAA0H,GACxK;AAAA,eACF;AAAA,aACF;AAAA,UACC,sBACC,oBAAC,UAAO,SAAO,MAAC,SAAQ,WACtB,+BAAC,QAAK,MAAM,oBAAoB,cAC9B;AAAA,gCAAC,aAAU,WAAU,eAAc;AAAA,YAClC,EAAE,oCAAoC;AAAA,aACzC,GACF,IACE;AAAA,WACN;AAAA,QAEC,sBACC,qBAAC,SAAI,WAAU,wBACb;AAAA,+BAAC,SAAM,SAAQ,WAAU,WAAU,WACjC;AAAA,gCAAC,WAAQ,WAAU,YAAW;AAAA,YAC7B,oBAAoB;AAAA,aACvB;AAAA,UACA,qBAAC,SAAM,SAAQ,WAAU,WAAU,WACjC;AAAA,gCAAC,kBAAe,WAAU,YAAW;AAAA,YACpC,EAAE,iCAAiC,iBAAiB,EAAE;AAAA,aACzD;AAAA,UACA,qBAAC,SAAM,SAAS,yBAAyB,WAAU,WACjD;AAAA,gCAAC,eAAY,WAAU,YAAW;AAAA,YACjC,oBAAoB,YACjB,EAAE,4CAA4C,qBAAqB,IACnE,EAAE,6CAA6C,sBAAsB;AAAA,aAC3E;AAAA,UACA,qBAAC,SAAM,SAAS,oBAAoB,WAAU,WAC5C;AAAA,gCAAC,WAAQ,WAAU,YAAW;AAAA,YAC7B,oBAAoB,iBACjB,EAAE,qDAAqD,mBAAmB,IAC1E,EAAE,uDAAuD,qBAAqB;AAAA,aACpF;AAAA,UACA,qBAAC,SAAM,SAAS,iBAAiB,WAAU,WACzC;AAAA,gCAAC,iBAAc,WAAU,YAAW;AAAA,YACnC,mBACI,eAAe,YACd,EAAE,+CAA+C,2BAA2B,IAC5E,EAAE,gDAAgD,2BAA2B,IAC/E,EAAE,4CAA4C,uBAAuB;AAAA,aAC3E;AAAA,WACF,IACE;AAAA,SACN;AAAA,MACA,qBAAC,eAAY,WAAU,aACrB;AAAA,6BAAC,SAAI,WAAU,6BACb;AAAA,+BAAC,SAAI,WAAU,2BACb;AAAA,iCAAC,SAAM,WAAU,+CACf;AAAA,kCAAC,WAAQ,WAAU,gCAA+B;AAAA,cAClD,oBAAC,UAAM,YAAE,yCAAyC,GAAE;AAAA,eACtD;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO,yBAAyB;AAAA,gBAChC,eAAe,CAAC,UAAU,yBAAyB,SAAS,EAAE;AAAA,gBAC9D,UAAU,oBAAoB,QAAQ,WAAW;AAAA,gBAEjD;AAAA,sCAAC,iBAAc,MAAK,MAClB;AAAA,oBAAC;AAAA;AAAA,sBACC,aACE,QAAQ,WAAW,IACf,EAAE,sCAAsC,uBAAuB,IAC/D;AAAA;AAAA,kBAER,GACF;AAAA,kBACA,oBAAC,iBACE,kBAAQ,IAAI,CAAC,SACZ,oBAAC,cAAoC,OAAO,KAAK,eAC9C,eAAK,SADS,KAAK,aAEtB,CACD,GACH;AAAA;AAAA;AAAA,YACF;AAAA,aACF;AAAA,UACA,qBAAC,SAAI,WAAU,aACb;AAAA,iCAAC,SAAM,WAAU,+CACf;AAAA,kCAAC,SAAM,WAAU,gCAA+B;AAAA,cAChD,oBAAC,UAAM,YAAE,wCAAwC,GAAE;AAAA,eACrD;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO,sBAAsB;AAAA,gBAC7B,eAAe,CAAC,UAAU,sBAAsB,SAAS,EAAE;AAAA,gBAC3D,UAAU,cAAc,WAAW;AAAA,gBAEnC;AAAA,sCAAC,iBAAc,MAAK,MAClB,8BAAC,eAAY,GACf;AAAA,kBACA,oBAAC,iBACE,wBAAc,IAAI,CAAC,eAClB,oBAAC,cAA4B,OAAO,YACjC,gCAAsB,UAAU,KADlB,UAEjB,CACD,GACH;AAAA;AAAA;AAAA,YACF;AAAA,aACF;AAAA,UACA,qBAAC,SAAI,WAAU,aACb;AAAA,iCAAC,SAAM,WAAU,+CACf;AAAA,kCAAC,kBAAe,WAAU,gCAA+B;AAAA,cACzD,oBAAC,UAAM,YAAE,uCAAuC,GAAE;AAAA,eACpD;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO;AAAA,gBACP,eAAe,CAAC,UAAU,qBAAqB,UAAU,WAAW,WAAW,QAAQ;AAAA,gBACvF,UAAU,qBAAqB,cAAc;AAAA,gBAE7C;AAAA,sCAAC,iBAAc,MAAK,MAClB,8BAAC,eAAY,GACf;AAAA,kBACA,qBAAC,iBACC;AAAA,wCAAC,cAAW,OAAM,UAAU,YAAE,sCAAsC,GAAE;AAAA,oBACpE,qBAAqB,cAAc,mBAAmB,qBAAqB,cAAc,WACzF,oBAAC,cAAW,OAAM,UAAU,YAAE,sCAAsC,GAAE,IACpE;AAAA,qBACN;AAAA;AAAA;AAAA,YACF;AAAA,aACF;AAAA,WACF;AAAA,QAEC,qBAAqB,cACpB,oBAAC,OAAE,WAAU,iCAAiC,8BAAoB,aAAY,IAC5E;AAAA,QAEJ,qBAAC,SAAI,WAAU,6BACb;AAAA,+BAAC,SAAI,WAAU,qCACb;AAAA,iCAAC,SAAI,WAAU,0CACb;AAAA,mCAAC,SAAI,WAAU,aACb;AAAA,qCAAC,SAAI,WAAU,2BACb;AAAA,sCAAC,QAAK,WAAU,uBAAsB;AAAA,kBACtC,oBAAC,QAAG,WAAU,yBAAyB,YAAE,yCAAyC,cAAc,GAAE;AAAA,mBACpG;AAAA,gBACA,oBAAC,OAAE,WAAU,iCACV,YAAE,+CAA+C,oGAAoG,GACxJ;AAAA,iBACF;AAAA,cACA,oBAAC,SAAM,SAAQ,WAAW,+BAAoB;AAAA,eAChD;AAAA,YAEA,oBAAC,aAAU,WAAU,QAAO;AAAA,YAE5B,qBAAC,SAAI,WAAU,iDACb;AAAA,mCAAC,SAAI,WAAU,aACb;AAAA,qCAAC,SAAM,WAAU,+CACf;AAAA,sCAAC,SAAM,WAAU,gCAA+B;AAAA,kBAChD,oBAAC,UAAM,YAAE,uCAAuC,YAAY,GAAE;AAAA,mBAChE;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO;AAAA,oBACP,UAAU,CAAC,UAAU,aAAa,MAAM,OAAO,KAAK;AAAA,oBACpD,WAAU;AAAA;AAAA,gBACZ;AAAA,iBACF;AAAA,cACA,oBAAC,SAAI,WAAU,uCACb,+BAAC,SAAI,WAAU,2CACb;AAAA,qCAAC,SAAI,WAAU,aACb;AAAA,sCAAC,SAAM,WAAU,uBAAuB,YAAE,sCAAsC,kBAAkB,GAAE;AAAA,kBACpG,oBAAC,OAAE,WAAU,iCACV,YAAE,0CAA0C,2EAA2E,GAC1H;AAAA,mBACF;AAAA,gBACA,oBAAC,UAAO,SAAS,UAAU,iBAAiB,aAAa;AAAA,iBAC3D,GACF;AAAA,eACF;AAAA,YAEC,cAAc,SAAS,IACtB,qBAAC,SAAI,WAAU,kBACb;AAAA,mCAAC,SAAI,WAAU,2BACb;AAAA,oCAAC,aAAU,WAAU,gCAA+B;AAAA,gBACpD,oBAAC,QAAG,WAAU,yBACX,YAAE,wCAAwC,gBAAgB,GAC7D;AAAA,iBACF;AAAA,cACA,oBAAC,OAAE,WAAU,iCACV,YAAE,4CAA4C,8DAA8D,GAC/G;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,QAAQ;AAAA,kBACR,QAAQ;AAAA,kBACR,UAAU;AAAA;AAAA,cACZ;AAAA,eACF,IACE;AAAA,YAEJ,qBAAC,SAAI,WAAU,0DACb;AAAA,kCAAC,OAAE,WAAU,iCACV,YAAE,4CAA4C,qFAAqF,GACtI;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,SAAS,MAAM,KAAK,gBAAgB;AAAA,kBACpC,UAAU,CAAC;AAAA,kBAEX;AAAA,wCAAC,QAAK,WAAU,eAAc;AAAA,oBAC7B,EAAE,oCAAoC,YAAY;AAAA;AAAA;AAAA,cACrD;AAAA,eACF;AAAA,aACF;AAAA,UAEA,qBAAC,SAAI,WAAU,qCACb;AAAA,iCAAC,SAAI,WAAU,0CACb;AAAA,mCAAC,SAAI,WAAU,aACb;AAAA,qCAAC,SAAI,WAAU,2BACb;AAAA,sCAAC,iBAAc,WAAU,uBAAsB;AAAA,kBAC/C,oBAAC,QAAG,WAAU,yBAAyB,YAAE,sCAAsC,oBAAoB,GAAE;AAAA,mBACvG;AAAA,gBACA,oBAAC,OAAE,WAAU,iCACV,YAAE,4CAA4C,+GAA+G,GAChK;AAAA,iBACF;AAAA,cACA,oBAAC,SAAM,SAAQ,WACZ,6BACI,eAAe,YACd,EAAE,oDAAoD,WAAW,IACjE,EAAE,qDAAqD,QAAQ,IACjE,EAAE,iDAAiD,eAAe,GACxE;AAAA,eACF;AAAA,YAEA,oBAAC,aAAU,WAAU,QAAO;AAAA,YAE5B,qBAAC,SAAI,WAAU,6BACb;AAAA,mCAAC,SAAI,WAAU,aACb;AAAA,qCAAC,SAAM,WAAU,+CACf;AAAA,sCAAC,UAAO,WAAU,gCAA+B;AAAA,kBACjD,oBAAC,UAAM,YAAE,qCAAqC,eAAe,GAAE;AAAA,mBACjE;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO,eAAe;AAAA,oBACtB,eAAe,CAAC,UAAU,qBAAqB;AAAA,sBAC7C,cAAc,UAAU,SAAS,SAAS;AAAA,oBAC5C,CAAC;AAAA,oBACD,UAAU,qBAAqB,oBAAoB,sBAAsB,CAAC,uBAAuB,CAAC;AAAA,oBAElG;AAAA,0CAAC,iBAAc,MAAK,MAClB,8BAAC,eAAY,GACf;AAAA,sBACA,qBAAC,iBACC;AAAA,4CAAC,cAAW,OAAM,YAAY,YAAE,yCAAyC,UAAU,GAAE;AAAA,wBACrF,oBAAC,cAAW,OAAM,QAAQ,YAAE,qCAAqC,MAAM,GAAE;AAAA,yBAC3E;AAAA;AAAA;AAAA,gBACF;AAAA,iBACF;AAAA,cACA,qBAAC,SAAI,WAAU,aACb;AAAA,qCAAC,SAAM,WAAU,+CACf;AAAA,sCAAC,iBAAc,WAAU,gCAA+B;AAAA,kBACxD,oBAAC,UACE,yBAAe,iBAAiB,SAC7B,EAAE,0CAA0C,iBAAiB,IAC7D,EAAE,8CAA8C,UAAU,GAChE;AAAA,mBACF;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO,eAAe;AAAA,oBACtB,UAAU,CAAC,UAAU,qBAAqB,EAAE,eAAe,MAAM,OAAO,MAAM,CAAC;AAAA,oBAC/E,UAAU,qBAAqB,oBAAoB,sBAAsB,CAAC,uBAAuB,CAAC;AAAA,oBAClG,aAAa,eAAe,iBAAiB,SAAS,cAAc;AAAA;AAAA,gBACtE;AAAA,gBACA,oBAAC,OAAE,WAAU,iCACV,yBAAe,iBAAiB,SAC7B,EAAE,yCAAyC,uDAAuD,IAClG,EAAE,6CAA6C,wDAAwD,GAC7G;AAAA,iBACF;AAAA,cACA,qBAAC,SAAI,WAAU,2BACb;AAAA,qCAAC,SAAM,WAAU,+CACf;AAAA,sCAAC,UAAO,WAAU,gCAA+B;AAAA,kBACjD,oBAAC,UAAM,YAAE,yCAAyC,UAAU,GAAE;AAAA,mBAChE;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO,eAAe;AAAA,oBACtB,UAAU,CAAC,UAAU,qBAAqB,EAAE,UAAU,MAAM,OAAO,MAAM,CAAC;AAAA,oBAC1E,UAAU,qBAAqB,oBAAoB,sBAAsB,CAAC,uBAAuB,CAAC;AAAA;AAAA,gBACpG;AAAA,iBACF;AAAA,eACF;AAAA,YAEA,qBAAC,SAAI,WAAU,mBACb;AAAA,kCAAC,SAAI,WAAU,uCACb,+BAAC,SAAI,WAAU,2CACb;AAAA,qCAAC,SAAI,WAAU,aACb;AAAA,sCAAC,SAAM,WAAU,uBAAuB,YAAE,yCAAyC,iCAAiC,GAAE;AAAA,kBACtH,oBAAC,OAAE,WAAU,iCACV,YAAE,6CAA6C,0FAA0F,GAC5I;AAAA,mBACF;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,SAAS,eAAe;AAAA,oBACxB,iBAAiB,CAAC,YAAY,qBAAqB,EAAE,UAAU,QAAQ,CAAC;AAAA,oBACxE,UAAU,qBAAqB,oBAAoB,sBAAsB,CAAC,uBAAuB,CAAC;AAAA;AAAA,gBACpG;AAAA,iBACF,GACF;AAAA,cACA,oBAAC,SAAI,WAAU,uCACb,+BAAC,SAAI,WAAU,2CACb;AAAA,qCAAC,SAAI,WAAU,aACb;AAAA,sCAAC,SAAM,WAAU,uBAAuB,YAAE,wCAAwC,kBAAkB,GAAE;AAAA,kBACtG,oBAAC,OAAE,WAAU,iCACV,YAAE,4CAA4C,mEAAmE,GACpH;AAAA,mBACF;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,SAAS,eAAe;AAAA,oBACxB,iBAAiB,CAAC,YAAY,qBAAqB,EAAE,WAAW,QAAQ,CAAC;AAAA,oBACzE,UAAU,qBAAqB,oBAAoB,sBAAsB,CAAC,uBAAuB,CAAC;AAAA;AAAA,gBACpG;AAAA,iBACF,GACF;AAAA,eACF;AAAA,YAEA,qBAAC,SAAI,WAAU,0DACb;AAAA,kCAAC,SAAI,WAAU,2CACb,8BAAC,SACE,6BACI,eAAe,YACd,EAAE,wCAAwC,+BAA+B;AAAA,gBACvE,OAAO,IAAI,KAAK,eAAe,SAAS,EAAE,eAAe;AAAA,cAC3D,CAAC,IACD,EAAE,yCAAyC,sDAAsD,IACnG,EAAE,qCAAqC,kDAAkD,GAC/F,GACF;AAAA,cACA,qBAAC,SAAI,WAAU,wBACb;AAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAQ;AAAA,oBACR,SAAS,MAAM,KAAK,qBAAqB;AAAA,oBACzC,UAAU,CAAC,oBAAoB;AAAA,oBAE9B,+BACG,EAAE,yCAAyC,aAAa,IACxD,EAAE,uCAAuC,iBAAiB;AAAA;AAAA,gBAChE;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAQ;AAAA,oBACR,SAAS,MAAM,KAAK,mBAAmB;AAAA,oBACvC,UAAU,oBAAoB,CAAC,uBAAuB,CAAC;AAAA,oBAEvD;AAAA,0CAAC,iBAAc,WAAU,eAAc;AAAA,sBACtC,mBACG,EAAE,uCAAuC,WAAW,IACpD,EAAE,qCAAqC,yBAAyB;AAAA;AAAA;AAAA,gBACtE;AAAA,iBACF;AAAA,eACF;AAAA,aACF;AAAA,WACF;AAAA,QAEC,uBAAuB,CAAC,oBAAoB,YAC3C,oBAAC,SAAM,QAAO,WACZ,8BAAC,oBACE,YAAE,sCAAsC,kGAAkG,GAC7I,GACF,IACE;AAAA,QACH,uBAAuB,CAAC,oBAAoB,iBAC3C,oBAAC,SAAM,QAAO,WACZ,8BAAC,oBACE,YAAE,iDAAiD,8FAA8F,GACpJ,GACF,IACE;AAAA,QACH,uBAAuB,oBAAoB,gBAAgB,QAC1D,oBAAC,SAAM,QAAO,eACZ,8BAAC,oBACE,YAAE,6CAA6C,4GAA4G,GAC9J,GACF,IACE;AAAA,SACN;AAAA,OACF;AAAA,IAEA;AAAA,MAAC;AAAA;AAAA,QACC,qBAAmB;AAAA,QACnB,OAAO,EAAE,2BAA2B;AAAA,QACpC;AAAA,QACA,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA,gBAAgB;AAAA,QAChB,gBAAgB;AAAA,QAChB,aAAa;AAAA,QACb,gBAAgB,CAAC,UAAU;AAAE,oBAAU,KAAK;AAAG,kBAAQ,CAAC;AAAA,QAAE;AAAA,QAC1D,mBAAmB,EAAE,uCAAuC;AAAA,QAC5D,aAAa,EAAE,SAAS,gBAAgB,MAAM,UAAU,QAAQ;AAAA,QAChE,YAAY,CAAC,QAAQ;AACnB,iBAAO,KAAK,2BAA2B,mBAAmB,IAAI,EAAE,CAAC,EAAE;AAAA,QACrE;AAAA,QACA,YAAY,CAAC,QACX,oBAAC,cAAW,OAAO;AAAA,UACjB;AAAA,YACE,IAAI;AAAA,YACJ,OAAO,EAAE,kCAAkC;AAAA,YAC3C,UAAU,MAAM;AAAE,qBAAO,KAAK,2BAA2B,mBAAmB,IAAI,EAAE,CAAC,EAAE;AAAA,YAAE;AAAA,UACzF;AAAA,UACA,GAAI,IAAI,WAAW,YAAY,CAAC;AAAA,YAC9B,IAAI;AAAA,YACJ,OAAO,EAAE,8BAA8B;AAAA,YACvC,aAAa;AAAA,YACb,UAAU,MAAM;AAAE,mBAAK,aAAa,GAAG;AAAA,YAAE;AAAA,UAC3C,CAAC,IAAI,CAAC;AAAA,UACN,GAAI,IAAI,WAAW,WAAW,CAAC;AAAA,YAC7B,IAAI;AAAA,YACJ,OAAO,EAAE,6BAA6B;AAAA,YACtC,UAAU,MAAM;AAAE,mBAAK,YAAY,GAAG;AAAA,YAAE;AAAA,UAC1C,CAAC,IAAI,CAAC;AAAA,QACR,GAAG;AAAA,QAEL,YAAY,EAAE,MAAM,UAAU,IAAI,OAAO,YAAY,eAAe,cAAc,QAAQ;AAAA,QAC1F;AAAA;AAAA,IACF;AAAA,KACF,GACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -26,6 +26,7 @@ function DevicesAdminListPage() {
26
26
  const [page, setPage] = React.useState(1);
27
27
  const [total, setTotal] = React.useState(0);
28
28
  const [totalPages, setTotalPages] = React.useState(1);
29
+ const [totalIsCapped, setTotalIsCapped] = React.useState(false);
29
30
  const [isLoading, setIsLoading] = React.useState(true);
30
31
  const [reloadToken, setReloadToken] = React.useState(0);
31
32
  const scopeVersion = useOrganizationScopeVersion();
@@ -109,6 +110,7 @@ function DevicesAdminListPage() {
109
110
  setRows(Array.isArray(payload.items) ? payload.items : []);
110
111
  setTotal(payload.total || 0);
111
112
  setTotalPages(payload.totalPages || 1);
113
+ setTotalIsCapped(payload?.totalIsCapped === true);
112
114
  }
113
115
  } catch (error) {
114
116
  if (!cancelled) {
@@ -222,7 +224,7 @@ function DevicesAdminListPage() {
222
224
  void handleDeactivate(row);
223
225
  } }
224
226
  ] }),
225
- pagination: { page, pageSize: 50, total, totalPages, onPageChange: setPage },
227
+ pagination: { page, pageSize: 50, total, totalPages, totalIsCapped, onPageChange: setPage },
226
228
  isLoading
227
229
  }
228
230
  ) }),
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/devices/backend/devices/page.tsx"],
4
- "sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport { Button } from '@open-mercato/ui/primitives/button'\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 { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'\n\ntype Row = {\n id: string\n user_id: string\n device_id: string\n platform: string\n client_app_version: string | null\n os_version: string | null\n push_provider: string | null\n push_token_updated_at: string | null\n last_seen_at: string | null\n created_at: string | null\n}\n\ntype ResponsePayload = {\n items: Row[]\n total: number\n page?: number\n pageSize?: number\n totalPages: number\n}\n\nfunction formatDate(value: string | null, t: (key: string) => string) {\n if (!value) return t('devices.list.noValue')\n try {\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return t('devices.list.noValue')\n return date.toLocaleString()\n } catch {\n return t('devices.list.noValue')\n }\n}\n\nexport default function DevicesAdminListPage() {\n const [rows, setRows] = React.useState<Row[]>([])\n const [page, setPage] = React.useState(1)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [isLoading, setIsLoading] = React.useState(true)\n const [reloadToken, setReloadToken] = React.useState(0)\n const scopeVersion = useOrganizationScopeVersion()\n const t = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const [filterValues, setFilterValues] = React.useState<FilterValues>({})\n const [userOptions, setUserOptions] = React.useState<{ value: string; label: string; description?: string | null }[]>([])\n\n // Devices admins may not hold auth.users.list; degrade gracefully (no options) instead of redirecting.\n const loadUserOptions = React.useCallback(async (query?: string) => {\n const params = new URLSearchParams()\n params.set('page', '1')\n params.set('pageSize', '20')\n if (query && query.trim().length > 0) params.set('search', query.trim())\n const call = await apiCall<{ items?: { id: string; name?: string | null; email?: string | null }[] }>(\n `/api/auth/users?${params.toString()}`,\n { headers: { 'x-om-forbidden-redirect': '0' } },\n { fallback: null },\n ).catch(() => null)\n if (!call || !call.ok) return []\n const next = (call.result?.items ?? []).flatMap((item) => {\n if (!item || typeof item.id !== 'string' || !item.id.trim()) return []\n const name = typeof item.name === 'string' && item.name.trim() ? item.name.trim() : null\n const email = typeof item.email === 'string' && item.email.trim() ? item.email.trim() : null\n const label = name ?? email ?? item.id\n return [{ value: item.id, label, description: email && email !== label ? email : null }]\n })\n setUserOptions((prev) => {\n const map = new Map(prev.map((opt) => [opt.value, opt]))\n for (const opt of next) map.set(opt.value, opt)\n return Array.from(map.values())\n })\n return next\n }, [])\n\n React.useEffect(() => { void loadUserOptions() }, [loadUserOptions, scopeVersion])\n\n // Reuse the picker cache to label the User column; rows whose owner isn't cached still link by id.\n const userLabelById = React.useMemo(\n () => new Map(userOptions.map((opt) => [opt.value, opt.label])),\n [userOptions],\n )\n\n const filters = React.useMemo<FilterDef[]>(() => [\n {\n id: 'platform',\n label: t('devices.list.columns.platform'),\n type: 'select',\n options: [\n { value: 'ios', label: 'iOS' },\n { value: 'android', label: 'Android' },\n { value: 'web', label: 'Web' },\n ],\n },\n {\n id: 'userId',\n label: t('devices.list.columns.user'),\n type: 'combobox',\n options: userOptions,\n loadOptions: loadUserOptions,\n },\n ], [t, userOptions, loadUserOptions])\n\n React.useEffect(() => {\n let cancelled = false\n async function load() {\n setIsLoading(true)\n try {\n const params = new URLSearchParams()\n params.set('page', String(page))\n params.set('pageSize', '50')\n const platform = typeof filterValues.platform === 'string' ? filterValues.platform.trim() : ''\n const userId = typeof filterValues.userId === 'string' ? filterValues.userId.trim() : ''\n if (platform) params.set('platform', platform)\n if (userId) params.set('userId', userId)\n const fallback: ResponsePayload = { items: [], total: 0, page, totalPages: 1 }\n const call = await apiCall<ResponsePayload>(`/api/devices/admin/devices?${params.toString()}`, undefined, { fallback })\n if (!call.ok) {\n const errorPayload = call.result as { error?: string } | undefined\n const message = typeof errorPayload?.error === 'string' ? errorPayload.error : t('devices.list.error.loadFailed')\n flash(message, 'error')\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 }\n } catch (error) {\n if (!cancelled) {\n const message = error instanceof Error ? error.message : t('devices.list.error.loadFailed')\n flash(message, 'error')\n }\n } finally {\n if (!cancelled) setIsLoading(false)\n }\n }\n load()\n return () => { cancelled = true }\n }, [page, reloadToken, scopeVersion, filterValues, t])\n\n const handleDeactivate = React.useCallback(async (row: Row) => {\n const confirmed = await confirm({\n title: t('devices.list.confirmDeactivate'),\n variant: 'destructive',\n })\n if (!confirmed) return\n try {\n // optimistic-lock-exempt: device deactivate is an idempotent soft-delete of a registry row, not a concurrent field edit\n const call = await apiCall<{ error?: string }>(\n `/api/devices/admin/devices/${encodeURIComponent(row.id)}`,\n { method: 'DELETE' },\n { fallback: null },\n )\n if (!call.ok) {\n const errorPayload = call.result as { error?: string } | undefined\n const message = typeof errorPayload?.error === 'string' ? errorPayload.error : t('devices.list.error.deactivateFailed')\n flash(message, 'error')\n return\n }\n flash(t('devices.list.success.deactivated'), 'success')\n setReloadToken((token) => token + 1)\n } catch (error) {\n const message = error instanceof Error ? error.message : t('devices.list.error.deactivateFailed')\n flash(message, 'error')\n }\n }, [confirm, t])\n\n const columns = React.useMemo<ColumnDef<Row>[]>(() => [\n {\n accessorKey: 'device_id',\n header: t('devices.list.columns.device'),\n cell: ({ row }) => <code className=\"text-xs\">{row.original.device_id}</code>,\n },\n { accessorKey: 'platform', header: t('devices.list.columns.platform') },\n {\n accessorKey: 'user_id',\n header: t('devices.list.columns.user'),\n cell: ({ row }) => {\n const userId = row.original.user_id\n const label = userLabelById.get(userId)\n return (\n // Stop the click bubbling to the row, whose default action navigates to the device edit page.\n <Link\n href={`/backend/users/${encodeURIComponent(userId)}/edit`}\n className=\"text-primary hover:underline\"\n onClick={(e) => e.stopPropagation()}\n >\n {label ?? <code className=\"text-xs\">{userId}</code>}\n </Link>\n )\n },\n },\n {\n accessorKey: 'client_app_version',\n header: t('devices.list.columns.appVersion'),\n cell: ({ row }) => row.original.client_app_version || t('devices.list.noValue'),\n },\n {\n accessorKey: 'os_version',\n header: t('devices.list.columns.osVersion'),\n cell: ({ row }) => row.original.os_version || t('devices.list.noValue'),\n },\n {\n accessorKey: 'push_provider',\n header: t('devices.list.columns.pushProvider'),\n cell: ({ row }) => row.original.push_provider || t('devices.list.noValue'),\n },\n {\n accessorKey: 'last_seen_at',\n header: t('devices.list.columns.lastSeen'),\n cell: ({ row }) => formatDate(row.original.last_seen_at, t),\n },\n ], [t, userLabelById])\n\n return (\n <Page>\n <PageBody>\n <DataTable\n title={t('devices.list.title')}\n actions={(\n <Button asChild>\n <Link href=\"/backend/devices/create\">{t('devices.list.actions.register')}</Link>\n </Button>\n )}\n columns={columns}\n data={rows}\n filters={filters}\n filterValues={filterValues}\n onFiltersApply={(values) => { setFilterValues(values); setPage(1) }}\n onFiltersClear={() => { setFilterValues({}); setPage(1) }}\n perspective={{ tableId: 'devices.list' }}\n rowActions={(row) => (\n <RowActions items={[\n { id: 'edit', label: t('devices.list.actions.edit'), href: `/backend/devices/${row.id}` },\n { id: 'deactivate', label: t('devices.list.actions.deactivate'), destructive: true, onSelect: () => { void handleDeactivate(row) } },\n ]} />\n )}\n pagination={{ page, pageSize: 50, total, totalPages, onPageChange: setPage }}\n isLoading={isLoading}\n />\n </PageBody>\n {ConfirmDialogElement}\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 { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport { Button } from '@open-mercato/ui/primitives/button'\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 { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'\n\ntype Row = {\n id: string\n user_id: string\n device_id: string\n platform: string\n client_app_version: string | null\n os_version: string | null\n push_provider: string | null\n push_token_updated_at: string | null\n last_seen_at: string | null\n created_at: string | null\n}\n\ntype ResponsePayload = {\n items: Row[]\n total: number\n page?: number\n pageSize?: number\n totalPages: number\n totalIsCapped?: boolean\n}\n\nfunction formatDate(value: string | null, t: (key: string) => string) {\n if (!value) return t('devices.list.noValue')\n try {\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return t('devices.list.noValue')\n return date.toLocaleString()\n } catch {\n return t('devices.list.noValue')\n }\n}\n\nexport default function DevicesAdminListPage() {\n const [rows, setRows] = React.useState<Row[]>([])\n const [page, setPage] = React.useState(1)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [totalIsCapped, setTotalIsCapped] = React.useState(false)\n const [isLoading, setIsLoading] = React.useState(true)\n const [reloadToken, setReloadToken] = React.useState(0)\n const scopeVersion = useOrganizationScopeVersion()\n const t = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const [filterValues, setFilterValues] = React.useState<FilterValues>({})\n const [userOptions, setUserOptions] = React.useState<{ value: string; label: string; description?: string | null }[]>([])\n\n // Devices admins may not hold auth.users.list; degrade gracefully (no options) instead of redirecting.\n const loadUserOptions = React.useCallback(async (query?: string) => {\n const params = new URLSearchParams()\n params.set('page', '1')\n params.set('pageSize', '20')\n if (query && query.trim().length > 0) params.set('search', query.trim())\n const call = await apiCall<{ items?: { id: string; name?: string | null; email?: string | null }[] }>(\n `/api/auth/users?${params.toString()}`,\n { headers: { 'x-om-forbidden-redirect': '0' } },\n { fallback: null },\n ).catch(() => null)\n if (!call || !call.ok) return []\n const next = (call.result?.items ?? []).flatMap((item) => {\n if (!item || typeof item.id !== 'string' || !item.id.trim()) return []\n const name = typeof item.name === 'string' && item.name.trim() ? item.name.trim() : null\n const email = typeof item.email === 'string' && item.email.trim() ? item.email.trim() : null\n const label = name ?? email ?? item.id\n return [{ value: item.id, label, description: email && email !== label ? email : null }]\n })\n setUserOptions((prev) => {\n const map = new Map(prev.map((opt) => [opt.value, opt]))\n for (const opt of next) map.set(opt.value, opt)\n return Array.from(map.values())\n })\n return next\n }, [])\n\n React.useEffect(() => { void loadUserOptions() }, [loadUserOptions, scopeVersion])\n\n // Reuse the picker cache to label the User column; rows whose owner isn't cached still link by id.\n const userLabelById = React.useMemo(\n () => new Map(userOptions.map((opt) => [opt.value, opt.label])),\n [userOptions],\n )\n\n const filters = React.useMemo<FilterDef[]>(() => [\n {\n id: 'platform',\n label: t('devices.list.columns.platform'),\n type: 'select',\n options: [\n { value: 'ios', label: 'iOS' },\n { value: 'android', label: 'Android' },\n { value: 'web', label: 'Web' },\n ],\n },\n {\n id: 'userId',\n label: t('devices.list.columns.user'),\n type: 'combobox',\n options: userOptions,\n loadOptions: loadUserOptions,\n },\n ], [t, userOptions, loadUserOptions])\n\n React.useEffect(() => {\n let cancelled = false\n async function load() {\n setIsLoading(true)\n try {\n const params = new URLSearchParams()\n params.set('page', String(page))\n params.set('pageSize', '50')\n const platform = typeof filterValues.platform === 'string' ? filterValues.platform.trim() : ''\n const userId = typeof filterValues.userId === 'string' ? filterValues.userId.trim() : ''\n if (platform) params.set('platform', platform)\n if (userId) params.set('userId', userId)\n const fallback: ResponsePayload = { items: [], total: 0, page, totalPages: 1 }\n const call = await apiCall<ResponsePayload>(`/api/devices/admin/devices?${params.toString()}`, undefined, { fallback })\n if (!call.ok) {\n const errorPayload = call.result as { error?: string } | undefined\n const message = typeof errorPayload?.error === 'string' ? errorPayload.error : t('devices.list.error.loadFailed')\n flash(message, 'error')\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 setTotalIsCapped(payload?.totalIsCapped === true)\n }\n } catch (error) {\n if (!cancelled) {\n const message = error instanceof Error ? error.message : t('devices.list.error.loadFailed')\n flash(message, 'error')\n }\n } finally {\n if (!cancelled) setIsLoading(false)\n }\n }\n load()\n return () => { cancelled = true }\n }, [page, reloadToken, scopeVersion, filterValues, t])\n\n const handleDeactivate = React.useCallback(async (row: Row) => {\n const confirmed = await confirm({\n title: t('devices.list.confirmDeactivate'),\n variant: 'destructive',\n })\n if (!confirmed) return\n try {\n // optimistic-lock-exempt: device deactivate is an idempotent soft-delete of a registry row, not a concurrent field edit\n const call = await apiCall<{ error?: string }>(\n `/api/devices/admin/devices/${encodeURIComponent(row.id)}`,\n { method: 'DELETE' },\n { fallback: null },\n )\n if (!call.ok) {\n const errorPayload = call.result as { error?: string } | undefined\n const message = typeof errorPayload?.error === 'string' ? errorPayload.error : t('devices.list.error.deactivateFailed')\n flash(message, 'error')\n return\n }\n flash(t('devices.list.success.deactivated'), 'success')\n setReloadToken((token) => token + 1)\n } catch (error) {\n const message = error instanceof Error ? error.message : t('devices.list.error.deactivateFailed')\n flash(message, 'error')\n }\n }, [confirm, t])\n\n const columns = React.useMemo<ColumnDef<Row>[]>(() => [\n {\n accessorKey: 'device_id',\n header: t('devices.list.columns.device'),\n cell: ({ row }) => <code className=\"text-xs\">{row.original.device_id}</code>,\n },\n { accessorKey: 'platform', header: t('devices.list.columns.platform') },\n {\n accessorKey: 'user_id',\n header: t('devices.list.columns.user'),\n cell: ({ row }) => {\n const userId = row.original.user_id\n const label = userLabelById.get(userId)\n return (\n // Stop the click bubbling to the row, whose default action navigates to the device edit page.\n <Link\n href={`/backend/users/${encodeURIComponent(userId)}/edit`}\n className=\"text-primary hover:underline\"\n onClick={(e) => e.stopPropagation()}\n >\n {label ?? <code className=\"text-xs\">{userId}</code>}\n </Link>\n )\n },\n },\n {\n accessorKey: 'client_app_version',\n header: t('devices.list.columns.appVersion'),\n cell: ({ row }) => row.original.client_app_version || t('devices.list.noValue'),\n },\n {\n accessorKey: 'os_version',\n header: t('devices.list.columns.osVersion'),\n cell: ({ row }) => row.original.os_version || t('devices.list.noValue'),\n },\n {\n accessorKey: 'push_provider',\n header: t('devices.list.columns.pushProvider'),\n cell: ({ row }) => row.original.push_provider || t('devices.list.noValue'),\n },\n {\n accessorKey: 'last_seen_at',\n header: t('devices.list.columns.lastSeen'),\n cell: ({ row }) => formatDate(row.original.last_seen_at, t),\n },\n ], [t, userLabelById])\n\n return (\n <Page>\n <PageBody>\n <DataTable\n title={t('devices.list.title')}\n actions={(\n <Button asChild>\n <Link href=\"/backend/devices/create\">{t('devices.list.actions.register')}</Link>\n </Button>\n )}\n columns={columns}\n data={rows}\n filters={filters}\n filterValues={filterValues}\n onFiltersApply={(values) => { setFilterValues(values); setPage(1) }}\n onFiltersClear={() => { setFilterValues({}); setPage(1) }}\n perspective={{ tableId: 'devices.list' }}\n rowActions={(row) => (\n <RowActions items={[\n { id: 'edit', label: t('devices.list.actions.edit'), href: `/backend/devices/${row.id}` },\n { id: 'deactivate', label: t('devices.list.actions.deactivate'), destructive: true, onSelect: () => { void handleDeactivate(row) } },\n ]} />\n )}\n pagination={{ page, pageSize: 50, total, totalPages, totalIsCapped, onPageChange: setPage }}\n isLoading={isLoading}\n />\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -141,6 +141,7 @@ function DirectoryOrganizationsPage() {
141
141
  }, [isSuperAdmin, t]);
142
142
  const total = data?.total ?? 0;
143
143
  const totalPages = data?.totalPages ?? 0;
144
+ const totalIsCapped = data?.totalIsCapped === true;
144
145
  const deleteMutationContextId = "directory-organizations-list:single-delete";
145
146
  const { runMutation: runDeleteMutation, retryLastMutation: retryDeleteMutation } = useGuardedMutation({
146
147
  contextId: deleteMutationContextId,
@@ -238,7 +239,7 @@ function DirectoryOrganizationsPage() {
238
239
  createLabel: t("directory.organizations.list.actions.create", "Create")
239
240
  }
240
241
  ),
241
- pagination: { page, pageSize: 50, total, totalPages, onPageChange: setPage },
242
+ pagination: { page, pageSize: 50, total, totalPages, totalIsCapped, onPageChange: setPage },
242
243
  isLoading
243
244
  }
244
245
  ) }),