@burdenoff/microfe-brainyrich 2026.705.1 → 2026.706.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.
Files changed (47) hide show
  1. package/dist/brainyrich/BrainyRichRoot.js +13 -13
  2. package/dist/brainyrich/components/ActorName.js +38 -0
  3. package/dist/brainyrich/components/ActorName.js.map +1 -0
  4. package/dist/brainyrich/components/ConfirmDialog.js +25 -0
  5. package/dist/brainyrich/components/ConfirmDialog.js.map +1 -0
  6. package/dist/brainyrich/components/LoadMore.js +24 -0
  7. package/dist/brainyrich/components/LoadMore.js.map +1 -0
  8. package/dist/brainyrich/components/index.js +5 -0
  9. package/dist/brainyrich/components/notify.js +38 -0
  10. package/dist/brainyrich/components/notify.js.map +1 -0
  11. package/dist/brainyrich/components/pickers.js +232 -0
  12. package/dist/brainyrich/components/pickers.js.map +1 -0
  13. package/dist/brainyrich/components/reuse/CommentThread.js +208 -0
  14. package/dist/brainyrich/components/reuse/CommentThread.js.map +1 -0
  15. package/dist/brainyrich/components/reuse/DocumentsPanel.js +237 -0
  16. package/dist/brainyrich/components/reuse/DocumentsPanel.js.map +1 -0
  17. package/dist/brainyrich/components/reuse/TagField.js +206 -0
  18. package/dist/brainyrich/components/reuse/TagField.js.map +1 -0
  19. package/dist/brainyrich/components/reuse/transport.js +24 -0
  20. package/dist/brainyrich/components/reuse/transport.js.map +1 -0
  21. package/dist/brainyrich/hooks/useBrainyRichApi.js +644 -372
  22. package/dist/brainyrich/hooks/useBrainyRichApi.js.map +1 -1
  23. package/dist/brainyrich/pages/AccountsPage.js +346 -293
  24. package/dist/brainyrich/pages/AccountsPage.js.map +1 -1
  25. package/dist/brainyrich/pages/AiAssistantPage.js +339 -320
  26. package/dist/brainyrich/pages/AiAssistantPage.js.map +1 -1
  27. package/dist/brainyrich/pages/AnalyticsPage.js +178 -164
  28. package/dist/brainyrich/pages/AnalyticsPage.js.map +1 -1
  29. package/dist/brainyrich/pages/DashboardPage.js +195 -169
  30. package/dist/brainyrich/pages/DashboardPage.js.map +1 -1
  31. package/dist/brainyrich/pages/FamilyPage.js +247 -198
  32. package/dist/brainyrich/pages/FamilyPage.js.map +1 -1
  33. package/dist/brainyrich/pages/GoalsPage.js +478 -442
  34. package/dist/brainyrich/pages/GoalsPage.js.map +1 -1
  35. package/dist/brainyrich/pages/InvestmentsPage.js.map +1 -1
  36. package/dist/brainyrich/pages/PortfoliosPage.js +438 -396
  37. package/dist/brainyrich/pages/PortfoliosPage.js.map +1 -1
  38. package/dist/brainyrich/pages/ReportsPage.js +246 -213
  39. package/dist/brainyrich/pages/ReportsPage.js.map +1 -1
  40. package/dist/brainyrich/pages/RiskPage.js +321 -173
  41. package/dist/brainyrich/pages/RiskPage.js.map +1 -1
  42. package/dist/brainyrich/pages/TaxPage.js +258 -225
  43. package/dist/brainyrich/pages/TaxPage.js.map +1 -1
  44. package/dist/brainyrich/pages/_shared.js.map +1 -1
  45. package/dist/node_modules/sonner/dist/index.js +163 -0
  46. package/dist/node_modules/sonner/dist/index.js.map +1 -0
  47. package/package.json +3 -2
@@ -1 +1 @@
1
- {"version":3,"file":"AiAssistantPage.js","names":[],"sources":["../../../src/brainyrich/pages/AiAssistantPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n AlertTriangle,\n BellRing,\n CheckCircle2,\n Info,\n Lightbulb,\n MoreHorizontal,\n Plus,\n ShieldAlert,\n XCircle,\n} from 'lucide-react';\nimport { tWithFallback } from '../utils/i18n';\nimport {\n useAcknowledgeInsight,\n useCreateInsight,\n useDismissInsight,\n useInsights,\n useResolveInsight,\n} from '../hooks/useBrainyRichApi';\nimport type {\n BraCreateInsightInput,\n BraInsight,\n BraInsightSeverity,\n BraInsightStatus,\n BraInsightType,\n} from '../types/bra';\nimport {\n EmptyState,\n ErrorState,\n KpiGrid,\n LoadingState,\n SectionShell,\n formatDate,\n statusBadgeVariant,\n} from './_shared';\n\nconst INSIGHT_TYPES: BraInsightType[] = [\n 'REBALANCE_DUE',\n 'DRIFT',\n 'CONCENTRATION_RISK',\n 'CASH_DRAG',\n 'FEE_ANOMALY',\n 'TAX_OPPORTUNITY',\n 'GOAL_AT_RISK',\n];\n\nconst INSIGHT_SEVERITIES: BraInsightSeverity[] = ['INFO', 'LOW', 'MEDIUM', 'HIGH', 'CRITICAL'];\n\nconst INSIGHT_STATUSES: BraInsightStatus[] = ['OPEN', 'ACKNOWLEDGED', 'RESOLVED', 'DISMISSED'];\n\nconst ALL = '__all__';\n\nfunction humanize(value: string): string {\n return value\n .toLowerCase()\n .split('_')\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(' ');\n}\n\ninterface SeverityMeta {\n icon: typeof Info;\n tone: string;\n}\n\nfunction severityMeta(severity: BraInsightSeverity): SeverityMeta {\n switch (severity) {\n case 'CRITICAL':\n return { icon: ShieldAlert, tone: 'text-status-error-text' };\n case 'HIGH':\n return { icon: AlertTriangle, tone: 'text-status-error-text' };\n case 'MEDIUM':\n return { icon: BellRing, tone: 'text-status-warning-text' };\n case 'LOW':\n return { icon: Lightbulb, tone: 'text-status-warning-text' };\n case 'INFO':\n default:\n return { icon: Info, tone: 'text-text-secondary' };\n }\n}\n\ninterface InsightFormState {\n title: string;\n type: BraInsightType;\n severity: BraInsightSeverity;\n subjectType: string;\n subjectId: string;\n detail: string;\n metrics: string;\n ownerId: string;\n}\n\nfunction emptyForm(): InsightFormState {\n return {\n title: '',\n type: 'DRIFT',\n severity: 'MEDIUM',\n subjectType: 'PORTFOLIO',\n subjectId: '',\n detail: '',\n metrics: '',\n ownerId: '',\n };\n}\n\nexport function AiAssistantPage() {\n const { t } = useI18n();\n const translate = (key: string, fallback: string, params?: Record<string, string | number>) =>\n tWithFallback(t, key, fallback, params);\n\n const [severityFilter, setSeverityFilter] = useState<string>(ALL);\n const [statusFilter, setStatusFilter] = useState<string>(ALL);\n const [typeFilter, setTypeFilter] = useState<string>(ALL);\n\n const {\n data: insights,\n isLoading,\n isError,\n refetch,\n } = useInsights({\n ...(severityFilter !== ALL ? { severity: severityFilter as BraInsightSeverity } : {}),\n ...(statusFilter !== ALL ? { status: statusFilter as BraInsightStatus } : {}),\n });\n\n const acknowledge = useAcknowledgeInsight();\n const dismiss = useDismissInsight();\n const resolve = useResolveInsight();\n const createInsight = useCreateInsight();\n\n const [createOpen, setCreateOpen] = useState(false);\n const [form, setForm] = useState<InsightFormState>(emptyForm);\n\n const setField = <K extends keyof InsightFormState>(key: K, value: InsightFormState[K]) =>\n setForm((prev) => ({ ...prev, [key]: value }));\n\n // Type is not a backend filter arg — narrow client-side.\n const filtered = useMemo(\n () => (typeFilter === ALL ? insights : insights.filter((i) => i.type === typeFilter)),\n [insights, typeFilter]\n );\n\n const counts = useMemo(() => {\n const open = insights.filter((i) => i.status === 'OPEN').length;\n const urgent = insights.filter(\n (i) => i.severity === 'HIGH' || i.severity === 'CRITICAL'\n ).length;\n const resolved = insights.filter((i) => i.status === 'RESOLVED').length;\n return { open, urgent, resolved };\n }, [insights]);\n\n const metricsValid = useMemo(() => {\n if (!form.metrics.trim()) return true;\n try {\n JSON.parse(form.metrics);\n return true;\n } catch {\n return false;\n }\n }, [form.metrics]);\n\n const formValid =\n form.title.trim().length > 0 &&\n form.subjectType.trim().length > 0 &&\n form.subjectId.trim().length > 0 &&\n metricsValid;\n\n const openCreate = () => {\n setForm(emptyForm());\n setCreateOpen(true);\n };\n\n const handleCreate = () => {\n if (!formValid) return;\n let metrics: Record<string, unknown> | undefined;\n if (form.metrics.trim()) {\n try {\n metrics = JSON.parse(form.metrics) as Record<string, unknown>;\n } catch {\n return;\n }\n }\n const input: BraCreateInsightInput = {\n title: form.title.trim(),\n type: form.type,\n severity: form.severity,\n subjectType: form.subjectType.trim(),\n subjectId: form.subjectId.trim(),\n detail: form.detail.trim() || null,\n ...(metrics ? { metrics } : {}),\n ...(form.ownerId.trim() ? { ownerId: form.ownerId.trim() } : {}),\n };\n createInsight.mutate(input, { onSuccess: () => setCreateOpen(false) });\n };\n\n const anyFilterActive = severityFilter !== ALL || statusFilter !== ALL || typeFilter !== ALL;\n\n const body = () => {\n if (isLoading) return <LoadingState rows={4} />;\n if (isError)\n return (\n <ErrorState\n title={translate('brainyrich.insights.error.title', 'Could not load insights')}\n description={translate(\n 'brainyrich.insights.error.description',\n 'We could not reach the insights service. Please try again.'\n )}\n onRetry={() => refetch()}\n />\n );\n\n return (\n <>\n <KpiGrid\n items={[\n {\n label: translate('brainyrich.insights.metrics.total', 'Insights'),\n value: String(insights.length),\n trend: translate('brainyrich.insights.metrics.totalTrend', 'In your inbox'),\n },\n {\n label: translate('brainyrich.insights.metrics.open', 'Open'),\n value: String(counts.open),\n trend: translate('brainyrich.insights.metrics.openTrend', 'Awaiting action'),\n deltaTone: counts.open > 0 ? 'negative' : 'positive',\n },\n {\n label: translate('brainyrich.insights.metrics.urgent', 'High priority'),\n value: String(counts.urgent),\n trend: translate('brainyrich.insights.metrics.urgentTrend', 'High or critical'),\n deltaTone: counts.urgent > 0 ? 'negative' : 'positive',\n },\n {\n label: translate('brainyrich.insights.metrics.resolved', 'Resolved'),\n value: String(counts.resolved),\n trend: translate('brainyrich.insights.metrics.resolvedTrend', 'Closed out'),\n deltaTone: 'positive',\n },\n ]}\n />\n\n {/* Filters */}\n <Card>\n <CardContent className=\"flex flex-col gap-3 p-4 sm:flex-row sm:items-end\">\n <div className=\"w-full space-y-1.5 sm:w-48\">\n <Label htmlFor=\"insight-filter-severity\">\n {translate('brainyrich.insights.filters.severity', 'Severity')}\n </Label>\n <Select value={severityFilter} onValueChange={setSeverityFilter}>\n <SelectTrigger id=\"insight-filter-severity\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={ALL}>\n {translate('brainyrich.insights.filters.all', 'All')}\n </SelectItem>\n {INSIGHT_SEVERITIES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"w-full space-y-1.5 sm:w-48\">\n <Label htmlFor=\"insight-filter-status\">\n {translate('brainyrich.insights.filters.status', 'Status')}\n </Label>\n <Select value={statusFilter} onValueChange={setStatusFilter}>\n <SelectTrigger id=\"insight-filter-status\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={ALL}>\n {translate('brainyrich.insights.filters.all', 'All')}\n </SelectItem>\n {INSIGHT_STATUSES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"w-full space-y-1.5 sm:w-56\">\n <Label htmlFor=\"insight-filter-type\">\n {translate('brainyrich.insights.filters.type', 'Type')}\n </Label>\n <Select value={typeFilter} onValueChange={setTypeFilter}>\n <SelectTrigger id=\"insight-filter-type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={ALL}>\n {translate('brainyrich.insights.filters.all', 'All')}\n </SelectItem>\n {INSIGHT_TYPES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </CardContent>\n </Card>\n\n {filtered.length === 0 ? (\n <EmptyState\n icon={<BellRing className=\"size-6\" aria-hidden=\"true\" />}\n title={\n anyFilterActive\n ? translate('brainyrich.insights.empty.filteredTitle', 'No matching insights')\n : translate('brainyrich.insights.empty.title', 'No advisory insights yet')\n }\n description={\n anyFilterActive\n ? translate(\n 'brainyrich.insights.empty.filteredDescription',\n 'No insights match the selected filters. Adjust or clear them to see more.'\n )\n : translate(\n 'brainyrich.insights.empty.description',\n 'Advisory insights flag rebalancing, drift, concentration and other opportunities. Create one to get started.'\n )\n }\n action={\n anyFilterActive ? (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => {\n setSeverityFilter(ALL);\n setStatusFilter(ALL);\n setTypeFilter(ALL);\n }}\n >\n {translate('brainyrich.insights.actions.clearFilters', 'Clear filters')}\n </Button>\n ) : (\n <Button size=\"sm\" onClick={openCreate}>\n <Plus className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.create', 'New insight')}\n </Button>\n )\n }\n />\n ) : (\n <div className=\"space-y-3\">\n {filtered.map((insight) => (\n <InsightCard\n key={insight.id}\n insight={insight}\n translate={translate}\n onAcknowledge={() => acknowledge.mutate(insight.id)}\n onDismiss={() => dismiss.mutate(insight.id)}\n onResolve={() => resolve.mutate(insight.id)}\n acknowledgePending={acknowledge.isPending}\n dismissPending={dismiss.isPending}\n resolvePending={resolve.isPending}\n />\n ))}\n </div>\n )}\n </>\n );\n };\n\n return (\n <>\n <SectionShell\n title={translate('brainyrich.insights.title', 'Insights')}\n description={translate(\n 'brainyrich.insights.description',\n 'Advisory insights across portfolios, accounts and goals — triage, acknowledge and resolve.'\n )}\n badges={[translate('brainyrich.insights.badges.advisory', 'Advisory')]}\n actionLabel={translate('brainyrich.insights.actions.create', 'New insight')}\n onAction={openCreate}\n >\n {body()}\n </SectionShell>\n\n <InsightFormDialog\n open={createOpen}\n form={form}\n setField={setField}\n metricsValid={metricsValid}\n valid={formValid}\n pending={createInsight.isPending}\n onSubmit={handleCreate}\n onOpenChange={(v) => setCreateOpen(v)}\n translate={translate}\n />\n </>\n );\n}\n\ntype Translate = (\n key: string,\n fallback: string,\n params?: Record<string, string | number>\n) => string;\n\ninterface InsightCardProps {\n insight: BraInsight;\n translate: Translate;\n onAcknowledge: () => void;\n onDismiss: () => void;\n onResolve: () => void;\n acknowledgePending: boolean;\n dismissPending: boolean;\n resolvePending: boolean;\n}\n\nfunction InsightCard({\n insight,\n translate,\n onAcknowledge,\n onDismiss,\n onResolve,\n acknowledgePending,\n dismissPending,\n resolvePending,\n}: InsightCardProps) {\n const meta = severityMeta(insight.severity);\n const SeverityIcon = meta.icon;\n const isClosed = insight.status === 'RESOLVED' || insight.status === 'DISMISSED';\n\n return (\n <Card>\n <CardHeader className=\"pb-3\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex min-w-0 items-start gap-3\">\n <span\n className={`mt-0.5 flex size-9 shrink-0 items-center justify-center rounded-full bg-bg-sunken ${meta.tone}`}\n >\n <SeverityIcon className=\"size-5\" aria-hidden=\"true\" />\n </span>\n <div className=\"min-w-0\">\n <CardTitle className=\"text-base\">{insight.title}</CardTitle>\n <CardDescription className=\"mt-1 flex flex-wrap items-center gap-2\">\n <Badge variant=\"outline\">{humanize(insight.type)}</Badge>\n <Badge variant={statusBadgeVariant(insight.severity)}>\n <span className={`inline-flex items-center gap-1 ${meta.tone}`}>\n <SeverityIcon className=\"size-3\" aria-hidden=\"true\" />\n {humanize(insight.severity)}\n </span>\n </Badge>\n <Badge variant={statusBadgeVariant(insight.status)}>\n {humanize(insight.status)}\n </Badge>\n </CardDescription>\n </div>\n </div>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={translate('brainyrich.insights.actions.menu', 'Insight actions')}\n >\n <MoreHorizontal className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem\n disabled={acknowledgePending || insight.status === 'ACKNOWLEDGED' || isClosed}\n onSelect={onAcknowledge}\n >\n <CheckCircle2 className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.acknowledge', 'Acknowledge')}\n </DropdownMenuItem>\n <DropdownMenuItem\n disabled={resolvePending || insight.status === 'RESOLVED'}\n onSelect={onResolve}\n >\n <CheckCircle2 className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.resolve', 'Resolve')}\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n className=\"text-status-error-text focus:text-status-error-text\"\n disabled={dismissPending || insight.status === 'DISMISSED'}\n onSelect={onDismiss}\n >\n <XCircle className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.dismiss', 'Dismiss')}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {insight.detail ? (\n <p className=\"text-sm text-text-secondary\">{insight.detail}</p>\n ) : null}\n <dl className=\"grid grid-cols-2 gap-3 rounded-lg bg-bg-sunken p-3 text-sm sm:grid-cols-3\">\n <div>\n <dt className=\"text-xs text-text-secondary\">\n {translate('brainyrich.insights.card.subjectType', 'Subject')}\n </dt>\n <dd className=\"font-medium text-text-primary\">{humanize(insight.subjectType)}</dd>\n </div>\n <div className=\"min-w-0\">\n <dt className=\"text-xs text-text-secondary\">\n {translate('brainyrich.insights.card.subjectId', 'Subject ID')}\n </dt>\n <dd className=\"truncate font-medium text-text-primary\" title={insight.subjectId}>\n {insight.subjectId}\n </dd>\n </div>\n <div>\n <dt className=\"text-xs text-text-secondary\">\n {translate('brainyrich.insights.card.created', 'Created')}\n </dt>\n <dd className=\"font-medium text-text-primary\">{formatDate(insight.createdAt)}</dd>\n </div>\n </dl>\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={acknowledgePending || insight.status === 'ACKNOWLEDGED' || isClosed}\n onClick={onAcknowledge}\n >\n <CheckCircle2 className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.acknowledge', 'Acknowledge')}\n </Button>\n <Button\n size=\"sm\"\n disabled={resolvePending || insight.status === 'RESOLVED'}\n onClick={onResolve}\n >\n <CheckCircle2 className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.resolve', 'Resolve')}\n </Button>\n </div>\n </CardContent>\n </Card>\n );\n}\n\ninterface InsightFormDialogProps {\n open: boolean;\n form: InsightFormState;\n setField: <K extends keyof InsightFormState>(key: K, value: InsightFormState[K]) => void;\n metricsValid: boolean;\n valid: boolean;\n pending: boolean;\n onSubmit: () => void;\n onOpenChange: (open: boolean) => void;\n translate: Translate;\n}\n\nfunction InsightFormDialog({\n open,\n form,\n setField,\n metricsValid,\n valid,\n pending,\n onSubmit,\n onOpenChange,\n translate,\n}: InsightFormDialogProps) {\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"max-h-[90vh] overflow-y-auto sm:max-w-lg\">\n <DialogHeader>\n <DialogTitle>\n {translate('brainyrich.insights.form.createTitle', 'New insight')}\n </DialogTitle>\n <DialogDescription>\n {translate(\n 'brainyrich.insights.form.subtitle',\n 'Flag an advisory insight against a portfolio, account, goal or household.'\n )}\n </DialogDescription>\n </DialogHeader>\n\n <form\n className=\"space-y-4\"\n onSubmit={(e) => {\n e.preventDefault();\n onSubmit();\n }}\n >\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-title\">\n {translate('brainyrich.insights.form.title', 'Title')}\n </Label>\n <Input\n id=\"insight-title\"\n value={form.title}\n onChange={(e) => setField('title', e.target.value)}\n placeholder={translate(\n 'brainyrich.insights.form.titlePlaceholder',\n 'e.g. Technology concentration above threshold'\n )}\n required\n />\n </div>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-type\">\n {translate('brainyrich.insights.form.type', 'Type')}\n </Label>\n <Select\n value={form.type}\n onValueChange={(v) => setField('type', v as BraInsightType)}\n >\n <SelectTrigger id=\"insight-type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {INSIGHT_TYPES.map((tpe) => (\n <SelectItem key={tpe} value={tpe}>\n {humanize(tpe)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-severity\">\n {translate('brainyrich.insights.form.severity', 'Severity')}\n </Label>\n <Select\n value={form.severity}\n onValueChange={(v) => setField('severity', v as BraInsightSeverity)}\n >\n <SelectTrigger id=\"insight-severity\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {INSIGHT_SEVERITIES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-subject-type\">\n {translate('brainyrich.insights.form.subjectType', 'Subject type')}\n </Label>\n <Input\n id=\"insight-subject-type\"\n value={form.subjectType}\n onChange={(e) => setField('subjectType', e.target.value)}\n placeholder={translate(\n 'brainyrich.insights.form.subjectTypePlaceholder',\n 'e.g. PORTFOLIO'\n )}\n required\n />\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-subject-id\">\n {translate('brainyrich.insights.form.subjectId', 'Subject ID')}\n </Label>\n <Input\n id=\"insight-subject-id\"\n value={form.subjectId}\n onChange={(e) => setField('subjectId', e.target.value)}\n placeholder={translate(\n 'brainyrich.insights.form.subjectIdPlaceholder',\n 'Referenced entity ID'\n )}\n required\n />\n </div>\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-owner\">\n {translate('brainyrich.insights.form.ownerId', 'Owner ID (optional)')}\n </Label>\n <Input\n id=\"insight-owner\"\n value={form.ownerId}\n onChange={(e) => setField('ownerId', e.target.value)}\n placeholder={translate(\n 'brainyrich.insights.form.ownerIdPlaceholder',\n 'Defaults to the current owner'\n )}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-detail\">\n {translate('brainyrich.insights.form.detail', 'Detail')}\n </Label>\n <Textarea\n id=\"insight-detail\"\n value={form.detail}\n onChange={(e) => setField('detail', e.target.value)}\n rows={3}\n placeholder={translate(\n 'brainyrich.insights.form.detailPlaceholder',\n 'Explain the finding and recommended action.'\n )}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-metrics\">\n {translate('brainyrich.insights.form.metrics', 'Metrics JSON (optional)')}\n </Label>\n <Textarea\n id=\"insight-metrics\"\n value={form.metrics}\n onChange={(e) => setField('metrics', e.target.value)}\n rows={3}\n className=\"font-mono text-xs\"\n placeholder='{ \"driftPct\": 8.2 }'\n aria-invalid={!metricsValid}\n />\n {!metricsValid ? (\n <p className=\"flex items-center gap-1 text-xs text-status-error-text\">\n <AlertTriangle className=\"size-3.5\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.form.metricsInvalid', 'Enter valid JSON or leave blank.')}\n </p>\n ) : null}\n </div>\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => onOpenChange(false)}\n disabled={pending}\n >\n {translate('brainyrich.insights.form.cancel', 'Cancel')}\n </Button>\n <Button type=\"submit\" disabled={!valid || pending}>\n {pending\n ? translate('brainyrich.insights.form.saving', 'Saving…')\n : translate('brainyrich.insights.form.create', 'Create insight')}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AiAssistantPage.js","names":[],"sources":["../../../src/brainyrich/pages/AiAssistantPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n AlertTriangle,\n BellRing,\n CheckCircle2,\n Info,\n Lightbulb,\n MoreHorizontal,\n Plus,\n ShieldAlert,\n XCircle,\n} from 'lucide-react';\nimport { tWithFallback } from '../utils/i18n';\nimport {\n useAccounts,\n useAcknowledgeInsight,\n useCreateInsight,\n useDismissInsight,\n useGoals,\n useHouseholds,\n usePagedInsights,\n usePortfolios,\n useResolveInsight,\n} from '../hooks/useBrainyRichApi';\nimport { ConfirmDialog, LoadMore, SubjectPicker, parseSubject } from '../components';\nimport type {\n BraCreateInsightInput,\n BraInsight,\n BraInsightSeverity,\n BraInsightStatus,\n BraInsightType,\n} from '../types/bra';\nimport {\n EmptyState,\n ErrorState,\n KpiGrid,\n LoadingState,\n SectionShell,\n formatDate,\n statusBadgeVariant,\n} from './_shared';\n\nconst INSIGHT_TYPES: BraInsightType[] = [\n 'REBALANCE_DUE',\n 'DRIFT',\n 'CONCENTRATION_RISK',\n 'CASH_DRAG',\n 'FEE_ANOMALY',\n 'TAX_OPPORTUNITY',\n 'GOAL_AT_RISK',\n];\n\nconst INSIGHT_SEVERITIES: BraInsightSeverity[] = ['INFO', 'LOW', 'MEDIUM', 'HIGH', 'CRITICAL'];\n\nconst INSIGHT_STATUSES: BraInsightStatus[] = ['OPEN', 'ACKNOWLEDGED', 'RESOLVED', 'DISMISSED'];\n\nconst ALL = '__all__';\n\nfunction humanize(value: string): string {\n return value\n .toLowerCase()\n .split('_')\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(' ');\n}\n\ninterface SeverityMeta {\n icon: typeof Info;\n tone: string;\n}\n\nfunction severityMeta(severity: BraInsightSeverity): SeverityMeta {\n switch (severity) {\n case 'CRITICAL':\n return { icon: ShieldAlert, tone: 'text-status-error-text' };\n case 'HIGH':\n return { icon: AlertTriangle, tone: 'text-status-error-text' };\n case 'MEDIUM':\n return { icon: BellRing, tone: 'text-status-warning-text' };\n case 'LOW':\n return { icon: Lightbulb, tone: 'text-status-warning-text' };\n case 'INFO':\n default:\n return { icon: Info, tone: 'text-text-secondary' };\n }\n}\n\ninterface InsightFormState {\n title: string;\n type: BraInsightType;\n severity: BraInsightSeverity;\n /** Encoded `SUBJECT_TYPE:id` token from <SubjectPicker>. */\n subject: string;\n detail: string;\n metrics: string;\n ownerId: string;\n}\n\nfunction emptyForm(): InsightFormState {\n return {\n title: '',\n type: 'DRIFT',\n severity: 'MEDIUM',\n subject: '',\n detail: '',\n metrics: '',\n ownerId: '',\n };\n}\n\nexport function AiAssistantPage() {\n const { t } = useI18n();\n const translate = (key: string, fallback: string, params?: Record<string, string | number>) =>\n tWithFallback(t, key, fallback, params);\n\n const [severityFilter, setSeverityFilter] = useState<string>(ALL);\n const [statusFilter, setStatusFilter] = useState<string>(ALL);\n const [typeFilter, setTypeFilter] = useState<string>(ALL);\n\n const {\n items: insights,\n hasMore,\n loadMore,\n isLoading,\n isFetchingNextPage,\n isError,\n refetch,\n } = usePagedInsights({\n ...(severityFilter !== ALL ? { severity: severityFilter as BraInsightSeverity } : {}),\n ...(statusFilter !== ALL ? { status: statusFilter as BraInsightStatus } : {}),\n });\n\n // Resolve subjectId -> referenced entity name via the list queries (react-query\n // dedupes these with the SubjectPicker's own calls).\n const accounts = useAccounts();\n const portfolios = usePortfolios();\n const goals = useGoals();\n const households = useHouseholds();\n const subjectNames = useMemo(() => {\n const map = new Map<string, string>();\n for (const a of accounts.data) map.set(a.id, a.name);\n for (const p of portfolios.data) map.set(p.id, p.name);\n for (const g of goals.data) map.set(g.id, g.name);\n for (const h of households.data) map.set(h.id, h.name);\n return map;\n }, [accounts.data, portfolios.data, goals.data, households.data]);\n\n const acknowledge = useAcknowledgeInsight();\n const dismiss = useDismissInsight();\n const resolve = useResolveInsight();\n const createInsight = useCreateInsight();\n\n const [createOpen, setCreateOpen] = useState(false);\n const [form, setForm] = useState<InsightFormState>(emptyForm);\n\n const setField = <K extends keyof InsightFormState>(key: K, value: InsightFormState[K]) =>\n setForm((prev) => ({ ...prev, [key]: value }));\n\n // Type is not a backend filter arg — narrow client-side.\n const filtered = useMemo(\n () => (typeFilter === ALL ? insights : insights.filter((i) => i.type === typeFilter)),\n [insights, typeFilter]\n );\n\n const counts = useMemo(() => {\n const open = insights.filter((i) => i.status === 'OPEN').length;\n const urgent = insights.filter(\n (i) => i.severity === 'HIGH' || i.severity === 'CRITICAL'\n ).length;\n const resolved = insights.filter((i) => i.status === 'RESOLVED').length;\n return { open, urgent, resolved };\n }, [insights]);\n\n const metricsValid = useMemo(() => {\n if (!form.metrics.trim()) return true;\n try {\n JSON.parse(form.metrics);\n return true;\n } catch {\n return false;\n }\n }, [form.metrics]);\n\n const formValid =\n form.title.trim().length > 0 && parseSubject(form.subject) !== null && metricsValid;\n\n const openCreate = () => {\n setForm(emptyForm());\n setCreateOpen(true);\n };\n\n const handleCreate = () => {\n if (!formValid) return;\n const subject = parseSubject(form.subject);\n if (!subject) return;\n let metrics: Record<string, unknown> | undefined;\n if (form.metrics.trim()) {\n try {\n metrics = JSON.parse(form.metrics) as Record<string, unknown>;\n } catch {\n return;\n }\n }\n const input: BraCreateInsightInput = {\n title: form.title.trim(),\n type: form.type,\n severity: form.severity,\n subjectType: subject.subjectType,\n subjectId: subject.subjectId,\n detail: form.detail.trim() || null,\n ...(metrics ? { metrics } : {}),\n ...(form.ownerId.trim() ? { ownerId: form.ownerId.trim() } : {}),\n };\n createInsight.mutate(input, { onSuccess: () => setCreateOpen(false) });\n };\n\n const anyFilterActive = severityFilter !== ALL || statusFilter !== ALL || typeFilter !== ALL;\n\n const body = () => {\n if (isLoading) return <LoadingState rows={4} />;\n if (isError)\n return (\n <ErrorState\n title={translate('brainyrich.insights.error.title', 'Could not load insights')}\n description={translate(\n 'brainyrich.insights.error.description',\n 'We could not reach the insights service. Please try again.'\n )}\n onRetry={() => refetch()}\n />\n );\n\n return (\n <>\n <KpiGrid\n items={[\n {\n label: translate('brainyrich.insights.metrics.total', 'Insights'),\n value: String(insights.length),\n trend: translate('brainyrich.insights.metrics.totalTrend', 'In your inbox'),\n },\n {\n label: translate('brainyrich.insights.metrics.open', 'Open'),\n value: String(counts.open),\n trend: translate('brainyrich.insights.metrics.openTrend', 'Awaiting action'),\n deltaTone: counts.open > 0 ? 'negative' : 'positive',\n },\n {\n label: translate('brainyrich.insights.metrics.urgent', 'High priority'),\n value: String(counts.urgent),\n trend: translate('brainyrich.insights.metrics.urgentTrend', 'High or critical'),\n deltaTone: counts.urgent > 0 ? 'negative' : 'positive',\n },\n {\n label: translate('brainyrich.insights.metrics.resolved', 'Resolved'),\n value: String(counts.resolved),\n trend: translate('brainyrich.insights.metrics.resolvedTrend', 'Closed out'),\n deltaTone: 'positive',\n },\n ]}\n />\n\n {/* Filters */}\n <Card>\n <CardContent className=\"flex flex-col gap-3 p-4 sm:flex-row sm:items-end\">\n <div className=\"w-full space-y-1.5 sm:w-48\">\n <Label htmlFor=\"insight-filter-severity\">\n {translate('brainyrich.insights.filters.severity', 'Severity')}\n </Label>\n <Select value={severityFilter} onValueChange={setSeverityFilter}>\n <SelectTrigger id=\"insight-filter-severity\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={ALL}>\n {translate('brainyrich.insights.filters.all', 'All')}\n </SelectItem>\n {INSIGHT_SEVERITIES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"w-full space-y-1.5 sm:w-48\">\n <Label htmlFor=\"insight-filter-status\">\n {translate('brainyrich.insights.filters.status', 'Status')}\n </Label>\n <Select value={statusFilter} onValueChange={setStatusFilter}>\n <SelectTrigger id=\"insight-filter-status\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={ALL}>\n {translate('brainyrich.insights.filters.all', 'All')}\n </SelectItem>\n {INSIGHT_STATUSES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"w-full space-y-1.5 sm:w-56\">\n <Label htmlFor=\"insight-filter-type\">\n {translate('brainyrich.insights.filters.type', 'Type')}\n </Label>\n <Select value={typeFilter} onValueChange={setTypeFilter}>\n <SelectTrigger id=\"insight-filter-type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={ALL}>\n {translate('brainyrich.insights.filters.all', 'All')}\n </SelectItem>\n {INSIGHT_TYPES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </CardContent>\n </Card>\n\n {filtered.length === 0 ? (\n <EmptyState\n icon={<BellRing className=\"size-6\" aria-hidden=\"true\" />}\n title={\n anyFilterActive\n ? translate('brainyrich.insights.empty.filteredTitle', 'No matching insights')\n : translate('brainyrich.insights.empty.title', 'No advisory insights yet')\n }\n description={\n anyFilterActive\n ? translate(\n 'brainyrich.insights.empty.filteredDescription',\n 'No insights match the selected filters. Adjust or clear them to see more.'\n )\n : translate(\n 'brainyrich.insights.empty.description',\n 'Advisory insights flag rebalancing, drift, concentration and other opportunities. Create one to get started.'\n )\n }\n action={\n anyFilterActive ? (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => {\n setSeverityFilter(ALL);\n setStatusFilter(ALL);\n setTypeFilter(ALL);\n }}\n >\n {translate('brainyrich.insights.actions.clearFilters', 'Clear filters')}\n </Button>\n ) : (\n <Button size=\"sm\" onClick={openCreate}>\n <Plus className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.create', 'New insight')}\n </Button>\n )\n }\n />\n ) : (\n <div className=\"space-y-3\">\n {filtered.map((insight) => (\n <InsightCard\n key={insight.id}\n insight={insight}\n subjectName={subjectNames.get(insight.subjectId)}\n translate={translate}\n onAcknowledge={() => acknowledge.mutate(insight.id)}\n onDismiss={() => dismiss.mutate(insight.id)}\n onResolve={() => resolve.mutate(insight.id)}\n acknowledgePending={acknowledge.isPending}\n dismissPending={dismiss.isPending}\n resolvePending={resolve.isPending}\n />\n ))}\n </div>\n )}\n\n <LoadMore\n hasMore={hasMore}\n onClick={loadMore}\n loading={isFetchingNextPage}\n label={translate('brainyrich.insights.actions.loadMore', 'Load more insights')}\n />\n </>\n );\n };\n\n return (\n <>\n <SectionShell\n title={translate('brainyrich.insights.title', 'Insights')}\n description={translate(\n 'brainyrich.insights.description',\n 'Advisory insights across portfolios, accounts and goals — triage, acknowledge and resolve.'\n )}\n badges={[translate('brainyrich.insights.badges.advisory', 'Advisory')]}\n actionLabel={translate('brainyrich.insights.actions.create', 'New insight')}\n onAction={openCreate}\n >\n {body()}\n </SectionShell>\n\n <InsightFormDialog\n open={createOpen}\n form={form}\n setField={setField}\n metricsValid={metricsValid}\n valid={formValid}\n pending={createInsight.isPending}\n onSubmit={handleCreate}\n onOpenChange={(v) => setCreateOpen(v)}\n translate={translate}\n />\n </>\n );\n}\n\ntype Translate = (\n key: string,\n fallback: string,\n params?: Record<string, string | number>\n) => string;\n\ninterface InsightCardProps {\n insight: BraInsight;\n /** Referenced entity name resolved from the list queries, if known. */\n subjectName?: string;\n translate: Translate;\n onAcknowledge: () => void;\n onDismiss: () => void;\n onResolve: () => void;\n acknowledgePending: boolean;\n dismissPending: boolean;\n resolvePending: boolean;\n}\n\nfunction InsightCard({\n insight,\n subjectName,\n translate,\n onAcknowledge,\n onDismiss,\n onResolve,\n acknowledgePending,\n dismissPending,\n resolvePending,\n}: InsightCardProps) {\n const meta = severityMeta(insight.severity);\n const SeverityIcon = meta.icon;\n const isClosed = insight.status === 'RESOLVED' || insight.status === 'DISMISSED';\n const [dismissOpen, setDismissOpen] = useState(false);\n\n return (\n <Card>\n <CardHeader className=\"pb-3\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex min-w-0 items-start gap-3\">\n <span\n className={`mt-0.5 flex size-9 shrink-0 items-center justify-center rounded-full bg-bg-sunken ${meta.tone}`}\n >\n <SeverityIcon className=\"size-5\" aria-hidden=\"true\" />\n </span>\n <div className=\"min-w-0\">\n <CardTitle className=\"text-base\">{insight.title}</CardTitle>\n <CardDescription className=\"mt-1 flex flex-wrap items-center gap-2\">\n <Badge variant=\"outline\">{humanize(insight.type)}</Badge>\n <Badge variant={statusBadgeVariant(insight.severity)}>\n <span className={`inline-flex items-center gap-1 ${meta.tone}`}>\n <SeverityIcon className=\"size-3\" aria-hidden=\"true\" />\n {humanize(insight.severity)}\n </span>\n </Badge>\n <Badge variant={statusBadgeVariant(insight.status)}>\n {humanize(insight.status)}\n </Badge>\n </CardDescription>\n </div>\n </div>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={translate('brainyrich.insights.actions.menu', 'Insight actions')}\n >\n <MoreHorizontal className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem\n disabled={acknowledgePending || insight.status === 'ACKNOWLEDGED' || isClosed}\n onSelect={onAcknowledge}\n >\n <CheckCircle2 className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.acknowledge', 'Acknowledge')}\n </DropdownMenuItem>\n <DropdownMenuItem\n disabled={resolvePending || insight.status === 'RESOLVED'}\n onSelect={onResolve}\n >\n <CheckCircle2 className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.resolve', 'Resolve')}\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n className=\"text-status-error-text focus:text-status-error-text\"\n disabled={dismissPending || insight.status === 'DISMISSED'}\n onSelect={(e) => {\n e.preventDefault();\n setDismissOpen(true);\n }}\n >\n <XCircle className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.dismiss', 'Dismiss')}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {insight.detail ? <p className=\"text-sm text-text-secondary\">{insight.detail}</p> : null}\n <dl className=\"grid grid-cols-2 gap-3 rounded-lg bg-bg-sunken p-3 text-sm sm:grid-cols-3\">\n <div>\n <dt className=\"text-xs text-text-secondary\">\n {translate('brainyrich.insights.card.subjectType', 'Subject')}\n </dt>\n <dd className=\"font-medium text-text-primary\">{humanize(insight.subjectType)}</dd>\n </div>\n <div className=\"min-w-0\">\n <dt className=\"text-xs text-text-secondary\">\n {translate('brainyrich.insights.card.subject', 'Reference')}\n </dt>\n <dd\n className=\"truncate font-medium text-text-primary\"\n title={subjectName ? `${subjectName} (${insight.subjectId})` : insight.subjectId}\n >\n {subjectName ?? insight.subjectId}\n </dd>\n </div>\n <div>\n <dt className=\"text-xs text-text-secondary\">\n {translate('brainyrich.insights.card.created', 'Created')}\n </dt>\n <dd className=\"font-medium text-text-primary\">{formatDate(insight.createdAt)}</dd>\n </div>\n </dl>\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={acknowledgePending || insight.status === 'ACKNOWLEDGED' || isClosed}\n onClick={onAcknowledge}\n >\n <CheckCircle2 className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.acknowledge', 'Acknowledge')}\n </Button>\n <Button\n size=\"sm\"\n disabled={resolvePending || insight.status === 'RESOLVED'}\n onClick={onResolve}\n >\n <CheckCircle2 className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.resolve', 'Resolve')}\n </Button>\n </div>\n </CardContent>\n\n <ConfirmDialog\n open={dismissOpen}\n onOpenChange={setDismissOpen}\n title={translate('brainyrich.insights.dismiss.title', 'Dismiss this insight?')}\n description={translate(\n 'brainyrich.insights.dismiss.description',\n 'Dismissing removes this insight from active triage. You can still find it by filtering for dismissed insights.'\n )}\n confirmLabel={translate('brainyrich.insights.actions.dismiss', 'Dismiss')}\n pendingLabel={translate('brainyrich.insights.dismiss.pending', 'Dismissing…')}\n destructive\n pending={dismissPending}\n onConfirm={onDismiss}\n />\n </Card>\n );\n}\n\ninterface InsightFormDialogProps {\n open: boolean;\n form: InsightFormState;\n setField: <K extends keyof InsightFormState>(key: K, value: InsightFormState[K]) => void;\n metricsValid: boolean;\n valid: boolean;\n pending: boolean;\n onSubmit: () => void;\n onOpenChange: (open: boolean) => void;\n translate: Translate;\n}\n\nfunction InsightFormDialog({\n open,\n form,\n setField,\n metricsValid,\n valid,\n pending,\n onSubmit,\n onOpenChange,\n translate,\n}: InsightFormDialogProps) {\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"max-h-[90vh] overflow-y-auto sm:max-w-lg\">\n <DialogHeader>\n <DialogTitle>\n {translate('brainyrich.insights.form.createTitle', 'New insight')}\n </DialogTitle>\n <DialogDescription>\n {translate(\n 'brainyrich.insights.form.subtitle',\n 'Flag an advisory insight against a portfolio, account, goal or household.'\n )}\n </DialogDescription>\n </DialogHeader>\n\n <form\n className=\"space-y-4\"\n onSubmit={(e) => {\n e.preventDefault();\n onSubmit();\n }}\n >\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-title\">\n {translate('brainyrich.insights.form.title', 'Title')}\n </Label>\n <Input\n id=\"insight-title\"\n value={form.title}\n onChange={(e) => setField('title', e.target.value)}\n placeholder={translate(\n 'brainyrich.insights.form.titlePlaceholder',\n 'e.g. Technology concentration above threshold'\n )}\n required\n />\n </div>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-type\">\n {translate('brainyrich.insights.form.type', 'Type')}\n </Label>\n <Select\n value={form.type}\n onValueChange={(v) => setField('type', v as BraInsightType)}\n >\n <SelectTrigger id=\"insight-type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {INSIGHT_TYPES.map((tpe) => (\n <SelectItem key={tpe} value={tpe}>\n {humanize(tpe)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-severity\">\n {translate('brainyrich.insights.form.severity', 'Severity')}\n </Label>\n <Select\n value={form.severity}\n onValueChange={(v) => setField('severity', v as BraInsightSeverity)}\n >\n <SelectTrigger id=\"insight-severity\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {INSIGHT_SEVERITIES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n <SubjectPicker\n id=\"insight-subject\"\n label={translate('brainyrich.insights.form.subject', 'Subject')}\n placeholder={translate(\n 'brainyrich.insights.form.subjectPlaceholder',\n 'Select an account, portfolio, goal or household'\n )}\n value={form.subject}\n onChange={(v) => setField('subject', v)}\n />\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-owner\">\n {translate('brainyrich.insights.form.ownerId', 'Owner ID (optional)')}\n </Label>\n <Input\n id=\"insight-owner\"\n value={form.ownerId}\n onChange={(e) => setField('ownerId', e.target.value)}\n placeholder={translate(\n 'brainyrich.insights.form.ownerIdPlaceholder',\n 'Defaults to the current owner'\n )}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-detail\">\n {translate('brainyrich.insights.form.detail', 'Detail')}\n </Label>\n <Textarea\n id=\"insight-detail\"\n value={form.detail}\n onChange={(e) => setField('detail', e.target.value)}\n rows={3}\n placeholder={translate(\n 'brainyrich.insights.form.detailPlaceholder',\n 'Explain the finding and recommended action.'\n )}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-metrics\">\n {translate('brainyrich.insights.form.metrics', 'Metrics JSON (optional)')}\n </Label>\n <Textarea\n id=\"insight-metrics\"\n value={form.metrics}\n onChange={(e) => setField('metrics', e.target.value)}\n rows={3}\n className=\"font-mono text-xs\"\n placeholder='{ \"driftPct\": 8.2 }'\n aria-invalid={!metricsValid}\n />\n {!metricsValid ? (\n <p className=\"flex items-center gap-1 text-xs text-status-error-text\">\n <AlertTriangle className=\"size-3.5\" aria-hidden=\"true\" />\n {translate(\n 'brainyrich.insights.form.metricsInvalid',\n 'Enter valid JSON or leave blank.'\n )}\n </p>\n ) : null}\n </div>\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => onOpenChange(false)}\n disabled={pending}\n >\n {translate('brainyrich.insights.form.cancel', 'Cancel')}\n </Button>\n <Button type=\"submit\" disabled={!valid || pending}>\n {pending\n ? translate('brainyrich.insights.form.saving', 'Saving…')\n : translate('brainyrich.insights.form.create', 'Create insight')}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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"}