@open-mercato/core 0.5.1-develop.2949.009dcdd2d5 → 0.5.1-develop.2954.610bab2d08
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.
- package/dist/helpers/integration/salesUi.js +25 -23
- package/dist/helpers/integration/salesUi.js.map +2 -2
- package/dist/modules/api_docs/frontend/docs/api/Explorer.js +24 -24
- package/dist/modules/api_docs/frontend/docs/api/Explorer.js.map +2 -2
- package/dist/modules/attachments/components/AttachmentPartitionSettings.js +15 -7
- package/dist/modules/attachments/components/AttachmentPartitionSettings.js.map +2 -2
- package/dist/modules/attachments/fields/attachment.js +4 -6
- package/dist/modules/attachments/fields/attachment.js.map +2 -2
- package/dist/modules/auth/api/users/route.js +63 -23
- package/dist/modules/auth/api/users/route.js.map +2 -2
- package/dist/modules/auth/backend/users/create/page.js +26 -26
- package/dist/modules/auth/backend/users/create/page.js.map +2 -2
- package/dist/modules/business_rules/components/ActionRow.js +36 -25
- package/dist/modules/business_rules/components/ActionRow.js.map +2 -2
- package/dist/modules/business_rules/components/ConditionGroup.js +14 -5
- package/dist/modules/business_rules/components/ConditionGroup.js.map +2 -2
- package/dist/modules/business_rules/components/ConditionRow.js +19 -10
- package/dist/modules/business_rules/components/ConditionRow.js.map +2 -2
- package/dist/modules/business_rules/components/RuleSetMembers.js +16 -10
- package/dist/modules/business_rules/components/RuleSetMembers.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js +30 -34
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/create/page.js +220 -223
- package/dist/modules/catalog/backend/catalog/products/create/page.js.map +2 -2
- package/dist/modules/catalog/components/PriceKindSettings.js +20 -19
- package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
- package/dist/modules/catalog/components/products/ProductUomSection.js +42 -37
- package/dist/modules/catalog/components/products/ProductUomSection.js.map +2 -2
- package/dist/modules/catalog/components/products/VariantBuilder.js +22 -18
- package/dist/modules/catalog/components/products/VariantBuilder.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js +18 -26
- package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js +4 -6
- package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js.map +2 -2
- package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js +5 -4
- package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js.map +2 -2
- package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js +19 -7
- package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/page.js +24 -21
- package/dist/modules/customers/backend/customers/deals/pipeline/page.js.map +2 -2
- package/dist/modules/customers/components/AddressEditor.js +24 -7
- package/dist/modules/customers/components/AddressEditor.js.map +2 -2
- package/dist/modules/customers/components/AddressFormatSettings.js +35 -25
- package/dist/modules/customers/components/AddressFormatSettings.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivityForm.js +20 -12
- package/dist/modules/customers/components/detail/ActivityForm.js.map +2 -2
- package/dist/modules/customers/components/detail/AnnualRevenueField.js +2 -2
- package/dist/modules/customers/components/detail/AnnualRevenueField.js.map +2 -2
- package/dist/modules/customers/components/detail/DealForm.js +19 -14
- package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
- package/dist/modules/customers/components/formConfig.js +16 -12
- package/dist/modules/customers/components/formConfig.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/customer-todos/widget.client.js +3 -2
- package/dist/modules/customers/widgets/dashboard/customer-todos/widget.client.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/new-customers/widget.client.js +18 -10
- package/dist/modules/customers/widgets/dashboard/new-customers/widget.client.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/new-deals/widget.client.js +3 -2
- package/dist/modules/customers/widgets/dashboard/new-deals/widget.client.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/next-interactions/widget.client.js +3 -2
- package/dist/modules/customers/widgets/dashboard/next-interactions/widget.client.js.map +2 -2
- package/dist/modules/dashboards/components/WidgetVisibilityEditor.js +27 -28
- package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.client.js +14 -6
- package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.js +14 -6
- package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.js +3 -2
- package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.client.js +3 -2
- package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.client.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/top-products/widget.client.js +17 -8
- package/dist/modules/dashboards/widgets/dashboard/top-products/widget.client.js.map +2 -2
- package/dist/modules/data_sync/backend/data-sync/page.js +40 -23
- package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
- package/dist/modules/data_sync/components/IntegrationScheduleTab.js +15 -6
- package/dist/modules/data_sync/components/IntegrationScheduleTab.js.map +2 -2
- package/dist/modules/dictionaries/components/AppearanceSelector.js +4 -4
- package/dist/modules/dictionaries/components/AppearanceSelector.js.map +2 -2
- package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js +4 -5
- package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js.map +2 -2
- package/dist/modules/dictionaries/components/DictionaryEntrySelect.js +22 -14
- package/dist/modules/dictionaries/components/DictionaryEntrySelect.js.map +2 -2
- package/dist/modules/dictionaries/fields/dictionary.js +18 -13
- package/dist/modules/dictionaries/fields/dictionary.js.map +2 -2
- package/dist/modules/entities/components/EncryptionManager.js +23 -19
- package/dist/modules/entities/components/EncryptionManager.js.map +2 -2
- package/dist/modules/feature_toggles/components/formConfig.js +17 -9
- package/dist/modules/feature_toggles/components/formConfig.js.map +2 -2
- package/dist/modules/feature_toggles/components/overrideFormConfig.js +17 -9
- package/dist/modules/feature_toggles/components/overrideFormConfig.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js +15 -8
- package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js.map +2 -2
- package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js +37 -22
- package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/[id]/page.js +22 -17
- package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js +12 -6
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js.map +2 -2
- package/dist/modules/planner/components/AvailabilityRulesEditor.js +19 -12
- package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
- package/dist/modules/resources/components/ResourceCrudForm.js +15 -10
- package/dist/modules/resources/components/ResourceCrudForm.js.map +3 -3
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +15 -18
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/dist/modules/sales/components/ProviderFieldInput.js +23 -20
- package/dist/modules/sales/components/ProviderFieldInput.js.map +2 -2
- package/dist/modules/sales/components/ShippingMethodsSettings.js +25 -17
- package/dist/modules/sales/components/ShippingMethodsSettings.js.map +3 -3
- package/dist/modules/sales/components/channels/ChannelOfferForm.js +35 -42
- package/dist/modules/sales/components/channels/ChannelOfferForm.js.map +2 -2
- package/dist/modules/sales/components/documents/AddressesSection.js +87 -90
- package/dist/modules/sales/components/documents/AddressesSection.js.map +2 -2
- package/dist/modules/sales/components/documents/AdjustmentDialog.js +17 -6
- package/dist/modules/sales/components/documents/AdjustmentDialog.js.map +3 -3
- package/dist/modules/sales/components/documents/LineItemDialog.js +42 -25
- package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentForm.js +96 -87
- package/dist/modules/sales/components/documents/SalesDocumentForm.js.map +2 -2
- package/dist/modules/sales/widgets/dashboard/new-orders/widget.client.js +20 -11
- package/dist/modules/sales/widgets/dashboard/new-orders/widget.client.js.map +2 -2
- package/dist/modules/sales/widgets/dashboard/new-quotes/widget.client.js +20 -11
- package/dist/modules/sales/widgets/dashboard/new-quotes/widget.client.js.map +2 -2
- package/dist/modules/shipping_carriers/lib/shipment-wizard/components/ConfigureStep.js +36 -22
- package/dist/modules/shipping_carriers/lib/shipment-wizard/components/ConfigureStep.js.map +2 -2
- package/dist/modules/staff/components/TeamMemberForm.js +14 -9
- package/dist/modules/staff/components/TeamMemberForm.js.map +3 -3
- package/dist/modules/workflows/backend/tasks/[id]/page.js +42 -21
- package/dist/modules/workflows/backend/tasks/[id]/page.js.map +2 -2
- package/dist/modules/workflows/components/ActivitiesEditor.js +14 -6
- package/dist/modules/workflows/components/ActivitiesEditor.js.map +3 -3
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js +25 -17
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js.map +3 -3
- package/dist/modules/workflows/components/EdgeEditDialog.js +48 -45
- package/dist/modules/workflows/components/EdgeEditDialog.js.map +2 -2
- package/dist/modules/workflows/components/NodeEditDialog.js +90 -90
- package/dist/modules/workflows/components/NodeEditDialog.js.map +2 -2
- package/dist/modules/workflows/components/StepsEditor.js +14 -6
- package/dist/modules/workflows/components/StepsEditor.js.map +3 -3
- package/dist/modules/workflows/components/TransitionsEditor.js +31 -26
- package/dist/modules/workflows/components/TransitionsEditor.js.map +3 -3
- package/dist/modules/workflows/components/fields/ActivityArrayEditor.js +19 -11
- package/dist/modules/workflows/components/fields/ActivityArrayEditor.js.map +3 -3
- package/dist/modules/workflows/components/fields/BusinessRuleConditionsEditor.js +12 -14
- package/dist/modules/workflows/components/fields/BusinessRuleConditionsEditor.js.map +2 -2
- package/dist/modules/workflows/components/fields/FormFieldArrayEditor.js +24 -16
- package/dist/modules/workflows/components/fields/FormFieldArrayEditor.js.map +3 -3
- package/dist/modules/workflows/components/fields/StartPreConditionsEditor.js +12 -13
- package/dist/modules/workflows/components/fields/StartPreConditionsEditor.js.map +2 -2
- package/dist/modules/workflows/components/mobile/MobileTaskForm.js +12 -8
- package/dist/modules/workflows/components/mobile/MobileTaskForm.js.map +2 -2
- package/dist/modules/workflows/frontend/checkout-demo/page.js +43 -46
- package/dist/modules/workflows/frontend/checkout-demo/page.js.map +2 -2
- package/package.json +3 -3
- package/src/helpers/integration/salesUi.ts +40 -30
- package/src/modules/api_docs/frontend/docs/api/Explorer.tsx +25 -19
- package/src/modules/attachments/components/AttachmentPartitionSettings.tsx +21 -11
- package/src/modules/attachments/fields/attachment.tsx +4 -6
- package/src/modules/auth/api/users/route.ts +75 -25
- package/src/modules/auth/backend/users/create/page.tsx +16 -20
- package/src/modules/business_rules/components/ActionRow.tsx +51 -32
- package/src/modules/business_rules/components/ConditionGroup.tsx +20 -9
- package/src/modules/business_rules/components/ConditionRow.tsx +24 -15
- package/src/modules/business_rules/components/RuleSetMembers.tsx +23 -13
- package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +47 -53
- package/src/modules/catalog/backend/catalog/products/create/page.tsx +84 -87
- package/src/modules/catalog/components/PriceKindSettings.tsx +9 -9
- package/src/modules/catalog/components/products/ProductUomSection.tsx +85 -83
- package/src/modules/catalog/components/products/VariantBuilder.tsx +49 -33
- package/src/modules/customer_accounts/backend/customer_accounts/users/[id]/page.tsx +12 -27
- package/src/modules/customer_accounts/backend/customer_accounts/users/page.tsx +4 -6
- package/src/modules/customer_accounts/widgets/injection/account-status/widget.client.tsx +5 -4
- package/src/modules/customers/backend/config/customers/pipeline-stages/page.tsx +28 -15
- package/src/modules/customers/backend/customers/deals/pipeline/page.tsx +37 -26
- package/src/modules/customers/components/AddressEditor.tsx +30 -16
- package/src/modules/customers/components/AddressFormatSettings.tsx +25 -19
- package/src/modules/customers/components/detail/ActivityForm.tsx +35 -23
- package/src/modules/customers/components/detail/AnnualRevenueField.tsx +2 -2
- package/src/modules/customers/components/detail/DealForm.tsx +33 -20
- package/src/modules/customers/components/formConfig.tsx +25 -17
- package/src/modules/customers/widgets/dashboard/customer-todos/widget.client.tsx +3 -2
- package/src/modules/customers/widgets/dashboard/new-customers/widget.client.tsx +21 -11
- package/src/modules/customers/widgets/dashboard/new-deals/widget.client.tsx +3 -2
- package/src/modules/customers/widgets/dashboard/next-interactions/widget.client.tsx +3 -2
- package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +17 -22
- package/src/modules/dashboards/widgets/dashboard/orders-by-status/widget.client.tsx +17 -7
- package/src/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.tsx +20 -10
- package/src/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.tsx +3 -2
- package/src/modules/dashboards/widgets/dashboard/top-customers/widget.client.tsx +3 -2
- package/src/modules/dashboards/widgets/dashboard/top-products/widget.client.tsx +20 -9
- package/src/modules/data_sync/backend/data-sync/page.tsx +64 -38
- package/src/modules/data_sync/components/IntegrationScheduleTab.tsx +18 -7
- package/src/modules/dictionaries/components/AppearanceSelector.tsx +4 -4
- package/src/modules/dictionaries/components/DictionaryEntriesEditor.tsx +3 -4
- package/src/modules/dictionaries/components/DictionaryEntrySelect.tsx +27 -21
- package/src/modules/dictionaries/fields/dictionary.tsx +36 -23
- package/src/modules/entities/components/EncryptionManager.tsx +49 -33
- package/src/modules/feature_toggles/components/formConfig.tsx +20 -10
- package/src/modules/feature_toggles/components/overrideFormConfig.tsx +20 -10
- package/src/modules/inbox_ops/backend/inbox-ops/settings/page.tsx +19 -10
- package/src/modules/inbox_ops/components/proposals/EditActionDialog.tsx +49 -26
- package/src/modules/integrations/backend/integrations/[id]/page.tsx +20 -11
- package/src/modules/integrations/backend/integrations/bundle/[id]/page.tsx +19 -9
- package/src/modules/planner/components/AvailabilityRulesEditor.tsx +34 -21
- package/src/modules/resources/components/ResourceCrudForm.tsx +24 -15
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +12 -15
- package/src/modules/sales/components/ProviderFieldInput.tsx +26 -17
- package/src/modules/sales/components/ShippingMethodsSettings.tsx +28 -20
- package/src/modules/sales/components/channels/ChannelOfferForm.tsx +51 -46
- package/src/modules/sales/components/documents/AddressesSection.tsx +78 -76
- package/src/modules/sales/components/documents/AdjustmentDialog.tsx +27 -15
- package/src/modules/sales/components/documents/LineItemDialog.tsx +69 -51
- package/src/modules/sales/components/documents/SalesDocumentForm.tsx +98 -87
- package/src/modules/sales/widgets/dashboard/new-orders/widget.client.tsx +23 -12
- package/src/modules/sales/widgets/dashboard/new-quotes/widget.client.tsx +23 -12
- package/src/modules/shipping_carriers/lib/shipment-wizard/components/ConfigureStep.tsx +35 -19
- package/src/modules/staff/components/TeamMemberForm.tsx +23 -14
- package/src/modules/workflows/backend/tasks/[id]/page.tsx +51 -23
- package/src/modules/workflows/components/ActivitiesEditor.tsx +20 -10
- package/src/modules/workflows/components/DefinitionTriggersEditor.tsx +28 -18
- package/src/modules/workflows/components/EdgeEditDialog.tsx +51 -40
- package/src/modules/workflows/components/NodeEditDialog.tsx +81 -77
- package/src/modules/workflows/components/StepsEditor.tsx +20 -10
- package/src/modules/workflows/components/TransitionsEditor.tsx +61 -44
- package/src/modules/workflows/components/fields/ActivityArrayEditor.tsx +22 -12
- package/src/modules/workflows/components/fields/BusinessRuleConditionsEditor.tsx +9 -13
- package/src/modules/workflows/components/fields/FormFieldArrayEditor.tsx +27 -17
- package/src/modules/workflows/components/fields/StartPreConditionsEditor.tsx +9 -12
- package/src/modules/workflows/components/mobile/MobileTaskForm.tsx +19 -11
- package/src/modules/workflows/frontend/checkout-demo/page.tsx +71 -60
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/integrations/backend/integrations/%5Bid%5D/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { usePathname, useRouter, useSearchParams } from 'next/navigation'\nimport { z } from 'zod'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CrudForm, type CrudField } from '@open-mercato/ui/backend/CrudForm'\nimport { WebhookSetupGuide } from '@open-mercato/ui/backend/WebhookSetupGuide'\nimport { InjectionSpot, useInjectionWidgets } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { FormHeader } from '@open-mercato/ui/backend/forms'\nimport { Card, CardHeader, CardTitle, CardContent } from '@open-mercato/ui/primitives/card'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Switch } from '@open-mercato/ui/primitives/switch'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from '@open-mercato/ui/primitives/tabs'\nimport { JsonDisplay } from '@open-mercato/ui/backend/JsonDisplay'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport {\n LEGACY_INTEGRATION_DETAIL_TABS_SPOT_ID,\n type CredentialFieldType,\n type IntegrationCredentialField,\n type IntegrationDetailBuiltInTab,\n} from '@open-mercato/shared/modules/integrations/types'\nimport { LoadingMessage, ErrorMessage } from '@open-mercato/ui/backend/detail'\nimport { Activity, AlertTriangle, Bell, Calendar, CheckCircle2, ChevronDown, ChevronRight, CreditCard, FileText, HardDrive, Key, MessageSquare, RefreshCw, Settings, Truck, Webhook, XCircle, Zap } from 'lucide-react'\nimport { IntegrationScheduleTab } from '../../../../data_sync/components/IntegrationScheduleTab'\nimport {\n buildIntegrationDetailInjectedTabs,\n filterIntegrationDetailWidgetsByKind,\n type IntegrationDetailInjectedTab,\n resolveIntegrationDetailWidgetSpotId,\n resolveRequestedIntegrationDetailTab,\n} from '../detail-page-widgets'\n\ntype CredentialField = IntegrationCredentialField\ntype BuiltInIntegrationDetailTab = 'credentials' | 'version' | 'health' | 'logs' | 'data-sync-schedule'\ntype IntegrationDetailTab = BuiltInIntegrationDetailTab | string\n\nconst UNSUPPORTED_CREDENTIAL_FIELD_TYPES = new Set<CredentialFieldType>(['oauth', 'ssh_keypair'])\n\nfunction isEditableCredentialField(field: CredentialField): boolean {\n return !UNSUPPORTED_CREDENTIAL_FIELD_TYPES.has(field.type)\n}\n\ntype ApiVersion = {\n id: string\n label?: string\n status: 'stable' | 'deprecated' | 'experimental'\n sunsetAt?: string\n migrationGuide?: string\n}\n\ntype IntegrationLogAnalytics = {\n lastActivityAt: string | null\n totalCount: number\n errorCount: number\n errorRate: number\n dailyCounts: number[]\n}\n\ntype IntegrationDetail = {\n integration: {\n id: string\n title: string\n description?: string\n category?: string\n hub?: string\n providerKey?: string | null\n bundleId?: string\n docsUrl?: string\n apiVersions?: ApiVersion[]\n detailPage?: {\n widgetSpotId?: string\n hiddenTabs?: IntegrationDetailBuiltInTab[]\n }\n credentials?: { fields: CredentialField[] }\n }\n bundle?: { id: string; title: string; credentials?: { fields: CredentialField[] } }\n state: {\n isEnabled: boolean\n apiVersion: string | null\n reauthRequired: boolean\n lastHealthStatus: string | null\n lastHealthCheckedAt: string | null\n lastHealthLatencyMs: number | null\n enabledAt: string | null\n }\n hasCredentials: boolean\n healthStatus: 'healthy' | 'degraded' | 'unhealthy' | 'unconfigured'\n analytics: IntegrationLogAnalytics\n}\n\ntype LogEntry = {\n id: string\n runId?: string | null\n scopeEntityType?: string | null\n scopeEntityId?: string | null\n level: 'info' | 'warn' | 'error'\n message: string\n createdAt: string\n code?: string | null\n payload?: Record<string, unknown> | null\n}\n\ntype IntegrationDetailPageProps = {\n params?: {\n id?: string | string[]\n }\n}\n\ntype HealthCheckResponse = {\n status: 'healthy' | 'degraded' | 'unhealthy' | 'unconfigured'\n message: string | null\n details: Record<string, unknown> | null\n checkedAt: string\n latencyMs: number | null\n}\n\nconst LOG_LEVEL_STYLES: Record<string, string> = {\n info: 'bg-blue-100 text-blue-800',\n warn: 'bg-yellow-100 text-yellow-800',\n error: 'bg-red-100 text-red-800',\n}\n\nconst HEALTH_STATUS_STYLES: Record<string, string> = {\n healthy: 'bg-green-100 text-green-800',\n degraded: 'bg-yellow-100 text-yellow-800',\n unhealthy: 'bg-red-100 text-red-800',\n unconfigured: 'bg-zinc-100 text-zinc-700',\n}\n\nconst HEALTH_STATUS_ICONS: Record<string, React.ElementType> = {\n healthy: CheckCircle2,\n degraded: AlertTriangle,\n unhealthy: XCircle,\n unconfigured: AlertTriangle,\n}\n\nfunction DetailLogSparkline({ counts, className }: { counts: number[]; className?: string }) {\n const max = Math.max(1, ...counts)\n const w = 120\n const h = 36\n const step = counts.length > 1 ? w / (counts.length - 1) : w\n const points = counts.map((count, index) => {\n const x = index * step\n const y = h - (count / max) * (h - 4) - 2\n return `${x},${y}`\n }).join(' ')\n return (\n <svg width={w} height={h} className={className} aria-hidden>\n <polyline\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n points={points}\n className=\"text-muted-foreground/80\"\n />\n </svg>\n )\n}\n\nconst CATEGORY_ICONS: Record<string, React.ElementType> = {\n payment: CreditCard,\n shipping: Truck,\n data_sync: RefreshCw,\n communication: MessageSquare,\n notification: Bell,\n storage: HardDrive,\n webhook: Webhook,\n}\n\nfunction resolveRouteId(value: string | string[] | undefined): string | undefined {\n if (Array.isArray(value)) return value[0]\n return value\n}\n\nfunction resolvePathnameId(pathname: string): string | undefined {\n const parts = pathname.split('/').filter(Boolean)\n const integrationId = parts.at(-1)\n if (!integrationId || integrationId === 'integrations' || integrationId === 'bundle') return undefined\n return decodeURIComponent(integrationId)\n}\n\nfunction buildCredentialFields(credFields: CredentialField[]): CrudField[] {\n return credFields.map((field) => {\n const shared = {\n id: field.key,\n label: field.label,\n description: field.helpDetails ? (\n <div className=\"space-y-1\">\n {field.helpText ? <div>{field.helpText}</div> : null}\n <WebhookSetupGuide guide={field.helpDetails} buttonLabel=\"Show details\" />\n </div>\n ) : field.helpText,\n placeholder: field.placeholder,\n required: field.required,\n }\n\n if (field.type === 'secret') {\n return {\n ...shared,\n type: 'custom' as const,\n component: ({ id, value, setValue, disabled }) => (\n <Input\n id={id}\n type=\"password\"\n placeholder={field.placeholder}\n value={typeof value === 'string' ? value : ''}\n onChange={(event) => setValue(event.target.value)}\n disabled={disabled}\n />\n ),\n }\n }\n\n if (field.type === 'select' && field.options) {\n return {\n ...shared,\n type: 'select' as const,\n options: field.options,\n }\n }\n\n if (field.type === 'boolean') {\n return {\n ...shared,\n type: 'checkbox' as const,\n }\n }\n\n return {\n ...shared,\n type: 'text' as const,\n }\n })\n}\n\nfunction isHealthLog(log: LogEntry): boolean {\n return log.message === 'Health check passed' || log.message.startsWith('Health check:')\n}\n\nfunction extractHealthDetails(payload: Record<string, unknown> | null | undefined): Record<string, unknown> {\n if (!payload) return {}\n return Object.fromEntries(\n Object.entries(payload).filter(([key, value]) => key !== 'status' && key !== 'message' && value !== undefined && value !== null),\n )\n}\n\nfunction formatHealthValue(value: unknown): string {\n if (typeof value === 'boolean') return value ? 'Yes' : 'No'\n if (typeof value === 'string') return value\n if (typeof value === 'number') return String(value)\n if (value instanceof Date) return value.toLocaleString()\n return JSON.stringify(value)\n}\n\nfunction formatTypeLabel(value: string): string {\n return value.split('_').filter(Boolean).map((part) => part[0]?.toUpperCase() + part.slice(1)).join(' ')\n}\n\nfunction isPrimitiveLogValue(value: unknown): value is string | number | boolean | null {\n return value === null || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean'\n}\n\nfunction formatLogDetailLabel(key: string): string {\n return key\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/[_-]+/g, ' ')\n .split(' ')\n .filter(Boolean)\n .map((part) => part[0]?.toUpperCase() + part.slice(1))\n .join(' ')\n}\n\nfunction formatLogPrimitiveValue(value: string | number | boolean | null): string {\n if (value === null) return 'None'\n if (typeof value === 'boolean') return value ? 'Yes' : 'No'\n return String(value)\n}\n\nfunction isAkeneoSettingsTab(tab: IntegrationDetailInjectedTab): boolean {\n return tab.id.includes('sync_akeneo') || tab.label.toLowerCase().includes('akeneo')\n}\n\nfunction splitLogPayload(payload: Record<string, unknown> | null | undefined) {\n if (!payload) {\n return {\n inlineEntries: [] as Array<[string, string | number | boolean | null]>,\n nestedEntries: [] as Array<[string, unknown]>,\n }\n }\n\n const inlineEntries: Array<[string, string | number | boolean | null]> = []\n const nestedEntries: Array<[string, unknown]> = []\n\n Object.entries(payload).forEach(([key, value]) => {\n if (isPrimitiveLogValue(value)) {\n inlineEntries.push([key, value])\n return\n }\n nestedEntries.push([key, value])\n })\n\n return { inlineEntries, nestedEntries }\n}\n\nexport default function IntegrationDetailPage({ params }: IntegrationDetailPageProps) {\n const pathname = usePathname()\n const router = useRouter()\n const searchParams = useSearchParams()\n const integrationId = resolveRouteId(params?.id) ?? resolvePathnameId(pathname)\n const t = useT()\n\n const [detail, setDetail] = React.useState<IntegrationDetail | null>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n\n const [credValues, setCredValues] = React.useState<Record<string, unknown>>({})\n const [credentialsFormKey, setCredentialsFormKey] = React.useState(0)\n const [isSavingCredentials, setIsSavingCredentials] = React.useState(false)\n\n const [logs, setLogs] = React.useState<LogEntry[]>([])\n const [logLevel, setLogLevel] = React.useState<string>('')\n const [isLoadingLogs, setIsLoadingLogs] = React.useState(false)\n const [expandedLogId, setExpandedLogId] = React.useState<string | null>(null)\n\n const [isCheckingHealth, setIsCheckingHealth] = React.useState(false)\n const [isTogglingState, setIsTogglingState] = React.useState(false)\n const [latestHealthResult, setLatestHealthResult] = React.useState<HealthCheckResponse | null>(null)\n const [activeTab, setActiveTab] = React.useState<IntegrationDetailTab>('credentials')\n\n const credentialsFormId = React.useId()\n\n const resolveCurrentIntegrationId = React.useCallback(() => {\n return integrationId ?? (\n typeof window !== 'undefined'\n ? resolvePathnameId(window.location.pathname)\n : undefined\n )\n }, [integrationId])\n\n const loadDetail = React.useCallback(async () => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) {\n setIsLoading(false)\n setError(t('integrations.detail.loadError', 'Failed to load integration'))\n return\n }\n setError(null)\n setIsLoading(true)\n try {\n const call = await apiCall<IntegrationDetail>(\n `/api/integrations/${encodeURIComponent(currentIntegrationId)}`,\n undefined,\n { fallback: null },\n )\n if (!call.ok || !call.result) {\n setError(t('integrations.detail.loadError', 'Failed to load integration'))\n setIsLoading(false)\n return\n }\n setDetail(call.result)\n setIsLoading(false)\n } catch {\n setError(t('integrations.detail.loadError', 'Failed to load integration'))\n setIsLoading(false)\n }\n }, [resolveCurrentIntegrationId, t])\n\n const loadCredentials = React.useCallback(async () => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) return\n const call = await apiCall<{ credentials: Record<string, unknown> }>(\n `/api/integrations/${encodeURIComponent(currentIntegrationId)}/credentials`,\n undefined,\n { fallback: null },\n )\n if (call.ok && call.result?.credentials) {\n setCredValues(call.result.credentials)\n setCredentialsFormKey((current) => current + 1)\n }\n }, [resolveCurrentIntegrationId])\n\n const loadLogs = React.useCallback(async () => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) return\n setIsLoadingLogs(true)\n const params = new URLSearchParams({ integrationId: currentIntegrationId, pageSize: '50' })\n if (logLevel) params.set('level', logLevel)\n const call = await apiCall<{ items: LogEntry[] }>(\n `/api/integrations/logs?${params.toString()}`,\n undefined,\n { fallback: { items: [] } },\n )\n if (call.ok && call.result) {\n setLogs(call.result.items)\n }\n setIsLoadingLogs(false)\n }, [logLevel, resolveCurrentIntegrationId])\n\n const detailWidgetSpotId = React.useMemo(\n () => resolveIntegrationDetailWidgetSpotId(detail?.integration ?? null, LEGACY_INTEGRATION_DETAIL_TABS_SPOT_ID),\n [detail?.integration],\n )\n const mutationContextId = React.useMemo(\n () => `integrations.detail:${integrationId ?? 'unknown'}`,\n [integrationId],\n )\n const { runMutation, retryLastMutation } = useGuardedMutation<Record<string, unknown>>({\n contextId: mutationContextId,\n spotId: detailWidgetSpotId,\n })\n const refreshDetail = React.useCallback(async () => {\n await loadDetail()\n await loadCredentials()\n }, [loadCredentials, loadDetail])\n const refreshLogs = React.useCallback(async () => {\n await loadLogs()\n }, [loadLogs])\n const injectionContext = React.useMemo(\n () => ({\n formId: mutationContextId,\n integrationDetailWidgetSpotId: detailWidgetSpotId,\n resourceKind: 'integrations.integration',\n resourceId: integrationId ?? detail?.integration.id,\n integrationId: integrationId ?? detail?.integration.id,\n integration: detail?.integration ?? null,\n detail,\n state: detail?.state ?? null,\n credentialValues: credValues,\n latestHealthResult,\n activeTab,\n setActiveTab,\n refreshDetail,\n refreshLogs,\n retryLastMutation,\n }),\n [\n activeTab,\n credValues,\n detail,\n detailWidgetSpotId,\n integrationId,\n latestHealthResult,\n mutationContextId,\n refreshDetail,\n refreshLogs,\n retryLastMutation,\n ],\n )\n const { widgets: detailWidgets } = useInjectionWidgets(detailWidgetSpotId, {\n context: injectionContext,\n triggerOnLoad: true,\n })\n const stackedDetailWidgets = React.useMemo(\n () => filterIntegrationDetailWidgetsByKind(detailWidgets, 'stack'),\n [detailWidgets],\n )\n const groupedDetailWidgets = React.useMemo(\n () => filterIntegrationDetailWidgetsByKind(detailWidgets, 'group'),\n [detailWidgets],\n )\n const injectedTabs = React.useMemo(\n () => buildIntegrationDetailInjectedTabs(\n detailWidgets,\n (widget) => (\n widget.placement?.groupLabel\n ? t(widget.placement.groupLabel, widget.module.metadata.title ?? widget.widgetId)\n : (widget.module.metadata.title ?? widget.widgetId)\n ),\n ),\n [detailWidgets, t],\n )\n const hasDataSyncScheduleTab = Boolean(\n detail?.integration.hub === 'data_sync'\n && detail?.integration.providerKey\n && detail.integration.providerKey.trim().length > 0,\n )\n const runMutationWithContext = React.useCallback(\n async <T,>({\n operation,\n mutationPayload,\n actionId,\n tabId,\n operationType = 'update',\n }: {\n operation: () => Promise<T>\n mutationPayload?: Record<string, unknown>\n actionId: string\n tabId?: string\n operationType?: 'create' | 'update' | 'delete'\n }): Promise<T> => {\n return runMutation({\n operation,\n mutationPayload,\n context: {\n ...injectionContext,\n operation: operationType,\n actionId,\n activeTab: tabId ?? activeTab,\n },\n })\n },\n [activeTab, injectionContext, runMutation],\n )\n\n React.useEffect(() => { void loadDetail() }, [loadDetail])\n React.useEffect(() => { void loadCredentials() }, [loadCredentials])\n React.useEffect(() => { void loadLogs() }, [loadLogs])\n React.useEffect(() => {\n setExpandedLogId((current) => (current && logs.some((log) => log.id === current) ? current : null))\n }, [logs])\n\n const handleToggleState = React.useCallback(async (enabled: boolean) => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) return\n setIsTogglingState(true)\n try {\n const call = await runMutationWithContext({\n actionId: 'toggle-state',\n mutationPayload: { integrationId: currentIntegrationId, isEnabled: enabled },\n operation: () => apiCall(`/api/integrations/${encodeURIComponent(currentIntegrationId)}/state`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ isEnabled: enabled }),\n }, { fallback: null }),\n })\n if (call.ok) {\n setDetail((prev) => prev ? {\n ...prev,\n state: {\n ...prev.state,\n isEnabled: enabled,\n enabledAt: enabled ? new Date().toISOString() : prev.state.enabledAt,\n },\n } : prev)\n flash(t('integrations.detail.stateUpdated'), 'success')\n } else {\n flash(t('integrations.detail.stateError'), 'error')\n }\n } catch {\n flash(t('integrations.detail.stateError'), 'error')\n } finally {\n setIsTogglingState(false)\n }\n }, [resolveCurrentIntegrationId, runMutationWithContext, t])\n\n const handleSaveCredentials = React.useCallback(async (values: Record<string, unknown>) => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) return\n setIsSavingCredentials(true)\n try {\n const call = await runMutationWithContext({\n actionId: 'save-credentials',\n tabId: 'credentials',\n mutationPayload: { integrationId: currentIntegrationId, credentials: values },\n operation: () => apiCall(`/api/integrations/${encodeURIComponent(currentIntegrationId)}/credentials`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ credentials: values }),\n }, { fallback: null }),\n })\n\n if (call.ok) {\n setCredValues(values)\n setCredentialsFormKey((current) => current + 1)\n flash(t('integrations.detail.credentials.saved'), 'success')\n return\n }\n\n const result = call.result as {\n error?: string\n details?: { fieldErrors?: Record<string, string>; formErrors?: string[] }\n } | null\n throw createCrudFormError(\n result?.error ?? t('integrations.detail.credentials.saveError', 'Failed to save credentials'),\n result?.details?.fieldErrors,\n { details: result?.details },\n )\n } finally {\n setIsSavingCredentials(false)\n }\n }, [resolveCurrentIntegrationId, runMutationWithContext, t])\n\n const handleVersionChange = React.useCallback(async (version: string) => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) return\n try {\n const call = await runMutationWithContext({\n actionId: 'change-version',\n tabId: 'version',\n mutationPayload: { integrationId: currentIntegrationId, apiVersion: version },\n operation: () => apiCall(`/api/integrations/${encodeURIComponent(currentIntegrationId)}/version`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ apiVersion: version }),\n }, { fallback: null }),\n })\n if (call.ok) {\n setDetail((prev) => prev ? { ...prev, state: { ...prev.state, apiVersion: version } } : prev)\n flash(t('integrations.detail.version.saved'), 'success')\n } else {\n flash(t('integrations.detail.version.saveError'), 'error')\n }\n } catch {\n flash(t('integrations.detail.version.saveError'), 'error')\n }\n }, [resolveCurrentIntegrationId, runMutationWithContext, t])\n\n const handleHealthCheck = React.useCallback(async () => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) return\n setIsCheckingHealth(true)\n try {\n const call = await runMutationWithContext({\n actionId: 'run-health-check',\n tabId: 'health',\n mutationPayload: { integrationId: currentIntegrationId },\n operation: () => apiCall<HealthCheckResponse>(\n `/api/integrations/${encodeURIComponent(currentIntegrationId)}/health`,\n { method: 'POST' },\n { fallback: null },\n ),\n })\n const result = call.result\n if (call.ok && result) {\n setLatestHealthResult(result)\n setDetail((prev) => prev ? {\n ...prev,\n healthStatus: result.status,\n state: {\n ...prev.state,\n lastHealthStatus: result.status === 'unconfigured' ? prev.state.lastHealthStatus : result.status,\n lastHealthCheckedAt: result.status === 'unconfigured' ? prev.state.lastHealthCheckedAt : result.checkedAt,\n lastHealthLatencyMs: result.latencyMs ?? prev.state.lastHealthLatencyMs,\n },\n } : prev)\n void refreshLogs()\n } else {\n flash(t('integrations.detail.health.checkError'), 'error')\n }\n } catch {\n flash(t('integrations.detail.health.checkError'), 'error')\n } finally {\n setIsCheckingHealth(false)\n }\n }, [refreshLogs, resolveCurrentIntegrationId, runMutationWithContext, t])\n\n const hasVersions = Boolean(detail?.integration.apiVersions?.length)\n const integration = detail?.integration ?? null\n const state = detail?.state ?? null\n const editableCredentialFields = React.useMemo(\n () => (detail?.integration.credentials?.fields ?? detail?.bundle?.credentials?.fields ?? []).filter(isEditableCredentialField),\n [detail?.bundle?.credentials?.fields, detail?.integration.credentials?.fields],\n )\n const credentialFormFields = React.useMemo(\n () => buildCredentialFields(editableCredentialFields),\n [editableCredentialFields],\n )\n const credentialSchema = React.useMemo(() => (\n z.object({}).passthrough().superRefine((rawValues, ctx) => {\n const values = rawValues as Record<string, unknown>\n\n editableCredentialFields.forEach((field) => {\n const value = values[field.key]\n\n if (field.type === 'boolean') {\n if (value !== undefined && value !== null && typeof value !== 'boolean') {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.boolean', 'Select a valid value.'),\n })\n }\n if (field.required && typeof value !== 'boolean') {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.required', '{field} is required.', { field: field.label }),\n })\n }\n return\n }\n\n if (value !== undefined && value !== null && typeof value !== 'string') {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.text', 'Enter a valid value.'),\n })\n return\n }\n\n const normalizedValue = typeof value === 'string' ? value : ''\n\n if (field.required && normalizedValue.trim().length === 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.required', '{field} is required.', { field: field.label }),\n })\n }\n\n if (normalizedValue.length > 20_000) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.tooLong', 'Value is too long.'),\n })\n }\n\n if (\n field.type === 'select'\n && normalizedValue\n && field.options\n && !field.options.some((option) => option.value === normalizedValue)\n ) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.option', 'Select one of the available options.'),\n })\n }\n })\n })\n ) as z.ZodType<Record<string, unknown>>, [editableCredentialFields, t])\n const latestHealthLog = React.useMemo(() => logs.find(isHealthLog) ?? null, [logs])\n const healthMessage =\n latestHealthResult?.message ??\n (typeof latestHealthLog?.payload?.message === 'string' ? latestHealthLog.payload.message : null)\n const healthDetailsSource = latestHealthResult?.details ?? extractHealthDetails(latestHealthLog?.payload)\n const healthDetails = latestHealthLog?.code\n ? { ...healthDetailsSource, code: latestHealthLog.code }\n : healthDetailsSource\n const healthDetailEntries = Object.entries(healthDetails)\n const resolvedIntegration = detail?.integration ?? null\n const resolvedState = detail?.state ?? null\n const displayHealthStatus =\n latestHealthResult?.status ?? detail?.healthStatus ?? resolvedState?.lastHealthStatus ?? 'unconfigured'\n\n const healthStatusDescription = displayHealthStatus && displayHealthStatus !== 'unconfigured'\n ? t(\n `integrations.detail.health.meaning.${displayHealthStatus}`,\n displayHealthStatus === 'healthy'\n ? 'The provider responded successfully using the current credentials.'\n : displayHealthStatus === 'degraded'\n ? 'The provider responded, but reported warnings or limited functionality.'\n : integration?.id === 'gateway_stripe'\n ? 'Stripe rejected the last check. This usually means the secret key is invalid, missing required permissions, revoked, or Stripe was temporarily unavailable.'\n : 'The last check failed. This usually means invalid credentials, missing permissions, or a provider outage.',\n )\n : displayHealthStatus === 'unconfigured'\n ? t(\n 'integrations.detail.health.meaning.unconfigured',\n 'Credentials or a health check are not configured, or the integration has not been probed yet.',\n )\n : null\n\n const CategoryIcon = resolvedIntegration?.category ? CATEGORY_ICONS[resolvedIntegration.category] : null\n const HealthStatusIcon = HEALTH_STATUS_ICONS[displayHealthStatus] ?? null\n const prioritizedInjectedTabs = resolvedIntegration?.id === 'sync_akeneo'\n ? [...injectedTabs].sort((left, right) => {\n const leftPriority = isAkeneoSettingsTab(left) ? 1 : 0\n const rightPriority = isAkeneoSettingsTab(right) ? 1 : 0\n if (leftPriority !== rightPriority) return rightPriority - leftPriority\n return 0\n })\n : injectedTabs\n const leadingInjectedTab = resolvedIntegration?.id === 'sync_akeneo'\n ? prioritizedInjectedTabs.find(isAkeneoSettingsTab) ?? null\n : null\n const trailingInjectedTabs = leadingInjectedTab\n ? prioritizedInjectedTabs.filter((tab) => tab.id !== leadingInjectedTab.id)\n : prioritizedInjectedTabs\n const hiddenBuiltInTabs = new Set(resolvedIntegration?.detailPage?.hiddenTabs ?? [])\n const showCredentialsTab = !hiddenBuiltInTabs.has('credentials')\n const showVersionTab = hasVersions && !hiddenBuiltInTabs.has('version')\n const showDataSyncScheduleTab = hasDataSyncScheduleTab && !hiddenBuiltInTabs.has('data-sync-schedule')\n const showHealthTab = !hiddenBuiltInTabs.has('health')\n const showLogsTab = !hiddenBuiltInTabs.has('logs')\n const visibleTabIds = [\n ...(showCredentialsTab ? ['credentials'] : []),\n ...(leadingInjectedTab ? [leadingInjectedTab.id] : []),\n ...(showVersionTab ? ['version'] : []),\n ...(showDataSyncScheduleTab ? ['data-sync-schedule'] : []),\n ...(showHealthTab ? ['health'] : []),\n ...(showLogsTab ? ['logs'] : []),\n ...trailingInjectedTabs.map((tab) => tab.id),\n ] satisfies IntegrationDetailTab[]\n const StateIcon = resolvedState?.isEnabled ? CheckCircle2 : XCircle\n const stateBadgeClass = resolvedState?.isEnabled\n ? 'border-emerald-500/30 bg-emerald-500/10 text-emerald-300'\n : 'border-zinc-500/30 bg-zinc-500/10 text-zinc-300'\n\n const showCredentialActions = showCredentialsTab && activeTab === 'credentials' && credentialFormFields.length > 0\n\n React.useEffect(() => {\n setActiveTab(resolveRequestedIntegrationDetailTab(searchParams?.get('tab'), visibleTabIds))\n }, [searchParams, visibleTabIds])\n\n const handleTabChange = React.useCallback((nextValue: string) => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n const nextTab = resolveRequestedIntegrationDetailTab(nextValue, visibleTabIds)\n setActiveTab(nextTab)\n if (!currentIntegrationId) return\n const basePath = `/backend/integrations/${encodeURIComponent(currentIntegrationId)}`\n router.replace(nextTab === 'credentials' ? basePath : `${basePath}?tab=${encodeURIComponent(nextTab)}`)\n }, [resolveCurrentIntegrationId, router, visibleTabIds])\n\n if (isLoading) return <Page><PageBody><LoadingMessage label={t('integrations.detail.title')} /></PageBody></Page>\n if (error || !detail || !resolvedIntegration || !resolvedState) {\n return <Page><PageBody><ErrorMessage label={error ?? t('integrations.detail.loadError')} /></PageBody></Page>\n }\n\n return (\n <Page>\n <PageBody className=\"space-y-6\">\n <FormHeader\n backHref=\"/backend/integrations\"\n title={resolvedIntegration.title}\n actions={{\n cancelHref: showCredentialActions ? '/backend/integrations' : undefined,\n submit: showCredentialActions\n ? {\n formId: credentialsFormId,\n pending: isSavingCredentials,\n label: t('integrations.detail.credentials.save', 'Save credentials'),\n pendingLabel: t('ui.forms.status.saving', 'Saving...'),\n }\n : undefined,\n }}\n />\n\n <div className=\"space-y-2\">\n {resolvedIntegration.description ? (\n <p className=\"text-sm text-muted-foreground\">{resolvedIntegration.description}</p>\n ) : null}\n <div className=\"flex flex-wrap items-center gap-4 text-sm text-muted-foreground\">\n {resolvedIntegration.category ? (\n <div className=\"flex items-center gap-2\">\n {CategoryIcon ? <CategoryIcon className=\"h-4 w-4\" /> : null}\n <span>{formatTypeLabel(resolvedIntegration.category)}</span>\n </div>\n ) : null}\n {resolvedIntegration.hub ? (\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground/80\">\n {t('integrations.detail.hub.label', 'Hub')}\n </span>\n <span>{formatTypeLabel(resolvedIntegration.hub)}</span>\n </div>\n ) : null}\n </div>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">{t('integrations.detail.analytics.title')}</CardTitle>\n </CardHeader>\n <CardContent className=\"flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between\">\n <div className=\"space-y-1 text-sm text-muted-foreground\">\n <p>\n {t('integrations.detail.analytics.totalEvents', { count: detail.analytics.totalCount })}\n </p>\n <p>\n {t('integrations.detail.analytics.errorRate', {\n rate: `${Math.round(detail.analytics.errorRate * 1000) / 10}%`,\n })}\n </p>\n <p>\n {detail.analytics.lastActivityAt\n ? `${t('integrations.detail.analytics.lastActivity')}: ${new Date(detail.analytics.lastActivityAt).toLocaleString()}`\n : t('integrations.detail.analytics.never')}\n </p>\n </div>\n <DetailLogSparkline counts={detail.analytics.dailyCounts} />\n </CardContent>\n </Card>\n\n <section className=\"rounded-lg border bg-card p-4\">\n <div className=\"flex items-center justify-between gap-4\">\n <div className=\"space-y-2\">\n <p className=\"text-overline uppercase tracking-wide text-muted-foreground\">\n {t('integrations.detail.state.label', 'State')}\n </p>\n <Badge variant=\"outline\" className={cn('gap-1.5 rounded-full px-3 py-1 text-xs font-medium', stateBadgeClass)}>\n <StateIcon className=\"h-3.5 w-3.5\" />\n {resolvedState.isEnabled\n ? t('integrations.detail.state.enabled', 'Enabled')\n : t('integrations.detail.state.disabled', 'Disabled')}\n </Badge>\n </div>\n <Switch\n checked={resolvedState.isEnabled}\n disabled={isTogglingState}\n onCheckedChange={(checked) => void handleToggleState(checked)}\n />\n </div>\n </section>\n\n {stackedDetailWidgets.length > 0 ? (\n <section className=\"space-y-4\">\n <InjectionSpot\n spotId={detailWidgetSpotId}\n context={injectionContext}\n data={detail}\n onDataChange={(next) => setDetail(next as IntegrationDetail)}\n widgetsOverride={stackedDetailWidgets}\n />\n </section>\n ) : null}\n\n {groupedDetailWidgets.length > 0 ? (\n <section className=\"grid gap-4 lg:grid-cols-2\">\n {groupedDetailWidgets.map((widget) => (\n <Card\n key={widget.widgetId}\n className={widget.placement?.column === 2 ? 'lg:col-start-2' : undefined}\n >\n <CardHeader>\n <CardTitle>\n {widget.placement?.groupLabel\n ? t(widget.placement.groupLabel, widget.module.metadata.title)\n : widget.module.metadata.title}\n </CardTitle>\n {widget.placement?.groupDescription ? (\n <p className=\"text-sm text-muted-foreground\">\n {widget.placement.groupDescription}\n </p>\n ) : null}\n </CardHeader>\n <CardContent>\n <widget.module.Widget\n context={injectionContext}\n data={detail}\n onDataChange={(next) => setDetail(next as IntegrationDetail)}\n />\n </CardContent>\n </Card>\n ))}\n </section>\n ) : null}\n\n <Tabs value={activeTab} onValueChange={handleTabChange} className=\"space-y-5\">\n <TabsList className=\"h-auto w-full justify-start overflow-x-auto rounded-none border-b border-border bg-transparent p-0\">\n {showCredentialsTab ? (\n <TabsTrigger\n value=\"credentials\"\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-foreground aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <Key className=\"h-4 w-4\" />\n <span>{t('integrations.detail.tabs.credentials')}</span>\n </span>\n </TabsTrigger>\n ) : null}\n {leadingInjectedTab ? (\n <TabsTrigger\n value={leadingInjectedTab.id}\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-foreground aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <Settings className=\"h-4 w-4\" />\n <span>{leadingInjectedTab.label}</span>\n </span>\n </TabsTrigger>\n ) : null}\n {showVersionTab ? (\n <TabsTrigger\n value=\"version\"\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-foreground aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <RefreshCw className=\"h-4 w-4\" />\n <span>{t('integrations.detail.tabs.version')}</span>\n </span>\n </TabsTrigger>\n ) : null}\n {showDataSyncScheduleTab ? (\n <TabsTrigger\n value=\"data-sync-schedule\"\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-foreground aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <Calendar className=\"h-4 w-4\" />\n <span>{t('data_sync.integrationTab.title', 'Sync schedules')}</span>\n </span>\n </TabsTrigger>\n ) : null}\n {showHealthTab ? (\n <TabsTrigger\n value=\"health\"\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-foreground aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <Activity className=\"h-4 w-4\" />\n <span>{t('integrations.detail.tabs.health')}</span>\n </span>\n </TabsTrigger>\n ) : null}\n {showLogsTab ? (\n <TabsTrigger\n value=\"logs\"\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-foreground aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <FileText className=\"h-4 w-4\" />\n <span>{t('integrations.detail.tabs.logs')}</span>\n </span>\n </TabsTrigger>\n ) : null}\n {trailingInjectedTabs.map((tab) => (\n <TabsTrigger\n key={tab.id}\n value={tab.id}\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-foreground aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <Settings className=\"h-4 w-4\" />\n <span>{tab.label}</span>\n </span>\n </TabsTrigger>\n ))}\n </TabsList>\n\n {showCredentialsTab ? (\n <TabsContent value=\"credentials\" className=\"mt-0\">\n <section className=\"space-y-4 rounded-lg border bg-card p-6\">\n {detail.bundle ? (\n <div className=\"rounded-lg border border-blue-200 bg-blue-50 p-3 text-sm text-blue-800\">\n {t('integrations.detail.credentials.bundleShared', { bundle: detail.bundle.title })}\n </div>\n ) : null}\n {credentialFormFields.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('integrations.detail.credentials.notConfigured')}\n </p>\n ) : (\n <CrudForm<Record<string, unknown>>\n key={`${resolvedIntegration.id}:${credentialsFormKey}`}\n formId={credentialsFormId}\n entityId=\"integrations.integration\"\n schema={credentialSchema}\n fields={credentialFormFields}\n initialValues={credValues}\n onSubmit={handleSaveCredentials}\n embedded\n hideFooterActions\n />\n )}\n </section>\n </TabsContent>\n ) : null}\n\n {showVersionTab ? (\n <TabsContent value=\"version\" className=\"mt-0 space-y-4\">\n <Card>\n <CardHeader>\n <CardTitle>{t('integrations.detail.version.select')}</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {resolvedIntegration.apiVersions?.map((version) => {\n const stableVersion = resolvedIntegration.apiVersions?.find((item) => item.status === 'stable')?.id\n const isSelected = (resolvedState.apiVersion ?? stableVersion) === version.id\n return (\n <div\n key={version.id}\n className={`flex cursor-pointer items-center justify-between rounded-lg border p-3 transition-colors ${isSelected ? 'border-primary bg-primary/5' : 'hover:bg-muted/50'}`}\n onClick={() => void handleVersionChange(version.id)}\n >\n <div>\n <span className=\"text-sm font-medium\">{version.label ?? version.id}</span>\n <Badge\n variant={version.status === 'stable' ? 'default' : version.status === 'deprecated' ? 'destructive' : 'secondary'}\n className=\"ml-2\"\n >\n {t(`integrations.detail.version.${version.status}`)}\n </Badge>\n {version.status === 'deprecated' && version.sunsetAt ? (\n <span className=\"ml-2 text-xs text-muted-foreground\">\n {t('integrations.detail.version.sunsetAt', { date: new Date(version.sunsetAt).toLocaleDateString() })}\n </span>\n ) : null}\n </div>\n {isSelected ? <Badge variant=\"outline\">{t('integrations.detail.version.current')}</Badge> : null}\n </div>\n )\n })}\n </CardContent>\n </Card>\n </TabsContent>\n ) : null}\n\n {showDataSyncScheduleTab ? (\n <TabsContent value=\"data-sync-schedule\" className=\"mt-0\">\n <IntegrationScheduleTab\n integrationId={resolvedIntegration.id}\n hasCredentials={detail.hasCredentials}\n isEnabled={resolvedState.isEnabled}\n />\n </TabsContent>\n ) : null}\n\n {showHealthTab ? (\n <TabsContent value=\"health\" className=\"mt-0 space-y-4\">\n <Card className=\"gap-4 py-4\">\n <CardHeader className=\"px-5\">\n <div className=\"flex items-center justify-between\">\n <CardTitle>{t('integrations.detail.health.title')}</CardTitle>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void handleHealthCheck()}\n disabled={isCheckingHealth}\n >\n {isCheckingHealth ? <Spinner className=\"mr-2 h-4 w-4\" /> : <Zap className=\"mr-2 h-4 w-4\" />}\n {isCheckingHealth ? t('integrations.detail.health.checking') : t('integrations.detail.health.check')}\n </Button>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3 px-5\">\n <div className=\"flex flex-wrap items-center gap-3 rounded-lg border bg-muted/20 px-4 py-3\">\n {displayHealthStatus ? (\n <Badge className={`gap-1.5 ${HEALTH_STATUS_STYLES[displayHealthStatus] ?? ''}`}>\n {HealthStatusIcon ? <HealthStatusIcon className=\"h-3.5 w-3.5\" /> : null}\n {t(`integrations.detail.health.${displayHealthStatus}`)}\n </Badge>\n ) : (\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <AlertTriangle className=\"h-4 w-4\" />\n <span>{t('integrations.detail.health.unknown')}</span>\n </div>\n )}\n {healthStatusDescription ? (\n <p className=\"min-w-0 flex-1 text-sm text-muted-foreground\">{healthStatusDescription}</p>\n ) : null}\n <p className=\"text-xs text-muted-foreground md:ml-auto\">\n {resolvedState.lastHealthCheckedAt\n ? t('integrations.detail.health.lastChecked', { date: new Date(resolvedState.lastHealthCheckedAt).toLocaleString() })\n : t('integrations.detail.health.neverChecked')\n }\n </p>\n </div>\n {healthMessage || healthDetailEntries.length > 0 ? (\n <div className={`grid gap-3 ${healthMessage && healthDetailEntries.length > 0 ? 'xl:grid-cols-[minmax(0,1.25fr)_minmax(0,1fr)]' : ''}`}>\n {healthMessage ? (\n <div className=\"rounded-lg border px-4 py-3\">\n <p className=\"text-overline font-medium uppercase tracking-widest text-muted-foreground\">\n {t('integrations.detail.health.lastResult', 'Last result')}\n </p>\n <p className=\"mt-1.5 text-sm\">{healthMessage}</p>\n </div>\n ) : null}\n {healthDetailEntries.length > 0 ? (\n <div className=\"rounded-lg border px-4 py-3\">\n <p className=\"text-overline font-medium uppercase tracking-widest text-muted-foreground\">\n {t('integrations.detail.health.details', 'Details')}\n </p>\n <dl className=\"mt-2 grid gap-x-6 gap-y-2 sm:grid-cols-2\">\n {healthDetailEntries.map(([key, value]) => (\n <div key={key}>\n <dt className=\"text-xs font-medium text-muted-foreground\">{formatLogDetailLabel(key)}</dt>\n <dd className=\"mt-0.5 text-sm\">{formatHealthValue(value)}</dd>\n </div>\n ))}\n </dl>\n </div>\n ) : null}\n </div>\n ) : null}\n </CardContent>\n </Card>\n </TabsContent>\n ) : null}\n\n {showLogsTab ? (\n <TabsContent value=\"logs\" className=\"mt-0 space-y-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"relative inline-flex\">\n <select\n className=\"h-11 min-w-40 appearance-none rounded-xl border border-border bg-card pl-4 pr-11 text-sm font-medium text-foreground shadow-sm transition-colors focus-visible:border-ring focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/30\"\n value={logLevel}\n onChange={(event) => setLogLevel(event.target.value)}\n >\n <option value=\"\">{t('integrations.detail.logs.level.all')}</option>\n <option value=\"info\">{t('integrations.detail.logs.level.info')}</option>\n <option value=\"warn\">{t('integrations.detail.logs.level.warn')}</option>\n <option value=\"error\">{t('integrations.detail.logs.level.error')}</option>\n </select>\n <ChevronDown className=\"pointer-events-none absolute right-4 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground\" />\n </div>\n </div>\n {isLoadingLogs ? (\n <div className=\"flex justify-center py-8\"><Spinner /></div>\n ) : logs.length === 0 ? (\n <p className=\"py-4 text-sm text-muted-foreground\">{t('integrations.detail.logs.empty')}</p>\n ) : (\n <div className=\"rounded-lg border\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b bg-muted/50\">\n <th className=\"px-4 py-2 text-left font-medium\">{t('integrations.detail.logs.columns.time')}</th>\n <th className=\"px-4 py-2 text-left font-medium\">{t('integrations.detail.logs.columns.level')}</th>\n <th className=\"px-4 py-2 text-left font-medium\">{t('integrations.detail.logs.columns.message')}</th>\n </tr>\n </thead>\n <tbody>\n {logs.map((log) => {\n const isExpanded = expandedLogId === log.id\n const metadataEntries = [\n ['Time', new Date(log.createdAt).toLocaleString()],\n ['Level', log.level],\n ['Code', log.code ?? null],\n ['Run ID', log.runId ?? null],\n ['Entity Type', log.scopeEntityType ?? null],\n ['Entity ID', log.scopeEntityId ?? null],\n ].filter((entry): entry is [string, string] => typeof entry[1] === 'string' && entry[1].trim().length > 0)\n const { inlineEntries, nestedEntries } = splitLogPayload(log.payload)\n\n return (\n <React.Fragment key={log.id}>\n <tr className=\"border-b last:border-0\">\n <td className=\"whitespace-nowrap px-4 py-2 text-muted-foreground\">\n {new Date(log.createdAt).toLocaleString()}\n </td>\n <td className=\"px-4 py-2\">\n <Badge variant=\"secondary\" className={LOG_LEVEL_STYLES[log.level] ?? ''}>\n {log.level}\n </Badge>\n </td>\n <td className=\"px-4 py-2\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-auto w-full justify-start gap-2 px-0 py-0 text-left hover:bg-transparent\"\n onClick={() => setExpandedLogId((current) => (current === log.id ? null : log.id))}\n >\n {isExpanded ? <ChevronDown className=\"h-4 w-4 shrink-0\" /> : <ChevronRight className=\"h-4 w-4 shrink-0\" />}\n <span className=\"truncate\">{log.message}</span>\n </Button>\n </td>\n </tr>\n {isExpanded ? (\n <tr className=\"border-b bg-muted/30 last:border-0\">\n <td colSpan={3} className=\"px-4 py-4\">\n <div className=\"space-y-4 rounded-lg border bg-card p-4\">\n <div className=\"grid gap-4 lg:grid-cols-[minmax(0,1.1fr)_minmax(0,0.9fr)]\">\n <div className=\"space-y-4\">\n <section className=\"space-y-3\">\n <div>\n <p className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground\">\n {t('integrations.detail.logs.details.summary', 'Summary')}\n </p>\n <p className=\"mt-1 text-sm font-medium\">{log.message}</p>\n </div>\n {metadataEntries.length > 0 ? (\n <dl className=\"grid gap-3 sm:grid-cols-2\">\n {metadataEntries.map(([label, value]) => (\n <div key={label} className=\"rounded-md border bg-muted/30 px-3 py-2\">\n <dt className=\"text-overline font-medium uppercase tracking-wide text-muted-foreground\">\n {label}\n </dt>\n <dd className=\"mt-1 break-all text-sm\">{value}</dd>\n </div>\n ))}\n </dl>\n ) : null}\n </section>\n\n {inlineEntries.length > 0 ? (\n <section className=\"space-y-3\">\n <p className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground\">\n {t('integrations.detail.logs.details.fields', 'Fields')}\n </p>\n <dl className=\"grid gap-3 sm:grid-cols-2\">\n {inlineEntries.map(([key, value]) => (\n <div key={key} className=\"rounded-md border bg-muted/30 px-3 py-2\">\n <dt className=\"text-overline font-medium uppercase tracking-wide text-muted-foreground\">\n {formatLogDetailLabel(key)}\n </dt>\n <dd className=\"mt-1 break-words text-sm\">\n {formatLogPrimitiveValue(value)}\n </dd>\n </div>\n ))}\n </dl>\n </section>\n ) : null}\n </div>\n\n <div className=\"space-y-3\">\n {nestedEntries.map(([key, value]) => (\n <JsonDisplay\n key={key}\n data={value}\n title={formatLogDetailLabel(key)}\n defaultExpanded\n maxInitialDepth={1}\n theme=\"dark\"\n maxHeight=\"16rem\"\n className=\"p-4\"\n />\n ))}\n {log.payload && nestedEntries.length === 0 ? (\n <JsonDisplay\n data={log.payload}\n title={t('integrations.detail.logs.details.payload', 'Payload')}\n defaultExpanded\n maxInitialDepth={1}\n theme=\"dark\"\n maxHeight=\"16rem\"\n className=\"p-4\"\n />\n ) : null}\n {!log.payload ? (\n <div className=\"rounded-lg border border-dashed px-4 py-6 text-sm text-muted-foreground\">\n {t('integrations.detail.logs.details.noPayload', 'No structured payload was stored for this log entry.')}\n </div>\n ) : null}\n </div>\n </div>\n </div>\n </td>\n </tr>\n ) : null}\n </React.Fragment>\n )\n })}\n </tbody>\n </table>\n </div>\n )}\n </TabsContent>\n ) : null}\n\n {injectedTabs.map((tab) => (\n <TabsContent key={tab.id} value={tab.id} className=\"mt-0 space-y-4\">\n <InjectionSpot\n spotId={detailWidgetSpotId}\n context={injectionContext}\n data={detail}\n onDataChange={(next) => setDetail(next as IntegrationDetail)}\n widgetsOverride={tab.widgets}\n />\n </TabsContent>\n ))}\n </Tabs>\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { usePathname, useRouter, useSearchParams } from 'next/navigation'\nimport { z } from 'zod'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CrudForm, type CrudField } from '@open-mercato/ui/backend/CrudForm'\nimport { WebhookSetupGuide } from '@open-mercato/ui/backend/WebhookSetupGuide'\nimport { InjectionSpot, useInjectionWidgets } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { FormHeader } from '@open-mercato/ui/backend/forms'\nimport { Card, CardHeader, CardTitle, CardContent } from '@open-mercato/ui/primitives/card'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { Switch } from '@open-mercato/ui/primitives/switch'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from '@open-mercato/ui/primitives/tabs'\nimport { JsonDisplay } from '@open-mercato/ui/backend/JsonDisplay'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport {\n LEGACY_INTEGRATION_DETAIL_TABS_SPOT_ID,\n type CredentialFieldType,\n type IntegrationCredentialField,\n type IntegrationDetailBuiltInTab,\n} from '@open-mercato/shared/modules/integrations/types'\nimport { LoadingMessage, ErrorMessage } from '@open-mercato/ui/backend/detail'\nimport { Activity, AlertTriangle, Bell, Calendar, CheckCircle2, ChevronDown, ChevronRight, CreditCard, FileText, HardDrive, Key, MessageSquare, RefreshCw, Settings, Truck, Webhook, XCircle, Zap } from 'lucide-react'\nimport { IntegrationScheduleTab } from '../../../../data_sync/components/IntegrationScheduleTab'\nimport {\n buildIntegrationDetailInjectedTabs,\n filterIntegrationDetailWidgetsByKind,\n type IntegrationDetailInjectedTab,\n resolveIntegrationDetailWidgetSpotId,\n resolveRequestedIntegrationDetailTab,\n} from '../detail-page-widgets'\n\ntype CredentialField = IntegrationCredentialField\ntype BuiltInIntegrationDetailTab = 'credentials' | 'version' | 'health' | 'logs' | 'data-sync-schedule'\ntype IntegrationDetailTab = BuiltInIntegrationDetailTab | string\n\nconst UNSUPPORTED_CREDENTIAL_FIELD_TYPES = new Set<CredentialFieldType>(['oauth', 'ssh_keypair'])\n\nfunction isEditableCredentialField(field: CredentialField): boolean {\n return !UNSUPPORTED_CREDENTIAL_FIELD_TYPES.has(field.type)\n}\n\ntype ApiVersion = {\n id: string\n label?: string\n status: 'stable' | 'deprecated' | 'experimental'\n sunsetAt?: string\n migrationGuide?: string\n}\n\ntype IntegrationLogAnalytics = {\n lastActivityAt: string | null\n totalCount: number\n errorCount: number\n errorRate: number\n dailyCounts: number[]\n}\n\ntype IntegrationDetail = {\n integration: {\n id: string\n title: string\n description?: string\n category?: string\n hub?: string\n providerKey?: string | null\n bundleId?: string\n docsUrl?: string\n apiVersions?: ApiVersion[]\n detailPage?: {\n widgetSpotId?: string\n hiddenTabs?: IntegrationDetailBuiltInTab[]\n }\n credentials?: { fields: CredentialField[] }\n }\n bundle?: { id: string; title: string; credentials?: { fields: CredentialField[] } }\n state: {\n isEnabled: boolean\n apiVersion: string | null\n reauthRequired: boolean\n lastHealthStatus: string | null\n lastHealthCheckedAt: string | null\n lastHealthLatencyMs: number | null\n enabledAt: string | null\n }\n hasCredentials: boolean\n healthStatus: 'healthy' | 'degraded' | 'unhealthy' | 'unconfigured'\n analytics: IntegrationLogAnalytics\n}\n\ntype LogEntry = {\n id: string\n runId?: string | null\n scopeEntityType?: string | null\n scopeEntityId?: string | null\n level: 'info' | 'warn' | 'error'\n message: string\n createdAt: string\n code?: string | null\n payload?: Record<string, unknown> | null\n}\n\ntype IntegrationDetailPageProps = {\n params?: {\n id?: string | string[]\n }\n}\n\ntype HealthCheckResponse = {\n status: 'healthy' | 'degraded' | 'unhealthy' | 'unconfigured'\n message: string | null\n details: Record<string, unknown> | null\n checkedAt: string\n latencyMs: number | null\n}\n\nconst LOG_LEVEL_STYLES: Record<string, string> = {\n info: 'bg-blue-100 text-blue-800',\n warn: 'bg-yellow-100 text-yellow-800',\n error: 'bg-red-100 text-red-800',\n}\n\nconst HEALTH_STATUS_STYLES: Record<string, string> = {\n healthy: 'bg-green-100 text-green-800',\n degraded: 'bg-yellow-100 text-yellow-800',\n unhealthy: 'bg-red-100 text-red-800',\n unconfigured: 'bg-zinc-100 text-zinc-700',\n}\n\nconst HEALTH_STATUS_ICONS: Record<string, React.ElementType> = {\n healthy: CheckCircle2,\n degraded: AlertTriangle,\n unhealthy: XCircle,\n unconfigured: AlertTriangle,\n}\n\nfunction DetailLogSparkline({ counts, className }: { counts: number[]; className?: string }) {\n const max = Math.max(1, ...counts)\n const w = 120\n const h = 36\n const step = counts.length > 1 ? w / (counts.length - 1) : w\n const points = counts.map((count, index) => {\n const x = index * step\n const y = h - (count / max) * (h - 4) - 2\n return `${x},${y}`\n }).join(' ')\n return (\n <svg width={w} height={h} className={className} aria-hidden>\n <polyline\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n points={points}\n className=\"text-muted-foreground/80\"\n />\n </svg>\n )\n}\n\nconst CATEGORY_ICONS: Record<string, React.ElementType> = {\n payment: CreditCard,\n shipping: Truck,\n data_sync: RefreshCw,\n communication: MessageSquare,\n notification: Bell,\n storage: HardDrive,\n webhook: Webhook,\n}\n\nfunction resolveRouteId(value: string | string[] | undefined): string | undefined {\n if (Array.isArray(value)) return value[0]\n return value\n}\n\nfunction resolvePathnameId(pathname: string): string | undefined {\n const parts = pathname.split('/').filter(Boolean)\n const integrationId = parts.at(-1)\n if (!integrationId || integrationId === 'integrations' || integrationId === 'bundle') return undefined\n return decodeURIComponent(integrationId)\n}\n\nfunction buildCredentialFields(credFields: CredentialField[]): CrudField[] {\n return credFields.map((field) => {\n const shared = {\n id: field.key,\n label: field.label,\n description: field.helpDetails ? (\n <div className=\"space-y-1\">\n {field.helpText ? <div>{field.helpText}</div> : null}\n <WebhookSetupGuide guide={field.helpDetails} buttonLabel=\"Show details\" />\n </div>\n ) : field.helpText,\n placeholder: field.placeholder,\n required: field.required,\n }\n\n if (field.type === 'secret') {\n return {\n ...shared,\n type: 'custom' as const,\n component: ({ id, value, setValue, disabled }) => (\n <Input\n id={id}\n type=\"password\"\n placeholder={field.placeholder}\n value={typeof value === 'string' ? value : ''}\n onChange={(event) => setValue(event.target.value)}\n disabled={disabled}\n />\n ),\n }\n }\n\n if (field.type === 'select' && field.options) {\n return {\n ...shared,\n type: 'select' as const,\n options: field.options,\n }\n }\n\n if (field.type === 'boolean') {\n return {\n ...shared,\n type: 'checkbox' as const,\n }\n }\n\n return {\n ...shared,\n type: 'text' as const,\n }\n })\n}\n\nfunction isHealthLog(log: LogEntry): boolean {\n return log.message === 'Health check passed' || log.message.startsWith('Health check:')\n}\n\nfunction extractHealthDetails(payload: Record<string, unknown> | null | undefined): Record<string, unknown> {\n if (!payload) return {}\n return Object.fromEntries(\n Object.entries(payload).filter(([key, value]) => key !== 'status' && key !== 'message' && value !== undefined && value !== null),\n )\n}\n\nfunction formatHealthValue(value: unknown): string {\n if (typeof value === 'boolean') return value ? 'Yes' : 'No'\n if (typeof value === 'string') return value\n if (typeof value === 'number') return String(value)\n if (value instanceof Date) return value.toLocaleString()\n return JSON.stringify(value)\n}\n\nfunction formatTypeLabel(value: string): string {\n return value.split('_').filter(Boolean).map((part) => part[0]?.toUpperCase() + part.slice(1)).join(' ')\n}\n\nfunction isPrimitiveLogValue(value: unknown): value is string | number | boolean | null {\n return value === null || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean'\n}\n\nfunction formatLogDetailLabel(key: string): string {\n return key\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/[_-]+/g, ' ')\n .split(' ')\n .filter(Boolean)\n .map((part) => part[0]?.toUpperCase() + part.slice(1))\n .join(' ')\n}\n\nfunction formatLogPrimitiveValue(value: string | number | boolean | null): string {\n if (value === null) return 'None'\n if (typeof value === 'boolean') return value ? 'Yes' : 'No'\n return String(value)\n}\n\nfunction isAkeneoSettingsTab(tab: IntegrationDetailInjectedTab): boolean {\n return tab.id.includes('sync_akeneo') || tab.label.toLowerCase().includes('akeneo')\n}\n\nfunction splitLogPayload(payload: Record<string, unknown> | null | undefined) {\n if (!payload) {\n return {\n inlineEntries: [] as Array<[string, string | number | boolean | null]>,\n nestedEntries: [] as Array<[string, unknown]>,\n }\n }\n\n const inlineEntries: Array<[string, string | number | boolean | null]> = []\n const nestedEntries: Array<[string, unknown]> = []\n\n Object.entries(payload).forEach(([key, value]) => {\n if (isPrimitiveLogValue(value)) {\n inlineEntries.push([key, value])\n return\n }\n nestedEntries.push([key, value])\n })\n\n return { inlineEntries, nestedEntries }\n}\n\nexport default function IntegrationDetailPage({ params }: IntegrationDetailPageProps) {\n const pathname = usePathname()\n const router = useRouter()\n const searchParams = useSearchParams()\n const integrationId = resolveRouteId(params?.id) ?? resolvePathnameId(pathname)\n const t = useT()\n\n const [detail, setDetail] = React.useState<IntegrationDetail | null>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n\n const [credValues, setCredValues] = React.useState<Record<string, unknown>>({})\n const [credentialsFormKey, setCredentialsFormKey] = React.useState(0)\n const [isSavingCredentials, setIsSavingCredentials] = React.useState(false)\n\n const [logs, setLogs] = React.useState<LogEntry[]>([])\n const [logLevel, setLogLevel] = React.useState<string>('')\n const [isLoadingLogs, setIsLoadingLogs] = React.useState(false)\n const [expandedLogId, setExpandedLogId] = React.useState<string | null>(null)\n\n const [isCheckingHealth, setIsCheckingHealth] = React.useState(false)\n const [isTogglingState, setIsTogglingState] = React.useState(false)\n const [latestHealthResult, setLatestHealthResult] = React.useState<HealthCheckResponse | null>(null)\n const [activeTab, setActiveTab] = React.useState<IntegrationDetailTab>('credentials')\n\n const credentialsFormId = React.useId()\n\n const resolveCurrentIntegrationId = React.useCallback(() => {\n return integrationId ?? (\n typeof window !== 'undefined'\n ? resolvePathnameId(window.location.pathname)\n : undefined\n )\n }, [integrationId])\n\n const loadDetail = React.useCallback(async () => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) {\n setIsLoading(false)\n setError(t('integrations.detail.loadError', 'Failed to load integration'))\n return\n }\n setError(null)\n setIsLoading(true)\n try {\n const call = await apiCall<IntegrationDetail>(\n `/api/integrations/${encodeURIComponent(currentIntegrationId)}`,\n undefined,\n { fallback: null },\n )\n if (!call.ok || !call.result) {\n setError(t('integrations.detail.loadError', 'Failed to load integration'))\n setIsLoading(false)\n return\n }\n setDetail(call.result)\n setIsLoading(false)\n } catch {\n setError(t('integrations.detail.loadError', 'Failed to load integration'))\n setIsLoading(false)\n }\n }, [resolveCurrentIntegrationId, t])\n\n const loadCredentials = React.useCallback(async () => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) return\n const call = await apiCall<{ credentials: Record<string, unknown> }>(\n `/api/integrations/${encodeURIComponent(currentIntegrationId)}/credentials`,\n undefined,\n { fallback: null },\n )\n if (call.ok && call.result?.credentials) {\n setCredValues(call.result.credentials)\n setCredentialsFormKey((current) => current + 1)\n }\n }, [resolveCurrentIntegrationId])\n\n const loadLogs = React.useCallback(async () => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) return\n setIsLoadingLogs(true)\n const params = new URLSearchParams({ integrationId: currentIntegrationId, pageSize: '50' })\n if (logLevel) params.set('level', logLevel)\n const call = await apiCall<{ items: LogEntry[] }>(\n `/api/integrations/logs?${params.toString()}`,\n undefined,\n { fallback: { items: [] } },\n )\n if (call.ok && call.result) {\n setLogs(call.result.items)\n }\n setIsLoadingLogs(false)\n }, [logLevel, resolveCurrentIntegrationId])\n\n const detailWidgetSpotId = React.useMemo(\n () => resolveIntegrationDetailWidgetSpotId(detail?.integration ?? null, LEGACY_INTEGRATION_DETAIL_TABS_SPOT_ID),\n [detail?.integration],\n )\n const mutationContextId = React.useMemo(\n () => `integrations.detail:${integrationId ?? 'unknown'}`,\n [integrationId],\n )\n const { runMutation, retryLastMutation } = useGuardedMutation<Record<string, unknown>>({\n contextId: mutationContextId,\n spotId: detailWidgetSpotId,\n })\n const refreshDetail = React.useCallback(async () => {\n await loadDetail()\n await loadCredentials()\n }, [loadCredentials, loadDetail])\n const refreshLogs = React.useCallback(async () => {\n await loadLogs()\n }, [loadLogs])\n const injectionContext = React.useMemo(\n () => ({\n formId: mutationContextId,\n integrationDetailWidgetSpotId: detailWidgetSpotId,\n resourceKind: 'integrations.integration',\n resourceId: integrationId ?? detail?.integration.id,\n integrationId: integrationId ?? detail?.integration.id,\n integration: detail?.integration ?? null,\n detail,\n state: detail?.state ?? null,\n credentialValues: credValues,\n latestHealthResult,\n activeTab,\n setActiveTab,\n refreshDetail,\n refreshLogs,\n retryLastMutation,\n }),\n [\n activeTab,\n credValues,\n detail,\n detailWidgetSpotId,\n integrationId,\n latestHealthResult,\n mutationContextId,\n refreshDetail,\n refreshLogs,\n retryLastMutation,\n ],\n )\n const { widgets: detailWidgets } = useInjectionWidgets(detailWidgetSpotId, {\n context: injectionContext,\n triggerOnLoad: true,\n })\n const stackedDetailWidgets = React.useMemo(\n () => filterIntegrationDetailWidgetsByKind(detailWidgets, 'stack'),\n [detailWidgets],\n )\n const groupedDetailWidgets = React.useMemo(\n () => filterIntegrationDetailWidgetsByKind(detailWidgets, 'group'),\n [detailWidgets],\n )\n const injectedTabs = React.useMemo(\n () => buildIntegrationDetailInjectedTabs(\n detailWidgets,\n (widget) => (\n widget.placement?.groupLabel\n ? t(widget.placement.groupLabel, widget.module.metadata.title ?? widget.widgetId)\n : (widget.module.metadata.title ?? widget.widgetId)\n ),\n ),\n [detailWidgets, t],\n )\n const hasDataSyncScheduleTab = Boolean(\n detail?.integration.hub === 'data_sync'\n && detail?.integration.providerKey\n && detail.integration.providerKey.trim().length > 0,\n )\n const runMutationWithContext = React.useCallback(\n async <T,>({\n operation,\n mutationPayload,\n actionId,\n tabId,\n operationType = 'update',\n }: {\n operation: () => Promise<T>\n mutationPayload?: Record<string, unknown>\n actionId: string\n tabId?: string\n operationType?: 'create' | 'update' | 'delete'\n }): Promise<T> => {\n return runMutation({\n operation,\n mutationPayload,\n context: {\n ...injectionContext,\n operation: operationType,\n actionId,\n activeTab: tabId ?? activeTab,\n },\n })\n },\n [activeTab, injectionContext, runMutation],\n )\n\n React.useEffect(() => { void loadDetail() }, [loadDetail])\n React.useEffect(() => { void loadCredentials() }, [loadCredentials])\n React.useEffect(() => { void loadLogs() }, [loadLogs])\n React.useEffect(() => {\n setExpandedLogId((current) => (current && logs.some((log) => log.id === current) ? current : null))\n }, [logs])\n\n const handleToggleState = React.useCallback(async (enabled: boolean) => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) return\n setIsTogglingState(true)\n try {\n const call = await runMutationWithContext({\n actionId: 'toggle-state',\n mutationPayload: { integrationId: currentIntegrationId, isEnabled: enabled },\n operation: () => apiCall(`/api/integrations/${encodeURIComponent(currentIntegrationId)}/state`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ isEnabled: enabled }),\n }, { fallback: null }),\n })\n if (call.ok) {\n setDetail((prev) => prev ? {\n ...prev,\n state: {\n ...prev.state,\n isEnabled: enabled,\n enabledAt: enabled ? new Date().toISOString() : prev.state.enabledAt,\n },\n } : prev)\n flash(t('integrations.detail.stateUpdated'), 'success')\n } else {\n flash(t('integrations.detail.stateError'), 'error')\n }\n } catch {\n flash(t('integrations.detail.stateError'), 'error')\n } finally {\n setIsTogglingState(false)\n }\n }, [resolveCurrentIntegrationId, runMutationWithContext, t])\n\n const handleSaveCredentials = React.useCallback(async (values: Record<string, unknown>) => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) return\n setIsSavingCredentials(true)\n try {\n const call = await runMutationWithContext({\n actionId: 'save-credentials',\n tabId: 'credentials',\n mutationPayload: { integrationId: currentIntegrationId, credentials: values },\n operation: () => apiCall(`/api/integrations/${encodeURIComponent(currentIntegrationId)}/credentials`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ credentials: values }),\n }, { fallback: null }),\n })\n\n if (call.ok) {\n setCredValues(values)\n setCredentialsFormKey((current) => current + 1)\n flash(t('integrations.detail.credentials.saved'), 'success')\n return\n }\n\n const result = call.result as {\n error?: string\n details?: { fieldErrors?: Record<string, string>; formErrors?: string[] }\n } | null\n throw createCrudFormError(\n result?.error ?? t('integrations.detail.credentials.saveError', 'Failed to save credentials'),\n result?.details?.fieldErrors,\n { details: result?.details },\n )\n } finally {\n setIsSavingCredentials(false)\n }\n }, [resolveCurrentIntegrationId, runMutationWithContext, t])\n\n const handleVersionChange = React.useCallback(async (version: string) => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) return\n try {\n const call = await runMutationWithContext({\n actionId: 'change-version',\n tabId: 'version',\n mutationPayload: { integrationId: currentIntegrationId, apiVersion: version },\n operation: () => apiCall(`/api/integrations/${encodeURIComponent(currentIntegrationId)}/version`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ apiVersion: version }),\n }, { fallback: null }),\n })\n if (call.ok) {\n setDetail((prev) => prev ? { ...prev, state: { ...prev.state, apiVersion: version } } : prev)\n flash(t('integrations.detail.version.saved'), 'success')\n } else {\n flash(t('integrations.detail.version.saveError'), 'error')\n }\n } catch {\n flash(t('integrations.detail.version.saveError'), 'error')\n }\n }, [resolveCurrentIntegrationId, runMutationWithContext, t])\n\n const handleHealthCheck = React.useCallback(async () => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) return\n setIsCheckingHealth(true)\n try {\n const call = await runMutationWithContext({\n actionId: 'run-health-check',\n tabId: 'health',\n mutationPayload: { integrationId: currentIntegrationId },\n operation: () => apiCall<HealthCheckResponse>(\n `/api/integrations/${encodeURIComponent(currentIntegrationId)}/health`,\n { method: 'POST' },\n { fallback: null },\n ),\n })\n const result = call.result\n if (call.ok && result) {\n setLatestHealthResult(result)\n setDetail((prev) => prev ? {\n ...prev,\n healthStatus: result.status,\n state: {\n ...prev.state,\n lastHealthStatus: result.status === 'unconfigured' ? prev.state.lastHealthStatus : result.status,\n lastHealthCheckedAt: result.status === 'unconfigured' ? prev.state.lastHealthCheckedAt : result.checkedAt,\n lastHealthLatencyMs: result.latencyMs ?? prev.state.lastHealthLatencyMs,\n },\n } : prev)\n void refreshLogs()\n } else {\n flash(t('integrations.detail.health.checkError'), 'error')\n }\n } catch {\n flash(t('integrations.detail.health.checkError'), 'error')\n } finally {\n setIsCheckingHealth(false)\n }\n }, [refreshLogs, resolveCurrentIntegrationId, runMutationWithContext, t])\n\n const hasVersions = Boolean(detail?.integration.apiVersions?.length)\n const integration = detail?.integration ?? null\n const state = detail?.state ?? null\n const editableCredentialFields = React.useMemo(\n () => (detail?.integration.credentials?.fields ?? detail?.bundle?.credentials?.fields ?? []).filter(isEditableCredentialField),\n [detail?.bundle?.credentials?.fields, detail?.integration.credentials?.fields],\n )\n const credentialFormFields = React.useMemo(\n () => buildCredentialFields(editableCredentialFields),\n [editableCredentialFields],\n )\n const credentialSchema = React.useMemo(() => (\n z.object({}).passthrough().superRefine((rawValues, ctx) => {\n const values = rawValues as Record<string, unknown>\n\n editableCredentialFields.forEach((field) => {\n const value = values[field.key]\n\n if (field.type === 'boolean') {\n if (value !== undefined && value !== null && typeof value !== 'boolean') {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.boolean', 'Select a valid value.'),\n })\n }\n if (field.required && typeof value !== 'boolean') {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.required', '{field} is required.', { field: field.label }),\n })\n }\n return\n }\n\n if (value !== undefined && value !== null && typeof value !== 'string') {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.text', 'Enter a valid value.'),\n })\n return\n }\n\n const normalizedValue = typeof value === 'string' ? value : ''\n\n if (field.required && normalizedValue.trim().length === 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.required', '{field} is required.', { field: field.label }),\n })\n }\n\n if (normalizedValue.length > 20_000) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.tooLong', 'Value is too long.'),\n })\n }\n\n if (\n field.type === 'select'\n && normalizedValue\n && field.options\n && !field.options.some((option) => option.value === normalizedValue)\n ) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.option', 'Select one of the available options.'),\n })\n }\n })\n })\n ) as z.ZodType<Record<string, unknown>>, [editableCredentialFields, t])\n const latestHealthLog = React.useMemo(() => logs.find(isHealthLog) ?? null, [logs])\n const healthMessage =\n latestHealthResult?.message ??\n (typeof latestHealthLog?.payload?.message === 'string' ? latestHealthLog.payload.message : null)\n const healthDetailsSource = latestHealthResult?.details ?? extractHealthDetails(latestHealthLog?.payload)\n const healthDetails = latestHealthLog?.code\n ? { ...healthDetailsSource, code: latestHealthLog.code }\n : healthDetailsSource\n const healthDetailEntries = Object.entries(healthDetails)\n const resolvedIntegration = detail?.integration ?? null\n const resolvedState = detail?.state ?? null\n const displayHealthStatus =\n latestHealthResult?.status ?? detail?.healthStatus ?? resolvedState?.lastHealthStatus ?? 'unconfigured'\n\n const healthStatusDescription = displayHealthStatus && displayHealthStatus !== 'unconfigured'\n ? t(\n `integrations.detail.health.meaning.${displayHealthStatus}`,\n displayHealthStatus === 'healthy'\n ? 'The provider responded successfully using the current credentials.'\n : displayHealthStatus === 'degraded'\n ? 'The provider responded, but reported warnings or limited functionality.'\n : integration?.id === 'gateway_stripe'\n ? 'Stripe rejected the last check. This usually means the secret key is invalid, missing required permissions, revoked, or Stripe was temporarily unavailable.'\n : 'The last check failed. This usually means invalid credentials, missing permissions, or a provider outage.',\n )\n : displayHealthStatus === 'unconfigured'\n ? t(\n 'integrations.detail.health.meaning.unconfigured',\n 'Credentials or a health check are not configured, or the integration has not been probed yet.',\n )\n : null\n\n const CategoryIcon = resolvedIntegration?.category ? CATEGORY_ICONS[resolvedIntegration.category] : null\n const HealthStatusIcon = HEALTH_STATUS_ICONS[displayHealthStatus] ?? null\n const prioritizedInjectedTabs = resolvedIntegration?.id === 'sync_akeneo'\n ? [...injectedTabs].sort((left, right) => {\n const leftPriority = isAkeneoSettingsTab(left) ? 1 : 0\n const rightPriority = isAkeneoSettingsTab(right) ? 1 : 0\n if (leftPriority !== rightPriority) return rightPriority - leftPriority\n return 0\n })\n : injectedTabs\n const leadingInjectedTab = resolvedIntegration?.id === 'sync_akeneo'\n ? prioritizedInjectedTabs.find(isAkeneoSettingsTab) ?? null\n : null\n const trailingInjectedTabs = leadingInjectedTab\n ? prioritizedInjectedTabs.filter((tab) => tab.id !== leadingInjectedTab.id)\n : prioritizedInjectedTabs\n const hiddenBuiltInTabs = new Set(resolvedIntegration?.detailPage?.hiddenTabs ?? [])\n const showCredentialsTab = !hiddenBuiltInTabs.has('credentials')\n const showVersionTab = hasVersions && !hiddenBuiltInTabs.has('version')\n const showDataSyncScheduleTab = hasDataSyncScheduleTab && !hiddenBuiltInTabs.has('data-sync-schedule')\n const showHealthTab = !hiddenBuiltInTabs.has('health')\n const showLogsTab = !hiddenBuiltInTabs.has('logs')\n const visibleTabIds = [\n ...(showCredentialsTab ? ['credentials'] : []),\n ...(leadingInjectedTab ? [leadingInjectedTab.id] : []),\n ...(showVersionTab ? ['version'] : []),\n ...(showDataSyncScheduleTab ? ['data-sync-schedule'] : []),\n ...(showHealthTab ? ['health'] : []),\n ...(showLogsTab ? ['logs'] : []),\n ...trailingInjectedTabs.map((tab) => tab.id),\n ] satisfies IntegrationDetailTab[]\n const StateIcon = resolvedState?.isEnabled ? CheckCircle2 : XCircle\n const stateBadgeClass = resolvedState?.isEnabled\n ? 'border-emerald-500/30 bg-emerald-500/10 text-emerald-300'\n : 'border-zinc-500/30 bg-zinc-500/10 text-zinc-300'\n\n const showCredentialActions = showCredentialsTab && activeTab === 'credentials' && credentialFormFields.length > 0\n\n React.useEffect(() => {\n setActiveTab(resolveRequestedIntegrationDetailTab(searchParams?.get('tab'), visibleTabIds))\n }, [searchParams, visibleTabIds])\n\n const handleTabChange = React.useCallback((nextValue: string) => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n const nextTab = resolveRequestedIntegrationDetailTab(nextValue, visibleTabIds)\n setActiveTab(nextTab)\n if (!currentIntegrationId) return\n const basePath = `/backend/integrations/${encodeURIComponent(currentIntegrationId)}`\n router.replace(nextTab === 'credentials' ? basePath : `${basePath}?tab=${encodeURIComponent(nextTab)}`)\n }, [resolveCurrentIntegrationId, router, visibleTabIds])\n\n if (isLoading) return <Page><PageBody><LoadingMessage label={t('integrations.detail.title')} /></PageBody></Page>\n if (error || !detail || !resolvedIntegration || !resolvedState) {\n return <Page><PageBody><ErrorMessage label={error ?? t('integrations.detail.loadError')} /></PageBody></Page>\n }\n\n return (\n <Page>\n <PageBody className=\"space-y-6\">\n <FormHeader\n backHref=\"/backend/integrations\"\n title={resolvedIntegration.title}\n actions={{\n cancelHref: showCredentialActions ? '/backend/integrations' : undefined,\n submit: showCredentialActions\n ? {\n formId: credentialsFormId,\n pending: isSavingCredentials,\n label: t('integrations.detail.credentials.save', 'Save credentials'),\n pendingLabel: t('ui.forms.status.saving', 'Saving...'),\n }\n : undefined,\n }}\n />\n\n <div className=\"space-y-2\">\n {resolvedIntegration.description ? (\n <p className=\"text-sm text-muted-foreground\">{resolvedIntegration.description}</p>\n ) : null}\n <div className=\"flex flex-wrap items-center gap-4 text-sm text-muted-foreground\">\n {resolvedIntegration.category ? (\n <div className=\"flex items-center gap-2\">\n {CategoryIcon ? <CategoryIcon className=\"h-4 w-4\" /> : null}\n <span>{formatTypeLabel(resolvedIntegration.category)}</span>\n </div>\n ) : null}\n {resolvedIntegration.hub ? (\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground/80\">\n {t('integrations.detail.hub.label', 'Hub')}\n </span>\n <span>{formatTypeLabel(resolvedIntegration.hub)}</span>\n </div>\n ) : null}\n </div>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">{t('integrations.detail.analytics.title')}</CardTitle>\n </CardHeader>\n <CardContent className=\"flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between\">\n <div className=\"space-y-1 text-sm text-muted-foreground\">\n <p>\n {t('integrations.detail.analytics.totalEvents', { count: detail.analytics.totalCount })}\n </p>\n <p>\n {t('integrations.detail.analytics.errorRate', {\n rate: `${Math.round(detail.analytics.errorRate * 1000) / 10}%`,\n })}\n </p>\n <p>\n {detail.analytics.lastActivityAt\n ? `${t('integrations.detail.analytics.lastActivity')}: ${new Date(detail.analytics.lastActivityAt).toLocaleString()}`\n : t('integrations.detail.analytics.never')}\n </p>\n </div>\n <DetailLogSparkline counts={detail.analytics.dailyCounts} />\n </CardContent>\n </Card>\n\n <section className=\"rounded-lg border bg-card p-4\">\n <div className=\"flex items-center justify-between gap-4\">\n <div className=\"space-y-2\">\n <p className=\"text-overline uppercase tracking-wide text-muted-foreground\">\n {t('integrations.detail.state.label', 'State')}\n </p>\n <Badge variant=\"outline\" className={cn('gap-1.5 rounded-full px-3 py-1 text-xs font-medium', stateBadgeClass)}>\n <StateIcon className=\"h-3.5 w-3.5\" />\n {resolvedState.isEnabled\n ? t('integrations.detail.state.enabled', 'Enabled')\n : t('integrations.detail.state.disabled', 'Disabled')}\n </Badge>\n </div>\n <Switch\n checked={resolvedState.isEnabled}\n disabled={isTogglingState}\n onCheckedChange={(checked) => void handleToggleState(checked)}\n />\n </div>\n </section>\n\n {stackedDetailWidgets.length > 0 ? (\n <section className=\"space-y-4\">\n <InjectionSpot\n spotId={detailWidgetSpotId}\n context={injectionContext}\n data={detail}\n onDataChange={(next) => setDetail(next as IntegrationDetail)}\n widgetsOverride={stackedDetailWidgets}\n />\n </section>\n ) : null}\n\n {groupedDetailWidgets.length > 0 ? (\n <section className=\"grid gap-4 lg:grid-cols-2\">\n {groupedDetailWidgets.map((widget) => (\n <Card\n key={widget.widgetId}\n className={widget.placement?.column === 2 ? 'lg:col-start-2' : undefined}\n >\n <CardHeader>\n <CardTitle>\n {widget.placement?.groupLabel\n ? t(widget.placement.groupLabel, widget.module.metadata.title)\n : widget.module.metadata.title}\n </CardTitle>\n {widget.placement?.groupDescription ? (\n <p className=\"text-sm text-muted-foreground\">\n {widget.placement.groupDescription}\n </p>\n ) : null}\n </CardHeader>\n <CardContent>\n <widget.module.Widget\n context={injectionContext}\n data={detail}\n onDataChange={(next) => setDetail(next as IntegrationDetail)}\n />\n </CardContent>\n </Card>\n ))}\n </section>\n ) : null}\n\n <Tabs value={activeTab} onValueChange={handleTabChange} className=\"space-y-5\">\n <TabsList className=\"h-auto w-full justify-start overflow-x-auto rounded-none border-b border-border bg-transparent p-0\">\n {showCredentialsTab ? (\n <TabsTrigger\n value=\"credentials\"\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-foreground aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <Key className=\"h-4 w-4\" />\n <span>{t('integrations.detail.tabs.credentials')}</span>\n </span>\n </TabsTrigger>\n ) : null}\n {leadingInjectedTab ? (\n <TabsTrigger\n value={leadingInjectedTab.id}\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-foreground aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <Settings className=\"h-4 w-4\" />\n <span>{leadingInjectedTab.label}</span>\n </span>\n </TabsTrigger>\n ) : null}\n {showVersionTab ? (\n <TabsTrigger\n value=\"version\"\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-foreground aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <RefreshCw className=\"h-4 w-4\" />\n <span>{t('integrations.detail.tabs.version')}</span>\n </span>\n </TabsTrigger>\n ) : null}\n {showDataSyncScheduleTab ? (\n <TabsTrigger\n value=\"data-sync-schedule\"\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-foreground aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <Calendar className=\"h-4 w-4\" />\n <span>{t('data_sync.integrationTab.title', 'Sync schedules')}</span>\n </span>\n </TabsTrigger>\n ) : null}\n {showHealthTab ? (\n <TabsTrigger\n value=\"health\"\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-foreground aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <Activity className=\"h-4 w-4\" />\n <span>{t('integrations.detail.tabs.health')}</span>\n </span>\n </TabsTrigger>\n ) : null}\n {showLogsTab ? (\n <TabsTrigger\n value=\"logs\"\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-foreground aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <FileText className=\"h-4 w-4\" />\n <span>{t('integrations.detail.tabs.logs')}</span>\n </span>\n </TabsTrigger>\n ) : null}\n {trailingInjectedTabs.map((tab) => (\n <TabsTrigger\n key={tab.id}\n value={tab.id}\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-foreground aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <Settings className=\"h-4 w-4\" />\n <span>{tab.label}</span>\n </span>\n </TabsTrigger>\n ))}\n </TabsList>\n\n {showCredentialsTab ? (\n <TabsContent value=\"credentials\" className=\"mt-0\">\n <section className=\"space-y-4 rounded-lg border bg-card p-6\">\n {detail.bundle ? (\n <div className=\"rounded-lg border border-blue-200 bg-blue-50 p-3 text-sm text-blue-800\">\n {t('integrations.detail.credentials.bundleShared', { bundle: detail.bundle.title })}\n </div>\n ) : null}\n {credentialFormFields.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('integrations.detail.credentials.notConfigured')}\n </p>\n ) : (\n <CrudForm<Record<string, unknown>>\n key={`${resolvedIntegration.id}:${credentialsFormKey}`}\n formId={credentialsFormId}\n entityId=\"integrations.integration\"\n schema={credentialSchema}\n fields={credentialFormFields}\n initialValues={credValues}\n onSubmit={handleSaveCredentials}\n embedded\n hideFooterActions\n />\n )}\n </section>\n </TabsContent>\n ) : null}\n\n {showVersionTab ? (\n <TabsContent value=\"version\" className=\"mt-0 space-y-4\">\n <Card>\n <CardHeader>\n <CardTitle>{t('integrations.detail.version.select')}</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {resolvedIntegration.apiVersions?.map((version) => {\n const stableVersion = resolvedIntegration.apiVersions?.find((item) => item.status === 'stable')?.id\n const isSelected = (resolvedState.apiVersion ?? stableVersion) === version.id\n return (\n <div\n key={version.id}\n className={`flex cursor-pointer items-center justify-between rounded-lg border p-3 transition-colors ${isSelected ? 'border-primary bg-primary/5' : 'hover:bg-muted/50'}`}\n onClick={() => void handleVersionChange(version.id)}\n >\n <div>\n <span className=\"text-sm font-medium\">{version.label ?? version.id}</span>\n <Badge\n variant={version.status === 'stable' ? 'default' : version.status === 'deprecated' ? 'destructive' : 'secondary'}\n className=\"ml-2\"\n >\n {t(`integrations.detail.version.${version.status}`)}\n </Badge>\n {version.status === 'deprecated' && version.sunsetAt ? (\n <span className=\"ml-2 text-xs text-muted-foreground\">\n {t('integrations.detail.version.sunsetAt', { date: new Date(version.sunsetAt).toLocaleDateString() })}\n </span>\n ) : null}\n </div>\n {isSelected ? <Badge variant=\"outline\">{t('integrations.detail.version.current')}</Badge> : null}\n </div>\n )\n })}\n </CardContent>\n </Card>\n </TabsContent>\n ) : null}\n\n {showDataSyncScheduleTab ? (\n <TabsContent value=\"data-sync-schedule\" className=\"mt-0\">\n <IntegrationScheduleTab\n integrationId={resolvedIntegration.id}\n hasCredentials={detail.hasCredentials}\n isEnabled={resolvedState.isEnabled}\n />\n </TabsContent>\n ) : null}\n\n {showHealthTab ? (\n <TabsContent value=\"health\" className=\"mt-0 space-y-4\">\n <Card className=\"gap-4 py-4\">\n <CardHeader className=\"px-5\">\n <div className=\"flex items-center justify-between\">\n <CardTitle>{t('integrations.detail.health.title')}</CardTitle>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void handleHealthCheck()}\n disabled={isCheckingHealth}\n >\n {isCheckingHealth ? <Spinner className=\"mr-2 h-4 w-4\" /> : <Zap className=\"mr-2 h-4 w-4\" />}\n {isCheckingHealth ? t('integrations.detail.health.checking') : t('integrations.detail.health.check')}\n </Button>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3 px-5\">\n <div className=\"flex flex-wrap items-center gap-3 rounded-lg border bg-muted/20 px-4 py-3\">\n {displayHealthStatus ? (\n <Badge className={`gap-1.5 ${HEALTH_STATUS_STYLES[displayHealthStatus] ?? ''}`}>\n {HealthStatusIcon ? <HealthStatusIcon className=\"h-3.5 w-3.5\" /> : null}\n {t(`integrations.detail.health.${displayHealthStatus}`)}\n </Badge>\n ) : (\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <AlertTriangle className=\"h-4 w-4\" />\n <span>{t('integrations.detail.health.unknown')}</span>\n </div>\n )}\n {healthStatusDescription ? (\n <p className=\"min-w-0 flex-1 text-sm text-muted-foreground\">{healthStatusDescription}</p>\n ) : null}\n <p className=\"text-xs text-muted-foreground md:ml-auto\">\n {resolvedState.lastHealthCheckedAt\n ? t('integrations.detail.health.lastChecked', { date: new Date(resolvedState.lastHealthCheckedAt).toLocaleString() })\n : t('integrations.detail.health.neverChecked')\n }\n </p>\n </div>\n {healthMessage || healthDetailEntries.length > 0 ? (\n <div className={`grid gap-3 ${healthMessage && healthDetailEntries.length > 0 ? 'xl:grid-cols-[minmax(0,1.25fr)_minmax(0,1fr)]' : ''}`}>\n {healthMessage ? (\n <div className=\"rounded-lg border px-4 py-3\">\n <p className=\"text-overline font-medium uppercase tracking-widest text-muted-foreground\">\n {t('integrations.detail.health.lastResult', 'Last result')}\n </p>\n <p className=\"mt-1.5 text-sm\">{healthMessage}</p>\n </div>\n ) : null}\n {healthDetailEntries.length > 0 ? (\n <div className=\"rounded-lg border px-4 py-3\">\n <p className=\"text-overline font-medium uppercase tracking-widest text-muted-foreground\">\n {t('integrations.detail.health.details', 'Details')}\n </p>\n <dl className=\"mt-2 grid gap-x-6 gap-y-2 sm:grid-cols-2\">\n {healthDetailEntries.map(([key, value]) => (\n <div key={key}>\n <dt className=\"text-xs font-medium text-muted-foreground\">{formatLogDetailLabel(key)}</dt>\n <dd className=\"mt-0.5 text-sm\">{formatHealthValue(value)}</dd>\n </div>\n ))}\n </dl>\n </div>\n ) : null}\n </div>\n ) : null}\n </CardContent>\n </Card>\n </TabsContent>\n ) : null}\n\n {showLogsTab ? (\n <TabsContent value=\"logs\" className=\"mt-0 space-y-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"inline-flex\">\n <Select\n value={logLevel || undefined}\n onValueChange={(value) => setLogLevel(value ?? '')}\n >\n <SelectTrigger size=\"lg\" className=\"min-w-40\">\n <SelectValue placeholder={t('integrations.detail.logs.level.all')} />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"info\">{t('integrations.detail.logs.level.info')}</SelectItem>\n <SelectItem value=\"warn\">{t('integrations.detail.logs.level.warn')}</SelectItem>\n <SelectItem value=\"error\">{t('integrations.detail.logs.level.error')}</SelectItem>\n </SelectContent>\n </Select>\n </div>\n </div>\n {isLoadingLogs ? (\n <div className=\"flex justify-center py-8\"><Spinner /></div>\n ) : logs.length === 0 ? (\n <p className=\"py-4 text-sm text-muted-foreground\">{t('integrations.detail.logs.empty')}</p>\n ) : (\n <div className=\"rounded-lg border\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b bg-muted/50\">\n <th className=\"px-4 py-2 text-left font-medium\">{t('integrations.detail.logs.columns.time')}</th>\n <th className=\"px-4 py-2 text-left font-medium\">{t('integrations.detail.logs.columns.level')}</th>\n <th className=\"px-4 py-2 text-left font-medium\">{t('integrations.detail.logs.columns.message')}</th>\n </tr>\n </thead>\n <tbody>\n {logs.map((log) => {\n const isExpanded = expandedLogId === log.id\n const metadataEntries = [\n ['Time', new Date(log.createdAt).toLocaleString()],\n ['Level', log.level],\n ['Code', log.code ?? null],\n ['Run ID', log.runId ?? null],\n ['Entity Type', log.scopeEntityType ?? null],\n ['Entity ID', log.scopeEntityId ?? null],\n ].filter((entry): entry is [string, string] => typeof entry[1] === 'string' && entry[1].trim().length > 0)\n const { inlineEntries, nestedEntries } = splitLogPayload(log.payload)\n\n return (\n <React.Fragment key={log.id}>\n <tr className=\"border-b last:border-0\">\n <td className=\"whitespace-nowrap px-4 py-2 text-muted-foreground\">\n {new Date(log.createdAt).toLocaleString()}\n </td>\n <td className=\"px-4 py-2\">\n <Badge variant=\"secondary\" className={LOG_LEVEL_STYLES[log.level] ?? ''}>\n {log.level}\n </Badge>\n </td>\n <td className=\"px-4 py-2\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-auto w-full justify-start gap-2 px-0 py-0 text-left hover:bg-transparent\"\n onClick={() => setExpandedLogId((current) => (current === log.id ? null : log.id))}\n >\n {isExpanded ? <ChevronDown className=\"h-4 w-4 shrink-0\" /> : <ChevronRight className=\"h-4 w-4 shrink-0\" />}\n <span className=\"truncate\">{log.message}</span>\n </Button>\n </td>\n </tr>\n {isExpanded ? (\n <tr className=\"border-b bg-muted/30 last:border-0\">\n <td colSpan={3} className=\"px-4 py-4\">\n <div className=\"space-y-4 rounded-lg border bg-card p-4\">\n <div className=\"grid gap-4 lg:grid-cols-[minmax(0,1.1fr)_minmax(0,0.9fr)]\">\n <div className=\"space-y-4\">\n <section className=\"space-y-3\">\n <div>\n <p className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground\">\n {t('integrations.detail.logs.details.summary', 'Summary')}\n </p>\n <p className=\"mt-1 text-sm font-medium\">{log.message}</p>\n </div>\n {metadataEntries.length > 0 ? (\n <dl className=\"grid gap-3 sm:grid-cols-2\">\n {metadataEntries.map(([label, value]) => (\n <div key={label} className=\"rounded-md border bg-muted/30 px-3 py-2\">\n <dt className=\"text-overline font-medium uppercase tracking-wide text-muted-foreground\">\n {label}\n </dt>\n <dd className=\"mt-1 break-all text-sm\">{value}</dd>\n </div>\n ))}\n </dl>\n ) : null}\n </section>\n\n {inlineEntries.length > 0 ? (\n <section className=\"space-y-3\">\n <p className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground\">\n {t('integrations.detail.logs.details.fields', 'Fields')}\n </p>\n <dl className=\"grid gap-3 sm:grid-cols-2\">\n {inlineEntries.map(([key, value]) => (\n <div key={key} className=\"rounded-md border bg-muted/30 px-3 py-2\">\n <dt className=\"text-overline font-medium uppercase tracking-wide text-muted-foreground\">\n {formatLogDetailLabel(key)}\n </dt>\n <dd className=\"mt-1 break-words text-sm\">\n {formatLogPrimitiveValue(value)}\n </dd>\n </div>\n ))}\n </dl>\n </section>\n ) : null}\n </div>\n\n <div className=\"space-y-3\">\n {nestedEntries.map(([key, value]) => (\n <JsonDisplay\n key={key}\n data={value}\n title={formatLogDetailLabel(key)}\n defaultExpanded\n maxInitialDepth={1}\n theme=\"dark\"\n maxHeight=\"16rem\"\n className=\"p-4\"\n />\n ))}\n {log.payload && nestedEntries.length === 0 ? (\n <JsonDisplay\n data={log.payload}\n title={t('integrations.detail.logs.details.payload', 'Payload')}\n defaultExpanded\n maxInitialDepth={1}\n theme=\"dark\"\n maxHeight=\"16rem\"\n className=\"p-4\"\n />\n ) : null}\n {!log.payload ? (\n <div className=\"rounded-lg border border-dashed px-4 py-6 text-sm text-muted-foreground\">\n {t('integrations.detail.logs.details.noPayload', 'No structured payload was stored for this log entry.')}\n </div>\n ) : null}\n </div>\n </div>\n </div>\n </td>\n </tr>\n ) : null}\n </React.Fragment>\n )\n })}\n </tbody>\n </table>\n </div>\n )}\n </TabsContent>\n ) : null}\n\n {injectedTabs.map((tab) => (\n <TabsContent key={tab.id} value={tab.id} className=\"mt-0 space-y-4\">\n <InjectionSpot\n spotId={detailWidgetSpotId}\n context={injectionContext}\n data={detail}\n onDataChange={(next) => setDetail(next as IntegrationDetail)}\n widgetsOverride={tab.widgets}\n />\n </TabsContent>\n ))}\n </Tabs>\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["params"]
|
|
7
7
|
}
|
|
@@ -9,6 +9,13 @@ import { Badge } from "@open-mercato/ui/primitives/badge";
|
|
|
9
9
|
import { Button } from "@open-mercato/ui/primitives/button";
|
|
10
10
|
import { Switch } from "@open-mercato/ui/primitives/switch";
|
|
11
11
|
import { Input } from "@open-mercato/ui/primitives/input";
|
|
12
|
+
import {
|
|
13
|
+
Select,
|
|
14
|
+
SelectContent,
|
|
15
|
+
SelectItem,
|
|
16
|
+
SelectTrigger,
|
|
17
|
+
SelectValue
|
|
18
|
+
} from "@open-mercato/ui/primitives/select";
|
|
12
19
|
import { Spinner } from "@open-mercato/ui/primitives/spinner";
|
|
13
20
|
import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
|
|
14
21
|
import { flash } from "@open-mercato/ui/backend/FlashMessages";
|
|
@@ -140,14 +147,13 @@ function BundleConfigPage({ params }) {
|
|
|
140
147
|
field.required && /* @__PURE__ */ jsx("span", { className: "text-red-500 ml-0.5", children: "*" })
|
|
141
148
|
] }),
|
|
142
149
|
field.type === "select" && field.options ? /* @__PURE__ */ jsxs(
|
|
143
|
-
|
|
150
|
+
Select,
|
|
144
151
|
{
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
onChange: (e) => setCredValues((prev) => ({ ...prev, [field.key]: e.target.value })),
|
|
152
|
+
value: credValues[field.key] || void 0,
|
|
153
|
+
onValueChange: (value) => setCredValues((prev) => ({ ...prev, [field.key]: value ?? "" })),
|
|
148
154
|
children: [
|
|
149
|
-
/* @__PURE__ */ jsx(
|
|
150
|
-
field.options.map((opt) => /* @__PURE__ */ jsx(
|
|
155
|
+
/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "\u2014" }) }),
|
|
156
|
+
/* @__PURE__ */ jsx(SelectContent, { children: field.options.map((opt) => /* @__PURE__ */ jsx(SelectItem, { value: opt.value, children: opt.label }, opt.value)) })
|
|
151
157
|
]
|
|
152
158
|
}
|
|
153
159
|
) : field.type === "boolean" ? /* @__PURE__ */ jsx(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../src/modules/integrations/backend/integrations/bundle/%5Bid%5D/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { usePathname } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Card, CardHeader, CardTitle, CardContent } from '@open-mercato/ui/primitives/card'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Switch } from '@open-mercato/ui/primitives/switch'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport type { CredentialFieldType, IntegrationCredentialField } from '@open-mercato/shared/modules/integrations/types'\nimport { LoadingMessage } from '@open-mercato/ui/backend/detail'\nimport { ErrorMessage } from '@open-mercato/ui/backend/detail'\n\ntype CredentialField = IntegrationCredentialField\n\nconst UNSUPPORTED_CREDENTIAL_FIELD_TYPES = new Set<CredentialFieldType>(['oauth', 'ssh_keypair'])\n\nfunction isEditableCredentialField(field: CredentialField): boolean {\n return !UNSUPPORTED_CREDENTIAL_FIELD_TYPES.has(field.type)\n}\n\ntype BundleIntegration = {\n id: string\n title: string\n description?: string\n category?: string\n isEnabled: boolean\n}\n\ntype BundleDetail = {\n integration: {\n id: string\n title: string\n description?: string\n bundleId?: string\n }\n bundle?: {\n id: string\n title: string\n description?: string\n credentials?: { fields: CredentialField[] }\n }\n bundleIntegrations: BundleIntegration[]\n state: { isEnabled: boolean }\n hasCredentials: boolean\n}\n\ntype BundleConfigPageProps = {\n params?: {\n id?: string | string[]\n }\n}\n\nfunction resolveRouteId(value: string | string[] | undefined): string | undefined {\n if (Array.isArray(value)) return value[0]\n return value\n}\n\nfunction resolvePathnameId(pathname: string): string | undefined {\n const parts = pathname.split('/').filter(Boolean)\n const bundleId = parts.at(-1)\n if (!bundleId || bundleId === 'bundle' || bundleId === 'integrations') return undefined\n return decodeURIComponent(bundleId)\n}\n\nexport default function BundleConfigPage({ params }: BundleConfigPageProps) {\n const pathname = usePathname()\n const bundleId = resolveRouteId(params?.id) ?? resolvePathnameId(pathname)\n const t = useT()\n\n const [detail, setDetail] = React.useState<BundleDetail | null>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [credValues, setCredValues] = React.useState<Record<string, unknown>>({})\n const [isSavingCreds, setIsSavingCreds] = React.useState(false)\n const [togglingIds, setTogglingIds] = React.useState<Set<string>>(new Set())\n\n const resolveCurrentBundleId = React.useCallback(() => {\n return bundleId ?? (\n typeof window !== 'undefined'\n ? resolvePathnameId(window.location.pathname)\n : undefined\n )\n }, [bundleId])\n\n const load = React.useCallback(async () => {\n const currentBundleId = resolveCurrentBundleId()\n if (!currentBundleId) {\n setError(t('integrations.detail.loadError'))\n setIsLoading(false)\n return\n }\n setIsLoading(true)\n setError(null)\n const call = await apiCall<BundleDetail>(\n `/api/integrations/${encodeURIComponent(currentBundleId)}`,\n undefined,\n { fallback: null },\n )\n if (!call.ok || !call.result) {\n setError(t('integrations.detail.loadError'))\n setIsLoading(false)\n return\n }\n setDetail(call.result)\n\n const credCall = await apiCall<{ credentials: Record<string, unknown> }>(\n `/api/integrations/${encodeURIComponent(currentBundleId)}/credentials`,\n undefined,\n { fallback: null },\n )\n if (credCall.ok && credCall.result?.credentials) {\n setCredValues(credCall.result.credentials)\n }\n setIsLoading(false)\n }, [resolveCurrentBundleId, t])\n\n React.useEffect(() => { void load() }, [load])\n\n const handleSaveCredentials = React.useCallback(async () => {\n const currentBundleId = resolveCurrentBundleId()\n if (!currentBundleId) return\n setIsSavingCreds(true)\n const call = await apiCall(`/api/integrations/${encodeURIComponent(currentBundleId)}/credentials`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ credentials: credValues }),\n }, { fallback: null })\n if (call.ok) {\n flash(t('integrations.detail.credentials.saved'), 'success')\n } else {\n flash(t('integrations.detail.credentials.saveError'), 'error')\n }\n setIsSavingCreds(false)\n }, [resolveCurrentBundleId, credValues, t])\n\n const handleToggle = React.useCallback(async (integrationId: string, enabled: boolean) => {\n setTogglingIds((prev) => new Set(prev).add(integrationId))\n const call = await apiCall(`/api/integrations/${encodeURIComponent(integrationId)}/state`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ isEnabled: enabled }),\n }, { fallback: null })\n if (call.ok) {\n setDetail((prev) => {\n if (!prev) return prev\n return {\n ...prev,\n bundleIntegrations: prev.bundleIntegrations.map((item) =>\n item.id === integrationId ? { ...item, isEnabled: enabled } : item,\n ),\n }\n })\n } else {\n flash(t('integrations.detail.stateError'), 'error')\n }\n setTogglingIds((prev) => { const next = new Set(prev); next.delete(integrationId); return next })\n }, [t])\n\n const handleBulkToggle = React.useCallback(async (enabled: boolean) => {\n if (!detail) return\n const targets = detail.bundleIntegrations.filter((item) => item.isEnabled !== enabled)\n await Promise.all(targets.map((item) => handleToggle(item.id, enabled)))\n }, [detail, handleToggle])\n\n if (isLoading) return <Page><PageBody><LoadingMessage label={t('integrations.bundle.title')} /></PageBody></Page>\n if (error || !detail?.bundle) return <Page><PageBody><ErrorMessage label={error ?? t('integrations.detail.loadError')} /></PageBody></Page>\n\n const credFields = (detail.bundle.credentials?.fields ?? []).filter(isEditableCredentialField)\n\n return (\n <Page>\n <PageBody className=\"space-y-6\">\n <div>\n <Link href=\"/backend/integrations\" className=\"text-sm text-muted-foreground hover:underline\">\n {t('integrations.detail.back')}\n </Link>\n </div>\n\n <div>\n <h1 className=\"text-2xl font-semibold\">{detail.bundle.title}</h1>\n {detail.bundle.description && (\n <p className=\"text-muted-foreground mt-1\">{detail.bundle.description}</p>\n )}\n </div>\n\n {credFields.length > 0 && (\n <Card>\n <CardHeader>\n <CardTitle>{t('integrations.bundle.sharedCredentials')}</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {credFields.map((field) => (\n <div key={field.key} className=\"space-y-1.5\">\n <label className=\"text-sm font-medium\">\n {field.label}{field.required && <span className=\"text-red-500 ml-0.5\">*</span>}\n </label>\n {field.type === 'select' && field.options ? (\n <select\n className=\"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm\"\n value={(credValues[field.key] as string) ?? ''}\n onChange={(e) => setCredValues((prev) => ({ ...prev, [field.key]: e.target.value }))}\n >\n <option value=\"\">\u2014</option>\n {field.options.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n </select>\n ) : field.type === 'boolean' ? (\n <Switch\n checked={Boolean(credValues[field.key])}\n onCheckedChange={(checked) => setCredValues((prev) => ({ ...prev, [field.key]: checked }))}\n />\n ) : (\n <Input\n type={field.type === 'secret' ? 'password' : 'text'}\n placeholder={field.placeholder}\n value={(credValues[field.key] as string) ?? ''}\n onChange={(e) => setCredValues((prev) => ({ ...prev, [field.key]: e.target.value }))}\n />\n )}\n </div>\n ))}\n <Button type=\"button\" onClick={() => void handleSaveCredentials()} disabled={isSavingCreds}>\n {isSavingCreds ? <Spinner className=\"mr-2 h-4 w-4\" /> : null}\n {t('integrations.detail.credentials.save')}\n </Button>\n </CardContent>\n </Card>\n )}\n\n <Card>\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle>{t('integrations.bundle.integrationToggles')}</CardTitle>\n <div className=\"flex gap-2\">\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => void handleBulkToggle(true)}>\n {t('integrations.marketplace.enableAll')}\n </Button>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => void handleBulkToggle(false)}>\n {t('integrations.marketplace.disableAll')}\n </Button>\n </div>\n </div>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-3\">\n {detail.bundleIntegrations.map((item) => (\n <div key={item.id} className=\"flex items-center justify-between rounded-lg border p-3\">\n <div>\n <Link\n href={`/backend/integrations/${encodeURIComponent(item.id)}`}\n className=\"text-sm font-medium hover:underline\"\n >\n {item.title}\n </Link>\n {item.category && (\n <Badge variant=\"secondary\" className=\"ml-2 text-xs\">{item.category}</Badge>\n )}\n {item.description && (\n <p className=\"text-xs text-muted-foreground mt-0.5\">{item.description}</p>\n )}\n </div>\n <div className=\"flex items-center gap-3\">\n <Button asChild variant=\"ghost\" size=\"sm\">\n <Link href={`/backend/integrations/${encodeURIComponent(item.id)}`}>\n {t('integrations.bundle.configureIntegration')}\n </Link>\n </Button>\n <Switch\n checked={item.isEnabled}\n disabled={togglingIds.has(item.id)}\n onCheckedChange={(checked) => void handleToggle(item.id, checked)}\n />\n </div>\n </div>\n ))}\n </div>\n </CardContent>\n </Card>\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { usePathname } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Card, CardHeader, CardTitle, CardContent } from '@open-mercato/ui/primitives/card'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Switch } from '@open-mercato/ui/primitives/switch'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport type { CredentialFieldType, IntegrationCredentialField } from '@open-mercato/shared/modules/integrations/types'\nimport { LoadingMessage } from '@open-mercato/ui/backend/detail'\nimport { ErrorMessage } from '@open-mercato/ui/backend/detail'\n\ntype CredentialField = IntegrationCredentialField\n\nconst UNSUPPORTED_CREDENTIAL_FIELD_TYPES = new Set<CredentialFieldType>(['oauth', 'ssh_keypair'])\n\nfunction isEditableCredentialField(field: CredentialField): boolean {\n return !UNSUPPORTED_CREDENTIAL_FIELD_TYPES.has(field.type)\n}\n\ntype BundleIntegration = {\n id: string\n title: string\n description?: string\n category?: string\n isEnabled: boolean\n}\n\ntype BundleDetail = {\n integration: {\n id: string\n title: string\n description?: string\n bundleId?: string\n }\n bundle?: {\n id: string\n title: string\n description?: string\n credentials?: { fields: CredentialField[] }\n }\n bundleIntegrations: BundleIntegration[]\n state: { isEnabled: boolean }\n hasCredentials: boolean\n}\n\ntype BundleConfigPageProps = {\n params?: {\n id?: string | string[]\n }\n}\n\nfunction resolveRouteId(value: string | string[] | undefined): string | undefined {\n if (Array.isArray(value)) return value[0]\n return value\n}\n\nfunction resolvePathnameId(pathname: string): string | undefined {\n const parts = pathname.split('/').filter(Boolean)\n const bundleId = parts.at(-1)\n if (!bundleId || bundleId === 'bundle' || bundleId === 'integrations') return undefined\n return decodeURIComponent(bundleId)\n}\n\nexport default function BundleConfigPage({ params }: BundleConfigPageProps) {\n const pathname = usePathname()\n const bundleId = resolveRouteId(params?.id) ?? resolvePathnameId(pathname)\n const t = useT()\n\n const [detail, setDetail] = React.useState<BundleDetail | null>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [credValues, setCredValues] = React.useState<Record<string, unknown>>({})\n const [isSavingCreds, setIsSavingCreds] = React.useState(false)\n const [togglingIds, setTogglingIds] = React.useState<Set<string>>(new Set())\n\n const resolveCurrentBundleId = React.useCallback(() => {\n return bundleId ?? (\n typeof window !== 'undefined'\n ? resolvePathnameId(window.location.pathname)\n : undefined\n )\n }, [bundleId])\n\n const load = React.useCallback(async () => {\n const currentBundleId = resolveCurrentBundleId()\n if (!currentBundleId) {\n setError(t('integrations.detail.loadError'))\n setIsLoading(false)\n return\n }\n setIsLoading(true)\n setError(null)\n const call = await apiCall<BundleDetail>(\n `/api/integrations/${encodeURIComponent(currentBundleId)}`,\n undefined,\n { fallback: null },\n )\n if (!call.ok || !call.result) {\n setError(t('integrations.detail.loadError'))\n setIsLoading(false)\n return\n }\n setDetail(call.result)\n\n const credCall = await apiCall<{ credentials: Record<string, unknown> }>(\n `/api/integrations/${encodeURIComponent(currentBundleId)}/credentials`,\n undefined,\n { fallback: null },\n )\n if (credCall.ok && credCall.result?.credentials) {\n setCredValues(credCall.result.credentials)\n }\n setIsLoading(false)\n }, [resolveCurrentBundleId, t])\n\n React.useEffect(() => { void load() }, [load])\n\n const handleSaveCredentials = React.useCallback(async () => {\n const currentBundleId = resolveCurrentBundleId()\n if (!currentBundleId) return\n setIsSavingCreds(true)\n const call = await apiCall(`/api/integrations/${encodeURIComponent(currentBundleId)}/credentials`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ credentials: credValues }),\n }, { fallback: null })\n if (call.ok) {\n flash(t('integrations.detail.credentials.saved'), 'success')\n } else {\n flash(t('integrations.detail.credentials.saveError'), 'error')\n }\n setIsSavingCreds(false)\n }, [resolveCurrentBundleId, credValues, t])\n\n const handleToggle = React.useCallback(async (integrationId: string, enabled: boolean) => {\n setTogglingIds((prev) => new Set(prev).add(integrationId))\n const call = await apiCall(`/api/integrations/${encodeURIComponent(integrationId)}/state`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ isEnabled: enabled }),\n }, { fallback: null })\n if (call.ok) {\n setDetail((prev) => {\n if (!prev) return prev\n return {\n ...prev,\n bundleIntegrations: prev.bundleIntegrations.map((item) =>\n item.id === integrationId ? { ...item, isEnabled: enabled } : item,\n ),\n }\n })\n } else {\n flash(t('integrations.detail.stateError'), 'error')\n }\n setTogglingIds((prev) => { const next = new Set(prev); next.delete(integrationId); return next })\n }, [t])\n\n const handleBulkToggle = React.useCallback(async (enabled: boolean) => {\n if (!detail) return\n const targets = detail.bundleIntegrations.filter((item) => item.isEnabled !== enabled)\n await Promise.all(targets.map((item) => handleToggle(item.id, enabled)))\n }, [detail, handleToggle])\n\n if (isLoading) return <Page><PageBody><LoadingMessage label={t('integrations.bundle.title')} /></PageBody></Page>\n if (error || !detail?.bundle) return <Page><PageBody><ErrorMessage label={error ?? t('integrations.detail.loadError')} /></PageBody></Page>\n\n const credFields = (detail.bundle.credentials?.fields ?? []).filter(isEditableCredentialField)\n\n return (\n <Page>\n <PageBody className=\"space-y-6\">\n <div>\n <Link href=\"/backend/integrations\" className=\"text-sm text-muted-foreground hover:underline\">\n {t('integrations.detail.back')}\n </Link>\n </div>\n\n <div>\n <h1 className=\"text-2xl font-semibold\">{detail.bundle.title}</h1>\n {detail.bundle.description && (\n <p className=\"text-muted-foreground mt-1\">{detail.bundle.description}</p>\n )}\n </div>\n\n {credFields.length > 0 && (\n <Card>\n <CardHeader>\n <CardTitle>{t('integrations.bundle.sharedCredentials')}</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {credFields.map((field) => (\n <div key={field.key} className=\"space-y-1.5\">\n <label className=\"text-sm font-medium\">\n {field.label}{field.required && <span className=\"text-red-500 ml-0.5\">*</span>}\n </label>\n {field.type === 'select' && field.options ? (\n <Select\n value={(credValues[field.key] as string) || undefined}\n onValueChange={(value) => setCredValues((prev) => ({ ...prev, [field.key]: value ?? '' }))}\n >\n <SelectTrigger>\n <SelectValue placeholder=\"\u2014\" />\n </SelectTrigger>\n <SelectContent>\n {field.options.map((opt) => (\n <SelectItem key={opt.value} value={opt.value}>{opt.label}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n ) : field.type === 'boolean' ? (\n <Switch\n checked={Boolean(credValues[field.key])}\n onCheckedChange={(checked) => setCredValues((prev) => ({ ...prev, [field.key]: checked }))}\n />\n ) : (\n <Input\n type={field.type === 'secret' ? 'password' : 'text'}\n placeholder={field.placeholder}\n value={(credValues[field.key] as string) ?? ''}\n onChange={(e) => setCredValues((prev) => ({ ...prev, [field.key]: e.target.value }))}\n />\n )}\n </div>\n ))}\n <Button type=\"button\" onClick={() => void handleSaveCredentials()} disabled={isSavingCreds}>\n {isSavingCreds ? <Spinner className=\"mr-2 h-4 w-4\" /> : null}\n {t('integrations.detail.credentials.save')}\n </Button>\n </CardContent>\n </Card>\n )}\n\n <Card>\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle>{t('integrations.bundle.integrationToggles')}</CardTitle>\n <div className=\"flex gap-2\">\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => void handleBulkToggle(true)}>\n {t('integrations.marketplace.enableAll')}\n </Button>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => void handleBulkToggle(false)}>\n {t('integrations.marketplace.disableAll')}\n </Button>\n </div>\n </div>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-3\">\n {detail.bundleIntegrations.map((item) => (\n <div key={item.id} className=\"flex items-center justify-between rounded-lg border p-3\">\n <div>\n <Link\n href={`/backend/integrations/${encodeURIComponent(item.id)}`}\n className=\"text-sm font-medium hover:underline\"\n >\n {item.title}\n </Link>\n {item.category && (\n <Badge variant=\"secondary\" className=\"ml-2 text-xs\">{item.category}</Badge>\n )}\n {item.description && (\n <p className=\"text-xs text-muted-foreground mt-0.5\">{item.description}</p>\n )}\n </div>\n <div className=\"flex items-center gap-3\">\n <Button asChild variant=\"ghost\" size=\"sm\">\n <Link href={`/backend/integrations/${encodeURIComponent(item.id)}`}>\n {t('integrations.bundle.configureIntegration')}\n </Link>\n </Button>\n <Switch\n checked={item.isEnabled}\n disabled={togglingIds.has(item.id)}\n onCheckedChange={(checked) => void handleToggle(item.id, checked)}\n />\n </div>\n </div>\n ))}\n </div>\n </CardContent>\n </Card>\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|