@open-mercato/core 0.6.4-develop.4199.1.86677441c2 → 0.6.4-develop.4210.1.d412061cfe
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/.turbo/turbo-build.log +1 -1
- package/dist/modules/api_docs/frontend/docs/api/Explorer.js +14 -14
- package/dist/modules/api_docs/frontend/docs/api/Explorer.js.map +2 -2
- package/dist/modules/attachments/components/AttachmentContentPreview.js +2 -2
- package/dist/modules/attachments/components/AttachmentContentPreview.js.map +2 -2
- package/dist/modules/audit_logs/backend/audit-logs/page.js +3 -3
- package/dist/modules/audit_logs/backend/audit-logs/page.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.js +3 -7
- package/dist/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivityCard.js +2 -2
- package/dist/modules/customers/components/detail/ActivityCard.js.map +2 -2
- package/dist/modules/customers/components/detail/AssignRoleDialog.js +34 -49
- package/dist/modules/customers/components/detail/AssignRoleDialog.js.map +2 -2
- package/dist/modules/customers/components/detail/ChangelogEntryRow.js +2 -2
- package/dist/modules/customers/components/detail/ChangelogEntryRow.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyDetailHeader.js +10 -1
- package/dist/modules/customers/components/detail/CompanyDetailHeader.js.map +2 -2
- package/dist/modules/customers/components/detail/DealLinkedEntitiesTab.js +7 -51
- package/dist/modules/customers/components/detail/DealLinkedEntitiesTab.js.map +2 -2
- package/dist/modules/customers/components/detail/DetailTabsLayout.js +1 -1
- package/dist/modules/customers/components/detail/DetailTabsLayout.js.map +2 -2
- package/dist/modules/customers/components/detail/ManageTagsDialog.js +25 -33
- package/dist/modules/customers/components/detail/ManageTagsDialog.js.map +2 -2
- package/dist/modules/customers/components/detail/PersonCard.js +3 -2
- package/dist/modules/customers/components/detail/PersonCard.js.map +2 -2
- package/dist/modules/customers/components/detail/PersonDetailHeader.js +3 -2
- package/dist/modules/customers/components/detail/PersonDetailHeader.js.map +2 -2
- package/dist/modules/customers/components/detail/RoleAssignmentRow.js +4 -5
- package/dist/modules/customers/components/detail/RoleAssignmentRow.js.map +2 -2
- package/dist/modules/customers/components/detail/utils.js +0 -7
- package/dist/modules/customers/components/detail/utils.js.map +2 -2
- package/dist/modules/customers/widgets/injection/ai-assistant-trigger/widget.client.js +3 -8
- package/dist/modules/customers/widgets/injection/ai-assistant-trigger/widget.client.js.map +2 -2
- package/dist/modules/dictionaries/components/AppearanceSelector.js +3 -4
- package/dist/modules/dictionaries/components/AppearanceSelector.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/[id]/page.js +17 -17
- package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
- package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js +1 -1
- package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js.map +2 -2
- package/dist/modules/planner/components/AvailabilityRulesEditor.js +65 -1
- package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
- package/dist/modules/planner/lib/deleteAvailabilityRuleSet.js +20 -0
- package/dist/modules/planner/lib/deleteAvailabilityRuleSet.js.map +7 -0
- package/dist/modules/resources/backend/resources/resources/[id]/page.js +2 -2
- package/dist/modules/resources/backend/resources/resources/[id]/page.js.map +2 -2
- package/dist/modules/sales/api/quotes/accept/route.js +14 -37
- package/dist/modules/sales/api/quotes/accept/route.js.map +3 -3
- package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js +1 -1
- package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +1 -1
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +6 -2
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-members/[id]/page.js +3 -2
- package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +1 -1
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
- package/dist/modules/translations/components/TranslationDrawerAction.js +27 -65
- package/dist/modules/translations/components/TranslationDrawerAction.js.map +2 -2
- package/dist/modules/translations/components/TranslationManager.js +2 -2
- package/dist/modules/translations/components/TranslationManager.js.map +2 -2
- package/dist/modules/translations/widgets/injection/translation-manager/widget.client.js +54 -92
- package/dist/modules/translations/widgets/injection/translation-manager/widget.client.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/api_docs/frontend/docs/api/Explorer.tsx +14 -14
- package/src/modules/attachments/components/AttachmentContentPreview.tsx +2 -2
- package/src/modules/audit_logs/backend/audit-logs/page.tsx +3 -3
- package/src/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.tsx +4 -8
- package/src/modules/customers/components/detail/ActivityCard.tsx +2 -4
- package/src/modules/customers/components/detail/AssignRoleDialog.tsx +28 -55
- package/src/modules/customers/components/detail/ChangelogEntryRow.tsx +6 -4
- package/src/modules/customers/components/detail/CompanyDetailHeader.tsx +7 -3
- package/src/modules/customers/components/detail/DealLinkedEntitiesTab.tsx +11 -49
- package/src/modules/customers/components/detail/DetailTabsLayout.tsx +1 -1
- package/src/modules/customers/components/detail/ManageTagsDialog.tsx +27 -36
- package/src/modules/customers/components/detail/PersonCard.tsx +3 -4
- package/src/modules/customers/components/detail/PersonDetailHeader.tsx +3 -4
- package/src/modules/customers/components/detail/RoleAssignmentRow.tsx +4 -7
- package/src/modules/customers/components/detail/utils.ts +0 -7
- package/src/modules/customers/widgets/injection/ai-assistant-trigger/widget.client.tsx +4 -9
- package/src/modules/dictionaries/components/AppearanceSelector.tsx +3 -4
- package/src/modules/integrations/backend/integrations/[id]/page.tsx +21 -21
- package/src/modules/planner/backend/planner/availability-rulesets/[id]/page.tsx +1 -1
- package/src/modules/planner/components/AvailabilityRulesEditor.tsx +62 -0
- package/src/modules/planner/lib/deleteAvailabilityRuleSet.ts +35 -0
- package/src/modules/resources/backend/resources/resources/[id]/page.tsx +2 -2
- package/src/modules/sales/api/quotes/accept/route.ts +22 -38
- package/src/modules/sales/backend/sales/channels/[channelId]/edit/page.tsx +1 -1
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +1 -1
- package/src/modules/sales/commands/documents.ts +16 -2
- package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +3 -2
- package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +1 -1
- package/src/modules/staff/i18n/de.json +5 -0
- package/src/modules/staff/i18n/en.json +5 -0
- package/src/modules/staff/i18n/es.json +5 -0
- package/src/modules/staff/i18n/pl.json +5 -0
- package/src/modules/translations/components/TranslationDrawerAction.tsx +31 -66
- package/src/modules/translations/components/TranslationManager.tsx +2 -2
- package/src/modules/translations/widgets/injection/translation-manager/widget.client.tsx +53 -84
|
@@ -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 {\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 { PasswordInput } from '@open-mercato/ui/primitives/password-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 { LogList, type LogListEntry } from '@open-mercato/ui/backend/LogList'\nimport { Activity, AlertTriangle, Bell, Calendar, CheckCircle2, CreditCard, FileText, FileX, HardDrive, Key, MessageSquare, RefreshCw, Settings, Truck, Webhook, XCircle, Zap } from 'lucide-react'\nimport { EmptyState } from '@open-mercato/ui/primitives/empty-state'\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\ntype DataSyncRunDetail = {\n id: string\n status: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled'\n progressJobId?: string | null\n createdCount?: number\n updatedCount?: number\n skippedCount?: number\n failedCount?: number\n progressJob?: {\n progressPercent?: number | null\n processedCount?: number | null\n totalCount?: number | null\n } | 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 formatRunStatusLabel(status: DataSyncRunDetail['status'], t: ReturnType<typeof useT>): string {\n switch (status) {\n case 'pending':\n return t('integrations.detail.runActivity.status.pending', 'Pending')\n case 'running':\n return t('integrations.detail.runActivity.status.running', 'Running')\n case 'completed':\n return t('integrations.detail.runActivity.status.completed', 'Completed')\n case 'failed':\n return t('integrations.detail.runActivity.status.failed', 'Failed')\n case 'cancelled':\n return t('integrations.detail.runActivity.status.cancelled', 'Cancelled')\n default:\n return status\n }\n}\n\nfunction RunActivityStrip({\n run,\n refreshedAt,\n isRefreshing,\n onRefresh,\n t,\n}: {\n run: DataSyncRunDetail | null\n refreshedAt: string | null\n isRefreshing: boolean\n onRefresh: () => void\n t: ReturnType<typeof useT>\n}) {\n if (!run) return null\n\n const progress = typeof run.progressJob?.progressPercent === 'number' ? run.progressJob.progressPercent : 0\n const processed = typeof run.progressJob?.processedCount === 'number' ? run.progressJob.processedCount : 0\n const total = typeof run.progressJob?.totalCount === 'number' ? run.progressJob.totalCount : null\n const statusClass = run.status === 'completed'\n ? 'border-emerald-500/30 bg-emerald-500/10 text-emerald-700 dark:text-emerald-300'\n : run.status === 'failed'\n ? 'border-red-500/30 bg-red-500/10 text-red-700 dark:text-red-300'\n : run.status === 'cancelled'\n ? 'border-zinc-500/30 bg-zinc-500/10 text-zinc-700 dark:text-zinc-300'\n : 'border-blue-500/30 bg-blue-500/10 text-blue-700 dark:text-blue-300'\n\n return (\n <div className=\"flex flex-wrap items-center gap-3 rounded-lg border bg-muted/20 px-4 py-3 text-sm\">\n <Badge variant=\"outline\" className={cn('gap-1.5', statusClass)}>\n <RefreshCw className={cn('h-3.5 w-3.5', run.status === 'running' ? 'animate-spin' : '')} />\n {formatRunStatusLabel(run.status, t)}\n </Badge>\n <span className=\"text-muted-foreground\">\n {t('integrations.detail.runActivity.processed', 'Processed')}: <span className=\"font-medium text-foreground\">{processed}{total !== null ? ` / ${total}` : ''}</span>\n </span>\n <span className=\"text-muted-foreground\">\n {t('integrations.detail.runActivity.progress', 'Progress')}: <span className=\"font-medium text-foreground\">{progress}%</span>\n </span>\n {refreshedAt ? (\n <span className=\"text-muted-foreground\">\n {t('integrations.detail.runActivity.lastRefreshed', 'Last refreshed')}: {new Date(refreshedAt).toLocaleTimeString()}\n </span>\n ) : null}\n <Button type=\"button\" variant=\"outline\" size=\"sm\" className=\"ml-auto\" onClick={onRefresh} disabled={isRefreshing}>\n {isRefreshing ? <Spinner className=\"mr-2 h-4 w-4\" /> : <RefreshCw className=\"mr-2 h-4 w-4\" />}\n {t('integrations.detail.runActivity.refresh', 'Refresh')}\n </Button>\n </div>\n )\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 visibleWhen: field.visibleWhen,\n }\n\n if (field.type === 'secret') {\n return {\n ...shared,\n type: 'custom' as const,\n component: ({ id, value, setValue, disabled }) => (\n <PasswordInput\n id={id}\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\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 [activeRunDetail, setActiveRunDetail] = React.useState<DataSyncRunDetail | null>(null)\n const [activeRunRefreshedAt, setActiveRunRefreshedAt] = React.useState<string | null>(null)\n const [isRefreshingRunActivity, setIsRefreshingRunActivity] = React.useState(false)\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 (options?: { showLoading?: boolean }) => {\n const showLoading = options?.showLoading ?? true\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) {\n if (showLoading) setIsLoading(false)\n if (showLoading) setError(t('integrations.detail.loadError', 'Failed to load integration'))\n return\n }\n if (showLoading) setError(null)\n if (showLoading) 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 if (showLoading) setError(t('integrations.detail.loadError', 'Failed to load integration'))\n if (showLoading) setIsLoading(false)\n return\n }\n setDetail(call.result)\n setError(null)\n if (showLoading) setIsLoading(false)\n } catch {\n if (showLoading) setError(t('integrations.detail.loadError', 'Failed to load integration'))\n if (showLoading) 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 const next = { ...call.result.credentials }\n if (currentIntegrationId === 'storage_s3') {\n const authMode = next.authMode\n if (authMode !== 'access_keys' && authMode !== 'ambient') {\n const hasKeys = Boolean(next.accessKeyId || next.secretAccessKey)\n next.authMode = hasKeys ? 'access_keys' : 'ambient'\n }\n }\n setCredValues(next)\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({ showLoading: false })\n await loadCredentials()\n }, [loadCredentials, loadDetail])\n const refreshLogs = React.useCallback(async () => {\n await loadLogs()\n }, [loadLogs])\n const refreshHealthSnapshot = React.useCallback(async () => {\n await loadDetail({ showLoading: false })\n }, [loadDetail])\n const runIdFromUrl = searchParams?.get('runId') ?? null\n const refreshRunActivity = React.useCallback(async (options?: { showLoading?: boolean }) => {\n if (!runIdFromUrl) {\n setActiveRunDetail(null)\n setActiveRunRefreshedAt(null)\n return null\n }\n if (options?.showLoading) setIsRefreshingRunActivity(true)\n try {\n const call = await apiCall<DataSyncRunDetail>(\n `/api/data_sync/runs/${encodeURIComponent(runIdFromUrl)}`,\n undefined,\n { fallback: null },\n )\n await loadLogs()\n await loadDetail({ showLoading: false })\n if (call.ok && call.result) {\n setActiveRunDetail(call.result)\n setActiveRunRefreshedAt(new Date().toISOString())\n return call.result\n }\n return null\n } finally {\n if (options?.showLoading) setIsRefreshingRunActivity(false)\n }\n }, [loadDetail, loadLogs, runIdFromUrl])\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 refreshHealthSnapshot,\n retryLastMutation,\n }),\n [\n activeTab,\n credValues,\n detail,\n detailWidgetSpotId,\n integrationId,\n latestHealthResult,\n mutationContextId,\n refreshDetail,\n refreshHealthSnapshot,\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\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 sanitizedValues = { ...values }\n if (currentIntegrationId === 'storage_s3') {\n const authMode = sanitizedValues.authMode\n if (authMode !== 'access_keys' && authMode !== 'ambient') {\n const hasKeys = Boolean(sanitizedValues.accessKeyId || sanitizedValues.secretAccessKey)\n sanitizedValues.authMode = hasKeys ? 'access_keys' : 'ambient'\n }\n if (sanitizedValues.authMode === 'ambient') {\n delete sanitizedValues.accessKeyId\n delete sanitizedValues.secretAccessKey\n delete sanitizedValues.sessionToken\n }\n }\n const call = await runMutationWithContext({\n actionId: 'save-credentials',\n tabId: 'credentials',\n mutationPayload: { integrationId: currentIntegrationId, credentials: sanitizedValues },\n operation: () => apiCall(`/api/integrations/${encodeURIComponent(currentIntegrationId)}/credentials`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ credentials: sanitizedValues }),\n }, { fallback: null }),\n })\n\n if (call.ok) {\n setCredValues(sanitizedValues)\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 if (field.visibleWhen) {\n const targetValue = values[field.visibleWhen.field]\n if (targetValue !== field.visibleWhen.equals) return\n }\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 latestOperationalLog = React.useMemo(\n () => logs.find((log) => (\n typeof log.payload?.operationalStatus === 'string'\n || typeof log.payload?.summary === 'string'\n )) ?? null,\n [logs],\n )\n const healthMessage =\n latestHealthResult?.message ??\n (typeof latestHealthLog?.payload?.message === 'string'\n ? latestHealthLog.payload.message\n : typeof latestOperationalLog?.payload?.summary === 'string'\n ? latestOperationalLog.payload.summary\n : null)\n const healthDetailsSource = latestHealthResult?.details ?? extractHealthDetails(latestHealthLog?.payload ?? latestOperationalLog?.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 const params = new URLSearchParams(searchParams?.toString() ?? '')\n if (nextTab === 'credentials') params.delete('tab')\n else params.set('tab', nextTab)\n const query = params.toString()\n router.replace(query ? `${basePath}?${query}` : basePath)\n }, [resolveCurrentIntegrationId, router, searchParams, visibleTabIds])\n\n React.useEffect(() => {\n if (!runIdFromUrl) {\n setActiveRunDetail(null)\n setActiveRunRefreshedAt(null)\n return\n }\n if (activeTab !== 'logs' && activeTab !== 'health') return\n\n let cancelled = false\n let timeoutId: ReturnType<typeof setTimeout> | null = null\n\n const poll = async () => {\n const detail = await refreshRunActivity()\n if (cancelled) return\n\n const status = detail?.status ?? null\n if (status === 'pending' || status === 'running') {\n timeoutId = setTimeout(() => {\n void poll()\n }, 4_000)\n }\n }\n\n void poll()\n\n return () => {\n cancelled = true\n if (timeoutId) clearTimeout(timeoutId)\n }\n }, [activeTab, refreshRunActivity, runIdFromUrl])\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 <RunActivityStrip\n run={activeRunDetail}\n refreshedAt={activeRunRefreshedAt}\n isRefreshing={isRefreshingRunActivity}\n onRefresh={() => void refreshRunActivity({ showLoading: true })}\n t={t}\n />\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 <div className=\"flex flex-wrap items-center gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void refreshRunActivity({ showLoading: true })}\n disabled={isRefreshingRunActivity || !runIdFromUrl}\n >\n {isRefreshingRunActivity ? <Spinner className=\"mr-2 h-4 w-4\" /> : <RefreshCw className=\"mr-2 h-4 w-4\" />}\n {t('integrations.detail.runActivity.refresh', 'Refresh')}\n </Button>\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 </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 <RunActivityStrip\n run={activeRunDetail}\n refreshedAt={activeRunRefreshedAt}\n isRefreshing={isRefreshingRunActivity}\n onRefresh={() => void refreshRunActivity({ showLoading: true })}\n t={t}\n />\n <div className=\"flex flex-wrap 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 <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void refreshRunActivity({ showLoading: true })}\n disabled={isRefreshingRunActivity || !runIdFromUrl}\n >\n {isRefreshingRunActivity ? <Spinner className=\"mr-2 h-4 w-4\" /> : <RefreshCw className=\"mr-2 h-4 w-4\" />}\n {t('integrations.detail.runActivity.refresh', 'Refresh')}\n </Button>\n </div>\n {isLoadingLogs ? (\n <div className=\"flex justify-center py-8\"><Spinner /></div>\n ) : (\n <LogList\n entries={logs.map<LogListEntry>((log) => {\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 id: log.id,\n time: new Date(log.createdAt).toLocaleString(),\n level: log.level,\n message: log.message,\n body: (\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 <EmptyState\n size=\"sm\"\n icon={<FileX className=\"h-8 w-8\" aria-hidden=\"true\" />}\n title={t('integrations.detail.logs.details.noPayload', 'No structured payload was stored for this log entry.')}\n />\n ) : null}\n </div>\n </div>\n ),\n }\n })}\n emptyMessage={t('integrations.detail.logs.empty')}\n />\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 { PasswordInput } from '@open-mercato/ui/primitives/password-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 { LogList, type LogListEntry } from '@open-mercato/ui/backend/LogList'\nimport { Activity, AlertTriangle, Bell, Calendar, CheckCircle2, CreditCard, FileText, FileX, HardDrive, Key, MessageSquare, RefreshCw, Settings, Truck, Webhook, XCircle, Zap } from 'lucide-react'\nimport { EmptyState } from '@open-mercato/ui/primitives/empty-state'\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\ntype DataSyncRunDetail = {\n id: string\n status: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled'\n progressJobId?: string | null\n createdCount?: number\n updatedCount?: number\n skippedCount?: number\n failedCount?: number\n progressJob?: {\n progressPercent?: number | null\n processedCount?: number | null\n totalCount?: number | null\n } | null\n}\n\nconst LOG_LEVEL_STYLES: Record<string, string> = {\n info: 'bg-status-info-bg text-status-info-text',\n warn: 'bg-status-warning-bg text-status-warning-text',\n error: 'bg-status-error-bg text-status-error-text',\n}\n\nconst HEALTH_STATUS_STYLES: Record<string, string> = {\n healthy: 'bg-status-success-bg text-status-success-text',\n degraded: 'bg-status-warning-bg text-status-warning-text',\n unhealthy: 'bg-status-error-bg text-status-error-text',\n unconfigured: 'bg-status-neutral-bg text-status-neutral-text',\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 formatRunStatusLabel(status: DataSyncRunDetail['status'], t: ReturnType<typeof useT>): string {\n switch (status) {\n case 'pending':\n return t('integrations.detail.runActivity.status.pending', 'Pending')\n case 'running':\n return t('integrations.detail.runActivity.status.running', 'Running')\n case 'completed':\n return t('integrations.detail.runActivity.status.completed', 'Completed')\n case 'failed':\n return t('integrations.detail.runActivity.status.failed', 'Failed')\n case 'cancelled':\n return t('integrations.detail.runActivity.status.cancelled', 'Cancelled')\n default:\n return status\n }\n}\n\nfunction RunActivityStrip({\n run,\n refreshedAt,\n isRefreshing,\n onRefresh,\n t,\n}: {\n run: DataSyncRunDetail | null\n refreshedAt: string | null\n isRefreshing: boolean\n onRefresh: () => void\n t: ReturnType<typeof useT>\n}) {\n if (!run) return null\n\n const progress = typeof run.progressJob?.progressPercent === 'number' ? run.progressJob.progressPercent : 0\n const processed = typeof run.progressJob?.processedCount === 'number' ? run.progressJob.processedCount : 0\n const total = typeof run.progressJob?.totalCount === 'number' ? run.progressJob.totalCount : null\n const statusClass = run.status === 'completed'\n ? 'border-status-success-border bg-status-success-bg text-status-success-text'\n : run.status === 'failed'\n ? 'border-status-error-border bg-status-error-bg text-status-error-text'\n : run.status === 'cancelled'\n ? 'border-status-neutral-border bg-status-neutral-bg text-status-neutral-text'\n : 'border-status-info-border bg-status-info-bg text-status-info-text'\n\n return (\n <div className=\"flex flex-wrap items-center gap-3 rounded-lg border bg-muted/20 px-4 py-3 text-sm\">\n <Badge variant=\"outline\" className={cn('gap-1.5', statusClass)}>\n <RefreshCw className={cn('h-3.5 w-3.5', run.status === 'running' ? 'animate-spin' : '')} />\n {formatRunStatusLabel(run.status, t)}\n </Badge>\n <span className=\"text-muted-foreground\">\n {t('integrations.detail.runActivity.processed', 'Processed')}: <span className=\"font-medium text-foreground\">{processed}{total !== null ? ` / ${total}` : ''}</span>\n </span>\n <span className=\"text-muted-foreground\">\n {t('integrations.detail.runActivity.progress', 'Progress')}: <span className=\"font-medium text-foreground\">{progress}%</span>\n </span>\n {refreshedAt ? (\n <span className=\"text-muted-foreground\">\n {t('integrations.detail.runActivity.lastRefreshed', 'Last refreshed')}: {new Date(refreshedAt).toLocaleTimeString()}\n </span>\n ) : null}\n <Button type=\"button\" variant=\"outline\" size=\"sm\" className=\"ml-auto\" onClick={onRefresh} disabled={isRefreshing}>\n {isRefreshing ? <Spinner className=\"mr-2 h-4 w-4\" /> : <RefreshCw className=\"mr-2 h-4 w-4\" />}\n {t('integrations.detail.runActivity.refresh', 'Refresh')}\n </Button>\n </div>\n )\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 visibleWhen: field.visibleWhen,\n }\n\n if (field.type === 'secret') {\n return {\n ...shared,\n type: 'custom' as const,\n component: ({ id, value, setValue, disabled }) => (\n <PasswordInput\n id={id}\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\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 [activeRunDetail, setActiveRunDetail] = React.useState<DataSyncRunDetail | null>(null)\n const [activeRunRefreshedAt, setActiveRunRefreshedAt] = React.useState<string | null>(null)\n const [isRefreshingRunActivity, setIsRefreshingRunActivity] = React.useState(false)\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 (options?: { showLoading?: boolean }) => {\n const showLoading = options?.showLoading ?? true\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) {\n if (showLoading) setIsLoading(false)\n if (showLoading) setError(t('integrations.detail.loadError', 'Failed to load integration'))\n return\n }\n if (showLoading) setError(null)\n if (showLoading) 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 if (showLoading) setError(t('integrations.detail.loadError', 'Failed to load integration'))\n if (showLoading) setIsLoading(false)\n return\n }\n setDetail(call.result)\n setError(null)\n if (showLoading) setIsLoading(false)\n } catch {\n if (showLoading) setError(t('integrations.detail.loadError', 'Failed to load integration'))\n if (showLoading) 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 const next = { ...call.result.credentials }\n if (currentIntegrationId === 'storage_s3') {\n const authMode = next.authMode\n if (authMode !== 'access_keys' && authMode !== 'ambient') {\n const hasKeys = Boolean(next.accessKeyId || next.secretAccessKey)\n next.authMode = hasKeys ? 'access_keys' : 'ambient'\n }\n }\n setCredValues(next)\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({ showLoading: false })\n await loadCredentials()\n }, [loadCredentials, loadDetail])\n const refreshLogs = React.useCallback(async () => {\n await loadLogs()\n }, [loadLogs])\n const refreshHealthSnapshot = React.useCallback(async () => {\n await loadDetail({ showLoading: false })\n }, [loadDetail])\n const runIdFromUrl = searchParams?.get('runId') ?? null\n const refreshRunActivity = React.useCallback(async (options?: { showLoading?: boolean }) => {\n if (!runIdFromUrl) {\n setActiveRunDetail(null)\n setActiveRunRefreshedAt(null)\n return null\n }\n if (options?.showLoading) setIsRefreshingRunActivity(true)\n try {\n const call = await apiCall<DataSyncRunDetail>(\n `/api/data_sync/runs/${encodeURIComponent(runIdFromUrl)}`,\n undefined,\n { fallback: null },\n )\n await loadLogs()\n await loadDetail({ showLoading: false })\n if (call.ok && call.result) {\n setActiveRunDetail(call.result)\n setActiveRunRefreshedAt(new Date().toISOString())\n return call.result\n }\n return null\n } finally {\n if (options?.showLoading) setIsRefreshingRunActivity(false)\n }\n }, [loadDetail, loadLogs, runIdFromUrl])\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 refreshHealthSnapshot,\n retryLastMutation,\n }),\n [\n activeTab,\n credValues,\n detail,\n detailWidgetSpotId,\n integrationId,\n latestHealthResult,\n mutationContextId,\n refreshDetail,\n refreshHealthSnapshot,\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\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 sanitizedValues = { ...values }\n if (currentIntegrationId === 'storage_s3') {\n const authMode = sanitizedValues.authMode\n if (authMode !== 'access_keys' && authMode !== 'ambient') {\n const hasKeys = Boolean(sanitizedValues.accessKeyId || sanitizedValues.secretAccessKey)\n sanitizedValues.authMode = hasKeys ? 'access_keys' : 'ambient'\n }\n if (sanitizedValues.authMode === 'ambient') {\n delete sanitizedValues.accessKeyId\n delete sanitizedValues.secretAccessKey\n delete sanitizedValues.sessionToken\n }\n }\n const call = await runMutationWithContext({\n actionId: 'save-credentials',\n tabId: 'credentials',\n mutationPayload: { integrationId: currentIntegrationId, credentials: sanitizedValues },\n operation: () => apiCall(`/api/integrations/${encodeURIComponent(currentIntegrationId)}/credentials`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ credentials: sanitizedValues }),\n }, { fallback: null }),\n })\n\n if (call.ok) {\n setCredValues(sanitizedValues)\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 if (field.visibleWhen) {\n const targetValue = values[field.visibleWhen.field]\n if (targetValue !== field.visibleWhen.equals) return\n }\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 latestOperationalLog = React.useMemo(\n () => logs.find((log) => (\n typeof log.payload?.operationalStatus === 'string'\n || typeof log.payload?.summary === 'string'\n )) ?? null,\n [logs],\n )\n const healthMessage =\n latestHealthResult?.message ??\n (typeof latestHealthLog?.payload?.message === 'string'\n ? latestHealthLog.payload.message\n : typeof latestOperationalLog?.payload?.summary === 'string'\n ? latestOperationalLog.payload.summary\n : null)\n const healthDetailsSource = latestHealthResult?.details ?? extractHealthDetails(latestHealthLog?.payload ?? latestOperationalLog?.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-status-success-border bg-status-success-bg text-status-success-text'\n : 'border-status-neutral-border bg-status-neutral-bg text-status-neutral-text'\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 const params = new URLSearchParams(searchParams?.toString() ?? '')\n if (nextTab === 'credentials') params.delete('tab')\n else params.set('tab', nextTab)\n const query = params.toString()\n router.replace(query ? `${basePath}?${query}` : basePath)\n }, [resolveCurrentIntegrationId, router, searchParams, visibleTabIds])\n\n React.useEffect(() => {\n if (!runIdFromUrl) {\n setActiveRunDetail(null)\n setActiveRunRefreshedAt(null)\n return\n }\n if (activeTab !== 'logs' && activeTab !== 'health') return\n\n let cancelled = false\n let timeoutId: ReturnType<typeof setTimeout> | null = null\n\n const poll = async () => {\n const detail = await refreshRunActivity()\n if (cancelled) return\n\n const status = detail?.status ?? null\n if (status === 'pending' || status === 'running') {\n timeoutId = setTimeout(() => {\n void poll()\n }, 4_000)\n }\n }\n\n void poll()\n\n return () => {\n cancelled = true\n if (timeoutId) clearTimeout(timeoutId)\n }\n }, [activeTab, refreshRunActivity, runIdFromUrl])\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-accent-indigo 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-accent-indigo 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-accent-indigo 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-accent-indigo 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-accent-indigo 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-accent-indigo 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-accent-indigo 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-status-info-border bg-status-info-bg p-3 text-sm text-status-info-text\">\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 <RunActivityStrip\n run={activeRunDetail}\n refreshedAt={activeRunRefreshedAt}\n isRefreshing={isRefreshingRunActivity}\n onRefresh={() => void refreshRunActivity({ showLoading: true })}\n t={t}\n />\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 <div className=\"flex flex-wrap items-center gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void refreshRunActivity({ showLoading: true })}\n disabled={isRefreshingRunActivity || !runIdFromUrl}\n >\n {isRefreshingRunActivity ? <Spinner className=\"mr-2 h-4 w-4\" /> : <RefreshCw className=\"mr-2 h-4 w-4\" />}\n {t('integrations.detail.runActivity.refresh', 'Refresh')}\n </Button>\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 </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 <RunActivityStrip\n run={activeRunDetail}\n refreshedAt={activeRunRefreshedAt}\n isRefreshing={isRefreshingRunActivity}\n onRefresh={() => void refreshRunActivity({ showLoading: true })}\n t={t}\n />\n <div className=\"flex flex-wrap 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 <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void refreshRunActivity({ showLoading: true })}\n disabled={isRefreshingRunActivity || !runIdFromUrl}\n >\n {isRefreshingRunActivity ? <Spinner className=\"mr-2 h-4 w-4\" /> : <RefreshCw className=\"mr-2 h-4 w-4\" />}\n {t('integrations.detail.runActivity.refresh', 'Refresh')}\n </Button>\n </div>\n {isLoadingLogs ? (\n <div className=\"flex justify-center py-8\"><Spinner /></div>\n ) : (\n <LogList\n entries={logs.map<LogListEntry>((log) => {\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 id: log.id,\n time: new Date(log.createdAt).toLocaleString(),\n level: log.level,\n message: log.message,\n body: (\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 <EmptyState\n size=\"sm\"\n icon={<FileX className=\"h-8 w-8\" aria-hidden=\"true\" />}\n title={t('integrations.detail.logs.details.noPayload', 'No structured payload was stored for this log entry.')}\n />\n ) : null}\n </div>\n </div>\n ),\n }\n })}\n emptyMessage={t('integrations.detail.logs.empty')}\n />\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", "detail"]
|
|
7
7
|
}
|
|
@@ -123,7 +123,7 @@ function PlannerAvailabilityRuleSetDetailPage({ params }) {
|
|
|
123
123
|
"aria-selected": activeTab === tab.id,
|
|
124
124
|
variant: "ghost",
|
|
125
125
|
size: "sm",
|
|
126
|
-
className: `relative -mb-px h-auto rounded-none border-b-2 px-0 py-2 font-medium ${activeTab === tab.id ? "border-
|
|
126
|
+
className: `relative -mb-px h-auto rounded-none border-b-2 px-0 py-2 font-medium ${activeTab === tab.id ? "border-accent-indigo text-foreground" : "border-transparent text-muted-foreground hover:text-foreground"}`,
|
|
127
127
|
onClick: () => setActiveTab(tab.id),
|
|
128
128
|
children: tab.label
|
|
129
129
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../src/modules/planner/backend/planner/availability-rulesets/%5Bid%5D/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { normalizeCrudServerError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { AvailabilityRulesEditor, type AvailabilityScheduleItemBuilder } from '@open-mercato/core/modules/planner/components/AvailabilityRulesEditor'\nimport { parseAvailabilityRuleWindow } from '@open-mercato/core/modules/planner/lib/availabilitySchedule'\nimport { extractCustomFieldEntries } from '@open-mercato/shared/lib/crud/custom-fields-client'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { AvailabilityRuleSetForm, buildAvailabilityRuleSetPayload, type AvailabilityRuleSetFormValues } from '@open-mercato/core/modules/planner/components/AvailabilityRuleSetForm'\n\nconst DAY_MS = 24 * 60 * 60 * 1000\n\nfunction toFullDayWindow(value: Date): { start: Date; end: Date } {\n const start = new Date(value.getFullYear(), value.getMonth(), value.getDate())\n const end = new Date(start.getTime() + DAY_MS)\n return { start, end }\n}\n\ntype RuleSetRecord = {\n id: string\n name: string\n description?: string | null\n timezone: string\n updatedAt?: string | null\n name_raw?: string | null\n} & Record<string, unknown>\n\ntype RuleSetResponse = {\n items?: RuleSetRecord[]\n}\n\nexport default function PlannerAvailabilityRuleSetDetailPage({ params }: { params?: { id?: string } }) {\n const rulesetId = params?.id\n const translate = useT()\n const router = useRouter()\n const [initialValues, setInitialValues] = React.useState<AvailabilityRuleSetFormValues | null>(null)\n const [activeTab, setActiveTab] = React.useState<'details' | 'availability'>('details')\n\n React.useEffect(() => {\n if (!rulesetId) return\n const rulesetIdValue = rulesetId\n let cancelled = false\n async function loadRuleSet() {\n try {\n const params = new URLSearchParams({ page: '1', pageSize: '1', ids: rulesetIdValue })\n const payload = await readApiResultOrThrow<RuleSetResponse>(\n `/api/planner/availability-rule-sets?${params.toString()}`,\n undefined,\n { errorMessage: translate('planner.availabilityRuleSets.form.errors.load', 'Failed to load schedule.') },\n )\n const record = Array.isArray(payload.items) ? payload.items[0] : null\n if (!record) throw new Error(translate('planner.availabilityRuleSets.form.errors.notFound', 'Schedule not found.'))\n const customFields = extractCustomFieldEntries(record)\n if (!cancelled) {\n setInitialValues({\n id: record.id,\n name: record.name ?? record.name_raw ?? '',\n description: record.description ?? '',\n timezone: record.timezone ?? 'UTC',\n ...customFields,\n })\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : translate('planner.availabilityRuleSets.form.errors.load', 'Failed to load schedule.')\n flash(message, 'error')\n }\n }\n loadRuleSet()\n return () => { cancelled = true }\n }, [rulesetId, translate])\n\n const handleSubmit = React.useCallback(async (values: AvailabilityRuleSetFormValues) => {\n if (!rulesetId) return\n const timezone = typeof initialValues?.timezone === 'string' && initialValues.timezone.trim().length\n ? initialValues.timezone.trim()\n : 'UTC'\n const payload = buildAvailabilityRuleSetPayload(values, { id: rulesetId, timezone })\n await updateCrud('planner/availability-rule-sets', payload, {\n errorMessage: translate('planner.availabilityRuleSets.form.errors.update', 'Failed to update schedule.'),\n })\n flash(translate('planner.availabilityRuleSets.form.flash.updated', 'Schedule updated.'), 'success')\n router.push('/backend/planner/availability-rulesets')\n }, [initialValues?.timezone, router, rulesetId, translate])\n\n const handleDelete = React.useCallback(async () => {\n if (!rulesetId) return\n try {\n await deleteCrud('planner/availability-rule-sets', rulesetId, {\n errorMessage: translate('planner.availabilityRuleSets.form.errors.delete', 'Failed to delete schedule.'),\n })\n flash(translate('planner.availabilityRuleSets.form.flash.deleted', 'Schedule deleted.'), 'success')\n router.push('/backend/planner/availability-rulesets')\n } catch (error) {\n const normalized = normalizeCrudServerError(error)\n flash(\n normalized.message ?? translate('planner.availabilityRuleSets.form.errors.delete', 'Failed to delete schedule.'),\n 'error',\n )\n }\n }, [router, rulesetId, translate])\n\n const buildScheduleItems: AvailabilityScheduleItemBuilder = React.useCallback(({ availabilityRules, bookedEvents, translate: translateLabel }) => {\n const overrideExdates = Array.from(new Set(\n availabilityRules\n .map((rule) => parseAvailabilityRuleWindow(rule))\n .filter((window) => window.repeat === 'once')\n .map((window) => toFullDayWindow(window.startAt).start.toISOString()),\n ))\n const availabilityItems = availabilityRules.map((rule) => {\n const window = parseAvailabilityRuleWindow(rule)\n const isUnavailable = rule.kind === 'unavailability'\n const titleKey = isUnavailable\n ? 'planner.availabilityRuleSets.availability.title.unavailable'\n : `planner.availabilityRuleSets.availability.title.${window.repeat}`\n const fallback = isUnavailable\n ? 'Unavailable'\n : window.repeat === 'weekly'\n ? 'Weekly availability'\n : window.repeat === 'daily'\n ? 'Daily availability'\n : 'Availability'\n const baseTitle = translateLabel(titleKey, fallback)\n const title = rule.note ? `${baseTitle}: ${rule.note}` : baseTitle\n const windowTime = window.repeat === 'once' ? toFullDayWindow(window.startAt) : { start: window.startAt, end: window.endAt }\n const exdates = window.repeat === 'once'\n ? rule.exdates ?? []\n : [...(rule.exdates ?? []), ...overrideExdates]\n return {\n id: rule.id,\n kind: isUnavailable ? 'exception' as const : 'availability' as const,\n title,\n startsAt: windowTime.start,\n endsAt: windowTime.end,\n metadata: { rule: { ...rule, exdates } },\n }\n })\n return availabilityItems\n }, [])\n\n const tabs = React.useMemo(() => ([\n { id: 'details', label: translate('planner.availabilityRuleSets.tabs.details', 'Details') },\n { id: 'availability', label: translate('planner.availabilityRuleSets.tabs.availability', 'Availability') },\n ]), [translate])\n\n const resolvedInitialValues = initialValues ?? {}\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-6\">\n <div className=\"border-b\">\n <nav className=\"flex flex-wrap items-center gap-5 text-sm\" aria-label={translate('planner.availabilityRuleSets.tabs.label', 'Schedule sections')}>\n {tabs.map((tab) => (\n <Button\n key={tab.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={activeTab === tab.id}\n variant=\"ghost\"\n size=\"sm\"\n className={`relative -mb-px h-auto rounded-none border-b-2 px-0 py-2 font-medium ${\n activeTab === tab.id\n ? 'border-
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { normalizeCrudServerError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { AvailabilityRulesEditor, type AvailabilityScheduleItemBuilder } from '@open-mercato/core/modules/planner/components/AvailabilityRulesEditor'\nimport { parseAvailabilityRuleWindow } from '@open-mercato/core/modules/planner/lib/availabilitySchedule'\nimport { extractCustomFieldEntries } from '@open-mercato/shared/lib/crud/custom-fields-client'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { AvailabilityRuleSetForm, buildAvailabilityRuleSetPayload, type AvailabilityRuleSetFormValues } from '@open-mercato/core/modules/planner/components/AvailabilityRuleSetForm'\n\nconst DAY_MS = 24 * 60 * 60 * 1000\n\nfunction toFullDayWindow(value: Date): { start: Date; end: Date } {\n const start = new Date(value.getFullYear(), value.getMonth(), value.getDate())\n const end = new Date(start.getTime() + DAY_MS)\n return { start, end }\n}\n\ntype RuleSetRecord = {\n id: string\n name: string\n description?: string | null\n timezone: string\n updatedAt?: string | null\n name_raw?: string | null\n} & Record<string, unknown>\n\ntype RuleSetResponse = {\n items?: RuleSetRecord[]\n}\n\nexport default function PlannerAvailabilityRuleSetDetailPage({ params }: { params?: { id?: string } }) {\n const rulesetId = params?.id\n const translate = useT()\n const router = useRouter()\n const [initialValues, setInitialValues] = React.useState<AvailabilityRuleSetFormValues | null>(null)\n const [activeTab, setActiveTab] = React.useState<'details' | 'availability'>('details')\n\n React.useEffect(() => {\n if (!rulesetId) return\n const rulesetIdValue = rulesetId\n let cancelled = false\n async function loadRuleSet() {\n try {\n const params = new URLSearchParams({ page: '1', pageSize: '1', ids: rulesetIdValue })\n const payload = await readApiResultOrThrow<RuleSetResponse>(\n `/api/planner/availability-rule-sets?${params.toString()}`,\n undefined,\n { errorMessage: translate('planner.availabilityRuleSets.form.errors.load', 'Failed to load schedule.') },\n )\n const record = Array.isArray(payload.items) ? payload.items[0] : null\n if (!record) throw new Error(translate('planner.availabilityRuleSets.form.errors.notFound', 'Schedule not found.'))\n const customFields = extractCustomFieldEntries(record)\n if (!cancelled) {\n setInitialValues({\n id: record.id,\n name: record.name ?? record.name_raw ?? '',\n description: record.description ?? '',\n timezone: record.timezone ?? 'UTC',\n ...customFields,\n })\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : translate('planner.availabilityRuleSets.form.errors.load', 'Failed to load schedule.')\n flash(message, 'error')\n }\n }\n loadRuleSet()\n return () => { cancelled = true }\n }, [rulesetId, translate])\n\n const handleSubmit = React.useCallback(async (values: AvailabilityRuleSetFormValues) => {\n if (!rulesetId) return\n const timezone = typeof initialValues?.timezone === 'string' && initialValues.timezone.trim().length\n ? initialValues.timezone.trim()\n : 'UTC'\n const payload = buildAvailabilityRuleSetPayload(values, { id: rulesetId, timezone })\n await updateCrud('planner/availability-rule-sets', payload, {\n errorMessage: translate('planner.availabilityRuleSets.form.errors.update', 'Failed to update schedule.'),\n })\n flash(translate('planner.availabilityRuleSets.form.flash.updated', 'Schedule updated.'), 'success')\n router.push('/backend/planner/availability-rulesets')\n }, [initialValues?.timezone, router, rulesetId, translate])\n\n const handleDelete = React.useCallback(async () => {\n if (!rulesetId) return\n try {\n await deleteCrud('planner/availability-rule-sets', rulesetId, {\n errorMessage: translate('planner.availabilityRuleSets.form.errors.delete', 'Failed to delete schedule.'),\n })\n flash(translate('planner.availabilityRuleSets.form.flash.deleted', 'Schedule deleted.'), 'success')\n router.push('/backend/planner/availability-rulesets')\n } catch (error) {\n const normalized = normalizeCrudServerError(error)\n flash(\n normalized.message ?? translate('planner.availabilityRuleSets.form.errors.delete', 'Failed to delete schedule.'),\n 'error',\n )\n }\n }, [router, rulesetId, translate])\n\n const buildScheduleItems: AvailabilityScheduleItemBuilder = React.useCallback(({ availabilityRules, bookedEvents, translate: translateLabel }) => {\n const overrideExdates = Array.from(new Set(\n availabilityRules\n .map((rule) => parseAvailabilityRuleWindow(rule))\n .filter((window) => window.repeat === 'once')\n .map((window) => toFullDayWindow(window.startAt).start.toISOString()),\n ))\n const availabilityItems = availabilityRules.map((rule) => {\n const window = parseAvailabilityRuleWindow(rule)\n const isUnavailable = rule.kind === 'unavailability'\n const titleKey = isUnavailable\n ? 'planner.availabilityRuleSets.availability.title.unavailable'\n : `planner.availabilityRuleSets.availability.title.${window.repeat}`\n const fallback = isUnavailable\n ? 'Unavailable'\n : window.repeat === 'weekly'\n ? 'Weekly availability'\n : window.repeat === 'daily'\n ? 'Daily availability'\n : 'Availability'\n const baseTitle = translateLabel(titleKey, fallback)\n const title = rule.note ? `${baseTitle}: ${rule.note}` : baseTitle\n const windowTime = window.repeat === 'once' ? toFullDayWindow(window.startAt) : { start: window.startAt, end: window.endAt }\n const exdates = window.repeat === 'once'\n ? rule.exdates ?? []\n : [...(rule.exdates ?? []), ...overrideExdates]\n return {\n id: rule.id,\n kind: isUnavailable ? 'exception' as const : 'availability' as const,\n title,\n startsAt: windowTime.start,\n endsAt: windowTime.end,\n metadata: { rule: { ...rule, exdates } },\n }\n })\n return availabilityItems\n }, [])\n\n const tabs = React.useMemo(() => ([\n { id: 'details', label: translate('planner.availabilityRuleSets.tabs.details', 'Details') },\n { id: 'availability', label: translate('planner.availabilityRuleSets.tabs.availability', 'Availability') },\n ]), [translate])\n\n const resolvedInitialValues = initialValues ?? {}\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-6\">\n <div className=\"border-b\">\n <nav className=\"flex flex-wrap items-center gap-5 text-sm\" aria-label={translate('planner.availabilityRuleSets.tabs.label', 'Schedule sections')}>\n {tabs.map((tab) => (\n <Button\n key={tab.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={activeTab === tab.id}\n variant=\"ghost\"\n size=\"sm\"\n className={`relative -mb-px h-auto rounded-none border-b-2 px-0 py-2 font-medium ${\n activeTab === tab.id\n ? 'border-accent-indigo text-foreground'\n : 'border-transparent text-muted-foreground hover:text-foreground'\n }`}\n onClick={() => setActiveTab(tab.id as 'details' | 'availability')}\n >\n {tab.label}\n </Button>\n ))}\n </nav>\n </div>\n\n {activeTab === 'details' ? (\n <AvailabilityRuleSetForm\n title={translate('planner.availabilityRuleSets.form.editTitle', 'Edit schedule')}\n backHref=\"/backend/planner/availability-rulesets\"\n cancelHref=\"/backend/planner/availability-rulesets\"\n initialValues={resolvedInitialValues}\n onSubmit={handleSubmit}\n onDelete={handleDelete}\n isLoading={!initialValues}\n loadingMessage={translate('planner.availabilityRuleSets.form.loading', 'Loading schedule...')}\n />\n ) : (\n <AvailabilityRulesEditor\n subjectType=\"ruleset\"\n subjectId={rulesetId ?? ''}\n initialTimezone={typeof initialValues?.timezone === 'string' ? initialValues.timezone : undefined}\n labelPrefix=\"planner.availabilityRuleSets\"\n mode=\"availability\"\n buildScheduleItems={buildScheduleItems}\n />\n )}\n </div>\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["params"]
|
|
7
7
|
}
|