@modern-admin/web 0.3.5 → 0.4.1
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/README.md +42 -0
- package/dist/config/runtime-config.d.ts +84 -0
- package/dist/config/runtime-config.js +19 -0
- package/dist/config/vite.d.ts +84 -0
- package/dist/config/vite.js +166 -0
- package/dist/lib/index.js +0 -1
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/mount.d.ts.map +1 -1
- package/dist/standalone/assets/{action-component-host-CXIbN-8V.js → action-component-host-BrEZDHZt.js} +2 -2
- package/dist/standalone/assets/action-component-host-BrEZDHZt.js.br +0 -0
- package/dist/standalone/assets/action-component-host-BrEZDHZt.js.gz +0 -0
- package/dist/standalone/assets/{action-component-host-CXIbN-8V.js.map → action-component-host-BrEZDHZt.js.map} +1 -1
- package/dist/standalone/assets/{action-page-OsWfKQ6C.js → action-page-Bx7kzeK7.js} +2 -2
- package/dist/standalone/assets/action-page-Bx7kzeK7.js.br +0 -0
- package/dist/standalone/assets/action-page-Bx7kzeK7.js.gz +0 -0
- package/dist/standalone/assets/{action-page-OsWfKQ6C.js.map → action-page-Bx7kzeK7.js.map} +1 -1
- package/dist/standalone/assets/{ai-assistant-widget-Bt4Z7Fmr.js → ai-assistant-widget-BbIXVrSu.js} +2 -2
- package/dist/standalone/assets/ai-assistant-widget-BbIXVrSu.js.br +0 -0
- package/dist/standalone/assets/ai-assistant-widget-BbIXVrSu.js.gz +0 -0
- package/dist/standalone/assets/{ai-assistant-widget-Bt4Z7Fmr.js.map → ai-assistant-widget-BbIXVrSu.js.map} +1 -1
- package/dist/standalone/assets/{audit-log-page-2wuGiWg-.js → audit-log-page-BoZh23oQ.js} +2 -2
- package/dist/standalone/assets/audit-log-page-BoZh23oQ.js.br +0 -0
- package/dist/standalone/assets/audit-log-page-BoZh23oQ.js.gz +0 -0
- package/dist/standalone/assets/{audit-log-page-2wuGiWg-.js.map → audit-log-page-BoZh23oQ.js.map} +1 -1
- package/dist/standalone/assets/{calendar-BZVUWakC.js → calendar-nvD_z7KQ.js} +2 -2
- package/dist/standalone/assets/calendar-nvD_z7KQ.js.br +0 -0
- package/dist/standalone/assets/calendar-nvD_z7KQ.js.gz +0 -0
- package/dist/standalone/assets/{calendar-BZVUWakC.js.map → calendar-nvD_z7KQ.js.map} +1 -1
- package/dist/standalone/assets/{chart-widget-BtJb6YXV.js → chart-widget-YeCL7jdB.js} +2 -2
- package/dist/standalone/assets/chart-widget-YeCL7jdB.js.br +0 -0
- package/dist/standalone/assets/chart-widget-YeCL7jdB.js.gz +0 -0
- package/dist/standalone/assets/{chart-widget-BtJb6YXV.js.map → chart-widget-YeCL7jdB.js.map} +1 -1
- package/dist/standalone/assets/{command-BNF_evMy.js → command-Sb0xL-se.js} +2 -2
- package/dist/standalone/assets/command-Sb0xL-se.js.br +0 -0
- package/dist/standalone/assets/command-Sb0xL-se.js.gz +0 -0
- package/dist/standalone/assets/{command-BNF_evMy.js.map → command-Sb0xL-se.js.map} +1 -1
- package/dist/standalone/assets/date-picker-C4HcgidQ.js +2 -0
- package/dist/standalone/assets/date-picker-C4HcgidQ.js.br +0 -0
- package/dist/standalone/assets/date-picker-C4HcgidQ.js.gz +0 -0
- package/dist/standalone/assets/date-picker-C4HcgidQ.js.map +1 -0
- package/dist/standalone/assets/{edit-page-DCRB9Y_q.js → edit-page-CW7-FAPC.js} +2 -2
- package/dist/standalone/assets/edit-page-CW7-FAPC.js.br +0 -0
- package/dist/standalone/assets/edit-page-CW7-FAPC.js.gz +0 -0
- package/dist/standalone/assets/{edit-page-DCRB9Y_q.js.map → edit-page-CW7-FAPC.js.map} +1 -1
- package/dist/standalone/assets/{empty-DAEAjFd3.js → empty-Cposcczv.js} +2 -2
- package/dist/standalone/assets/empty-Cposcczv.js.br +0 -0
- package/dist/standalone/assets/empty-Cposcczv.js.gz +0 -0
- package/dist/standalone/assets/{empty-DAEAjFd3.js.map → empty-Cposcczv.js.map} +1 -1
- package/dist/standalone/assets/{global-search-dialog-HMLztOho.js → global-search-dialog-DLv_nIvM.js} +2 -2
- package/dist/standalone/assets/global-search-dialog-DLv_nIvM.js.br +0 -0
- package/dist/standalone/assets/global-search-dialog-DLv_nIvM.js.gz +0 -0
- package/dist/standalone/assets/{global-search-dialog-HMLztOho.js.map → global-search-dialog-DLv_nIvM.js.map} +1 -1
- package/dist/standalone/assets/{heavy-fields-ZuqfOFMv.js → heavy-fields-BiCEgD2L.js} +2 -2
- package/dist/standalone/assets/heavy-fields-BiCEgD2L.js.br +0 -0
- package/dist/standalone/assets/heavy-fields-BiCEgD2L.js.gz +0 -0
- package/dist/standalone/assets/{heavy-fields-ZuqfOFMv.js.map → heavy-fields-BiCEgD2L.js.map} +1 -1
- package/dist/standalone/assets/{home-page-HmheewiP.js → home-page-BSz1wGk0.js} +3 -3
- package/dist/standalone/assets/home-page-BSz1wGk0.js.br +0 -0
- package/dist/standalone/assets/home-page-BSz1wGk0.js.gz +0 -0
- package/dist/standalone/assets/{home-page-HmheewiP.js.map → home-page-BSz1wGk0.js.map} +1 -1
- package/dist/standalone/assets/{icon-registry-BV44--RL.js → icon-registry-BQU4fIc4.js} +2 -2
- package/dist/standalone/assets/icon-registry-BQU4fIc4.js.br +0 -0
- package/dist/standalone/assets/{icon-registry-BV44--RL.js.gz → icon-registry-BQU4fIc4.js.gz} +0 -0
- package/dist/standalone/assets/{icon-registry-BV44--RL.js.map → icon-registry-BQU4fIc4.js.map} +1 -1
- package/dist/standalone/assets/index-BL8keDxQ.js +15 -0
- package/dist/standalone/assets/index-BL8keDxQ.js.br +0 -0
- package/dist/standalone/assets/index-BL8keDxQ.js.gz +0 -0
- package/dist/standalone/assets/{index-t4woXGa-.js.map → index-BL8keDxQ.js.map} +1 -1
- package/dist/standalone/assets/{json-editor-sGw4fDoj.js → json-editor-CAIgxYb3.js} +2 -2
- package/dist/standalone/assets/json-editor-CAIgxYb3.js.br +0 -0
- package/dist/standalone/assets/json-editor-CAIgxYb3.js.gz +0 -0
- package/dist/standalone/assets/{json-editor-sGw4fDoj.js.map → json-editor-CAIgxYb3.js.map} +1 -1
- package/dist/standalone/assets/{property-renderer-DyCwdVkh.js → property-renderer-B8Md-EqW.js} +4 -4
- package/dist/standalone/assets/property-renderer-B8Md-EqW.js.br +0 -0
- package/dist/standalone/assets/property-renderer-B8Md-EqW.js.gz +0 -0
- package/dist/standalone/assets/property-renderer-B8Md-EqW.js.map +1 -0
- package/dist/standalone/assets/{reference-Dfd804y3.js → reference-WPaf6IdD.js} +2 -2
- package/dist/standalone/assets/reference-WPaf6IdD.js.br +0 -0
- package/dist/standalone/assets/reference-WPaf6IdD.js.gz +0 -0
- package/dist/standalone/assets/{reference-Dfd804y3.js.map → reference-WPaf6IdD.js.map} +1 -1
- package/dist/standalone/assets/{revisions-button-DXZAh2Lu.js → revisions-button-0WtL6bsZ.js} +2 -2
- package/dist/standalone/assets/revisions-button-0WtL6bsZ.js.br +0 -0
- package/dist/standalone/assets/revisions-button-0WtL6bsZ.js.gz +0 -0
- package/dist/standalone/assets/{revisions-button-DXZAh2Lu.js.map → revisions-button-0WtL6bsZ.js.map} +1 -1
- package/dist/standalone/assets/{select-BWf6walM.js → select-CR4acjX0.js} +2 -2
- package/dist/standalone/assets/select-CR4acjX0.js.br +0 -0
- package/dist/standalone/assets/select-CR4acjX0.js.gz +0 -0
- package/dist/standalone/assets/{select-BWf6walM.js.map → select-CR4acjX0.js.map} +1 -1
- package/dist/standalone/assets/{settings-page-Co7sWbbL.js → settings-page-DtguXLAP.js} +2 -2
- package/dist/standalone/assets/settings-page-DtguXLAP.js.br +0 -0
- package/dist/standalone/assets/settings-page-DtguXLAP.js.gz +0 -0
- package/dist/standalone/assets/{settings-page-Co7sWbbL.js.map → settings-page-DtguXLAP.js.map} +1 -1
- package/dist/standalone/assets/{show-page-D-_vldWV.js → show-page-Dnox2NwO.js} +2 -2
- package/dist/standalone/assets/show-page-Dnox2NwO.js.br +0 -0
- package/dist/standalone/assets/show-page-Dnox2NwO.js.gz +0 -0
- package/dist/standalone/assets/{show-page-D-_vldWV.js.map → show-page-Dnox2NwO.js.map} +1 -1
- package/dist/standalone/assets/{tabs-khcHka8W.js → tabs-DUS8e6dR.js} +2 -2
- package/dist/standalone/assets/tabs-DUS8e6dR.js.br +0 -0
- package/dist/standalone/assets/tabs-DUS8e6dR.js.gz +0 -0
- package/dist/standalone/assets/{tabs-khcHka8W.js.map → tabs-DUS8e6dR.js.map} +1 -1
- package/dist/standalone/assets/{value-format-CPnbnlE6.js → value-format-Cgau0meh.js} +2 -2
- package/dist/standalone/assets/value-format-Cgau0meh.js.br +0 -0
- package/dist/standalone/assets/{value-format-CPnbnlE6.js.gz → value-format-Cgau0meh.js.gz} +0 -0
- package/dist/standalone/assets/{value-format-CPnbnlE6.js.map → value-format-Cgau0meh.js.map} +1 -1
- package/dist/standalone/assets/{wizard-create-page-CFwMs8E3.js → wizard-create-page-v2-Aw8Oj.js} +2 -2
- package/dist/standalone/assets/wizard-create-page-v2-Aw8Oj.js.br +0 -0
- package/dist/standalone/assets/wizard-create-page-v2-Aw8Oj.js.gz +0 -0
- package/dist/standalone/assets/{wizard-create-page-CFwMs8E3.js.map → wizard-create-page-v2-Aw8Oj.js.map} +1 -1
- package/dist/standalone/assets/{zod-BbfEBA4A.js → zod-BrelKLfy.js} +2 -2
- package/dist/standalone/assets/zod-BrelKLfy.js.br +0 -0
- package/dist/standalone/assets/zod-BrelKLfy.js.gz +0 -0
- package/dist/standalone/assets/{zod-BbfEBA4A.js.map → zod-BrelKLfy.js.map} +1 -1
- package/dist/standalone/index.html +4 -4
- package/dist/standalone/index.html.br +0 -0
- package/dist/standalone/index.html.gz +0 -0
- package/package.json +28 -6
- package/src/mount.tsx +8 -2
- package/src/standalone.tsx +1 -0
- package/src/vite.ts +219 -0
- package/vite.config.ts +13 -104
- package/dist/standalone/assets/action-component-host-CXIbN-8V.js.br +0 -0
- package/dist/standalone/assets/action-component-host-CXIbN-8V.js.gz +0 -0
- package/dist/standalone/assets/action-page-OsWfKQ6C.js.br +0 -0
- package/dist/standalone/assets/action-page-OsWfKQ6C.js.gz +0 -0
- package/dist/standalone/assets/ai-assistant-widget-Bt4Z7Fmr.js.br +0 -0
- package/dist/standalone/assets/ai-assistant-widget-Bt4Z7Fmr.js.gz +0 -0
- package/dist/standalone/assets/audit-log-page-2wuGiWg-.js.br +0 -0
- package/dist/standalone/assets/audit-log-page-2wuGiWg-.js.gz +0 -0
- package/dist/standalone/assets/calendar-BZVUWakC.js.br +0 -0
- package/dist/standalone/assets/calendar-BZVUWakC.js.gz +0 -0
- package/dist/standalone/assets/chart-widget-BtJb6YXV.js.br +0 -0
- package/dist/standalone/assets/chart-widget-BtJb6YXV.js.gz +0 -0
- package/dist/standalone/assets/command-BNF_evMy.js.br +0 -0
- package/dist/standalone/assets/command-BNF_evMy.js.gz +0 -0
- package/dist/standalone/assets/date-picker-LfbUehd1.js +0 -2
- package/dist/standalone/assets/date-picker-LfbUehd1.js.br +0 -0
- package/dist/standalone/assets/date-picker-LfbUehd1.js.gz +0 -0
- package/dist/standalone/assets/date-picker-LfbUehd1.js.map +0 -1
- package/dist/standalone/assets/edit-page-DCRB9Y_q.js.br +0 -0
- package/dist/standalone/assets/edit-page-DCRB9Y_q.js.gz +0 -0
- package/dist/standalone/assets/empty-DAEAjFd3.js.br +0 -0
- package/dist/standalone/assets/empty-DAEAjFd3.js.gz +0 -0
- package/dist/standalone/assets/global-search-dialog-HMLztOho.js.br +0 -0
- package/dist/standalone/assets/global-search-dialog-HMLztOho.js.gz +0 -0
- package/dist/standalone/assets/heavy-fields-ZuqfOFMv.js.br +0 -0
- package/dist/standalone/assets/heavy-fields-ZuqfOFMv.js.gz +0 -0
- package/dist/standalone/assets/home-page-HmheewiP.js.br +0 -0
- package/dist/standalone/assets/home-page-HmheewiP.js.gz +0 -0
- package/dist/standalone/assets/icon-registry-BV44--RL.js.br +0 -0
- package/dist/standalone/assets/index-t4woXGa-.js +0 -15
- package/dist/standalone/assets/index-t4woXGa-.js.br +0 -0
- package/dist/standalone/assets/index-t4woXGa-.js.gz +0 -0
- package/dist/standalone/assets/json-editor-sGw4fDoj.js.br +0 -0
- package/dist/standalone/assets/json-editor-sGw4fDoj.js.gz +0 -0
- package/dist/standalone/assets/property-renderer-DyCwdVkh.js.br +0 -0
- package/dist/standalone/assets/property-renderer-DyCwdVkh.js.gz +0 -0
- package/dist/standalone/assets/property-renderer-DyCwdVkh.js.map +0 -1
- package/dist/standalone/assets/reference-Dfd804y3.js.br +0 -0
- package/dist/standalone/assets/reference-Dfd804y3.js.gz +0 -0
- package/dist/standalone/assets/revisions-button-DXZAh2Lu.js.br +0 -0
- package/dist/standalone/assets/revisions-button-DXZAh2Lu.js.gz +0 -0
- package/dist/standalone/assets/select-BWf6walM.js.br +0 -0
- package/dist/standalone/assets/select-BWf6walM.js.gz +0 -0
- package/dist/standalone/assets/settings-page-Co7sWbbL.js.br +0 -0
- package/dist/standalone/assets/settings-page-Co7sWbbL.js.gz +0 -0
- package/dist/standalone/assets/show-page-D-_vldWV.js.br +0 -0
- package/dist/standalone/assets/show-page-D-_vldWV.js.gz +0 -0
- package/dist/standalone/assets/tabs-khcHka8W.js.br +0 -0
- package/dist/standalone/assets/tabs-khcHka8W.js.gz +0 -0
- package/dist/standalone/assets/value-format-CPnbnlE6.js.br +0 -0
- package/dist/standalone/assets/wizard-create-page-CFwMs8E3.js.br +0 -0
- package/dist/standalone/assets/wizard-create-page-CFwMs8E3.js.gz +0 -0
- package/dist/standalone/assets/zod-BbfEBA4A.js.br +0 -0
- package/dist/standalone/assets/zod-BbfEBA4A.js.gz +0 -0
package/dist/standalone/assets/{settings-page-Co7sWbbL.js.map → settings-page-DtguXLAP.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-page-Co7sWbbL.js","names":[],"sources":["../../../../react/src/pages/settings-shared.tsx","../../../../react/src/pages/ai-assistant-settings-section.tsx","../../../../react/src/pages/settings-page.tsx"],"sourcesContent":["// Shared layout primitives for the Settings hub. Every section in\n// `settings-page.tsx` (API keys, webhooks, AI assistant, ...) should use\n// these so the look, spacing, and mobile behavior stays uniform.\n\nimport * as React from 'react'\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n Empty,\n EmptyDescription,\n EmptyHeader,\n EmptyMedia,\n EmptyTitle,\n cn,\n} from '@modern-admin/ui'\n\ntype IconComponent = React.ComponentType<{ className?: string }>\n\ninterface SettingsCardProps {\n icon: IconComponent\n title: React.ReactNode\n description?: React.ReactNode\n action?: React.ReactNode\n /** Removes default padding/header so the card body can fill edge-to-edge. */\n bodyClassName?: string\n children: React.ReactNode\n}\n\n/**\n * Unified card wrapper for a settings section. Header collapses\n * vertically on mobile and lays the action button to the right on `sm+`.\n * `CardContent` gets `min-w-0` so tables/grids inside can shrink and\n * scroll horizontally instead of forcing the parent grid wider.\n */\nexport function SettingsCard({\n icon: Icon,\n title,\n description,\n action,\n bodyClassName,\n children,\n}: SettingsCardProps): React.ReactElement {\n return (\n <Card>\n <CardHeader\n className={cn(\n 'flex-col items-start gap-2',\n action && 'sm:flex-row sm:items-center sm:justify-between',\n )}\n >\n <div className=\"flex min-w-0 flex-col gap-1.5\">\n <CardTitle className=\"flex items-center gap-2\">\n <Icon className=\"size-5\" />\n {title}\n </CardTitle>\n {description ? <CardDescription>{description}</CardDescription> : null}\n </div>\n {action}\n </CardHeader>\n <CardContent className={cn('min-w-0', bodyClassName)}>{children}</CardContent>\n </Card>\n )\n}\n\n/**\n * Horizontal-scroll wrapper for tables inside `SettingsCard`. On mobile\n * the content extends to the card edges (`-mx-6`) so the user sees the\n * left edge of the table flush with the card; from `sm+` the negative\n * margin is removed.\n */\nexport function SettingsTableScroll({ children }: { children: React.ReactNode }): React.ReactElement {\n return <div className=\"-mx-6 overflow-x-auto sm:mx-0\">{children}</div>\n}\n\ninterface SettingsEmptyProps {\n icon: IconComponent\n title: React.ReactNode\n description?: React.ReactNode\n}\n\nexport function SettingsEmpty({ icon: Icon, title, description }: SettingsEmptyProps): React.ReactElement {\n return (\n <Empty className=\"border-0\">\n <EmptyHeader>\n <EmptyMedia>\n <Icon />\n </EmptyMedia>\n <EmptyTitle>{title}</EmptyTitle>\n {description ? <EmptyDescription>{description}</EmptyDescription> : null}\n </EmptyHeader>\n </Empty>\n )\n}\n\ninterface SettingsListStateProps {\n isLoading: boolean\n error: unknown\n isEmpty: boolean\n loadingLabel: React.ReactNode\n empty: SettingsEmptyProps\n children: React.ReactNode\n}\n\n/**\n * Renders one of: loading row, destructive error banner, empty state, or\n * the actual list `children`. Keeps every section's \"list with status\"\n * surface identical.\n */\nexport function SettingsListState({\n isLoading,\n error,\n isEmpty,\n loadingLabel,\n empty,\n children,\n}: SettingsListStateProps): React.ReactElement {\n if (isLoading) {\n return <div className=\"py-8 text-center text-sm text-muted-foreground\">{loadingLabel}</div>\n }\n if (error) {\n return (\n <div className=\"rounded-md border border-destructive/50 bg-destructive/10 p-4 text-sm text-destructive\">\n {error instanceof Error ? error.message : String(error)}\n </div>\n )\n }\n if (isEmpty) {\n return <SettingsEmpty {...empty} />\n }\n return <>{children}</>\n}\n","import * as React from 'react'\nimport { useMutation, useQuery } from '@tanstack/react-query'\nimport { Badge, Button, Input, Label, Switch, Textarea } from '@modern-admin/ui'\nimport { Bot, KeyRound, Save } from 'lucide-react'\nimport { useAdminClient } from '../provider.js'\nimport { useNotify } from '../notify.js'\nimport { useI18n } from '../i18n.js'\nimport type { AiAssistantSettings } from '../client.js'\nimport { SettingsCard } from './settings-shared.js'\n\nexport function AiAssistantSettingsSection(): React.ReactElement {\n const client = useAdminClient()\n const notify = useNotify()\n const { t } = useI18n()\n const settings = useQuery({\n queryKey: ['modern-admin', 'ai-assistant', 'settings'],\n queryFn: () => client.getAiAssistantSettings(),\n })\n const [form, setForm] = React.useState({\n enabled: true,\n model: 'google/gemini-3.1-flash-lite-preview',\n apiKey: '',\n systemPrompt: '',\n })\n\n React.useEffect(() => {\n if (!settings.data) return\n setForm({\n enabled: settings.data.enabled,\n model: settings.data.model,\n apiKey: '',\n systemPrompt: settings.data.systemPrompt,\n })\n }, [settings.data])\n\n const save = useMutation({\n mutationFn: async (): Promise<AiAssistantSettings> =>\n client.updateAiAssistantSettings({\n enabled: form.enabled,\n model: form.model,\n ...(form.apiKey.trim() ? { apiKey: form.apiKey.trim() } : {}),\n systemPrompt: form.systemPrompt,\n }),\n onSuccess: () => {\n settings.refetch()\n setForm((prev) => ({ ...prev, apiKey: '' }))\n notify.success({ message: t('aiAssistant:settings.saved') })\n },\n onError: (err) => {\n notify.error({ message: err instanceof Error ? err.message : String(err) })\n },\n })\n\n if (settings.isLoading) {\n return <div className=\"py-8 text-sm text-muted-foreground\">{t('common:loading')}</div>\n }\n\n if (settings.error) {\n return (\n <div className=\"rounded-md border border-destructive/50 bg-destructive/10 p-4 text-sm text-destructive\">\n {settings.error instanceof Error ? settings.error.message : String(settings.error)}\n </div>\n )\n }\n\n const data = settings.data\n if (!data) {\n return <div className=\"py-8 text-sm text-muted-foreground\">{t('aiAssistant:settings.empty')}</div>\n }\n\n return (\n <div className=\"flex flex-col gap-4\">\n <SettingsCard\n icon={Bot}\n title={t('aiAssistant:settings.title')}\n description={t('aiAssistant:settings.description')}\n bodyClassName=\"space-y-4\"\n >\n <div className=\"flex flex-wrap items-center gap-2\">\n <Badge variant={data.enabled ? 'secondary' : 'outline'}>\n {data.enabled ? t('aiAssistant:settings.enabled') : t('aiAssistant:settings.disabled')}\n </Badge>\n <Badge variant={data.configured ? 'secondary' : 'outline'}>\n {data.configured ? t('aiAssistant:settings.configured') : t('aiAssistant:settings.apiKeyRequired')}\n </Badge>\n <Badge variant=\"outline\">{t('aiAssistant:settings.readOnly')}</Badge>\n <Badge variant=\"outline\">{t('aiAssistant:settings.provider', { provider: data.provider })}</Badge>\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"flex items-center justify-between rounded-lg border border-border p-3\">\n <div className=\"space-y-1\">\n <Label htmlFor=\"ai-assistant-enabled\">{t('aiAssistant:settings.enableLabel')}</Label>\n <p className=\"text-xs text-muted-foreground\">\n {t('aiAssistant:settings.enableHint')}\n </p>\n </div>\n <Switch\n id=\"ai-assistant-enabled\"\n checked={form.enabled}\n disabled={!data.canManage || save.isPending}\n onCheckedChange={(enabled) => setForm((prev) => ({ ...prev, enabled }))}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"ai-assistant-model\">{t('aiAssistant:settings.modelLabel')}</Label>\n <Input\n id=\"ai-assistant-model\"\n value={form.model}\n disabled={!data.canManage || save.isPending}\n onChange={(e) => setForm((prev) => ({ ...prev, model: e.target.value }))}\n placeholder=\"google/gemini-3.1-flash-lite-preview\"\n />\n </div>\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"ai-assistant-api-key\" className=\"flex items-center gap-2\">\n <KeyRound className=\"size-4\"/>\n {t('aiAssistant:settings.apiKeyLabel')}\n </Label>\n <Input\n id=\"ai-assistant-api-key\"\n type=\"password\"\n value={form.apiKey}\n disabled={!data.canManage || save.isPending}\n onChange={(e) => setForm((prev) => ({ ...prev, apiKey: e.target.value }))}\n placeholder={data.maskedApiKey ?? 'sk-or-v1-...'}\n />\n <p className=\"text-xs text-muted-foreground\">\n {t('aiAssistant:settings.apiKeyHint')}\n </p>\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"ai-assistant-system-prompt\">{t('aiAssistant:settings.systemPromptLabel')}</Label>\n <Textarea\n id=\"ai-assistant-system-prompt\"\n value={form.systemPrompt}\n disabled={!data.canManage || save.isPending}\n onChange={(e) => setForm((prev) => ({ ...prev, systemPrompt: e.target.value }))}\n rows={8}\n placeholder={t('aiAssistant:settings.systemPromptPlaceholder')}\n />\n </div>\n\n <div className=\"flex items-center justify-between gap-3 rounded-lg border border-border p-3 text-sm\">\n <div>\n <div className=\"font-medium\">{t('aiAssistant:settings.accessTitle')}</div>\n <div className=\"text-muted-foreground\">\n {t('aiAssistant:settings.accessDescription')}\n </div>\n </div>\n <Badge variant=\"outline\">{t('aiAssistant:settings.futureToolsReady')}</Badge>\n </div>\n\n <div className=\"flex justify-end\">\n <Button onClick={() => save.mutate()} disabled={!data.canManage || save.isPending || !form.model.trim()}>\n <Save className=\"size-4\"/>\n {save.isPending ? t('aiAssistant:settings.saving') : t('aiAssistant:settings.save')}\n </Button>\n </div>\n </SettingsCard>\n </div>\n )\n}\n","// Admin Settings hub. Reachable from the user/profile dropdown menu and\n// rendered by the router for `/settings/<section>`. Currently three\n// sections: `api-keys`, `webhooks`, `ai-assistant`; the layout is built so\n// adding more sections is just a new entry in `SECTIONS` + a switch case.\n\nimport * as React from 'react'\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport {\n Badge,\n Button,\n Checkbox,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n InfoTooltip,\n Input,\n JsonEditor,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Switch,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n cn,\n} from '@modern-admin/ui'\nimport {\n AlertTriangle,\n Bot,\n Check,\n Copy,\n Edit,\n Eye,\n EyeOff,\n KeyRound,\n Plus,\n Settings as SettingsIcon,\n Trash2,\n X,\n} from 'lucide-react'\nimport { useAdminClient } from '../provider.js'\nimport { useFeatures, useResources } from '../hooks.js'\nimport { useI18n } from '../i18n.js'\nimport { Link, useNavigate } from '../router.js'\nimport { useNotify } from '../notify.js'\nimport { useDialogs } from '../dialogs.js'\nimport type { ApiKeyRecord, WebhookInput, WebhookRecord } from '../client.js'\nimport type { ResourceJSON } from '../types.js'\nimport { getSettingsSectionExtensions } from '../extension-registry.js'\nimport { AiAssistantSettingsSection } from './ai-assistant-settings-section.js'\nimport { SettingsCard, SettingsListState, SettingsTableScroll } from './settings-shared.js'\n\nconst KEY_LIST = ['modern-admin', 'api-keys'] as const\nconst KEY_WEBHOOKS = ['modern-admin', 'webhooks'] as const\n\ntype BuiltInSectionKey = 'api-keys' | 'ai-assistant' | 'webhooks'\n\ninterface SectionDef {\n key: string\n labelKey: string\n icon: React.ComponentType<{ className?: string }>\n /** When `true`, the section is supplied by an extension (no built-in renderer). */\n isExtension?: boolean\n}\n\nconst BUILT_IN_SECTIONS: SectionDef[] = [\n { key: 'api-keys', labelKey: 'settings:apiKeys.title', icon: KeyRound },\n { key: 'webhooks', labelKey: 'settings:webhooks.title', icon: SettingsIcon },\n { key: 'ai-assistant', labelKey: 'aiAssistant:title', icon: Bot },\n]\n\nexport function SettingsPage({ section }: { section?: string }): React.ReactElement {\n const { t } = useI18n()\n const navigate = useNavigate()\n const features = useFeatures()\n // Only surface built-in sections whose backend subsystem is wired.\n // Extension sections are always shown when registered.\n const SECTIONS = React.useMemo<SectionDef[]>(\n () => [\n ...BUILT_IN_SECTIONS.filter((s) =>\n s.key === 'api-keys' ? features.apiKeys\n : s.key === 'webhooks' ? features.webhooks\n : s.key === 'ai-assistant' ? features.aiAssistant\n : true,\n ),\n ...getSettingsSectionExtensions().map((ext) => ({\n key: ext.key,\n labelKey: ext.labelKey,\n icon: ext.icon,\n isExtension: true as const,\n })),\n ],\n\n [features.apiKeys, features.webhooks, features.aiAssistant],\n )\n // Resolve the requested section. If the URL is bogus or the section is\n // disabled, fall back to the first enabled section.\n const builtInKeys: BuiltInSectionKey[] = ['api-keys', 'webhooks', 'ai-assistant']\n const isBuiltIn = (k: string): k is BuiltInSectionKey =>\n (builtInKeys as string[]).includes(k)\n const requested: string | null = section ?? null\n const active: string | null =\n requested && SECTIONS.some((s) => s.key === requested)\n ? requested\n : (SECTIONS[0]?.key ?? null)\n if (active === null) {\n // Defensive: the user menu hides Settings entirely when no section is\n // available, so users normally won't land here. Direct navigation to\n // /settings without any configured section ends up showing this.\n return (\n <div className=\"rounded-md border border-dashed bg-card p-8 text-center text-sm text-muted-foreground\">\n {t('settings:noSectionsConfigured')}\n </div>\n )\n }\n return (\n // `minmax(0,1fr)` (not bare `1fr`) lets the content column shrink below\n // its intrinsic min-width — otherwise wide tables push the whole grid\n // past the viewport at ~`lg` widths (~1000–1100px).\n <div className=\"flex flex-col gap-4 lg:grid lg:grid-cols-[14rem_minmax(0,1fr)]\">\n {/* Mobile: dropdown selector (handles many sections gracefully) */}\n <div className=\"lg:hidden\">\n <Select value={active ?? ''} onValueChange={(v) => navigate({ name: 'settings', section: v })}>\n <SelectTrigger className=\"w-full\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {SECTIONS.map(({ key, labelKey, icon: Icon }) => (\n <SelectItem key={key} value={key}>\n <span className=\"flex items-center gap-2\">\n <Icon className=\"size-4\" />\n <span>{t(labelKey)}</span>\n </span>\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n {/* Desktop: sidebar nav */}\n <aside className=\"hidden lg:block\">\n <nav className=\"flex flex-col gap-1\">\n {SECTIONS.map(({ key, labelKey, icon: Icon }) => (\n <Link\n key={key}\n to={{ name: 'settings', section: key }}\n className={cn(\n 'flex items-center gap-2 rounded-md px-3 py-2 text-sm hover:bg-accent',\n active === key && 'bg-accent font-medium',\n )}\n >\n <Icon className=\"size-4\" />\n <span>{t(labelKey)}</span>\n </Link>\n ))}\n </nav>\n </aside>\n <section className=\"min-w-0\">\n {active && isBuiltIn(active) && active === 'api-keys' && <ApiKeysSection />}\n {active && isBuiltIn(active) && active === 'webhooks' && <WebhooksSection />}\n {active && isBuiltIn(active) && active === 'ai-assistant' && <AiAssistantSettingsSection />}\n {active && !isBuiltIn(active) && (() => {\n const extSection = getSettingsSectionExtensions().find((e) => e.key === active)\n return extSection ? <extSection.component /> : null\n })()}\n </section>\n </div>\n )\n}\n\n// ─── API Keys section ─────────────────────────────────────────────────────────\n\nfunction ApiKeysSection(): React.ReactElement {\n const { t } = useI18n()\n const client = useAdminClient()\n const qc = useQueryClient()\n const notify = useNotify()\n const dialogs = useDialogs()\n const resources = useResources()\n const [editorOpen, setEditorOpen] = React.useState(false)\n const [editing, setEditing] = React.useState<ApiKeyRecord | null>(null)\n const [createdSecret, setCreatedSecret] = React.useState<{ key: string; record: ApiKeyRecord } | null>(null)\n\n const list = useQuery({\n queryKey: KEY_LIST,\n queryFn: () => client.listApiKeys(),\n })\n\n const deleteMut = useMutation({\n mutationFn: (id: string) => client.deleteApiKey(id),\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: KEY_LIST })\n notify.success({ key: 'settings:apiKeys.notice.revoked' })\n },\n onError: (err) => notify.error({ message: err instanceof Error ? err.message : String(err) }),\n })\n\n const toggleEnabledMut = useMutation({\n mutationFn: (vars: { id: string; enabled: boolean }) =>\n client.updateApiKey(vars.id, { enabled: vars.enabled }),\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY_LIST }),\n onError: (err) => notify.error({ message: err instanceof Error ? err.message : String(err) }),\n })\n\n const onCreate = (): void => {\n setEditing(null)\n setEditorOpen(true)\n }\n\n const onEdit = (key: ApiKeyRecord): void => {\n setEditing(key)\n setEditorOpen(true)\n }\n\n const onRevoke = async (key: ApiKeyRecord): Promise<void> => {\n const ok = await dialogs.confirm({\n title: t('settings:apiKeys.confirmRevoke.title'),\n description: t('settings:apiKeys.confirmRevoke.description', { name: key.name ?? key.id }),\n confirmLabel: t('settings:apiKeys.actions.revoke'),\n destructive: true,\n })\n if (ok) deleteMut.mutate(key.id)\n }\n\n const keys = list.data?.keys ?? []\n\n return (\n <div className=\"flex flex-col gap-4\">\n <SettingsCard\n icon={KeyRound}\n title={t('settings:apiKeys.title')}\n description={t('settings:apiKeys.description')}\n action={\n <Button onClick={onCreate} size=\"sm\">\n <Plus className=\"size-4\" />\n <span>{t('settings:apiKeys.actions.create')}</span>\n </Button>\n }\n >\n <SettingsListState\n isLoading={list.isLoading}\n error={list.error}\n isEmpty={keys.length === 0}\n loadingLabel={t('common:loading')}\n empty={{\n icon: KeyRound,\n title: t('settings:apiKeys.empty.title'),\n description: t('settings:apiKeys.empty.description'),\n }}\n >\n <SettingsTableScroll>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>{t('settings:apiKeys.columns.name')}</TableHead>\n <TableHead className=\"hidden sm:table-cell\">{t('settings:apiKeys.columns.start')}</TableHead>\n <TableHead className=\"hidden md:table-cell\">{t('settings:apiKeys.columns.permissions')}</TableHead>\n <TableHead className=\"hidden md:table-cell\">{t('settings:apiKeys.columns.expiresAt')}</TableHead>\n <TableHead>{t('settings:apiKeys.columns.enabled')}</TableHead>\n <TableHead className=\"text-right\">{t('settings:apiKeys.columns.actions')}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {keys.map((k) => (\n <TableRow key={k.id}>\n <TableCell className=\"font-medium\">\n <div className=\"flex flex-col\">\n <span>{k.name ?? k.id}</span>\n {k.lastRequest && (\n <span className=\"text-xs text-muted-foreground\">\n {t('settings:apiKeys.lastUsed', { date: formatDate(k.lastRequest) })}\n </span>\n )}\n </div>\n </TableCell>\n <TableCell className=\"hidden font-mono text-xs sm:table-cell\">\n {k.start ? `${k.start}…` : '—'}\n </TableCell>\n <TableCell className=\"hidden md:table-cell\">\n <PermissionsSummary permissions={k.permissions} />\n </TableCell>\n <TableCell className=\"hidden md:table-cell text-xs\">\n {k.expiresAt ? formatDate(k.expiresAt) : t('settings:apiKeys.expiresNever')}\n </TableCell>\n <TableCell>\n <Switch\n checked={k.enabled}\n onCheckedChange={(enabled) => toggleEnabledMut.mutate({ id: k.id, enabled })}\n aria-label={t('settings:apiKeys.columns.enabled')}\n />\n </TableCell>\n <TableCell className=\"text-right\">\n <div className=\"inline-flex gap-1\">\n <Button variant=\"ghost\" size=\"sm\" onClick={() => onEdit(k)} aria-label={t('settings:apiKeys.actions.edit')}>\n <Edit className=\"size-4\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => onRevoke(k)}\n aria-label={t('settings:apiKeys.actions.revoke')}\n disabled={deleteMut.isPending}\n >\n <Trash2 className=\"size-4 text-destructive\" />\n </Button>\n </div>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </SettingsTableScroll>\n </SettingsListState>\n </SettingsCard>\n\n <ApiKeyEditorDialog\n key={editing?.id ?? 'new'}\n open={editorOpen}\n onOpenChange={setEditorOpen}\n editing={editing}\n resources={resources}\n onCreated={(result) => {\n setEditorOpen(false)\n setCreatedSecret(result)\n qc.invalidateQueries({ queryKey: KEY_LIST })\n }}\n onUpdated={() => {\n setEditorOpen(false)\n qc.invalidateQueries({ queryKey: KEY_LIST })\n }}\n />\n\n <CreatedSecretDialog\n secret={createdSecret}\n onClose={() => setCreatedSecret(null)}\n />\n </div>\n )\n}\n\n// ─── Permissions matrix editor ────────────────────────────────────────────────\n\ninterface PermissionsState {\n /** resourceId -> Set<actionName>. `'*'` means all actions of that resource. */\n byResource: Record<string, Set<string>>\n}\n\nconst buildState = (perms: Record<string, string[]>): PermissionsState => ({\n byResource: Object.fromEntries(\n Object.entries(perms).map(([k, v]) => [k, new Set(v)]),\n ),\n})\n\nconst stateToWire = (state: PermissionsState): Record<string, string[]> => {\n const out: Record<string, string[]> = {}\n for (const [k, set] of Object.entries(state.byResource)) {\n if (set.size === 0) continue\n out[k] = Array.from(set)\n }\n return out\n}\n\nfunction PermissionsMatrix({\n resources,\n state,\n onChange,\n}: {\n resources: ResourceJSON[]\n state: PermissionsState\n onChange: (next: PermissionsState) => void\n}): React.ReactElement {\n const { t } = useI18n()\n\n const toggle = (resourceId: string, action: string): void => {\n const set = new Set(state.byResource[resourceId] ?? [])\n if (set.has(action)) set.delete(action)\n else set.add(action)\n onChange({ byResource: { ...state.byResource, [resourceId]: set } })\n }\n\n const toggleAll = (resourceId: string, actions: string[]): void => {\n const current = state.byResource[resourceId] ?? new Set<string>()\n const allSelected = actions.every((a) => current.has(a))\n const next = new Set<string>(allSelected ? [] : actions)\n onChange({ byResource: { ...state.byResource, [resourceId]: next } })\n }\n\n const resourcesWithActions = React.useMemo(\n () => resources.filter((r) => (r.actions ?? []).length > 0),\n [resources],\n )\n\n const allGloballySelected =\n resourcesWithActions.length > 0 &&\n resourcesWithActions.every((r) => {\n const actions = (r.actions ?? []).map((a) => a.name)\n const current = state.byResource[r.id] ?? new Set<string>()\n return actions.every((a) => current.has(a))\n })\n\n const toggleAllResources = (): void => {\n const select = !allGloballySelected\n const next: Record<string, Set<string>> = { ...state.byResource }\n for (const r of resources) {\n const actions = (r.actions ?? []).map((a) => a.name)\n next[r.id] = select ? new Set(actions) : new Set<string>()\n }\n onChange({ byResource: next })\n }\n\n if (resources.length === 0) {\n return (\n <p className=\"text-sm text-muted-foreground\">{t('settings:apiKeys.permissions.noResources')}</p>\n )\n }\n\n return (\n <div className=\"rounded-md border border-border\">\n {resourcesWithActions.length > 0 && (\n <div className=\"flex flex-wrap items-center justify-end gap-2 border-b border-border bg-muted/30 px-3 py-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"h-8\"\n onClick={toggleAllResources}\n >\n {allGloballySelected ? (\n <>\n <X className=\"mr-1.5 size-3.5\" />\n {t('settings:apiKeys.permissions.clearAllResources')}\n </>\n ) : (\n <>\n <Check className=\"mr-1.5 size-3.5\" />\n {t('settings:apiKeys.permissions.selectAllResources')}\n </>\n )}\n </Button>\n </div>\n )}\n <div className=\"max-h-[24rem] overflow-y-auto\">\n <Table>\n <TableHeader className=\"sticky top-0 bg-card\">\n <TableRow>\n <TableHead className=\"w-[14rem]\">{t('settings:apiKeys.permissions.resource')}</TableHead>\n <TableHead>{t('settings:apiKeys.permissions.actions')}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {resources.map((r) => {\n const actions = (r.actions ?? []).map((a) => a.name)\n const current = state.byResource[r.id] ?? new Set<string>()\n const allSelected = actions.length > 0 && actions.every((a) => current.has(a))\n return (\n <TableRow key={r.id}>\n <TableCell className=\"align-top\">\n <div className=\"flex flex-col gap-1\">\n <span className=\"font-medium\">{r.name}</span>\n <span className=\"text-xs text-muted-foreground\">{r.id}</span>\n <button\n type=\"button\"\n className=\"mt-1 inline-flex items-center gap-1 self-start text-xs text-primary hover:underline\"\n onClick={() => toggleAll(r.id, actions)}\n >\n {allSelected ? <X className=\"size-3\" /> : <Check className=\"size-3\" />}\n {allSelected\n ? t('settings:apiKeys.permissions.clearAll')\n : t('settings:apiKeys.permissions.selectAll')}\n </button>\n </div>\n </TableCell>\n <TableCell>\n <div className=\"flex flex-wrap gap-2\">\n {actions.map((a) => {\n const checked = current.has(a)\n return (\n <label\n key={a}\n className={cn(\n 'inline-flex cursor-pointer items-center gap-1.5 rounded-md border border-border px-2 py-1 text-xs',\n checked && 'border-primary bg-primary/10 text-primary',\n )}\n >\n <Checkbox\n checked={checked}\n onCheckedChange={() => toggle(r.id, a)}\n className=\"size-3.5\"\n />\n <span>{a}</span>\n </label>\n )\n })}\n </div>\n </TableCell>\n </TableRow>\n )\n })}\n </TableBody>\n </Table>\n </div>\n </div>\n )\n}\n\nfunction PermissionsSummary({ permissions }: { permissions: Record<string, string[]> }): React.ReactElement {\n const { t } = useI18n()\n const entries = Object.entries(permissions)\n if (entries.length === 0) {\n return <Badge variant=\"outline\">{t('settings:apiKeys.permissions.none')}</Badge>\n }\n const totalActions = entries.reduce((sum, [, a]) => sum + a.length, 0)\n return (\n <Badge variant=\"secondary\">\n {t('settings:apiKeys.permissions.summary', { resources: entries.length, actions: totalActions })}\n </Badge>\n )\n}\n\n// ─── Editor dialog ────────────────────────────────────────────────────────────\n\nfunction ApiKeyEditorDialog({\n open,\n onOpenChange,\n editing,\n resources,\n onCreated,\n onUpdated,\n}: {\n open: boolean\n onOpenChange: (open: boolean) => void\n editing: ApiKeyRecord | null\n resources: ResourceJSON[]\n onCreated: (result: { key: string; record: ApiKeyRecord }) => void\n onUpdated: (record: ApiKeyRecord) => void\n}): React.ReactElement {\n const { t } = useI18n()\n const client = useAdminClient()\n const notify = useNotify()\n const isEdit = !!editing\n const [name, setName] = React.useState(editing?.name ?? '')\n const [expiresInDays, setExpiresInDays] = React.useState<string>(() => {\n if (!editing?.expiresAt) return ''\n const ms = new Date(editing.expiresAt).getTime() - Date.now()\n return ms > 0 ? String(Math.max(1, Math.round(ms / (24 * 60 * 60 * 1000)))) : ''\n })\n const [permissions, setPermissions] = React.useState<PermissionsState>(() =>\n buildState(editing?.permissions ?? {}),\n )\n\n const save = useMutation({\n mutationFn: async (): Promise<{ key?: string; record: ApiKeyRecord }> => {\n const wire = stateToWire(permissions)\n if (isEdit && editing) {\n const expiry = expiresInDays.trim() === '' ? null : Number(expiresInDays)\n const res = await client.updateApiKey(editing.id, {\n name: name.trim(),\n permissions: wire,\n expiresInDays: expiry === null ? null : Number.isFinite(expiry) && expiry > 0 ? expiry : undefined,\n })\n return { record: res.record }\n }\n const expiry = expiresInDays.trim() === '' ? null : Number(expiresInDays)\n return client.createApiKey({\n name: name.trim(),\n permissions: wire,\n expiresInDays: expiry === null ? null : Number.isFinite(expiry) && expiry > 0 ? expiry : undefined,\n }) as Promise<{ key: string; record: ApiKeyRecord }>\n },\n onSuccess: (result) => {\n if (isEdit) {\n notify.success({ key: 'settings:apiKeys.notice.updated' })\n onUpdated(result.record)\n } else {\n if (result.key) onCreated({ key: result.key, record: result.record })\n }\n },\n onError: (err) => notify.error({ message: err instanceof Error ? err.message : String(err) }),\n })\n\n // Sync state when dialog re-opens against a different record.\n React.useEffect(() => {\n if (!open) return\n setName(editing?.name ?? '')\n setPermissions(buildState(editing?.permissions ?? {}))\n if (!editing?.expiresAt) setExpiresInDays('')\n else {\n const ms = new Date(editing.expiresAt).getTime() - Date.now()\n setExpiresInDays(ms > 0 ? String(Math.max(1, Math.round(ms / (24 * 60 * 60 * 1000)))) : '')\n }\n }, [open, editing])\n\n const totalSelected = Object.values(permissions.byResource).reduce(\n (sum, set) => sum + (set?.size ?? 0),\n 0,\n )\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"max-w-3xl\">\n <DialogHeader>\n <DialogTitle>\n {isEdit ? t('settings:apiKeys.editor.titleEdit') : t('settings:apiKeys.editor.titleCreate')}\n </DialogTitle>\n <DialogDescription>{t('settings:apiKeys.editor.description')}</DialogDescription>\n </DialogHeader>\n <form\n className=\"flex flex-col gap-4\"\n onSubmit={(e) => {\n e.preventDefault()\n if (!name.trim()) return\n save.mutate()\n }}\n >\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1.5\">\n <Label htmlFor=\"api-key-name\">{t('settings:apiKeys.editor.name')}</Label>\n <Input\n id=\"api-key-name\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder={t('settings:apiKeys.editor.namePlaceholder')}\n required\n maxLength={64}\n />\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <Label htmlFor=\"api-key-expires\">{t('settings:apiKeys.editor.expiresInDays')}</Label>\n <Input\n id=\"api-key-expires\"\n type=\"number\"\n min={1}\n max={3650}\n value={expiresInDays}\n onChange={(e) => setExpiresInDays(e.target.value)}\n placeholder={t('settings:apiKeys.editor.expiresPlaceholder')}\n />\n <span className=\"text-xs text-muted-foreground\">\n {t('settings:apiKeys.editor.expiresHint')}\n </span>\n </div>\n </div>\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex items-center justify-between\">\n <Label>{t('settings:apiKeys.editor.permissions')}</Label>\n <span className=\"text-xs text-muted-foreground\">\n {t('settings:apiKeys.editor.selectedActions', { count: totalSelected })}\n </span>\n </div>\n <PermissionsMatrix resources={resources} state={permissions} onChange={setPermissions} />\n </div>\n <DialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => onOpenChange(false)}>\n {t('common:cancel')}\n </Button>\n <Button type=\"submit\" disabled={save.isPending || !name.trim() || totalSelected === 0}>\n {save.isPending ? t('common:saving') : isEdit ? t('common:save') : t('settings:apiKeys.actions.create')}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n )\n}\n\n// ─── Webhooks section ─────────────────────────────────────────────────────────\n\nconst WEBHOOK_EVENTS = ['record.created', 'record.updated', 'record.deleted', '*']\n\nfunction WebhooksSection(): React.ReactElement {\n const { t } = useI18n()\n const client = useAdminClient()\n const qc = useQueryClient()\n const notify = useNotify()\n const dialogs = useDialogs()\n const resources = useResources()\n const [editorOpen, setEditorOpen] = React.useState(false)\n const [editing, setEditing] = React.useState<WebhookRecord | null>(null)\n const [selectedId, setSelectedId] = React.useState<string | null>(null)\n\n const list = useQuery({\n queryKey: KEY_WEBHOOKS,\n queryFn: () => client.listWebhooks(),\n })\n const deliveries = useQuery({\n queryKey: ['modern-admin', 'webhooks', selectedId, 'deliveries'],\n queryFn: () => client.listWebhookDeliveries(selectedId!),\n enabled: !!selectedId,\n })\n const deleteMut = useMutation({\n mutationFn: (id: string) => client.deleteWebhook(id),\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: KEY_WEBHOOKS })\n notify.success({ key: 'settings:webhooks.notice.deleted' })\n },\n onError: (err) => notify.error({ message: err instanceof Error ? err.message : String(err) }),\n })\n const testMut = useMutation({\n mutationFn: (id: string) => client.testWebhook(id),\n onSuccess: () => {\n if (selectedId) qc.invalidateQueries({ queryKey: ['modern-admin', 'webhooks', selectedId, 'deliveries'] })\n notify.success({ key: 'settings:webhooks.notice.testQueued' })\n },\n onError: (err) => notify.error({ message: err instanceof Error ? err.message : String(err) }),\n })\n\n const webhooks = list.data?.webhooks ?? []\n\n const onDelete = async (webhook: WebhookRecord): Promise<void> => {\n const ok = await dialogs.confirm({\n title: t('settings:webhooks.confirmDelete.title'),\n description: t('settings:webhooks.confirmDelete.description', { name: webhook.name }),\n confirmLabel: t('common:delete'),\n destructive: true,\n })\n if (ok) deleteMut.mutate(webhook.id)\n }\n\n return (\n <div className=\"flex flex-col gap-4\">\n <SettingsCard\n icon={SettingsIcon}\n title={t('settings:webhooks.title')}\n description={t('settings:webhooks.description')}\n action={\n <Button size=\"sm\" onClick={() => { setEditing(null); setEditorOpen(true) }}>\n <Plus className=\"size-4\" />\n {t('settings:webhooks.actions.create')}\n </Button>\n }\n >\n <SettingsListState\n isLoading={list.isLoading}\n error={list.error}\n isEmpty={webhooks.length === 0}\n loadingLabel={t('common:loading')}\n empty={{\n icon: SettingsIcon,\n title: t('settings:webhooks.empty.title'),\n description: t('settings:webhooks.empty.description'),\n }}\n >\n <SettingsTableScroll>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>{t('settings:webhooks.columns.name')}</TableHead>\n <TableHead>{t('settings:webhooks.columns.resource')}</TableHead>\n <TableHead>{t('settings:webhooks.columns.events')}</TableHead>\n <TableHead>{t('settings:webhooks.columns.enabled')}</TableHead>\n <TableHead className=\"text-right\">{t('settings:webhooks.columns.actions')}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {webhooks.map((webhook) => (\n <TableRow key={webhook.id}>\n <TableCell>\n <button\n type=\"button\"\n className=\"text-left font-medium hover:underline\"\n onClick={() => setSelectedId(webhook.id)}\n >\n {webhook.name}\n </button>\n <div className=\"max-w-xs truncate text-xs text-muted-foreground\">{webhook.url}</div>\n </TableCell>\n <TableCell>{resourceName(resources, webhook.resourceId, t('settings:webhooks.editor.allResources'))}</TableCell>\n <TableCell className=\"max-w-xs\">\n <div className=\"flex flex-wrap gap-1\">\n {webhook.events.map((event) => <Badge key={event} variant=\"outline\">{event}</Badge>)}\n </div>\n </TableCell>\n <TableCell>{webhook.enabled ? t('common:yes') : t('common:no')}</TableCell>\n <TableCell className=\"text-right\">\n <div className=\"inline-flex gap-1\">\n <Button variant=\"ghost\" size=\"sm\" onClick={() => testMut.mutate(webhook.id)}>\n {t('settings:webhooks.actions.test')}\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => { setEditing(webhook); setEditorOpen(true) }}>\n <Edit className=\"size-4\" />\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => void onDelete(webhook)}>\n <Trash2 className=\"size-4 text-destructive\" />\n </Button>\n </div>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </SettingsTableScroll>\n </SettingsListState>\n </SettingsCard>\n\n {selectedId && (\n <SettingsCard icon={SettingsIcon} title={t('settings:webhooks.deliveries.title')}>\n {deliveries.isLoading ? (\n <div className=\"py-4 text-sm text-muted-foreground\">{t('common:loading')}</div>\n ) : (\n <SettingsTableScroll>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>{t('settings:webhooks.deliveries.status')}</TableHead>\n <TableHead>{t('settings:webhooks.deliveries.event')}</TableHead>\n <TableHead>{t('settings:webhooks.deliveries.attempt')}</TableHead>\n <TableHead>{t('settings:webhooks.deliveries.response')}</TableHead>\n <TableHead>{t('settings:webhooks.deliveries.createdAt')}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {(deliveries.data?.deliveries ?? []).map((delivery) => (\n <TableRow key={delivery.id}>\n <TableCell>{delivery.status}</TableCell>\n <TableCell>{delivery.event}</TableCell>\n <TableCell>{delivery.attempt}</TableCell>\n <TableCell className=\"max-w-sm truncate\">\n {delivery.responseStatus ?? delivery.error ?? delivery.responseBody ?? '—'}\n </TableCell>\n <TableCell>{formatDate(delivery.createdAt)}</TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </SettingsTableScroll>\n )}\n </SettingsCard>\n )}\n\n <WebhookEditorDialog\n key={editing?.id ?? 'new'}\n open={editorOpen}\n onOpenChange={setEditorOpen}\n webhook={editing}\n resources={resources}\n />\n </div>\n )\n}\n\nfunction WebhookEditorDialog({\n open,\n onOpenChange,\n webhook,\n resources,\n}: {\n open: boolean\n onOpenChange(open: boolean): void\n webhook: WebhookRecord | null\n resources: ResourceJSON[]\n}): React.ReactElement {\n const { t } = useI18n()\n const client = useAdminClient()\n const qc = useQueryClient()\n const notify = useNotify()\n const [name, setName] = React.useState(webhook?.name ?? '')\n const [url, setUrl] = React.useState(webhook?.url ?? '')\n const [resourceId, setResourceId] = React.useState(webhook?.resourceId ?? '')\n const [enabled, setEnabled] = React.useState(webhook?.enabled ?? true)\n const [secret, setSecret] = React.useState(webhook?.secret ?? '')\n const [events, setEvents] = React.useState<string[]>(webhook?.events ?? ['record.created', 'record.updated'])\n const [headers, setHeaders] = React.useState<Record<string, unknown>>(webhook?.headers ?? {})\n const [filters, setFilters] = React.useState<Record<string, unknown>>(webhook?.filters ?? {})\n const [payloadFields, setPayloadFields] = React.useState<string[]>(webhook?.payloadFields ?? [])\n const selectedResource = resources.find((r) => r.id === resourceId)\n\n const save = useMutation({\n mutationFn: (payload: WebhookInput) =>\n webhook ? client.updateWebhook(webhook.id, payload) : client.createWebhook(payload),\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: KEY_WEBHOOKS })\n notify.success({ key: 'settings:webhooks.notice.saved' })\n onOpenChange(false)\n },\n onError: (err) => notify.error({ message: err instanceof Error ? err.message : String(err) }),\n })\n\n const toggleEvent = (event: string): void => {\n setEvents((prev) => prev.includes(event) ? prev.filter((e) => e !== event) : [...prev, event])\n }\n\n const onSubmit = (e: React.FormEvent): void => {\n e.preventDefault()\n save.mutate({\n name: name.trim(),\n url: url.trim(),\n events,\n resourceId: resourceId || null,\n enabled,\n ...(secret.trim() ? { secret: secret.trim() } : {}),\n headers: stringRecord(headers),\n filters: stringRecord(filters),\n payloadFields,\n })\n }\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"max-w-3xl\">\n <DialogHeader>\n <DialogTitle>{webhook ? t('settings:webhooks.editor.titleEdit') : t('settings:webhooks.editor.titleCreate')}</DialogTitle>\n <DialogDescription>{t('settings:webhooks.editor.description')}</DialogDescription>\n </DialogHeader>\n <form className=\"space-y-4\" onSubmit={onSubmit}>\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"space-y-1.5\">\n <Label>{t('settings:webhooks.editor.name')}</Label>\n <Input value={name} onChange={(e) => setName(e.target.value)} required />\n </div>\n <div className=\"space-y-1.5\">\n <Label>{t('settings:webhooks.editor.url')}</Label>\n <Input value={url} onChange={(e) => setUrl(e.target.value)} required type=\"url\" />\n </div>\n <div className=\"space-y-1.5\">\n <Label>{t('settings:webhooks.editor.resource')}</Label>\n <Select\n value={resourceId || '__all__'}\n onValueChange={(v) => { setResourceId(v === '__all__' ? '' : v); setPayloadFields([]) }}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__all__\">{t('settings:webhooks.editor.allResources')}</SelectItem>\n {resources.map((resource) => (\n <SelectItem key={resource.id} value={resource.id}>\n {resource.name}\n {resource.name !== resource.id && (\n <span className=\"ml-1.5 text-xs text-muted-foreground\">({resource.id})</span>\n )}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-1.5\">\n <div className=\"flex items-center gap-1.5\">\n <Label>{t('settings:webhooks.editor.secret')}</Label>\n <InfoTooltip\n content={t('settings:webhooks.editor.secretHint')}\n ariaLabel={t('settings:webhooks.editor.secret')}\n side=\"right\"\n />\n </div>\n <Input value={secret} onChange={(e) => setSecret(e.target.value)} type=\"password\" />\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <Switch checked={enabled} onCheckedChange={setEnabled} />\n <Label>{t('settings:webhooks.editor.enabled')}</Label>\n </div>\n <div className=\"space-y-2\">\n <Label>{t('settings:webhooks.editor.events')}</Label>\n <div className=\"flex flex-wrap gap-2\">\n {WEBHOOK_EVENTS.map((event) => (\n <label key={event} className=\"flex items-center gap-2 rounded-md border border-border px-3 py-2 text-sm\">\n <Checkbox checked={events.includes(event)} onCheckedChange={() => toggleEvent(event)} />\n {event}\n </label>\n ))}\n </div>\n </div>\n {selectedResource && (\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-1.5\">\n <Label>{t('settings:webhooks.editor.payloadFields')}</Label>\n <InfoTooltip\n content={t('settings:webhooks.editor.payloadFieldsHint')}\n ariaLabel={t('settings:webhooks.editor.payloadFields')}\n side=\"right\"\n />\n </div>\n <div className=\"grid gap-2 sm:grid-cols-2\">\n {selectedResource.properties.map((property) => (\n <label key={property.path} className=\"flex items-center gap-2 text-sm\">\n <Checkbox\n checked={payloadFields.includes(property.path)}\n onCheckedChange={() =>\n setPayloadFields((prev) =>\n prev.includes(property.path)\n ? prev.filter((p) => p !== property.path)\n : [...prev, property.path],\n )\n }\n />\n {property.label}\n </label>\n ))}\n </div>\n </div>\n )}\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"space-y-1.5\">\n <div className=\"flex items-center gap-1.5\">\n <Label>{t('settings:webhooks.editor.headers')}</Label>\n <InfoTooltip\n content={t('settings:webhooks.editor.headersHint')}\n ariaLabel={t('settings:webhooks.editor.headers')}\n side=\"top\"\n />\n </div>\n <JsonEditor value={headers} onChange={(next) => setHeaders(toJsonRecord(next))} />\n </div>\n <div className=\"space-y-1.5\">\n <div className=\"flex items-center gap-1.5\">\n <Label>{t('settings:webhooks.editor.filters')}</Label>\n <InfoTooltip\n content={t('settings:webhooks.editor.filtersHint')}\n ariaLabel={t('settings:webhooks.editor.filters')}\n side=\"top\"\n />\n </div>\n <JsonEditor value={filters} onChange={(next) => setFilters(toJsonRecord(next))} />\n </div>\n </div>\n <DialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => onOpenChange(false)}>{t('common:cancel')}</Button>\n <Button type=\"submit\" disabled={save.isPending || !name.trim() || !url.trim() || events.length === 0}>\n {save.isPending ? t('common:saving') : t('common:save')}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n )\n}\n\nconst resourceName = (\n resources: ResourceJSON[],\n id: string | null | undefined,\n fallback: string,\n): string => id ? (resources.find((r) => r.id === id)?.name ?? id) : fallback\n\nconst toJsonRecord = (value: unknown): Record<string, unknown> =>\n value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : {}\n\nconst stringRecord = (value: Record<string, unknown>): Record<string, string> => {\n const out: Record<string, string> = {}\n for (const [key, item] of Object.entries(value)) {\n if (item != null && item !== '') out[key] = String(item)\n }\n return out\n}\n\n// ─── Created-secret dialog ────────────────────────────────────────────────────\n\nfunction CreatedSecretDialog({\n secret,\n onClose,\n}: {\n secret: { key: string; record: ApiKeyRecord } | null\n onClose: () => void\n}): React.ReactElement {\n const { t } = useI18n()\n const notify = useNotify()\n const [reveal, setReveal] = React.useState(false)\n const [copied, setCopied] = React.useState(false)\n\n React.useEffect(() => {\n if (!secret) {\n setReveal(false)\n setCopied(false)\n }\n }, [secret])\n\n const onCopy = async (): Promise<void> => {\n if (!secret) return\n try {\n await navigator.clipboard.writeText(secret.key)\n setCopied(true)\n notify.success({ key: 'settings:apiKeys.notice.copied' })\n setTimeout(() => setCopied(false), 1500)\n } catch {\n notify.error({ key: 'settings:apiKeys.notice.copyFailed' })\n }\n }\n\n return (\n <Dialog open={!!secret} onOpenChange={(open) => !open && onClose()}>\n <DialogContent className=\"max-w-lg\">\n <DialogHeader>\n <DialogTitle className=\"flex items-center gap-2\">\n <SettingsIcon className=\"size-5\" />\n {t('settings:apiKeys.created.title')}\n </DialogTitle>\n <DialogDescription>{t('settings:apiKeys.created.description')}</DialogDescription>\n </DialogHeader>\n <div className=\"rounded-md border border-amber-300/60 bg-amber-50 p-3 text-sm text-amber-900 dark:border-amber-300/30 dark:bg-amber-950/40 dark:text-amber-200\">\n <div className=\"flex items-start gap-2\">\n <AlertTriangle className=\"mt-0.5 size-4\" />\n <p>{t('settings:apiKeys.created.warning')}</p>\n </div>\n </div>\n <div className=\"flex items-stretch gap-2\">\n <div className=\"relative flex-1\">\n <Input\n readOnly\n type={reveal ? 'text' : 'password'}\n value={secret?.key ?? ''}\n className=\"pr-10 font-mono text-xs\"\n onFocus={(e) => e.currentTarget.select()}\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"absolute right-1 top-1/2 -translate-y-1/2\"\n onClick={() => setReveal((v) => !v)}\n aria-label={reveal ? t('settings:apiKeys.created.hide') : t('settings:apiKeys.created.reveal')}\n >\n {reveal ? <EyeOff className=\"size-4\" /> : <Eye className=\"size-4\" />}\n </Button>\n </div>\n <Button type=\"button\" onClick={onCopy} variant=\"secondary\">\n {copied ? <Check className=\"size-4\" /> : <Copy className=\"size-4\" />}\n <span className=\"hidden sm:inline\">\n {copied ? t('settings:apiKeys.created.copied') : t('settings:apiKeys.created.copy')}\n </span>\n </Button>\n </div>\n <DialogFooter>\n <Button onClick={onClose}>{t('common:done')}</Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n\nconst formatDate = (input: string | Date): string => {\n try {\n return new Date(input).toLocaleString()\n } catch {\n return String(input)\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"settings-page-DtguXLAP.js","names":[],"sources":["../../../../react/src/pages/settings-shared.tsx","../../../../react/src/pages/ai-assistant-settings-section.tsx","../../../../react/src/pages/settings-page.tsx"],"sourcesContent":["// Shared layout primitives for the Settings hub. Every section in\n// `settings-page.tsx` (API keys, webhooks, AI assistant, ...) should use\n// these so the look, spacing, and mobile behavior stays uniform.\n\nimport * as React from 'react'\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n Empty,\n EmptyDescription,\n EmptyHeader,\n EmptyMedia,\n EmptyTitle,\n cn,\n} from '@modern-admin/ui'\n\ntype IconComponent = React.ComponentType<{ className?: string }>\n\ninterface SettingsCardProps {\n icon: IconComponent\n title: React.ReactNode\n description?: React.ReactNode\n action?: React.ReactNode\n /** Removes default padding/header so the card body can fill edge-to-edge. */\n bodyClassName?: string\n children: React.ReactNode\n}\n\n/**\n * Unified card wrapper for a settings section. Header collapses\n * vertically on mobile and lays the action button to the right on `sm+`.\n * `CardContent` gets `min-w-0` so tables/grids inside can shrink and\n * scroll horizontally instead of forcing the parent grid wider.\n */\nexport function SettingsCard({\n icon: Icon,\n title,\n description,\n action,\n bodyClassName,\n children,\n}: SettingsCardProps): React.ReactElement {\n return (\n <Card>\n <CardHeader\n className={cn(\n 'flex-col items-start gap-2',\n action && 'sm:flex-row sm:items-center sm:justify-between',\n )}\n >\n <div className=\"flex min-w-0 flex-col gap-1.5\">\n <CardTitle className=\"flex items-center gap-2\">\n <Icon className=\"size-5\" />\n {title}\n </CardTitle>\n {description ? <CardDescription>{description}</CardDescription> : null}\n </div>\n {action}\n </CardHeader>\n <CardContent className={cn('min-w-0', bodyClassName)}>{children}</CardContent>\n </Card>\n )\n}\n\n/**\n * Horizontal-scroll wrapper for tables inside `SettingsCard`. On mobile\n * the content extends to the card edges (`-mx-6`) so the user sees the\n * left edge of the table flush with the card; from `sm+` the negative\n * margin is removed.\n */\nexport function SettingsTableScroll({ children }: { children: React.ReactNode }): React.ReactElement {\n return <div className=\"-mx-6 overflow-x-auto sm:mx-0\">{children}</div>\n}\n\ninterface SettingsEmptyProps {\n icon: IconComponent\n title: React.ReactNode\n description?: React.ReactNode\n}\n\nexport function SettingsEmpty({ icon: Icon, title, description }: SettingsEmptyProps): React.ReactElement {\n return (\n <Empty className=\"border-0\">\n <EmptyHeader>\n <EmptyMedia>\n <Icon />\n </EmptyMedia>\n <EmptyTitle>{title}</EmptyTitle>\n {description ? <EmptyDescription>{description}</EmptyDescription> : null}\n </EmptyHeader>\n </Empty>\n )\n}\n\ninterface SettingsListStateProps {\n isLoading: boolean\n error: unknown\n isEmpty: boolean\n loadingLabel: React.ReactNode\n empty: SettingsEmptyProps\n children: React.ReactNode\n}\n\n/**\n * Renders one of: loading row, destructive error banner, empty state, or\n * the actual list `children`. Keeps every section's \"list with status\"\n * surface identical.\n */\nexport function SettingsListState({\n isLoading,\n error,\n isEmpty,\n loadingLabel,\n empty,\n children,\n}: SettingsListStateProps): React.ReactElement {\n if (isLoading) {\n return <div className=\"py-8 text-center text-sm text-muted-foreground\">{loadingLabel}</div>\n }\n if (error) {\n return (\n <div className=\"rounded-md border border-destructive/50 bg-destructive/10 p-4 text-sm text-destructive\">\n {error instanceof Error ? error.message : String(error)}\n </div>\n )\n }\n if (isEmpty) {\n return <SettingsEmpty {...empty} />\n }\n return <>{children}</>\n}\n","import * as React from 'react'\nimport { useMutation, useQuery } from '@tanstack/react-query'\nimport { Badge, Button, Input, Label, Switch, Textarea } from '@modern-admin/ui'\nimport { Bot, KeyRound, Save } from 'lucide-react'\nimport { useAdminClient } from '../provider.js'\nimport { useNotify } from '../notify.js'\nimport { useI18n } from '../i18n.js'\nimport type { AiAssistantSettings } from '../client.js'\nimport { SettingsCard } from './settings-shared.js'\n\nexport function AiAssistantSettingsSection(): React.ReactElement {\n const client = useAdminClient()\n const notify = useNotify()\n const { t } = useI18n()\n const settings = useQuery({\n queryKey: ['modern-admin', 'ai-assistant', 'settings'],\n queryFn: () => client.getAiAssistantSettings(),\n })\n const [form, setForm] = React.useState({\n enabled: true,\n model: 'google/gemini-3.1-flash-lite-preview',\n apiKey: '',\n systemPrompt: '',\n })\n\n React.useEffect(() => {\n if (!settings.data) return\n setForm({\n enabled: settings.data.enabled,\n model: settings.data.model,\n apiKey: '',\n systemPrompt: settings.data.systemPrompt,\n })\n }, [settings.data])\n\n const save = useMutation({\n mutationFn: async (): Promise<AiAssistantSettings> =>\n client.updateAiAssistantSettings({\n enabled: form.enabled,\n model: form.model,\n ...(form.apiKey.trim() ? { apiKey: form.apiKey.trim() } : {}),\n systemPrompt: form.systemPrompt,\n }),\n onSuccess: () => {\n settings.refetch()\n setForm((prev) => ({ ...prev, apiKey: '' }))\n notify.success({ message: t('aiAssistant:settings.saved') })\n },\n onError: (err) => {\n notify.error({ message: err instanceof Error ? err.message : String(err) })\n },\n })\n\n if (settings.isLoading) {\n return <div className=\"py-8 text-sm text-muted-foreground\">{t('common:loading')}</div>\n }\n\n if (settings.error) {\n return (\n <div className=\"rounded-md border border-destructive/50 bg-destructive/10 p-4 text-sm text-destructive\">\n {settings.error instanceof Error ? settings.error.message : String(settings.error)}\n </div>\n )\n }\n\n const data = settings.data\n if (!data) {\n return <div className=\"py-8 text-sm text-muted-foreground\">{t('aiAssistant:settings.empty')}</div>\n }\n\n return (\n <div className=\"flex flex-col gap-4\">\n <SettingsCard\n icon={Bot}\n title={t('aiAssistant:settings.title')}\n description={t('aiAssistant:settings.description')}\n bodyClassName=\"space-y-4\"\n >\n <div className=\"flex flex-wrap items-center gap-2\">\n <Badge variant={data.enabled ? 'secondary' : 'outline'}>\n {data.enabled ? t('aiAssistant:settings.enabled') : t('aiAssistant:settings.disabled')}\n </Badge>\n <Badge variant={data.configured ? 'secondary' : 'outline'}>\n {data.configured ? t('aiAssistant:settings.configured') : t('aiAssistant:settings.apiKeyRequired')}\n </Badge>\n <Badge variant=\"outline\">{t('aiAssistant:settings.readOnly')}</Badge>\n <Badge variant=\"outline\">{t('aiAssistant:settings.provider', { provider: data.provider })}</Badge>\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"flex items-center justify-between rounded-lg border border-border p-3\">\n <div className=\"space-y-1\">\n <Label htmlFor=\"ai-assistant-enabled\">{t('aiAssistant:settings.enableLabel')}</Label>\n <p className=\"text-xs text-muted-foreground\">\n {t('aiAssistant:settings.enableHint')}\n </p>\n </div>\n <Switch\n id=\"ai-assistant-enabled\"\n checked={form.enabled}\n disabled={!data.canManage || save.isPending}\n onCheckedChange={(enabled) => setForm((prev) => ({ ...prev, enabled }))}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"ai-assistant-model\">{t('aiAssistant:settings.modelLabel')}</Label>\n <Input\n id=\"ai-assistant-model\"\n value={form.model}\n disabled={!data.canManage || save.isPending}\n onChange={(e) => setForm((prev) => ({ ...prev, model: e.target.value }))}\n placeholder=\"google/gemini-3.1-flash-lite-preview\"\n />\n </div>\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"ai-assistant-api-key\" className=\"flex items-center gap-2\">\n <KeyRound className=\"size-4\"/>\n {t('aiAssistant:settings.apiKeyLabel')}\n </Label>\n <Input\n id=\"ai-assistant-api-key\"\n type=\"password\"\n value={form.apiKey}\n disabled={!data.canManage || save.isPending}\n onChange={(e) => setForm((prev) => ({ ...prev, apiKey: e.target.value }))}\n placeholder={data.maskedApiKey ?? 'sk-or-v1-...'}\n />\n <p className=\"text-xs text-muted-foreground\">\n {t('aiAssistant:settings.apiKeyHint')}\n </p>\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"ai-assistant-system-prompt\">{t('aiAssistant:settings.systemPromptLabel')}</Label>\n <Textarea\n id=\"ai-assistant-system-prompt\"\n value={form.systemPrompt}\n disabled={!data.canManage || save.isPending}\n onChange={(e) => setForm((prev) => ({ ...prev, systemPrompt: e.target.value }))}\n rows={8}\n placeholder={t('aiAssistant:settings.systemPromptPlaceholder')}\n />\n </div>\n\n <div className=\"flex items-center justify-between gap-3 rounded-lg border border-border p-3 text-sm\">\n <div>\n <div className=\"font-medium\">{t('aiAssistant:settings.accessTitle')}</div>\n <div className=\"text-muted-foreground\">\n {t('aiAssistant:settings.accessDescription')}\n </div>\n </div>\n <Badge variant=\"outline\">{t('aiAssistant:settings.futureToolsReady')}</Badge>\n </div>\n\n <div className=\"flex justify-end\">\n <Button onClick={() => save.mutate()} disabled={!data.canManage || save.isPending || !form.model.trim()}>\n <Save className=\"size-4\"/>\n {save.isPending ? t('aiAssistant:settings.saving') : t('aiAssistant:settings.save')}\n </Button>\n </div>\n </SettingsCard>\n </div>\n )\n}\n","// Admin Settings hub. Reachable from the user/profile dropdown menu and\n// rendered by the router for `/settings/<section>`. Currently three\n// sections: `api-keys`, `webhooks`, `ai-assistant`; the layout is built so\n// adding more sections is just a new entry in `SECTIONS` + a switch case.\n\nimport * as React from 'react'\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport {\n Badge,\n Button,\n Checkbox,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n InfoTooltip,\n Input,\n JsonEditor,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Switch,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n cn,\n} from '@modern-admin/ui'\nimport {\n AlertTriangle,\n Bot,\n Check,\n Copy,\n Edit,\n Eye,\n EyeOff,\n KeyRound,\n Plus,\n Settings as SettingsIcon,\n Trash2,\n X,\n} from 'lucide-react'\nimport { useAdminClient } from '../provider.js'\nimport { useFeatures, useResources } from '../hooks.js'\nimport { useI18n } from '../i18n.js'\nimport { Link, useNavigate } from '../router.js'\nimport { useNotify } from '../notify.js'\nimport { useDialogs } from '../dialogs.js'\nimport type { ApiKeyRecord, WebhookInput, WebhookRecord } from '../client.js'\nimport type { ResourceJSON } from '../types.js'\nimport { getSettingsSectionExtensions } from '../extension-registry.js'\nimport { AiAssistantSettingsSection } from './ai-assistant-settings-section.js'\nimport { SettingsCard, SettingsListState, SettingsTableScroll } from './settings-shared.js'\n\nconst KEY_LIST = ['modern-admin', 'api-keys'] as const\nconst KEY_WEBHOOKS = ['modern-admin', 'webhooks'] as const\n\ntype BuiltInSectionKey = 'api-keys' | 'ai-assistant' | 'webhooks'\n\ninterface SectionDef {\n key: string\n labelKey: string\n icon: React.ComponentType<{ className?: string }>\n /** When `true`, the section is supplied by an extension (no built-in renderer). */\n isExtension?: boolean\n}\n\nconst BUILT_IN_SECTIONS: SectionDef[] = [\n { key: 'api-keys', labelKey: 'settings:apiKeys.title', icon: KeyRound },\n { key: 'webhooks', labelKey: 'settings:webhooks.title', icon: SettingsIcon },\n { key: 'ai-assistant', labelKey: 'aiAssistant:title', icon: Bot },\n]\n\nexport function SettingsPage({ section }: { section?: string }): React.ReactElement {\n const { t } = useI18n()\n const navigate = useNavigate()\n const features = useFeatures()\n // Only surface built-in sections whose backend subsystem is wired.\n // Extension sections are always shown when registered.\n const SECTIONS = React.useMemo<SectionDef[]>(\n () => [\n ...BUILT_IN_SECTIONS.filter((s) =>\n s.key === 'api-keys' ? features.apiKeys\n : s.key === 'webhooks' ? features.webhooks\n : s.key === 'ai-assistant' ? features.aiAssistant\n : true,\n ),\n ...getSettingsSectionExtensions().map((ext) => ({\n key: ext.key,\n labelKey: ext.labelKey,\n icon: ext.icon,\n isExtension: true as const,\n })),\n ],\n\n [features.apiKeys, features.webhooks, features.aiAssistant],\n )\n // Resolve the requested section. If the URL is bogus or the section is\n // disabled, fall back to the first enabled section.\n const builtInKeys: BuiltInSectionKey[] = ['api-keys', 'webhooks', 'ai-assistant']\n const isBuiltIn = (k: string): k is BuiltInSectionKey =>\n (builtInKeys as string[]).includes(k)\n const requested: string | null = section ?? null\n const active: string | null =\n requested && SECTIONS.some((s) => s.key === requested)\n ? requested\n : (SECTIONS[0]?.key ?? null)\n if (active === null) {\n // Defensive: the user menu hides Settings entirely when no section is\n // available, so users normally won't land here. Direct navigation to\n // /settings without any configured section ends up showing this.\n return (\n <div className=\"rounded-md border border-dashed bg-card p-8 text-center text-sm text-muted-foreground\">\n {t('settings:noSectionsConfigured')}\n </div>\n )\n }\n return (\n // `minmax(0,1fr)` (not bare `1fr`) lets the content column shrink below\n // its intrinsic min-width — otherwise wide tables push the whole grid\n // past the viewport at ~`lg` widths (~1000–1100px).\n <div className=\"flex flex-col gap-4 lg:grid lg:grid-cols-[14rem_minmax(0,1fr)]\">\n {/* Mobile: dropdown selector (handles many sections gracefully) */}\n <div className=\"lg:hidden\">\n <Select value={active ?? ''} onValueChange={(v) => navigate({ name: 'settings', section: v })}>\n <SelectTrigger className=\"w-full\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {SECTIONS.map(({ key, labelKey, icon: Icon }) => (\n <SelectItem key={key} value={key}>\n <span className=\"flex items-center gap-2\">\n <Icon className=\"size-4\" />\n <span>{t(labelKey)}</span>\n </span>\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n {/* Desktop: sidebar nav */}\n <aside className=\"hidden lg:block\">\n <nav className=\"flex flex-col gap-1\">\n {SECTIONS.map(({ key, labelKey, icon: Icon }) => (\n <Link\n key={key}\n to={{ name: 'settings', section: key }}\n className={cn(\n 'flex items-center gap-2 rounded-md px-3 py-2 text-sm hover:bg-accent',\n active === key && 'bg-accent font-medium',\n )}\n >\n <Icon className=\"size-4\" />\n <span>{t(labelKey)}</span>\n </Link>\n ))}\n </nav>\n </aside>\n <section className=\"min-w-0\">\n {active && isBuiltIn(active) && active === 'api-keys' && <ApiKeysSection />}\n {active && isBuiltIn(active) && active === 'webhooks' && <WebhooksSection />}\n {active && isBuiltIn(active) && active === 'ai-assistant' && <AiAssistantSettingsSection />}\n {active && !isBuiltIn(active) && (() => {\n const extSection = getSettingsSectionExtensions().find((e) => e.key === active)\n return extSection ? <extSection.component /> : null\n })()}\n </section>\n </div>\n )\n}\n\n// ─── API Keys section ─────────────────────────────────────────────────────────\n\nfunction ApiKeysSection(): React.ReactElement {\n const { t } = useI18n()\n const client = useAdminClient()\n const qc = useQueryClient()\n const notify = useNotify()\n const dialogs = useDialogs()\n const resources = useResources()\n const [editorOpen, setEditorOpen] = React.useState(false)\n const [editing, setEditing] = React.useState<ApiKeyRecord | null>(null)\n const [createdSecret, setCreatedSecret] = React.useState<{ key: string; record: ApiKeyRecord } | null>(null)\n\n const list = useQuery({\n queryKey: KEY_LIST,\n queryFn: () => client.listApiKeys(),\n })\n\n const deleteMut = useMutation({\n mutationFn: (id: string) => client.deleteApiKey(id),\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: KEY_LIST })\n notify.success({ key: 'settings:apiKeys.notice.revoked' })\n },\n onError: (err) => notify.error({ message: err instanceof Error ? err.message : String(err) }),\n })\n\n const toggleEnabledMut = useMutation({\n mutationFn: (vars: { id: string; enabled: boolean }) =>\n client.updateApiKey(vars.id, { enabled: vars.enabled }),\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY_LIST }),\n onError: (err) => notify.error({ message: err instanceof Error ? err.message : String(err) }),\n })\n\n const onCreate = (): void => {\n setEditing(null)\n setEditorOpen(true)\n }\n\n const onEdit = (key: ApiKeyRecord): void => {\n setEditing(key)\n setEditorOpen(true)\n }\n\n const onRevoke = async (key: ApiKeyRecord): Promise<void> => {\n const ok = await dialogs.confirm({\n title: t('settings:apiKeys.confirmRevoke.title'),\n description: t('settings:apiKeys.confirmRevoke.description', { name: key.name ?? key.id }),\n confirmLabel: t('settings:apiKeys.actions.revoke'),\n destructive: true,\n })\n if (ok) deleteMut.mutate(key.id)\n }\n\n const keys = list.data?.keys ?? []\n\n return (\n <div className=\"flex flex-col gap-4\">\n <SettingsCard\n icon={KeyRound}\n title={t('settings:apiKeys.title')}\n description={t('settings:apiKeys.description')}\n action={\n <Button onClick={onCreate} size=\"sm\">\n <Plus className=\"size-4\" />\n <span>{t('settings:apiKeys.actions.create')}</span>\n </Button>\n }\n >\n <SettingsListState\n isLoading={list.isLoading}\n error={list.error}\n isEmpty={keys.length === 0}\n loadingLabel={t('common:loading')}\n empty={{\n icon: KeyRound,\n title: t('settings:apiKeys.empty.title'),\n description: t('settings:apiKeys.empty.description'),\n }}\n >\n <SettingsTableScroll>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>{t('settings:apiKeys.columns.name')}</TableHead>\n <TableHead className=\"hidden sm:table-cell\">{t('settings:apiKeys.columns.start')}</TableHead>\n <TableHead className=\"hidden md:table-cell\">{t('settings:apiKeys.columns.permissions')}</TableHead>\n <TableHead className=\"hidden md:table-cell\">{t('settings:apiKeys.columns.expiresAt')}</TableHead>\n <TableHead>{t('settings:apiKeys.columns.enabled')}</TableHead>\n <TableHead className=\"text-right\">{t('settings:apiKeys.columns.actions')}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {keys.map((k) => (\n <TableRow key={k.id}>\n <TableCell className=\"font-medium\">\n <div className=\"flex flex-col\">\n <span>{k.name ?? k.id}</span>\n {k.lastRequest && (\n <span className=\"text-xs text-muted-foreground\">\n {t('settings:apiKeys.lastUsed', { date: formatDate(k.lastRequest) })}\n </span>\n )}\n </div>\n </TableCell>\n <TableCell className=\"hidden font-mono text-xs sm:table-cell\">\n {k.start ? `${k.start}…` : '—'}\n </TableCell>\n <TableCell className=\"hidden md:table-cell\">\n <PermissionsSummary permissions={k.permissions} />\n </TableCell>\n <TableCell className=\"hidden md:table-cell text-xs\">\n {k.expiresAt ? formatDate(k.expiresAt) : t('settings:apiKeys.expiresNever')}\n </TableCell>\n <TableCell>\n <Switch\n checked={k.enabled}\n onCheckedChange={(enabled) => toggleEnabledMut.mutate({ id: k.id, enabled })}\n aria-label={t('settings:apiKeys.columns.enabled')}\n />\n </TableCell>\n <TableCell className=\"text-right\">\n <div className=\"inline-flex gap-1\">\n <Button variant=\"ghost\" size=\"sm\" onClick={() => onEdit(k)} aria-label={t('settings:apiKeys.actions.edit')}>\n <Edit className=\"size-4\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => onRevoke(k)}\n aria-label={t('settings:apiKeys.actions.revoke')}\n disabled={deleteMut.isPending}\n >\n <Trash2 className=\"size-4 text-destructive\" />\n </Button>\n </div>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </SettingsTableScroll>\n </SettingsListState>\n </SettingsCard>\n\n <ApiKeyEditorDialog\n key={editing?.id ?? 'new'}\n open={editorOpen}\n onOpenChange={setEditorOpen}\n editing={editing}\n resources={resources}\n onCreated={(result) => {\n setEditorOpen(false)\n setCreatedSecret(result)\n qc.invalidateQueries({ queryKey: KEY_LIST })\n }}\n onUpdated={() => {\n setEditorOpen(false)\n qc.invalidateQueries({ queryKey: KEY_LIST })\n }}\n />\n\n <CreatedSecretDialog\n secret={createdSecret}\n onClose={() => setCreatedSecret(null)}\n />\n </div>\n )\n}\n\n// ─── Permissions matrix editor ────────────────────────────────────────────────\n\ninterface PermissionsState {\n /** resourceId -> Set<actionName>. `'*'` means all actions of that resource. */\n byResource: Record<string, Set<string>>\n}\n\nconst buildState = (perms: Record<string, string[]>): PermissionsState => ({\n byResource: Object.fromEntries(\n Object.entries(perms).map(([k, v]) => [k, new Set(v)]),\n ),\n})\n\nconst stateToWire = (state: PermissionsState): Record<string, string[]> => {\n const out: Record<string, string[]> = {}\n for (const [k, set] of Object.entries(state.byResource)) {\n if (set.size === 0) continue\n out[k] = Array.from(set)\n }\n return out\n}\n\nfunction PermissionsMatrix({\n resources,\n state,\n onChange,\n}: {\n resources: ResourceJSON[]\n state: PermissionsState\n onChange: (next: PermissionsState) => void\n}): React.ReactElement {\n const { t } = useI18n()\n\n const toggle = (resourceId: string, action: string): void => {\n const set = new Set(state.byResource[resourceId] ?? [])\n if (set.has(action)) set.delete(action)\n else set.add(action)\n onChange({ byResource: { ...state.byResource, [resourceId]: set } })\n }\n\n const toggleAll = (resourceId: string, actions: string[]): void => {\n const current = state.byResource[resourceId] ?? new Set<string>()\n const allSelected = actions.every((a) => current.has(a))\n const next = new Set<string>(allSelected ? [] : actions)\n onChange({ byResource: { ...state.byResource, [resourceId]: next } })\n }\n\n const resourcesWithActions = React.useMemo(\n () => resources.filter((r) => (r.actions ?? []).length > 0),\n [resources],\n )\n\n const allGloballySelected =\n resourcesWithActions.length > 0 &&\n resourcesWithActions.every((r) => {\n const actions = (r.actions ?? []).map((a) => a.name)\n const current = state.byResource[r.id] ?? new Set<string>()\n return actions.every((a) => current.has(a))\n })\n\n const toggleAllResources = (): void => {\n const select = !allGloballySelected\n const next: Record<string, Set<string>> = { ...state.byResource }\n for (const r of resources) {\n const actions = (r.actions ?? []).map((a) => a.name)\n next[r.id] = select ? new Set(actions) : new Set<string>()\n }\n onChange({ byResource: next })\n }\n\n if (resources.length === 0) {\n return (\n <p className=\"text-sm text-muted-foreground\">{t('settings:apiKeys.permissions.noResources')}</p>\n )\n }\n\n return (\n <div className=\"rounded-md border border-border\">\n {resourcesWithActions.length > 0 && (\n <div className=\"flex flex-wrap items-center justify-end gap-2 border-b border-border bg-muted/30 px-3 py-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"h-8\"\n onClick={toggleAllResources}\n >\n {allGloballySelected ? (\n <>\n <X className=\"mr-1.5 size-3.5\" />\n {t('settings:apiKeys.permissions.clearAllResources')}\n </>\n ) : (\n <>\n <Check className=\"mr-1.5 size-3.5\" />\n {t('settings:apiKeys.permissions.selectAllResources')}\n </>\n )}\n </Button>\n </div>\n )}\n <div className=\"max-h-[24rem] overflow-y-auto\">\n <Table>\n <TableHeader className=\"sticky top-0 bg-card\">\n <TableRow>\n <TableHead className=\"w-[14rem]\">{t('settings:apiKeys.permissions.resource')}</TableHead>\n <TableHead>{t('settings:apiKeys.permissions.actions')}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {resources.map((r) => {\n const actions = (r.actions ?? []).map((a) => a.name)\n const current = state.byResource[r.id] ?? new Set<string>()\n const allSelected = actions.length > 0 && actions.every((a) => current.has(a))\n return (\n <TableRow key={r.id}>\n <TableCell className=\"align-top\">\n <div className=\"flex flex-col gap-1\">\n <span className=\"font-medium\">{r.name}</span>\n <span className=\"text-xs text-muted-foreground\">{r.id}</span>\n <button\n type=\"button\"\n className=\"mt-1 inline-flex items-center gap-1 self-start text-xs text-primary hover:underline\"\n onClick={() => toggleAll(r.id, actions)}\n >\n {allSelected ? <X className=\"size-3\" /> : <Check className=\"size-3\" />}\n {allSelected\n ? t('settings:apiKeys.permissions.clearAll')\n : t('settings:apiKeys.permissions.selectAll')}\n </button>\n </div>\n </TableCell>\n <TableCell>\n <div className=\"flex flex-wrap gap-2\">\n {actions.map((a) => {\n const checked = current.has(a)\n return (\n <label\n key={a}\n className={cn(\n 'inline-flex cursor-pointer items-center gap-1.5 rounded-md border border-border px-2 py-1 text-xs',\n checked && 'border-primary bg-primary/10 text-primary',\n )}\n >\n <Checkbox\n checked={checked}\n onCheckedChange={() => toggle(r.id, a)}\n className=\"size-3.5\"\n />\n <span>{a}</span>\n </label>\n )\n })}\n </div>\n </TableCell>\n </TableRow>\n )\n })}\n </TableBody>\n </Table>\n </div>\n </div>\n )\n}\n\nfunction PermissionsSummary({ permissions }: { permissions: Record<string, string[]> }): React.ReactElement {\n const { t } = useI18n()\n const entries = Object.entries(permissions)\n if (entries.length === 0) {\n return <Badge variant=\"outline\">{t('settings:apiKeys.permissions.none')}</Badge>\n }\n const totalActions = entries.reduce((sum, [, a]) => sum + a.length, 0)\n return (\n <Badge variant=\"secondary\">\n {t('settings:apiKeys.permissions.summary', { resources: entries.length, actions: totalActions })}\n </Badge>\n )\n}\n\n// ─── Editor dialog ────────────────────────────────────────────────────────────\n\nfunction ApiKeyEditorDialog({\n open,\n onOpenChange,\n editing,\n resources,\n onCreated,\n onUpdated,\n}: {\n open: boolean\n onOpenChange: (open: boolean) => void\n editing: ApiKeyRecord | null\n resources: ResourceJSON[]\n onCreated: (result: { key: string; record: ApiKeyRecord }) => void\n onUpdated: (record: ApiKeyRecord) => void\n}): React.ReactElement {\n const { t } = useI18n()\n const client = useAdminClient()\n const notify = useNotify()\n const isEdit = !!editing\n const [name, setName] = React.useState(editing?.name ?? '')\n const [expiresInDays, setExpiresInDays] = React.useState<string>(() => {\n if (!editing?.expiresAt) return ''\n const ms = new Date(editing.expiresAt).getTime() - Date.now()\n return ms > 0 ? String(Math.max(1, Math.round(ms / (24 * 60 * 60 * 1000)))) : ''\n })\n const [permissions, setPermissions] = React.useState<PermissionsState>(() =>\n buildState(editing?.permissions ?? {}),\n )\n\n const save = useMutation({\n mutationFn: async (): Promise<{ key?: string; record: ApiKeyRecord }> => {\n const wire = stateToWire(permissions)\n if (isEdit && editing) {\n const expiry = expiresInDays.trim() === '' ? null : Number(expiresInDays)\n const res = await client.updateApiKey(editing.id, {\n name: name.trim(),\n permissions: wire,\n expiresInDays: expiry === null ? null : Number.isFinite(expiry) && expiry > 0 ? expiry : undefined,\n })\n return { record: res.record }\n }\n const expiry = expiresInDays.trim() === '' ? null : Number(expiresInDays)\n return client.createApiKey({\n name: name.trim(),\n permissions: wire,\n expiresInDays: expiry === null ? null : Number.isFinite(expiry) && expiry > 0 ? expiry : undefined,\n }) as Promise<{ key: string; record: ApiKeyRecord }>\n },\n onSuccess: (result) => {\n if (isEdit) {\n notify.success({ key: 'settings:apiKeys.notice.updated' })\n onUpdated(result.record)\n } else {\n if (result.key) onCreated({ key: result.key, record: result.record })\n }\n },\n onError: (err) => notify.error({ message: err instanceof Error ? err.message : String(err) }),\n })\n\n // Sync state when dialog re-opens against a different record.\n React.useEffect(() => {\n if (!open) return\n setName(editing?.name ?? '')\n setPermissions(buildState(editing?.permissions ?? {}))\n if (!editing?.expiresAt) setExpiresInDays('')\n else {\n const ms = new Date(editing.expiresAt).getTime() - Date.now()\n setExpiresInDays(ms > 0 ? String(Math.max(1, Math.round(ms / (24 * 60 * 60 * 1000)))) : '')\n }\n }, [open, editing])\n\n const totalSelected = Object.values(permissions.byResource).reduce(\n (sum, set) => sum + (set?.size ?? 0),\n 0,\n )\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"max-w-3xl\">\n <DialogHeader>\n <DialogTitle>\n {isEdit ? t('settings:apiKeys.editor.titleEdit') : t('settings:apiKeys.editor.titleCreate')}\n </DialogTitle>\n <DialogDescription>{t('settings:apiKeys.editor.description')}</DialogDescription>\n </DialogHeader>\n <form\n className=\"flex flex-col gap-4\"\n onSubmit={(e) => {\n e.preventDefault()\n if (!name.trim()) return\n save.mutate()\n }}\n >\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1.5\">\n <Label htmlFor=\"api-key-name\">{t('settings:apiKeys.editor.name')}</Label>\n <Input\n id=\"api-key-name\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder={t('settings:apiKeys.editor.namePlaceholder')}\n required\n maxLength={64}\n />\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <Label htmlFor=\"api-key-expires\">{t('settings:apiKeys.editor.expiresInDays')}</Label>\n <Input\n id=\"api-key-expires\"\n type=\"number\"\n min={1}\n max={3650}\n value={expiresInDays}\n onChange={(e) => setExpiresInDays(e.target.value)}\n placeholder={t('settings:apiKeys.editor.expiresPlaceholder')}\n />\n <span className=\"text-xs text-muted-foreground\">\n {t('settings:apiKeys.editor.expiresHint')}\n </span>\n </div>\n </div>\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex items-center justify-between\">\n <Label>{t('settings:apiKeys.editor.permissions')}</Label>\n <span className=\"text-xs text-muted-foreground\">\n {t('settings:apiKeys.editor.selectedActions', { count: totalSelected })}\n </span>\n </div>\n <PermissionsMatrix resources={resources} state={permissions} onChange={setPermissions} />\n </div>\n <DialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => onOpenChange(false)}>\n {t('common:cancel')}\n </Button>\n <Button type=\"submit\" disabled={save.isPending || !name.trim() || totalSelected === 0}>\n {save.isPending ? t('common:saving') : isEdit ? t('common:save') : t('settings:apiKeys.actions.create')}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n )\n}\n\n// ─── Webhooks section ─────────────────────────────────────────────────────────\n\nconst WEBHOOK_EVENTS = ['record.created', 'record.updated', 'record.deleted', '*']\n\nfunction WebhooksSection(): React.ReactElement {\n const { t } = useI18n()\n const client = useAdminClient()\n const qc = useQueryClient()\n const notify = useNotify()\n const dialogs = useDialogs()\n const resources = useResources()\n const [editorOpen, setEditorOpen] = React.useState(false)\n const [editing, setEditing] = React.useState<WebhookRecord | null>(null)\n const [selectedId, setSelectedId] = React.useState<string | null>(null)\n\n const list = useQuery({\n queryKey: KEY_WEBHOOKS,\n queryFn: () => client.listWebhooks(),\n })\n const deliveries = useQuery({\n queryKey: ['modern-admin', 'webhooks', selectedId, 'deliveries'],\n queryFn: () => client.listWebhookDeliveries(selectedId!),\n enabled: !!selectedId,\n })\n const deleteMut = useMutation({\n mutationFn: (id: string) => client.deleteWebhook(id),\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: KEY_WEBHOOKS })\n notify.success({ key: 'settings:webhooks.notice.deleted' })\n },\n onError: (err) => notify.error({ message: err instanceof Error ? err.message : String(err) }),\n })\n const testMut = useMutation({\n mutationFn: (id: string) => client.testWebhook(id),\n onSuccess: () => {\n if (selectedId) qc.invalidateQueries({ queryKey: ['modern-admin', 'webhooks', selectedId, 'deliveries'] })\n notify.success({ key: 'settings:webhooks.notice.testQueued' })\n },\n onError: (err) => notify.error({ message: err instanceof Error ? err.message : String(err) }),\n })\n\n const webhooks = list.data?.webhooks ?? []\n\n const onDelete = async (webhook: WebhookRecord): Promise<void> => {\n const ok = await dialogs.confirm({\n title: t('settings:webhooks.confirmDelete.title'),\n description: t('settings:webhooks.confirmDelete.description', { name: webhook.name }),\n confirmLabel: t('common:delete'),\n destructive: true,\n })\n if (ok) deleteMut.mutate(webhook.id)\n }\n\n return (\n <div className=\"flex flex-col gap-4\">\n <SettingsCard\n icon={SettingsIcon}\n title={t('settings:webhooks.title')}\n description={t('settings:webhooks.description')}\n action={\n <Button size=\"sm\" onClick={() => { setEditing(null); setEditorOpen(true) }}>\n <Plus className=\"size-4\" />\n {t('settings:webhooks.actions.create')}\n </Button>\n }\n >\n <SettingsListState\n isLoading={list.isLoading}\n error={list.error}\n isEmpty={webhooks.length === 0}\n loadingLabel={t('common:loading')}\n empty={{\n icon: SettingsIcon,\n title: t('settings:webhooks.empty.title'),\n description: t('settings:webhooks.empty.description'),\n }}\n >\n <SettingsTableScroll>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>{t('settings:webhooks.columns.name')}</TableHead>\n <TableHead>{t('settings:webhooks.columns.resource')}</TableHead>\n <TableHead>{t('settings:webhooks.columns.events')}</TableHead>\n <TableHead>{t('settings:webhooks.columns.enabled')}</TableHead>\n <TableHead className=\"text-right\">{t('settings:webhooks.columns.actions')}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {webhooks.map((webhook) => (\n <TableRow key={webhook.id}>\n <TableCell>\n <button\n type=\"button\"\n className=\"text-left font-medium hover:underline\"\n onClick={() => setSelectedId(webhook.id)}\n >\n {webhook.name}\n </button>\n <div className=\"max-w-xs truncate text-xs text-muted-foreground\">{webhook.url}</div>\n </TableCell>\n <TableCell>{resourceName(resources, webhook.resourceId, t('settings:webhooks.editor.allResources'))}</TableCell>\n <TableCell className=\"max-w-xs\">\n <div className=\"flex flex-wrap gap-1\">\n {webhook.events.map((event) => <Badge key={event} variant=\"outline\">{event}</Badge>)}\n </div>\n </TableCell>\n <TableCell>{webhook.enabled ? t('common:yes') : t('common:no')}</TableCell>\n <TableCell className=\"text-right\">\n <div className=\"inline-flex gap-1\">\n <Button variant=\"ghost\" size=\"sm\" onClick={() => testMut.mutate(webhook.id)}>\n {t('settings:webhooks.actions.test')}\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => { setEditing(webhook); setEditorOpen(true) }}>\n <Edit className=\"size-4\" />\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => void onDelete(webhook)}>\n <Trash2 className=\"size-4 text-destructive\" />\n </Button>\n </div>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </SettingsTableScroll>\n </SettingsListState>\n </SettingsCard>\n\n {selectedId && (\n <SettingsCard icon={SettingsIcon} title={t('settings:webhooks.deliveries.title')}>\n {deliveries.isLoading ? (\n <div className=\"py-4 text-sm text-muted-foreground\">{t('common:loading')}</div>\n ) : (\n <SettingsTableScroll>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>{t('settings:webhooks.deliveries.status')}</TableHead>\n <TableHead>{t('settings:webhooks.deliveries.event')}</TableHead>\n <TableHead>{t('settings:webhooks.deliveries.attempt')}</TableHead>\n <TableHead>{t('settings:webhooks.deliveries.response')}</TableHead>\n <TableHead>{t('settings:webhooks.deliveries.createdAt')}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {(deliveries.data?.deliveries ?? []).map((delivery) => (\n <TableRow key={delivery.id}>\n <TableCell>{delivery.status}</TableCell>\n <TableCell>{delivery.event}</TableCell>\n <TableCell>{delivery.attempt}</TableCell>\n <TableCell className=\"max-w-sm truncate\">\n {delivery.responseStatus ?? delivery.error ?? delivery.responseBody ?? '—'}\n </TableCell>\n <TableCell>{formatDate(delivery.createdAt)}</TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </SettingsTableScroll>\n )}\n </SettingsCard>\n )}\n\n <WebhookEditorDialog\n key={editing?.id ?? 'new'}\n open={editorOpen}\n onOpenChange={setEditorOpen}\n webhook={editing}\n resources={resources}\n />\n </div>\n )\n}\n\nfunction WebhookEditorDialog({\n open,\n onOpenChange,\n webhook,\n resources,\n}: {\n open: boolean\n onOpenChange(open: boolean): void\n webhook: WebhookRecord | null\n resources: ResourceJSON[]\n}): React.ReactElement {\n const { t } = useI18n()\n const client = useAdminClient()\n const qc = useQueryClient()\n const notify = useNotify()\n const [name, setName] = React.useState(webhook?.name ?? '')\n const [url, setUrl] = React.useState(webhook?.url ?? '')\n const [resourceId, setResourceId] = React.useState(webhook?.resourceId ?? '')\n const [enabled, setEnabled] = React.useState(webhook?.enabled ?? true)\n const [secret, setSecret] = React.useState(webhook?.secret ?? '')\n const [events, setEvents] = React.useState<string[]>(webhook?.events ?? ['record.created', 'record.updated'])\n const [headers, setHeaders] = React.useState<Record<string, unknown>>(webhook?.headers ?? {})\n const [filters, setFilters] = React.useState<Record<string, unknown>>(webhook?.filters ?? {})\n const [payloadFields, setPayloadFields] = React.useState<string[]>(webhook?.payloadFields ?? [])\n const selectedResource = resources.find((r) => r.id === resourceId)\n\n const save = useMutation({\n mutationFn: (payload: WebhookInput) =>\n webhook ? client.updateWebhook(webhook.id, payload) : client.createWebhook(payload),\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: KEY_WEBHOOKS })\n notify.success({ key: 'settings:webhooks.notice.saved' })\n onOpenChange(false)\n },\n onError: (err) => notify.error({ message: err instanceof Error ? err.message : String(err) }),\n })\n\n const toggleEvent = (event: string): void => {\n setEvents((prev) => prev.includes(event) ? prev.filter((e) => e !== event) : [...prev, event])\n }\n\n const onSubmit = (e: React.FormEvent): void => {\n e.preventDefault()\n save.mutate({\n name: name.trim(),\n url: url.trim(),\n events,\n resourceId: resourceId || null,\n enabled,\n ...(secret.trim() ? { secret: secret.trim() } : {}),\n headers: stringRecord(headers),\n filters: stringRecord(filters),\n payloadFields,\n })\n }\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"max-w-3xl\">\n <DialogHeader>\n <DialogTitle>{webhook ? t('settings:webhooks.editor.titleEdit') : t('settings:webhooks.editor.titleCreate')}</DialogTitle>\n <DialogDescription>{t('settings:webhooks.editor.description')}</DialogDescription>\n </DialogHeader>\n <form className=\"space-y-4\" onSubmit={onSubmit}>\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"space-y-1.5\">\n <Label>{t('settings:webhooks.editor.name')}</Label>\n <Input value={name} onChange={(e) => setName(e.target.value)} required />\n </div>\n <div className=\"space-y-1.5\">\n <Label>{t('settings:webhooks.editor.url')}</Label>\n <Input value={url} onChange={(e) => setUrl(e.target.value)} required type=\"url\" />\n </div>\n <div className=\"space-y-1.5\">\n <Label>{t('settings:webhooks.editor.resource')}</Label>\n <Select\n value={resourceId || '__all__'}\n onValueChange={(v) => { setResourceId(v === '__all__' ? '' : v); setPayloadFields([]) }}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__all__\">{t('settings:webhooks.editor.allResources')}</SelectItem>\n {resources.map((resource) => (\n <SelectItem key={resource.id} value={resource.id}>\n {resource.name}\n {resource.name !== resource.id && (\n <span className=\"ml-1.5 text-xs text-muted-foreground\">({resource.id})</span>\n )}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-1.5\">\n <div className=\"flex items-center gap-1.5\">\n <Label>{t('settings:webhooks.editor.secret')}</Label>\n <InfoTooltip\n content={t('settings:webhooks.editor.secretHint')}\n ariaLabel={t('settings:webhooks.editor.secret')}\n side=\"right\"\n />\n </div>\n <Input value={secret} onChange={(e) => setSecret(e.target.value)} type=\"password\" />\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <Switch checked={enabled} onCheckedChange={setEnabled} />\n <Label>{t('settings:webhooks.editor.enabled')}</Label>\n </div>\n <div className=\"space-y-2\">\n <Label>{t('settings:webhooks.editor.events')}</Label>\n <div className=\"flex flex-wrap gap-2\">\n {WEBHOOK_EVENTS.map((event) => (\n <label key={event} className=\"flex items-center gap-2 rounded-md border border-border px-3 py-2 text-sm\">\n <Checkbox checked={events.includes(event)} onCheckedChange={() => toggleEvent(event)} />\n {event}\n </label>\n ))}\n </div>\n </div>\n {selectedResource && (\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-1.5\">\n <Label>{t('settings:webhooks.editor.payloadFields')}</Label>\n <InfoTooltip\n content={t('settings:webhooks.editor.payloadFieldsHint')}\n ariaLabel={t('settings:webhooks.editor.payloadFields')}\n side=\"right\"\n />\n </div>\n <div className=\"grid gap-2 sm:grid-cols-2\">\n {selectedResource.properties.map((property) => (\n <label key={property.path} className=\"flex items-center gap-2 text-sm\">\n <Checkbox\n checked={payloadFields.includes(property.path)}\n onCheckedChange={() =>\n setPayloadFields((prev) =>\n prev.includes(property.path)\n ? prev.filter((p) => p !== property.path)\n : [...prev, property.path],\n )\n }\n />\n {property.label}\n </label>\n ))}\n </div>\n </div>\n )}\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"space-y-1.5\">\n <div className=\"flex items-center gap-1.5\">\n <Label>{t('settings:webhooks.editor.headers')}</Label>\n <InfoTooltip\n content={t('settings:webhooks.editor.headersHint')}\n ariaLabel={t('settings:webhooks.editor.headers')}\n side=\"top\"\n />\n </div>\n <JsonEditor value={headers} onChange={(next) => setHeaders(toJsonRecord(next))} />\n </div>\n <div className=\"space-y-1.5\">\n <div className=\"flex items-center gap-1.5\">\n <Label>{t('settings:webhooks.editor.filters')}</Label>\n <InfoTooltip\n content={t('settings:webhooks.editor.filtersHint')}\n ariaLabel={t('settings:webhooks.editor.filters')}\n side=\"top\"\n />\n </div>\n <JsonEditor value={filters} onChange={(next) => setFilters(toJsonRecord(next))} />\n </div>\n </div>\n <DialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => onOpenChange(false)}>{t('common:cancel')}</Button>\n <Button type=\"submit\" disabled={save.isPending || !name.trim() || !url.trim() || events.length === 0}>\n {save.isPending ? t('common:saving') : t('common:save')}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n )\n}\n\nconst resourceName = (\n resources: ResourceJSON[],\n id: string | null | undefined,\n fallback: string,\n): string => id ? (resources.find((r) => r.id === id)?.name ?? id) : fallback\n\nconst toJsonRecord = (value: unknown): Record<string, unknown> =>\n value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : {}\n\nconst stringRecord = (value: Record<string, unknown>): Record<string, string> => {\n const out: Record<string, string> = {}\n for (const [key, item] of Object.entries(value)) {\n if (item != null && item !== '') out[key] = String(item)\n }\n return out\n}\n\n// ─── Created-secret dialog ────────────────────────────────────────────────────\n\nfunction CreatedSecretDialog({\n secret,\n onClose,\n}: {\n secret: { key: string; record: ApiKeyRecord } | null\n onClose: () => void\n}): React.ReactElement {\n const { t } = useI18n()\n const notify = useNotify()\n const [reveal, setReveal] = React.useState(false)\n const [copied, setCopied] = React.useState(false)\n\n React.useEffect(() => {\n if (!secret) {\n setReveal(false)\n setCopied(false)\n }\n }, [secret])\n\n const onCopy = async (): Promise<void> => {\n if (!secret) return\n try {\n await navigator.clipboard.writeText(secret.key)\n setCopied(true)\n notify.success({ key: 'settings:apiKeys.notice.copied' })\n setTimeout(() => setCopied(false), 1500)\n } catch {\n notify.error({ key: 'settings:apiKeys.notice.copyFailed' })\n }\n }\n\n return (\n <Dialog open={!!secret} onOpenChange={(open) => !open && onClose()}>\n <DialogContent className=\"max-w-lg\">\n <DialogHeader>\n <DialogTitle className=\"flex items-center gap-2\">\n <SettingsIcon className=\"size-5\" />\n {t('settings:apiKeys.created.title')}\n </DialogTitle>\n <DialogDescription>{t('settings:apiKeys.created.description')}</DialogDescription>\n </DialogHeader>\n <div className=\"rounded-md border border-amber-300/60 bg-amber-50 p-3 text-sm text-amber-900 dark:border-amber-300/30 dark:bg-amber-950/40 dark:text-amber-200\">\n <div className=\"flex items-start gap-2\">\n <AlertTriangle className=\"mt-0.5 size-4\" />\n <p>{t('settings:apiKeys.created.warning')}</p>\n </div>\n </div>\n <div className=\"flex items-stretch gap-2\">\n <div className=\"relative flex-1\">\n <Input\n readOnly\n type={reveal ? 'text' : 'password'}\n value={secret?.key ?? ''}\n className=\"pr-10 font-mono text-xs\"\n onFocus={(e) => e.currentTarget.select()}\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"absolute right-1 top-1/2 -translate-y-1/2\"\n onClick={() => setReveal((v) => !v)}\n aria-label={reveal ? t('settings:apiKeys.created.hide') : t('settings:apiKeys.created.reveal')}\n >\n {reveal ? <EyeOff className=\"size-4\" /> : <Eye className=\"size-4\" />}\n </Button>\n </div>\n <Button type=\"button\" onClick={onCopy} variant=\"secondary\">\n {copied ? <Check className=\"size-4\" /> : <Copy className=\"size-4\" />}\n <span className=\"hidden sm:inline\">\n {copied ? t('settings:apiKeys.created.copied') : t('settings:apiKeys.created.copy')}\n </span>\n </Button>\n </div>\n <DialogFooter>\n <Button onClick={onClose}>{t('common:done')}</Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n\nconst formatDate = (input: string | Date): string => {\n try {\n return new Date(input).toLocaleString()\n } catch {\n return String(input)\n }\n}\n"],"mappings":"+qCAqCA,SAAgB,EAAa,CAC3B,KAAM,EACN,QACA,cACA,SACA,gBACA,YACwC,CACxC,OACE,EAAA,EAAA,KAAA,CAAC,GAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAA,CAAC,GAAD,CACE,UAAW,EACT,6BACA,GAAU,gDACZ,WAJF,EAME,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,yCAAf,EACE,EAAA,EAAA,KAAA,CAAC,GAAD,CAAW,UAAU,mCAArB,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAM,UAAU,QAAU,CAAA,EACzB,CACQ,IACV,GAAc,EAAA,EAAA,IAAA,CAAC,GAAD,CAAA,SAAkB,CAA6B,CAAA,EAAI,IAC/D,IACJ,CACS,KACZ,EAAA,EAAA,IAAA,CAAC,GAAD,CAAa,UAAW,EAAG,UAAW,CAAa,EAAI,UAAsB,CAAA,CACzE,CAAA,CAAA,CAEV,CAQA,SAAgB,GAAoB,CAAE,YAA+D,CACnG,OAAO,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,gCAAiC,UAAc,CAAA,CACvE,CAQA,SAAgB,GAAc,CAAE,KAAM,EAAM,QAAO,eAAuD,CACxG,OACE,EAAA,EAAA,IAAA,CAAC,GAAD,CAAO,UAAU,qBACf,EAAA,EAAA,KAAA,CAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,UACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,CAAA,CACG,CAAA,GACZ,EAAA,EAAA,IAAA,CAAC,GAAD,CAAA,SAAa,CAAkB,CAAA,EAC9B,GAAc,EAAA,EAAA,IAAA,CAAC,GAAD,CAAA,SAAmB,CAA8B,CAAA,EAAI,IACzD,CAAA,CAAA,CACR,CAAA,CAEX,CAgBA,SAAgB,GAAkB,CAChC,YACA,QACA,UACA,eACA,QACA,YAC6C,CAc7C,OAbI,GACK,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,0DAAkD,CAAkB,CAAA,EAExF,GAEA,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,kGACZ,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,CACnD,CAAA,EAGL,GACK,EAAA,EAAA,IAAA,CAAC,GAAD,CAAe,GAAI,CAAQ,CAAA,GAE7B,EAAA,EAAA,IAAA,CAAA,EAAA,SAAA,CAAG,UAAW,CAAA,CACvB,CC3HA,SAAgB,IAAiD,CAC/D,IAAM,EAAS,EAAe,EACxB,EAAS,EAAU,EACnB,CAAE,KAAM,EAAQ,EAChB,EAAW,EAAS,CACxB,SAAU,CAAC,eAAgB,eAAgB,UAAU,EACrD,YAAe,EAAO,uBAAuB,CAC/C,CAAC,EACK,CAAC,EAAM,GAAA,EAAiB,SAAS,CACrC,QAAS,GACT,MAAO,uCACP,OAAQ,GACR,aAAc,EAChB,CAAC,EAED,EAAM,cAAgB,CACf,EAAS,MACd,EAAQ,CACN,QAAS,EAAS,KAAK,QACvB,MAAO,EAAS,KAAK,MACrB,OAAQ,GACR,aAAc,EAAS,KAAK,YAC9B,CAAC,CACH,EAAG,CAAC,EAAS,IAAI,CAAC,EAElB,IAAM,EAAO,EAAY,CACvB,WAAY,SACV,EAAO,0BAA0B,CAC/B,QAAS,EAAK,QACd,MAAO,EAAK,MACZ,GAAI,EAAK,OAAO,KAAK,EAAI,CAAE,OAAQ,EAAK,OAAO,KAAK,CAAE,EAAI,CAAC,EAC3D,aAAc,EAAK,YACrB,CAAC,EACH,cAAiB,CACf,EAAS,QAAQ,EACjB,EAAS,IAAU,CAAE,GAAG,EAAM,OAAQ,EAAG,EAAE,EAC3C,EAAO,QAAQ,CAAE,QAAS,EAAE,4BAA4B,CAAE,CAAC,CAC7D,EACA,QAAU,GAAQ,CAChB,EAAO,MAAM,CAAE,QAAS,aAAe,MAAQ,EAAI,QAAU,OAAO,CAAG,CAAE,CAAC,CAC5E,CACF,CAAC,EAED,GAAI,EAAS,UACX,OAAO,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,8CAAsC,EAAE,gBAAgB,CAAO,CAAA,EAGvF,GAAI,EAAS,MACX,OACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,kGACZ,EAAS,iBAAiB,MAAQ,EAAS,MAAM,QAAU,OAAO,EAAS,KAAK,CAC9E,CAAA,EAIT,IAAM,EAAO,EAAS,KAKtB,OAJK,GAKH,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,gCACb,EAAA,EAAA,KAAA,CAAC,EAAD,CACE,KAAM,EACN,MAAO,EAAE,4BAA4B,EACrC,YAAa,EAAE,kCAAkC,EACjD,cAAc,qBAJhB,EAME,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,6CAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,QAAS,EAAK,QAAU,YAAc,mBAC1C,EAAK,QAAU,EAAE,8BAA8B,EAAI,EAAE,+BAA+B,CAChF,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,QAAS,EAAK,WAAa,YAAc,mBAC7C,EAAK,WAAa,EAAE,iCAAiC,EAAI,EAAE,qCAAqC,CAC5F,CAAA,GACP,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,QAAQ,mBAAW,EAAE,+BAA+B,CAAS,CAAA,GACpE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,QAAQ,mBAAW,EAAE,gCAAiC,CAAE,SAAU,EAAK,QAAS,CAAC,CAAS,CAAA,CAC9F,KAEL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,qCAAf,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,iFAAf,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,qBAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,QAAQ,gCAAwB,EAAE,kCAAkC,CAAS,CAAA,GACpF,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAU,yCACV,EAAE,iCAAiC,CACnC,CAAA,CACA,KACL,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,GAAG,uBACH,QAAS,EAAK,QACd,SAAU,CAAC,EAAK,WAAa,EAAK,UAClC,gBAAkB,GAAY,EAAS,IAAU,CAAE,GAAG,EAAM,SAAQ,EAAE,CACvE,CAAA,CACE,KAEL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,uBAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,QAAQ,8BAAsB,EAAE,iCAAiC,CAAS,CAAA,GACjF,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,GAAG,qBACH,MAAO,EAAK,MACZ,SAAU,CAAC,EAAK,WAAa,EAAK,UAClC,SAAW,GAAM,EAAS,IAAU,CAAE,GAAG,EAAM,MAAO,EAAE,OAAO,KAAM,EAAE,EACvE,YAAY,sCACb,CAAA,CACE,GACF,KAEL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,uBAAf,EACE,EAAA,EAAA,KAAA,CAAC,EAAD,CAAO,QAAQ,uBAAuB,UAAU,mCAAhD,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAU,UAAU,QAAS,CAAA,EAC5B,EAAE,kCAAkC,CAChC,KACP,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,GAAG,uBACH,KAAK,WACL,MAAO,EAAK,OACZ,SAAU,CAAC,EAAK,WAAa,EAAK,UAClC,SAAW,GAAM,EAAS,IAAU,CAAE,GAAG,EAAM,OAAQ,EAAE,OAAO,KAAM,EAAE,EACxE,YAAa,EAAK,cAAgB,cACnC,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAU,yCACV,EAAE,iCAAiC,CACnC,CAAA,CACA,KAEL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,uBAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,QAAQ,sCAA8B,EAAE,wCAAwC,CAAS,CAAA,GAChG,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,GAAG,6BACH,MAAO,EAAK,aACZ,SAAU,CAAC,EAAK,WAAa,EAAK,UAClC,SAAW,GAAM,EAAS,IAAU,CAAE,GAAG,EAAM,aAAc,EAAE,OAAO,KAAM,EAAE,EAC9E,KAAM,EACN,YAAa,EAAE,8CAA8C,CAC9D,CAAA,CACE,KAEL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,+FAAf,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,uBAAe,EAAE,kCAAkC,CAAO,CAAA,GACzE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,iCACZ,EAAE,wCAAwC,CACxC,CAAA,CACF,CAAA,CAAA,GACL,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,QAAQ,mBAAW,EAAE,uCAAuC,CAAS,CAAA,CACzE,KAEL,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,6BACb,EAAA,EAAA,KAAA,CAAC,EAAD,CAAQ,YAAe,EAAK,OAAO,EAAG,SAAU,CAAC,EAAK,WAAa,EAAK,WAAa,CAAC,EAAK,MAAM,KAAK,WAAtG,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAM,UAAU,QAAS,CAAA,EACxB,EAAK,UAAY,EAAE,6BAA6B,EAAI,EAAE,2BAA2B,CAC5E,GACL,CAAA,CACO,GACX,CAAA,GAjGE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,8CAAsC,EAAE,4BAA4B,CAAO,CAAA,CAmGrG,CCzGA,IAAM,EAAW,CAAC,eAAgB,UAAU,EACtC,GAAe,CAAC,eAAgB,UAAU,EAY1C,GAAkC,CACtC,CAAE,IAAK,WAAY,SAAU,yBAA0B,KAAM,CAAS,EACtE,CAAE,IAAK,WAAY,SAAU,0BAA2B,KAAM,CAAa,EAC3E,CAAE,IAAK,eAAgB,SAAU,oBAAqB,KAAM,CAAI,CAClE,EAEA,SAAgB,GAAa,CAAE,WAAqD,CAClF,GAAM,CAAE,GAAM,EAAQ,EAChB,EAAW,EAAY,EACvB,EAAW,GAAY,EAGvB,EAAA,EAAiB,YACf,CACJ,GAAG,GAAkB,OAAQ,GAC3B,EAAE,MAAQ,WAAa,EAAS,QAC5B,EAAE,MAAQ,WAAa,EAAS,SAC9B,EAAE,MAAQ,gBAAiB,EAAS,WAE5C,EACA,GAAG,GAA6B,CAAC,CAAC,IAAK,IAAS,CAC9C,IAAK,EAAI,IACT,SAAU,EAAI,SACd,KAAM,EAAI,KACV,YAAa,EACf,EAAE,CACJ,EAEA,CAAC,EAAS,QAAS,EAAS,SAAU,EAAS,WAAW,CAC5D,EAGM,EAAmC,CAAC,WAAY,WAAY,cAAc,EAC1E,EAAa,GAChB,EAAyB,SAAS,CAAC,EAChC,EAA2B,GAAW,KACtC,EACJ,GAAa,EAAS,KAAM,GAAM,EAAE,MAAQ,CAAS,EACjD,EACC,EAAS,EAAE,EAAE,KAAO,KAW3B,OAVI,IAAW,MAKX,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,iGACZ,EAAE,+BAA+B,CAC/B,CAAA,GAOP,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,0EAAf,EAEE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,sBACb,EAAA,EAAA,KAAA,CAAC,EAAD,CAAQ,MAAO,GAAU,GAAI,cAAgB,GAAM,EAAS,CAAE,KAAM,WAAY,QAAS,CAAE,CAAC,WAA5F,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAe,UAAU,mBACvB,EAAA,EAAA,IAAA,CAAC,EAAD,CAAc,CAAA,CACD,CAAA,GACf,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SACG,EAAS,KAAK,CAAE,MAAK,WAAU,KAAM,MACpC,EAAA,EAAA,IAAA,CAAC,EAAD,CAAsB,MAAO,YAC3B,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAU,mCAAhB,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAM,UAAU,QAAU,CAAA,GAC1B,EAAA,EAAA,IAAA,CAAC,OAAD,CAAA,SAAO,EAAE,CAAQ,CAAQ,CAAA,CACrB,GACI,EALK,CAKL,CACb,CACY,CAAA,CACT,GACL,CAAA,GAEL,EAAA,EAAA,IAAA,CAAC,QAAD,CAAO,UAAU,4BACf,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,+BACZ,EAAS,KAAK,CAAE,MAAK,WAAU,KAAM,MACpC,EAAA,EAAA,KAAA,CAAC,EAAD,CAEE,GAAI,CAAE,KAAM,WAAY,QAAS,CAAI,EACrC,UAAW,EACT,uEACA,IAAW,GAAO,uBACpB,WANF,EAQE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAM,UAAU,QAAU,CAAA,GAC1B,EAAA,EAAA,IAAA,CAAC,OAAD,CAAA,SAAO,EAAE,CAAQ,CAAQ,CAAA,CACrB,GATC,CASD,CACP,CACE,CAAA,CACA,CAAA,GACP,EAAA,EAAA,KAAA,CAAC,UAAD,CAAS,UAAU,mBAAnB,CACG,GAAU,EAAU,CAAM,GAAK,IAAW,aAAc,EAAA,EAAA,IAAA,CAAC,GAAD,CAAiB,CAAA,EACzE,GAAU,EAAU,CAAM,GAAK,IAAW,aAAc,EAAA,EAAA,IAAA,CAAC,GAAD,CAAkB,CAAA,EAC1E,GAAU,EAAU,CAAM,GAAK,IAAW,iBAAkB,EAAA,EAAA,IAAA,CAAC,GAAD,CAA6B,CAAA,EACzF,GAAU,CAAC,EAAU,CAAM,QAAY,CACtC,IAAM,EAAa,GAA6B,CAAC,CAAC,KAAM,GAAM,EAAE,MAAQ,CAAM,EAC9E,OAAO,GAAa,EAAA,EAAA,IAAA,CAAC,EAAW,UAAZ,CAAuB,CAAA,EAAI,IACjD,EAAA,CAAG,CACI,GACN,GAET,CAIA,SAAS,IAAqC,CAC5C,GAAM,CAAE,KAAM,EAAQ,EAChB,EAAS,EAAe,EACxB,EAAK,EAAe,EACpB,EAAS,EAAU,EACnB,EAAU,GAAW,EACrB,EAAY,GAAa,EACzB,CAAC,EAAY,GAAA,EAAuB,SAAS,EAAK,EAClD,CAAC,EAAS,GAAA,EAAoB,SAA8B,IAAI,EAChE,CAAC,EAAe,GAAA,EAA0B,SAAuD,IAAI,EAErG,EAAO,EAAS,CACpB,SAAU,EACV,YAAe,EAAO,YAAY,CACpC,CAAC,EAEK,EAAY,EAAY,CAC5B,WAAa,GAAe,EAAO,aAAa,CAAE,EAClD,cAAiB,CACf,EAAG,kBAAkB,CAAE,SAAU,CAAS,CAAC,EAC3C,EAAO,QAAQ,CAAE,IAAK,iCAAkC,CAAC,CAC3D,EACA,QAAU,GAAQ,EAAO,MAAM,CAAE,QAAS,aAAe,MAAQ,EAAI,QAAU,OAAO,CAAG,CAAE,CAAC,CAC9F,CAAC,EAEK,EAAmB,EAAY,CACnC,WAAa,GACX,EAAO,aAAa,EAAK,GAAI,CAAE,QAAS,EAAK,OAAQ,CAAC,EACxD,cAAiB,EAAG,kBAAkB,CAAE,SAAU,CAAS,CAAC,EAC5D,QAAU,GAAQ,EAAO,MAAM,CAAE,QAAS,aAAe,MAAQ,EAAI,QAAU,OAAO,CAAG,CAAE,CAAC,CAC9F,CAAC,EAEK,MAAuB,CAC3B,EAAW,IAAI,EACf,EAAc,EAAI,CACpB,EAEM,EAAU,GAA4B,CAC1C,EAAW,CAAG,EACd,EAAc,EAAI,CACpB,EAEM,EAAW,KAAO,IAAqC,CAOvD,MANa,EAAQ,QAAQ,CAC/B,MAAO,EAAE,sCAAsC,EAC/C,YAAa,EAAE,6CAA8C,CAAE,KAAM,EAAI,MAAQ,EAAI,EAAG,CAAC,EACzF,aAAc,EAAE,iCAAiC,EACjD,YAAa,EACf,CAAC,GACO,EAAU,OAAO,EAAI,EAAE,CACjC,EAEM,EAAO,EAAK,MAAM,MAAQ,CAAC,EAEjC,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,+BAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,KAAM,EACN,MAAO,EAAE,wBAAwB,EACjC,YAAa,EAAE,8BAA8B,EAC7C,QACE,EAAA,EAAA,KAAA,CAAC,EAAD,CAAQ,QAAS,EAAU,KAAK,cAAhC,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAM,UAAU,QAAU,CAAA,GAC1B,EAAA,EAAA,IAAA,CAAC,OAAD,CAAA,SAAO,EAAE,iCAAiC,CAAQ,CAAA,CAC5C,cAGV,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,UAAW,EAAK,UAChB,MAAO,EAAK,MACZ,QAAS,EAAK,SAAW,EACzB,aAAc,EAAE,gBAAgB,EAChC,MAAO,CACL,KAAM,EACN,MAAO,EAAE,8BAA8B,EACvC,YAAa,EAAE,oCAAoC,CACrD,YAEA,EAAA,EAAA,IAAA,CAAC,GAAD,CAAA,UACE,EAAA,EAAA,KAAA,CAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,UACE,EAAA,EAAA,KAAA,CAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAY,EAAE,+BAA+B,CAAa,CAAA,GAC1D,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,UAAU,gCAAwB,EAAE,gCAAgC,CAAa,CAAA,GAC5F,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,UAAU,gCAAwB,EAAE,sCAAsC,CAAa,CAAA,GAClG,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,UAAU,gCAAwB,EAAE,oCAAoC,CAAa,CAAA,GAChG,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAY,EAAE,kCAAkC,CAAa,CAAA,GAC7D,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,UAAU,sBAAc,EAAE,kCAAkC,CAAa,CAAA,CAC5E,CAAA,CAAA,CACC,CAAA,GACb,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SACG,EAAK,IAAK,IACT,EAAA,EAAA,KAAA,CAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,UAAU,wBACnB,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,yBAAf,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAA,SAAO,EAAE,MAAQ,EAAE,EAAS,CAAA,EAC3B,EAAE,cACD,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,yCACb,EAAE,4BAA6B,CAAE,KAAM,EAAW,EAAE,WAAW,CAAE,CAAC,CAC/D,CAAA,CAEL,GACI,CAAA,GACX,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,UAAU,kDAClB,EAAE,MAAQ,GAAG,EAAE,MAAM,GAAK,GAClB,CAAA,GACX,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,UAAU,iCACnB,EAAA,EAAA,IAAA,CAAC,GAAD,CAAoB,YAAa,EAAE,WAAc,CAAA,CACxC,CAAA,GACX,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,UAAU,wCAClB,EAAE,UAAY,EAAW,EAAE,SAAS,EAAI,EAAE,+BAA+B,CACjE,CAAA,GACX,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,UACE,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,QAAS,EAAE,QACX,gBAAkB,GAAY,EAAiB,OAAO,CAAE,GAAI,EAAE,GAAI,SAAQ,CAAC,EAC3E,aAAY,EAAE,kCAAkC,CACjD,CAAA,CACQ,CAAA,GACX,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,UAAU,uBACnB,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,6BAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAQ,QAAQ,QAAQ,KAAK,KAAK,YAAe,EAAO,CAAC,EAAG,aAAY,EAAE,+BAA+B,YACvG,EAAA,EAAA,IAAA,CAAC,EAAD,CAAM,UAAU,QAAU,CAAA,CACpB,CAAA,GACR,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,QAAQ,QACR,KAAK,KACL,YAAe,EAAS,CAAC,EACzB,aAAY,EAAE,iCAAiC,EAC/C,SAAU,EAAU,oBAEpB,EAAA,EAAA,IAAA,CAAC,EAAD,CAAQ,UAAU,yBAA2B,CAAA,CACvC,CAAA,CACL,GACI,CAAA,CACH,CAAA,EA3CK,EAAE,EA2CP,CACX,CACQ,CAAA,CACN,CAAA,CAAA,CACY,CAAA,CACJ,CAAA,CACP,CAAA,GAEd,EAAA,EAAA,IAAA,CAAC,GAAD,CAEE,KAAM,EACN,aAAc,EACL,UACE,YACX,UAAY,GAAW,CACrB,EAAc,EAAK,EACnB,EAAiB,CAAM,EACvB,EAAG,kBAAkB,CAAE,SAAU,CAAS,CAAC,CAC7C,EACA,cAAiB,CACf,EAAc,EAAK,EACnB,EAAG,kBAAkB,CAAE,SAAU,CAAS,CAAC,CAC7C,CACD,EAdM,GAAS,IAAM,KAcrB,GAED,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,OAAQ,EACR,YAAe,EAAiB,IAAI,CACrC,CAAA,CACE,GAET,CASA,IAAM,GAAc,IAAuD,CACzE,WAAY,OAAO,YACjB,OAAO,QAAQ,CAAK,CAAC,CAAC,KAAK,CAAC,EAAG,KAAO,CAAC,EAAG,IAAI,IAAI,CAAC,CAAC,CAAC,CACvD,CACF,GAEM,GAAe,GAAsD,CACzE,IAAM,EAAgC,CAAC,EACvC,IAAK,GAAM,CAAC,EAAG,KAAQ,OAAO,QAAQ,EAAM,UAAU,EAChD,EAAI,OAAS,IACjB,EAAI,GAAK,MAAM,KAAK,CAAG,GAEzB,OAAO,CACT,EAEA,SAAS,GAAkB,CACzB,YACA,QACA,YAKqB,CACrB,GAAM,CAAE,KAAM,EAAQ,EAEhB,GAAU,EAAoB,IAAyB,CAC3D,IAAM,EAAM,IAAI,IAAI,EAAM,WAAW,IAAe,CAAC,CAAC,EAClD,EAAI,IAAI,CAAM,EAAG,EAAI,OAAO,CAAM,EACjC,EAAI,IAAI,CAAM,EACnB,EAAS,CAAE,WAAY,CAAE,GAAG,EAAM,YAAa,GAAa,CAAI,CAAE,CAAC,CACrE,EAEM,GAAa,EAAoB,IAA4B,CACjE,IAAM,EAAU,EAAM,WAAW,IAAe,IAAI,IAC9C,EAAc,EAAQ,MAAO,GAAM,EAAQ,IAAI,CAAC,CAAC,EACjD,EAAO,IAAI,IAAY,EAAc,CAAC,EAAI,CAAO,EACvD,EAAS,CAAE,WAAY,CAAE,GAAG,EAAM,YAAa,GAAa,CAAK,CAAE,CAAC,CACtE,EAEM,EAAA,EAA6B,YAC3B,EAAU,OAAQ,IAAO,EAAE,SAAW,CAAC,EAAA,CAAG,OAAS,CAAC,EAC1D,CAAC,CAAS,CACZ,EAEM,EACJ,EAAqB,OAAS,GAC9B,EAAqB,MAAO,GAAM,CAChC,IAAM,GAAW,EAAE,SAAW,CAAC,EAAA,CAAG,IAAK,GAAM,EAAE,IAAI,EAC7C,EAAU,EAAM,WAAW,EAAE,KAAO,IAAI,IAC9C,OAAO,EAAQ,MAAO,GAAM,EAAQ,IAAI,CAAC,CAAC,CAC5C,CAAC,EAkBH,OANI,EAAU,SAAW,GAErB,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAU,yCAAiC,EAAE,0CAA0C,CAAK,CAAA,GAKjG,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,2CAAf,CACG,EAAqB,OAAS,IAC7B,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,uGACb,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,KAAK,SACL,QAAQ,UACR,KAAK,KACL,UAAU,MACV,YAzB6B,CACrC,IAAM,EAAS,CAAC,EACV,EAAoC,CAAE,GAAG,EAAM,UAAW,EAChE,IAAK,IAAM,KAAK,EAAW,CACzB,IAAM,GAAW,EAAE,SAAW,CAAC,EAAA,CAAG,IAAK,GAAM,EAAE,IAAI,EACnD,EAAK,EAAE,IAAM,EAAS,IAAI,IAAI,CAAO,EAAI,IAAI,GAC/C,CACA,EAAS,CAAE,WAAY,CAAK,CAAC,CAC/B,WAmBW,GACC,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAG,UAAU,iBAAmB,CAAA,EAC/B,EAAE,gDAAgD,CACnD,CAAA,CAAA,GAEF,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CAAO,UAAU,iBAAmB,CAAA,EACnC,EAAE,iDAAiD,CACpD,CAAA,CAAA,CAEE,CAAA,CACL,CAAA,GAEP,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,0CACb,EAAA,EAAA,KAAA,CAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAa,UAAU,iCACrB,EAAA,EAAA,KAAA,CAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,UAAU,qBAAa,EAAE,uCAAuC,CAAa,CAAA,GACxF,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAY,EAAE,sCAAsC,CAAa,CAAA,CACzD,CAAA,CAAA,CACC,CAAA,GACb,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SACG,EAAU,IAAK,GAAM,CACpB,IAAM,GAAW,EAAE,SAAW,CAAC,EAAA,CAAG,IAAK,GAAM,EAAE,IAAI,EAC7C,EAAU,EAAM,WAAW,EAAE,KAAO,IAAI,IACxC,EAAc,EAAQ,OAAS,GAAK,EAAQ,MAAO,GAAM,EAAQ,IAAI,CAAC,CAAC,EAC7E,OACE,EAAA,EAAA,KAAA,CAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,UAAU,sBACnB,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,+BAAf,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,uBAAe,EAAE,IAAW,CAAA,GAC5C,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,yCAAiC,EAAE,EAAS,CAAA,GAC5D,EAAA,EAAA,KAAA,CAAC,SAAD,CACE,KAAK,SACL,UAAU,sFACV,YAAe,EAAU,EAAE,GAAI,CAAO,WAHxC,CAKG,GAAc,EAAA,EAAA,IAAA,CAAC,EAAD,CAAG,UAAU,QAAU,CAAA,GAAI,EAAA,EAAA,IAAA,CAAC,GAAD,CAAO,UAAU,QAAU,CAAA,EAEjE,EADH,EACK,wCACA,wCAAwC,CACxC,GACL,GACI,CAAA,GACX,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,UACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,gCACZ,EAAQ,IAAK,GAAM,CAClB,IAAM,EAAU,EAAQ,IAAI,CAAC,EAC7B,OACE,EAAA,EAAA,KAAA,CAAC,QAAD,CAEE,UAAW,EACT,oGACA,GAAW,2CACb,WALF,EAOE,EAAA,EAAA,IAAA,CAAC,EAAD,CACW,UACT,oBAAuB,EAAO,EAAE,GAAI,CAAC,EACrC,UAAU,UACX,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,OAAD,CAAA,SAAO,CAAQ,CAAA,CACV,GAZA,CAYA,CAEX,CAAC,CACE,CAAA,CACI,CAAA,CACH,CAAA,EAxCK,EAAE,EAwCP,CAEd,CAAC,CACQ,CAAA,CACN,CAAA,CAAA,CACJ,CAAA,CACF,GAET,CAEA,SAAS,GAAmB,CAAE,eAA8E,CAC1G,GAAM,CAAE,GAAM,EAAQ,EAChB,EAAU,OAAO,QAAQ,CAAW,EAC1C,GAAI,EAAQ,SAAW,EACrB,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,QAAQ,mBAAW,EAAE,mCAAmC,CAAS,CAAA,EAEjF,IAAM,EAAe,EAAQ,QAAQ,EAAK,EAAG,KAAO,EAAM,EAAE,OAAQ,CAAC,EACrE,OACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,QAAQ,qBACZ,EAAE,uCAAwC,CAAE,UAAW,EAAQ,OAAQ,QAAS,CAAa,CAAC,CAC1F,CAAA,CAEX,CAIA,SAAS,GAAmB,CAC1B,OACA,eACA,UACA,YACA,YACA,aAQqB,CACrB,GAAM,CAAE,KAAM,EAAQ,EAChB,EAAS,EAAe,EACxB,EAAS,EAAU,EACnB,EAAS,CAAC,CAAC,EACX,CAAC,EAAM,GAAA,EAAiB,SAAS,GAAS,MAAQ,EAAE,EACpD,CAAC,EAAe,GAAA,EAA0B,aAAuB,CACrE,GAAI,CAAC,GAAS,UAAW,MAAO,GAChC,IAAM,EAAK,IAAI,KAAK,EAAQ,SAAS,CAAC,CAAC,QAAQ,EAAI,KAAK,IAAI,EAC5D,OAAO,EAAK,EAAI,OAAO,KAAK,IAAI,EAAG,KAAK,MAAM,GAAM,KAAU,GAAK,IAAK,CAAC,CAAC,EAAI,EAChF,CAAC,EACK,CAAC,EAAa,GAAA,EAAwB,aAC1C,GAAW,GAAS,aAAe,CAAC,CAAC,CACvC,EAEM,EAAO,EAAY,CACvB,WAAY,SAA6D,CACvE,IAAM,EAAO,GAAY,CAAW,EACpC,GAAI,GAAU,EAAS,CACrB,IAAM,EAAS,EAAc,KAAK,IAAM,GAAK,KAAO,OAAO,CAAa,EAMxE,MAAO,CAAE,QAAQ,MALC,EAAO,aAAa,EAAQ,GAAI,CAChD,KAAM,EAAK,KAAK,EAChB,YAAa,EACb,cAAe,IAAW,KAAO,KAAO,OAAO,SAAS,CAAM,GAAK,EAAS,EAAI,EAAS,IAAA,EAC3F,CAAC,EAAA,CACoB,MAAO,CAC9B,CACA,IAAM,EAAS,EAAc,KAAK,IAAM,GAAK,KAAO,OAAO,CAAa,EACxE,OAAO,EAAO,aAAa,CACzB,KAAM,EAAK,KAAK,EAChB,YAAa,EACb,cAAe,IAAW,KAAO,KAAO,OAAO,SAAS,CAAM,GAAK,EAAS,EAAI,EAAS,IAAA,EAC3F,CAAC,CACH,EACA,UAAY,GAAW,CACjB,GACF,EAAO,QAAQ,CAAE,IAAK,iCAAkC,CAAC,EACzD,EAAU,EAAO,MAAM,GAEnB,EAAO,KAAK,EAAU,CAAE,IAAK,EAAO,IAAK,OAAQ,EAAO,MAAO,CAAC,CAExE,EACA,QAAU,GAAQ,EAAO,MAAM,CAAE,QAAS,aAAe,MAAQ,EAAI,QAAU,OAAO,CAAG,CAAE,CAAC,CAC9F,CAAC,EAGD,EAAM,cAAgB,CACf,KAGL,GAFA,EAAQ,GAAS,MAAQ,EAAE,EAC3B,EAAe,GAAW,GAAS,aAAe,CAAC,CAAC,CAAC,EACjD,CAAC,GAAS,UAAW,EAAiB,EAAE,MACvC,CACH,IAAM,EAAK,IAAI,KAAK,EAAQ,SAAS,CAAC,CAAC,QAAQ,EAAI,KAAK,IAAI,EAC5D,EAAiB,EAAK,EAAI,OAAO,KAAK,IAAI,EAAG,KAAK,MAAM,GAAM,KAAU,GAAK,IAAK,CAAC,CAAC,EAAI,EAAE,CAC5F,CACF,EAAG,CAAC,EAAM,CAAO,CAAC,EAElB,IAAM,EAAgB,OAAO,OAAO,EAAY,UAAU,CAAC,CAAC,QACzD,EAAK,IAAQ,GAAO,GAAK,MAAQ,GAClC,CACF,EAEA,OACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAc,OAAoB,yBAChC,EAAA,EAAA,KAAA,CAAC,EAAD,CAAe,UAAU,qBAAzB,EACE,EAAA,EAAA,KAAA,CAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SACY,EAAT,EAAW,oCAAyC,qCAAqC,CAC/E,CAAA,GACb,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAoB,EAAE,qCAAqC,CAAqB,CAAA,CACpE,CAAA,CAAA,GACd,EAAA,EAAA,KAAA,CAAC,OAAD,CACE,UAAU,sBACV,SAAW,GAAM,CACf,EAAE,eAAe,EACZ,EAAK,KAAK,GACf,EAAK,OAAO,CACd,WANF,EAQE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,qCAAf,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,iCAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,QAAQ,wBAAgB,EAAE,8BAA8B,CAAS,CAAA,GACxE,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,GAAG,eACH,MAAO,EACP,SAAW,GAAM,EAAQ,EAAE,OAAO,KAAK,EACvC,YAAa,EAAE,yCAAyC,EACxD,SAAA,GACA,UAAW,EACZ,CAAA,CACE,KACL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,iCAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,QAAQ,2BAAmB,EAAE,uCAAuC,CAAS,CAAA,GACpF,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,GAAG,kBACH,KAAK,SACL,IAAK,EACL,IAAK,KACL,MAAO,EACP,SAAW,GAAM,EAAiB,EAAE,OAAO,KAAK,EAChD,YAAa,EAAE,4CAA4C,CAC5D,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,yCACb,EAAE,qCAAqC,CACpC,CAAA,CACH,GACF,KACL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,+BAAf,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,6CAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAQ,EAAE,qCAAqC,CAAS,CAAA,GACxD,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,yCACb,EAAE,0CAA2C,CAAE,MAAO,CAAc,CAAC,CAClE,CAAA,CACH,KACL,EAAA,EAAA,IAAA,CAAC,GAAD,CAA8B,YAAW,MAAO,EAAa,SAAU,CAAiB,CAAA,CACrF,KACL,EAAA,EAAA,KAAA,CAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAQ,KAAK,SAAS,QAAQ,UAAU,YAAe,EAAa,EAAK,WACtE,EAAE,eAAe,CACZ,CAAA,GACR,EAAA,EAAA,IAAA,CAAC,EAAD,CAAQ,KAAK,SAAS,SAAU,EAAK,WAAa,CAAC,EAAK,KAAK,GAAK,IAAkB,WACjF,EAAK,UAAY,EAAE,eAAe,EAAa,EAAT,EAAW,cAAmB,iCAAiC,CAChG,CAAA,CACI,CAAA,CAAA,CACV,GACO,GACT,CAAA,CAEZ,CAIA,IAAM,GAAiB,CAAC,iBAAkB,iBAAkB,iBAAkB,GAAG,EAEjF,SAAS,IAAsC,CAC7C,GAAM,CAAE,KAAM,EAAQ,EAChB,EAAS,EAAe,EACxB,EAAK,EAAe,EACpB,EAAS,EAAU,EACnB,EAAU,GAAW,EACrB,EAAY,GAAa,EACzB,CAAC,EAAY,GAAA,EAAuB,SAAS,EAAK,EAClD,CAAC,EAAS,GAAA,EAAoB,SAA+B,IAAI,EACjE,CAAC,EAAY,GAAA,EAAuB,SAAwB,IAAI,EAEhE,EAAO,EAAS,CACpB,SAAU,GACV,YAAe,EAAO,aAAa,CACrC,CAAC,EACK,EAAa,EAAS,CAC1B,SAAU,CAAC,eAAgB,WAAY,EAAY,YAAY,EAC/D,YAAe,EAAO,sBAAsB,CAAW,EACvD,QAAS,CAAC,CAAC,CACb,CAAC,EACK,EAAY,EAAY,CAC5B,WAAa,GAAe,EAAO,cAAc,CAAE,EACnD,cAAiB,CACf,EAAG,kBAAkB,CAAE,SAAU,EAAa,CAAC,EAC/C,EAAO,QAAQ,CAAE,IAAK,kCAAmC,CAAC,CAC5D,EACA,QAAU,GAAQ,EAAO,MAAM,CAAE,QAAS,aAAe,MAAQ,EAAI,QAAU,OAAO,CAAG,CAAE,CAAC,CAC9F,CAAC,EACK,EAAU,EAAY,CAC1B,WAAa,GAAe,EAAO,YAAY,CAAE,EACjD,cAAiB,CACX,GAAY,EAAG,kBAAkB,CAAE,SAAU,CAAC,eAAgB,WAAY,EAAY,YAAY,CAAE,CAAC,EACzG,EAAO,QAAQ,CAAE,IAAK,qCAAsC,CAAC,CAC/D,EACA,QAAU,GAAQ,EAAO,MAAM,CAAE,QAAS,aAAe,MAAQ,EAAI,QAAU,OAAO,CAAG,CAAE,CAAC,CAC9F,CAAC,EAEK,EAAW,EAAK,MAAM,UAAY,CAAC,EAEnC,EAAW,KAAO,IAA0C,CAO5D,MANa,EAAQ,QAAQ,CAC/B,MAAO,EAAE,uCAAuC,EAChD,YAAa,EAAE,8CAA+C,CAAE,KAAM,EAAQ,IAAK,CAAC,EACpF,aAAc,EAAE,eAAe,EAC/B,YAAa,EACf,CAAC,GACO,EAAU,OAAO,EAAQ,EAAE,CACrC,EAEA,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,+BAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,KAAM,EACN,MAAO,EAAE,yBAAyB,EAClC,YAAa,EAAE,+BAA+B,EAC9C,QACE,EAAA,EAAA,KAAA,CAAC,EAAD,CAAQ,KAAK,KAAK,YAAe,CAAE,EAAW,IAAI,EAAG,EAAc,EAAI,CAAE,WAAzE,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAM,UAAU,QAAU,CAAA,EACzB,EAAE,kCAAkC,CAC/B,cAGV,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,UAAW,EAAK,UAChB,MAAO,EAAK,MACZ,QAAS,EAAS,SAAW,EAC7B,aAAc,EAAE,gBAAgB,EAChC,MAAO,CACL,KAAM,EACN,MAAO,EAAE,+BAA+B,EACxC,YAAa,EAAE,qCAAqC,CACtD,YAEA,EAAA,EAAA,IAAA,CAAC,GAAD,CAAA,UACE,EAAA,EAAA,KAAA,CAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,UACE,EAAA,EAAA,KAAA,CAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAY,EAAE,gCAAgC,CAAa,CAAA,GAC3D,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAY,EAAE,oCAAoC,CAAa,CAAA,GAC/D,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAY,EAAE,kCAAkC,CAAa,CAAA,GAC7D,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAY,EAAE,mCAAmC,CAAa,CAAA,GAC9D,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,UAAU,sBAAc,EAAE,mCAAmC,CAAa,CAAA,CAC7E,CAAA,CAAA,CACC,CAAA,GACb,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SACG,EAAS,IAAK,IACb,EAAA,EAAA,KAAA,CAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAA,CAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,KAAK,SACL,UAAU,wCACV,YAAe,EAAc,EAAQ,EAAE,WAEtC,EAAQ,IACH,CAAA,GACR,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,2DAAmD,EAAQ,GAAS,CAAA,CAC1E,CAAA,CAAA,GACX,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAY,GAAa,EAAW,EAAQ,WAAY,EAAE,uCAAuC,CAAC,CAAa,CAAA,GAC/G,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,UAAU,qBACnB,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,gCACZ,EAAQ,OAAO,IAAK,IAAU,EAAA,EAAA,IAAA,CAAC,EAAD,CAAmB,QAAQ,mBAAW,CAAa,EAAvC,CAAuC,CAAC,CAChF,CAAA,CACI,CAAA,GACX,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAY,EAAQ,QAAU,EAAE,YAAY,EAAI,EAAE,WAAW,CAAa,CAAA,GAC1E,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,UAAU,uBACnB,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,6BAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAQ,QAAQ,QAAQ,KAAK,KAAK,YAAe,EAAQ,OAAO,EAAQ,EAAE,WACvE,EAAE,gCAAgC,CAC7B,CAAA,GACR,EAAA,EAAA,IAAA,CAAC,EAAD,CAAQ,QAAQ,QAAQ,KAAK,KAAK,YAAe,CAAE,EAAW,CAAO,EAAG,EAAc,EAAI,CAAE,YAC1F,EAAA,EAAA,IAAA,CAAC,EAAD,CAAM,UAAU,QAAU,CAAA,CACpB,CAAA,GACR,EAAA,EAAA,IAAA,CAAC,EAAD,CAAQ,QAAQ,QAAQ,KAAK,KAAK,YAAe,KAAK,EAAS,CAAO,YACpE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAQ,UAAU,yBAA2B,CAAA,CACvC,CAAA,CACL,GACI,CAAA,CACH,CAAA,EA/BK,EAAQ,EA+Bb,CACX,CACQ,CAAA,CACN,CAAA,CAAA,CACY,CAAA,CACJ,CAAA,CACP,CAAA,EAEb,IACC,EAAA,EAAA,IAAA,CAAC,EAAD,CAAc,KAAM,EAAc,MAAO,EAAE,oCAAoC,WAC5E,EAAW,WACV,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,8CAAsC,EAAE,gBAAgB,CAAO,CAAA,GAE9E,EAAA,EAAA,IAAA,CAAC,GAAD,CAAA,UACE,EAAA,EAAA,KAAA,CAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,UACE,EAAA,EAAA,KAAA,CAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAY,EAAE,qCAAqC,CAAa,CAAA,GAChE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAY,EAAE,oCAAoC,CAAa,CAAA,GAC/D,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAY,EAAE,sCAAsC,CAAa,CAAA,GACjE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAY,EAAE,uCAAuC,CAAa,CAAA,GAClE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAY,EAAE,wCAAwC,CAAa,CAAA,CAC3D,CAAA,CAAA,CACC,CAAA,GACb,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,UACI,EAAW,MAAM,YAAc,CAAC,EAAA,CAAG,IAAK,IACxC,EAAA,EAAA,KAAA,CAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAY,EAAS,MAAkB,CAAA,GACvC,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAY,EAAS,KAAiB,CAAA,GACtC,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAY,EAAS,OAAmB,CAAA,GACxC,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,UAAU,6BAClB,EAAS,gBAAkB,EAAS,OAAS,EAAS,cAAgB,GAC9D,CAAA,GACX,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAY,EAAW,EAAS,SAAS,CAAa,CAAA,CAC9C,CAAA,EARK,EAAS,EAQd,CACX,CACQ,CAAA,CACN,CAAA,CAAA,CACY,CAAA,CAEX,CAAA,GAGhB,EAAA,EAAA,IAAA,CAAC,GAAD,CAEE,KAAM,EACN,aAAc,EACd,QAAS,EACE,WACZ,EALM,GAAS,IAAM,KAKrB,CACE,GAET,CAEA,SAAS,GAAoB,CAC3B,OACA,eACA,UACA,aAMqB,CACrB,GAAM,CAAE,KAAM,EAAQ,EAChB,EAAS,EAAe,EACxB,EAAK,EAAe,EACpB,EAAS,EAAU,EACnB,CAAC,EAAM,GAAA,EAAiB,SAAS,GAAS,MAAQ,EAAE,EACpD,CAAC,EAAK,GAAA,EAAgB,SAAS,GAAS,KAAO,EAAE,EACjD,CAAC,EAAY,GAAA,EAAuB,SAAS,GAAS,YAAc,EAAE,EACtE,CAAC,EAAS,GAAA,EAAoB,SAAS,GAAS,SAAW,EAAI,EAC/D,CAAC,EAAQ,GAAA,EAAmB,SAAS,GAAS,QAAU,EAAE,EAC1D,CAAC,EAAQ,GAAA,EAAmB,SAAmB,GAAS,QAAU,CAAC,iBAAkB,gBAAgB,CAAC,EACtG,CAAC,EAAS,GAAA,EAAoB,SAAkC,GAAS,SAAW,CAAC,CAAC,EACtF,CAAC,GAAS,IAAA,EAAoB,SAAkC,GAAS,SAAW,CAAC,CAAC,EACtF,CAAC,GAAe,IAAA,EAA0B,SAAmB,GAAS,eAAiB,CAAC,CAAC,EACzF,EAAmB,EAAU,KAAM,GAAM,EAAE,KAAO,CAAU,EAE5D,EAAO,EAAY,CACvB,WAAa,GACX,EAAU,EAAO,cAAc,EAAQ,GAAI,CAAO,EAAI,EAAO,cAAc,CAAO,EACpF,cAAiB,CACf,EAAG,kBAAkB,CAAE,SAAU,EAAa,CAAC,EAC/C,EAAO,QAAQ,CAAE,IAAK,gCAAiC,CAAC,EACxD,EAAa,EAAK,CACpB,EACA,QAAU,GAAQ,EAAO,MAAM,CAAE,QAAS,aAAe,MAAQ,EAAI,QAAU,OAAO,CAAG,CAAE,CAAC,CAC9F,CAAC,EAEK,EAAe,GAAwB,CAC3C,EAAW,GAAS,EAAK,SAAS,CAAK,EAAI,EAAK,OAAQ,GAAM,IAAM,CAAK,EAAI,CAAC,GAAG,EAAM,CAAK,CAAC,CAC/F,EAiBA,OACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAc,OAAoB,yBAChC,EAAA,EAAA,KAAA,CAAC,EAAD,CAAe,UAAU,qBAAzB,EACE,EAAA,EAAA,KAAA,CAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAwB,EAAV,EAAY,qCAA0C,sCAAsC,CAAe,CAAA,GACzH,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAoB,EAAE,sCAAsC,CAAqB,CAAA,CACrE,CAAA,CAAA,GACd,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAU,YAAsB,SAtB1B,GAA6B,CAC7C,EAAE,eAAe,EACjB,EAAK,OAAO,CACV,KAAM,EAAK,KAAK,EAChB,IAAK,EAAI,KAAK,EACd,SACA,WAAY,GAAc,KAC1B,UACA,GAAI,EAAO,KAAK,EAAI,CAAE,OAAQ,EAAO,KAAK,CAAE,EAAI,CAAC,EACjD,QAAS,GAAa,CAAO,EAC7B,QAAS,GAAa,EAAO,EAC7B,gBACF,CAAC,CACH,WASM,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,qCAAf,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,uBAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAQ,EAAE,+BAA+B,CAAS,CAAA,GAClD,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAO,EAAM,SAAW,GAAM,EAAQ,EAAE,OAAO,KAAK,EAAG,SAAA,EAAU,CAAA,CACrE,KACL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,uBAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAQ,EAAE,8BAA8B,CAAS,CAAA,GACjD,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAO,EAAK,SAAW,GAAM,EAAO,EAAE,OAAO,KAAK,EAAG,SAAA,GAAS,KAAK,KAAO,CAAA,CAC9E,KACL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,uBAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAQ,EAAE,mCAAmC,CAAS,CAAA,GACtD,EAAA,EAAA,KAAA,CAAC,EAAD,CACE,MAAO,GAAc,UACrB,cAAgB,GAAM,CAAE,EAAc,IAAM,UAAY,GAAK,CAAC,EAAG,GAAiB,CAAC,CAAC,CAAE,WAFxF,EAIE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,UACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAc,CAAA,CACD,CAAA,GACf,EAAA,EAAA,KAAA,CAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAY,MAAM,mBAAW,EAAE,uCAAuC,CAAc,CAAA,EACnF,EAAU,IAAK,IACd,EAAA,EAAA,KAAA,CAAC,EAAD,CAA8B,MAAO,EAAS,YAA9C,CACG,EAAS,KACT,EAAS,OAAS,EAAS,KAC1B,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAU,gDAAhB,CAAuD,IAAE,EAAS,GAAG,GAAO,GAEpE,GALK,EAAS,EAKd,CACb,CACY,CAAA,CAAA,CACT,GACL,KACL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,uBAAf,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,qCAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAQ,EAAE,iCAAiC,CAAS,CAAA,GACpD,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,QAAS,EAAE,qCAAqC,EAChD,UAAW,EAAE,iCAAiC,EAC9C,KAAK,OACN,CAAA,CACE,KACL,EAAA,EAAA,IAAA,CAAC,EAAD,CAAO,MAAO,EAAQ,SAAW,GAAM,EAAU,EAAE,OAAO,KAAK,EAAG,KAAK,UAAY,CAAA,CAChF,GACF,KACL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,mCAAf,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CAAQ,QAAS,EAAS,gBAAiB,CAAa,CAAA,GACxD,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAQ,EAAE,kCAAkC,CAAS,CAAA,CAClD,KACL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,qBAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAQ,EAAE,iCAAiC,CAAS,CAAA,GACpD,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,gCACZ,GAAe,IAAK,IACnB,EAAA,EAAA,KAAA,CAAC,QAAD,CAAmB,UAAU,qFAA7B,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAU,QAAS,EAAO,SAAS,CAAK,EAAG,oBAAuB,EAAY,CAAK,CAAI,CAAA,EACtF,CACI,GAHK,CAGL,CACR,CACE,CAAA,CACF,IACJ,IACC,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,qBAAf,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,qCAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAQ,EAAE,wCAAwC,CAAS,CAAA,GAC3D,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,QAAS,EAAE,4CAA4C,EACvD,UAAW,EAAE,wCAAwC,EACrD,KAAK,OACN,CAAA,CACE,KACL,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,qCACZ,EAAiB,WAAW,IAAK,IAChC,EAAA,EAAA,KAAA,CAAC,QAAD,CAA2B,UAAU,2CAArC,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,QAAS,GAAc,SAAS,EAAS,IAAI,EAC7C,oBACE,GAAkB,GAChB,EAAK,SAAS,EAAS,IAAI,EACvB,EAAK,OAAQ,GAAM,IAAM,EAAS,IAAI,EACtC,CAAC,GAAG,EAAM,EAAS,IAAI,CAC7B,CAEH,CAAA,EACA,EAAS,KACL,GAZK,EAAS,IAYd,CACR,CACE,CAAA,CACF,KAEP,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,qCAAf,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,uBAAf,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,qCAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAQ,EAAE,kCAAkC,CAAS,CAAA,GACrD,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,QAAS,EAAE,sCAAsC,EACjD,UAAW,EAAE,kCAAkC,EAC/C,KAAK,KACN,CAAA,CACE,KACL,EAAA,EAAA,IAAA,CAAC,EAAD,CAAY,MAAO,EAAS,SAAW,GAAS,EAAW,GAAa,CAAI,CAAC,CAAI,CAAA,CAC9E,KACL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,uBAAf,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,qCAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAQ,EAAE,kCAAkC,CAAS,CAAA,GACrD,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,QAAS,EAAE,sCAAsC,EACjD,UAAW,EAAE,kCAAkC,EAC/C,KAAK,KACN,CAAA,CACE,KACL,EAAA,EAAA,IAAA,CAAC,EAAD,CAAY,MAAO,GAAS,SAAW,GAAS,GAAW,GAAa,CAAI,CAAC,CAAI,CAAA,CAC9E,GACF,KACL,EAAA,EAAA,KAAA,CAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAQ,KAAK,SAAS,QAAQ,UAAU,YAAe,EAAa,EAAK,WAAI,EAAE,eAAe,CAAU,CAAA,GACxG,EAAA,EAAA,IAAA,CAAC,EAAD,CAAQ,KAAK,SAAS,SAAU,EAAK,WAAa,CAAC,EAAK,KAAK,GAAK,CAAC,EAAI,KAAK,GAAK,EAAO,SAAW,WAChG,EAAK,UAAY,EAAE,eAAe,EAAI,EAAE,aAAa,CAChD,CAAA,CACI,CAAA,CAAA,CACV,GACO,GACT,CAAA,CAEZ,CAEA,IAAM,IACJ,EACA,EACA,IACW,EAAM,EAAU,KAAM,GAAM,EAAE,KAAO,CAAE,CAAC,EAAE,MAAQ,EAAM,EAE/D,GAAgB,GACpB,GAAS,OAAO,GAAU,UAAY,CAAC,MAAM,QAAQ,CAAK,EAAI,EAAmC,CAAC,EAE9F,GAAgB,GAA2D,CAC/E,IAAM,EAA8B,CAAC,EACrC,IAAK,GAAM,CAAC,EAAK,KAAS,OAAO,QAAQ,CAAK,EACxC,GAAQ,MAAQ,IAAS,KAAI,EAAI,GAAO,OAAO,CAAI,GAEzD,OAAO,CACT,EAIA,SAAS,GAAoB,CAC3B,SACA,WAIqB,CACrB,GAAM,CAAE,KAAM,EAAQ,EAChB,EAAS,EAAU,EACnB,CAAC,EAAQ,GAAA,EAAmB,SAAS,EAAK,EAC1C,CAAC,EAAQ,GAAA,EAAmB,SAAS,EAAK,EAqBhD,OAnBA,EAAM,cAAgB,CACf,IACH,EAAU,EAAK,EACf,EAAU,EAAK,EAEnB,EAAG,CAAC,CAAM,CAAC,GAeT,EAAA,EAAA,IAAA,CAAC,EAAD,CAAQ,KAAM,CAAC,CAAC,EAAQ,aAAe,GAAS,CAAC,GAAQ,EAAQ,YAC/D,EAAA,EAAA,KAAA,CAAC,EAAD,CAAe,UAAU,oBAAzB,EACE,EAAA,EAAA,KAAA,CAAC,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,KAAA,CAAC,EAAD,CAAa,UAAU,mCAAvB,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAc,UAAU,QAAU,CAAA,EACjC,EAAE,gCAAgC,CACxB,KACb,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,SAAoB,EAAE,sCAAsC,CAAqB,CAAA,CACrE,CAAA,CAAA,GACd,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,2JACb,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,kCAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAe,UAAU,eAAiB,CAAA,GAC1C,EAAA,EAAA,IAAA,CAAC,IAAD,CAAA,SAAI,EAAE,kCAAkC,CAAK,CAAA,CAC1C,GACF,CAAA,GACL,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,oCAAf,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,2BAAf,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,SAAA,GACA,KAAM,EAAS,OAAS,WACxB,MAAO,GAAQ,KAAO,GACtB,UAAU,0BACV,QAAU,GAAM,EAAE,cAAc,OAAO,CACxC,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,KAAK,SACL,QAAQ,QACR,KAAK,KACL,UAAU,4CACV,YAAe,EAAW,GAAM,CAAC,CAAC,EAClC,aAAqB,EAAT,EAAW,gCAAqC,iCAAiC,WAE5F,GAAS,EAAA,EAAA,IAAA,CAAC,GAAD,CAAQ,UAAU,QAAU,CAAA,GAAI,EAAA,EAAA,IAAA,CAAC,GAAD,CAAK,UAAU,QAAU,CAAA,CAC7D,CAAA,CACL,KACL,EAAA,EAAA,KAAA,CAAC,EAAD,CAAQ,KAAK,SAAS,QAAS,SAhDG,CACnC,KACL,GAAI,CACF,MAAM,UAAU,UAAU,UAAU,EAAO,GAAG,EAC9C,EAAU,EAAI,EACd,EAAO,QAAQ,CAAE,IAAK,gCAAiC,CAAC,EACxD,eAAiB,EAAU,EAAK,EAAG,IAAI,CACzC,MAAQ,CACN,EAAO,MAAM,CAAE,IAAK,oCAAqC,CAAC,CAC5D,CACF,EAsC+C,QAAQ,qBAA/C,CACG,GAAS,EAAA,EAAA,IAAA,CAAC,GAAD,CAAO,UAAU,QAAU,CAAA,GAAI,EAAA,EAAA,IAAA,CAAC,EAAD,CAAM,UAAU,QAAU,CAAA,GACnE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,4BACJ,EAAT,EAAW,kCAAuC,+BAA+B,CAC9E,CAAA,CACA,GACL,KACL,EAAA,EAAA,IAAA,CAAC,EAAD,CAAA,UACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAQ,QAAS,WAAU,EAAE,aAAa,CAAU,CAAA,CACxC,CAAA,CACD,GACT,CAAA,CAEZ,CAEA,IAAM,EAAc,GAAiC,CACnD,GAAI,CACF,OAAO,IAAI,KAAK,CAAK,CAAC,CAAC,eAAe,CACxC,MAAQ,CACN,OAAO,OAAO,CAAK,CACrB,CACF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e,n as t}from"./createLucideIcon-CUopU_LC.js";import{S as n}from"./with-selector-NDLhu4dT.js";import{t as r}from"./trash-2-DhyKQCKv.js";import{t as i}from"./circle-alert-0EyKeic4.js";import{t as a}from"./pencil-BO-k3yTG.js";import{t as o}from"./zap-b3saQVKc.js";import{s}from"./dist-Dpg8xy_r.js";import{Ct as c,F as l,K as u,N as d,U as f,et as p,i as m,n as h,q as g,z as _}from"./router-wFvtgo77.js";import{c as v,l as y,n as b,o as x,r as S,s as C}from"./action-component-host-
|
|
2
|
-
//# sourceMappingURL=show-page-
|
|
1
|
+
import{a as e,n as t}from"./createLucideIcon-CUopU_LC.js";import{S as n}from"./with-selector-NDLhu4dT.js";import{t as r}from"./trash-2-DhyKQCKv.js";import{t as i}from"./circle-alert-0EyKeic4.js";import{t as a}from"./pencil-BO-k3yTG.js";import{t as o}from"./zap-b3saQVKc.js";import{s}from"./dist-Dpg8xy_r.js";import{Ct as c,F as l,K as u,N as d,U as f,et as p,i as m,n as h,q as g,z as _}from"./router-wFvtgo77.js";import{c as v,l as y,n as b,o as x,r as S,s as C}from"./action-component-host-BrEZDHZt.js";import{a as w,i as T,n as E,t as D}from"./card-4cS4uWCP.js";import{i as O,n as k,r as A,t as j}from"./tabs-DUS8e6dR.js";import{a as M,c as N,l as P,o as F,r as I,s as L,t as R}from"./property-renderer-B8Md-EqW.js";import{t as z}from"./revisions-button-0WtL6bsZ.js";import{_ as B,b as V,i as H,n as U,r as W,v as G,x as K,y as q}from"./index-BL8keDxQ.js";var J=e(t(),1),Y=n();function X({parentRecordId:e,related:t,active:n}){let[r,i]=J.useState({perPage:10}),[a,o]=J.useState(n);return J.useEffect(()=>{n&&o(!0)},[n]),a?(0,Y.jsx)(I,{resourceId:t.resourceId,query:r,onQueryChange:i,lockedFilters:{[t.foreignKey]:e},embedPadding:!1,features:{breadcrumbs:!1,title:!1,create:!1,export:!1,card:!1}}):null}function Z({resource:e,recordId:t}){let{t:n}=p(),r=g(),i=e.showRelatedResources!==!1,a=J.useMemo(()=>i?N(e,r):[],[i,e,r]),[o,s]=J.useState(()=>a[0]?`${a[0].resourceId}::${a[0].foreignKey}`:``);if(J.useEffect(()=>{a.length!==0&&(a.some(e=>`${e.resourceId}::${e.foreignKey}`===o)||s(`${a[0].resourceId}::${a[0].foreignKey}`))},[o,a]),a.length===0)return null;let c=e=>e.label??r.find(t=>t.id===e.resourceId)?.name??e.resourceId;return(0,Y.jsxs)(D,{children:[(0,Y.jsx)(T,{children:(0,Y.jsx)(w,{className:`text-base`,children:n(`common:relatedRecords`)})}),(0,Y.jsx)(E,{children:(0,Y.jsxs)(j,{value:o,onValueChange:s,children:[(0,Y.jsx)(A,{className:`w-full justify-start`,children:a.map(e=>{let t=`${e.resourceId}::${e.foreignKey}`;return(0,Y.jsx)(O,{value:t,children:c(e)},t)})}),a.map(e=>{let n=`${e.resourceId}::${e.foreignKey}`;return(0,Y.jsx)(k,{value:n,className:`mt-4`,children:(0,Y.jsx)(X,{parentRecordId:t,related:e,active:o===n})},n)})]})})]})}function Q({error:e,t}){let{status:n,message:r}=c(e),a=t(n===404?`errors:notFound`:n===403?`errors:forbidden`:`errors:server`);return(0,Y.jsxs)(`div`,{className:`flex items-start gap-3 rounded-lg border border-destructive/50 bg-destructive/10 p-4 dark:bg-destructive/15`,children:[(0,Y.jsx)(i,{className:`mt-0.5 size-5 shrink-0 text-destructive`}),(0,Y.jsxs)(`div`,{className:`space-y-1 text-sm`,children:[(0,Y.jsx)(`p`,{className:`font-semibold text-destructive`,children:a}),(0,Y.jsx)(`p`,{className:`text-destructive/90`,children:r})]})]})}function $({resourceId:e,recordId:t}){let n=u(e),i=f(e,t),c=d(e),g=_(e),O=l(),{t:k}=p(),A=m(),j=W(),N=H(),I=F(e),J=i.data?.record,X=C((n?.actions??[]).filter(e=>e.actionType===`record`&&![`show`,`edit`,`delete`].includes(e.name)),J),$=x(`edit`,J),ee=x(`delete`,J);U(`mod+e`,()=>{!i.data||!$||A({name:`edit`,resourceId:e,recordId:t})},{description:k(`common:edit`)});let te=async()=>{await j.confirm({title:k(`common:confirmDelete`),confirmLabel:k(`common:delete`),destructive:!0})&&(await c.mutateAsync(t),A({name:`list`,resourceId:e}))};if(!n)return(0,Y.jsx)(`div`,{className:`p-6`,children:k(`common:loading`)});let ne=G(),re=i.data?.record?.title||t;return(0,Y.jsxs)(`div`,{className:`space-y-2 sm:space-y-4`,children:[(0,Y.jsx)(v,{items:[y(k(`common:home`)),{label:n.name,to:{name:`list`,resourceId:e}},{label:re}]}),(0,Y.jsxs)(D,{children:[(0,Y.jsxs)(T,{className:`flex flex-row items-center justify-between gap-3`,children:[(0,Y.jsxs)(w,{className:`truncate`,children:[n.name,` #`,t]}),i.data&&(0,Y.jsxs)(`div`,{className:`flex shrink-0 flex-wrap gap-2`,children:[O.history&&(0,Y.jsx)(z,{resourceId:e,recordId:t}),$&&(0,Y.jsxs)(q,{children:[(0,Y.jsx)(K,{asChild:!0,children:(0,Y.jsx)(s,{variant:`outline-primary`,size:`sm`,asChild:!0,children:(0,Y.jsxs)(h,{to:{name:`edit`,resourceId:e,recordId:t},"aria-label":k(`common:edit`),children:[(0,Y.jsx)(a,{className:`size-4`}),(0,Y.jsx)(`span`,{className:`hidden sm:inline`,children:k(`common:edit`)})]})})}),(0,Y.jsxs)(V,{className:`flex items-center gap-1.5`,children:[(0,Y.jsx)(`span`,{children:k(`common:edit`)}),(0,Y.jsxs)(`span`,{className:`inline-flex items-center gap-0.5`,children:[(0,Y.jsx)(B,{children:ne}),(0,Y.jsx)(`span`,{className:`text-muted-foreground`,children:`+`}),(0,Y.jsx)(B,{children:`E`})]})]})]}),ee&&(0,Y.jsxs)(s,{variant:`outline-destructive`,size:`sm`,disabled:c.isPending,onClick:()=>void te(),"aria-label":k(`common:delete`),children:[(0,Y.jsx)(r,{className:`size-4`}),(0,Y.jsx)(`span`,{className:`hidden sm:inline`,children:k(`common:delete`)})]}),X.length>0&&(0,Y.jsx)(S,{actions:X,onAction:async e=>{if(M(e)){I(e,{recordId:t});return}await L(e,j)&&g.mutateAsync({recordId:t,actionName:e.name}).then(e=>b(N,e.notice)).catch(e=>N.error({message:e.message}))},t:k,trigger:(0,Y.jsxs)(s,{variant:`outline`,size:`sm`,disabled:g.isPending,"aria-label":k(`common:actions`),children:[(0,Y.jsx)(o,{className:`size-4`}),(0,Y.jsx)(`span`,{className:`hidden sm:inline`,children:k(`common:actions`)})]})})]})]}),(0,Y.jsx)(E,{children:(0,Y.jsxs)(`div`,{className:`space-y-4`,children:[i.isLoading&&(0,Y.jsx)(`p`,{className:`text-muted-foreground`,children:k(`common:loading`)}),i.isError&&(0,Y.jsx)(Q,{error:i.error,t:k}),i.data&&(0,Y.jsx)(`dl`,{className:`[column-fill:_balance] md:columns-2`,children:P(n.properties,`show`,n.propertyOrder?.show).map(e=>(0,Y.jsxs)(`div`,{className:`mb-8 break-inside-avoid`,children:[(0,Y.jsx)(`dt`,{className:`text-xs font-semibold uppercase tracking-wide text-muted-foreground`,children:e.label}),(0,Y.jsx)(`dd`,{className:`mt-1`,children:(0,Y.jsx)(R,{property:e,value:i.data.record.params[e.path],view:`show`,populated:i.data.record.populated})})]},e.path))})]})})]}),i.data&&(0,Y.jsx)(Z,{resource:n,recordId:t})]})}export{$ as ResourceShowPage};
|
|
2
|
+
//# sourceMappingURL=show-page-Dnox2NwO.js.map
|
|
Binary file
|
|
Binary file
|