@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":"GoalsPage.js","names":[],"sources":["../../../src/brainyrich/pages/GoalsPage.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 Sheet,\n SheetContent,\n SheetDescription,\n SheetHeader,\n SheetTitle,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n AlertTriangle,\n CalendarClock,\n Link2,\n MoreHorizontal,\n Plus,\n RefreshCw,\n Target,\n Trash2,\n TrendingDown,\n TrendingUp,\n Unlink,\n} from 'lucide-react';\nimport { tWithFallback } from '../utils/i18n';\nimport {\n useAccounts,\n useArchiveGoal,\n useCreateGoal,\n useGoal,\n useGoalFundings,\n useGoals,\n useHouseholds,\n useLinkGoalFunding,\n useRecalcGoalProjection,\n useUnlinkGoalFunding,\n useUpdateGoal,\n} from '../hooks/useBrainyRichApi';\nimport type {\n BraCreateGoalInput,\n BraGoal,\n BraGoalProjection,\n BraGoalStatus,\n BraGoalType,\n BraUpdateGoalInput,\n} from '../types/bra';\nimport {\n EmptyState,\n ErrorState,\n KpiGrid,\n LoadingState,\n SectionShell,\n formatDate,\n formatMoney,\n statusBadgeVariant,\n} from './_shared';\n\nconst GOAL_TYPES: BraGoalType[] = [\n 'RETIREMENT',\n 'EDUCATION',\n 'HOME',\n 'EMERGENCY_FUND',\n 'MAJOR_PURCHASE',\n 'WEALTH_GROWTH',\n 'CUSTOM',\n];\n\nconst GOAL_STATUSES: BraGoalStatus[] = ['ACTIVE', 'ACHIEVED', 'ON_HOLD', 'ABANDONED'];\n\ninterface ProjectionMeta {\n icon: typeof TrendingUp;\n tone: string;\n}\n\nfunction projectionMeta(projection: BraGoalProjection): ProjectionMeta {\n switch (projection) {\n case 'AHEAD':\n case 'ON_TRACK':\n return { icon: TrendingUp, tone: 'text-status-success-text' };\n case 'BEHIND':\n return { icon: TrendingDown, tone: 'text-status-warning-text' };\n case 'AT_RISK':\n default:\n return { icon: AlertTriangle, tone: 'text-status-error-text' };\n }\n}\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\n/** yyyy-mm-dd for a date input, guarded against absent/invalid ISO strings. */\nfunction toDateInput(iso?: string | null): string {\n if (!iso) return '';\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return '';\n return d.toISOString().slice(0, 10);\n}\n\ninterface GoalFormState {\n name: string;\n type: BraGoalType;\n status: BraGoalStatus;\n targetAmount: string;\n targetDate: string;\n monthlyContribution: string;\n priority: string;\n currency: string;\n householdId: string;\n notes: string;\n tags: string;\n}\n\nfunction emptyForm(): GoalFormState {\n return {\n name: '',\n type: 'CUSTOM',\n status: 'ACTIVE',\n targetAmount: '',\n targetDate: '',\n monthlyContribution: '',\n priority: '1',\n currency: 'USD',\n householdId: '',\n notes: '',\n tags: '',\n };\n}\n\nfunction formFromGoal(goal: BraGoal): GoalFormState {\n return {\n name: goal.name,\n type: goal.type,\n status: goal.status,\n targetAmount: String(goal.targetAmount),\n targetDate: toDateInput(goal.targetDate),\n monthlyContribution: String(goal.monthlyContribution),\n priority: String(goal.priority),\n currency: goal.currency,\n householdId: goal.householdId ?? '',\n notes: goal.notes ?? '',\n tags: goal.tags.join(', '),\n };\n}\n\nfunction parseTags(raw: string): string[] {\n return raw\n .split(',')\n .map((t) => t.trim())\n .filter(Boolean);\n}\n\nconst HOUSEHOLD_NONE = '__none__';\n\nexport function GoalsPage() {\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 { data: goals, isLoading, isError, refetch } = useGoals();\n const { data: households } = useHouseholds();\n\n const createGoal = useCreateGoal();\n const updateGoal = useUpdateGoal();\n const archiveGoal = useArchiveGoal();\n\n const [createOpen, setCreateOpen] = useState(false);\n const [editing, setEditing] = useState<BraGoal | null>(null);\n const [detailId, setDetailId] = useState<string | null>(null);\n const [form, setForm] = useState<GoalFormState>(emptyForm);\n\n const setField = <K extends keyof GoalFormState>(key: K, value: GoalFormState[K]) =>\n setForm((prev) => ({ ...prev, [key]: value }));\n\n const totals = useMemo(() => {\n const totalTarget = goals.reduce((s, g) => s + g.targetAmount, 0);\n const totalMonthly = goals.reduce((s, g) => s + g.monthlyContribution, 0);\n const atRisk = goals.filter(\n (g) => g.projection === 'AT_RISK' || g.projection === 'BEHIND'\n ).length;\n return { totalTarget, totalMonthly, atRisk };\n }, [goals]);\n\n const currency = goals[0]?.currency ?? 'USD';\n\n const openCreate = () => {\n setForm(emptyForm());\n setCreateOpen(true);\n };\n\n const openEdit = (goal: BraGoal) => {\n setForm(formFromGoal(goal));\n setEditing(goal);\n };\n\n const formValid =\n form.name.trim().length > 0 && Number(form.targetAmount) > 0 && form.targetDate.length > 0;\n\n const handleCreate = () => {\n if (!formValid) return;\n const input: BraCreateGoalInput = {\n name: form.name.trim(),\n type: form.type,\n targetAmount: Number(form.targetAmount),\n targetDate: new Date(form.targetDate).toISOString(),\n monthlyContribution: Number(form.monthlyContribution) || 0,\n priority: Number(form.priority) || 1,\n currency: form.currency.trim() || 'USD',\n notes: form.notes.trim() || null,\n tags: parseTags(form.tags),\n ...(form.householdId ? { householdId: form.householdId } : {}),\n };\n createGoal.mutate(input, { onSuccess: () => setCreateOpen(false) });\n };\n\n const handleUpdate = () => {\n if (!editing || !formValid) return;\n const input: BraUpdateGoalInput = {\n name: form.name.trim(),\n type: form.type,\n status: form.status,\n targetAmount: Number(form.targetAmount),\n targetDate: new Date(form.targetDate).toISOString(),\n monthlyContribution: Number(form.monthlyContribution) || 0,\n priority: Number(form.priority) || 1,\n currency: form.currency.trim() || 'USD',\n notes: form.notes.trim() || null,\n tags: parseTags(form.tags),\n };\n updateGoal.mutate({ id: editing.id, input }, { onSuccess: () => setEditing(null) });\n };\n\n const body = () => {\n if (isLoading) return <LoadingState rows={4} />;\n if (isError)\n return (\n <ErrorState\n title={translate('brainyrich.goals.error.title', 'Could not load goals')}\n description={translate(\n 'brainyrich.goals.error.description',\n 'We could not reach the goals service. Please try again.'\n )}\n onRetry={() => refetch()}\n />\n );\n if (goals.length === 0)\n return (\n <EmptyState\n icon={<Target className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.goals.empty.title', 'No financial goals yet')}\n description={translate(\n 'brainyrich.goals.empty.description',\n 'Create your first goal to start tracking progress toward a milestone.'\n )}\n action={\n <Button size=\"sm\" onClick={openCreate}>\n <Plus className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.goals.actions.createGoal', 'New goal')}\n </Button>\n }\n />\n );\n\n return (\n <>\n <KpiGrid\n items={[\n {\n label: translate('brainyrich.goals.metrics.activeGoals', 'Goals'),\n value: String(goals.length),\n trend: translate('brainyrich.goals.metrics.activeGoalsTrend', 'Being tracked'),\n },\n {\n label: translate('brainyrich.goals.metrics.totalTarget', 'Total target'),\n value: formatMoney(totals.totalTarget, currency),\n },\n {\n label: translate('brainyrich.goals.metrics.monthly', 'Monthly contributions'),\n value: formatMoney(totals.totalMonthly, currency),\n trend: translate('brainyrich.goals.metrics.monthlyTrend', 'Across all goals'),\n },\n {\n label: translate('brainyrich.goals.metrics.atRisk', 'Needs attention'),\n value: String(totals.atRisk),\n trend: translate('brainyrich.goals.metrics.atRiskTrend', 'Behind or at risk'),\n deltaTone: totals.atRisk > 0 ? 'negative' : 'positive',\n },\n ]}\n />\n\n <div className=\"grid gap-4 md:grid-cols-2 xl:grid-cols-3\">\n {goals.map((g) => {\n const proj = projectionMeta(g.projection);\n const ProjIcon = proj.icon;\n return (\n <Card key={g.id} className=\"flex flex-col\">\n <CardHeader className=\"pb-3\">\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <Target className=\"size-4 shrink-0 text-text-secondary\" aria-hidden=\"true\" />\n <span className=\"truncate\">{g.name}</span>\n </CardTitle>\n <CardDescription className=\"mt-1 flex flex-wrap items-center gap-2\">\n <Badge variant=\"outline\">{humanize(g.type)}</Badge>\n <Badge variant={statusBadgeVariant(g.status)}>{humanize(g.status)}</Badge>\n </CardDescription>\n </div>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={translate('brainyrich.goals.actions.menu', 'Goal actions')}\n >\n <MoreHorizontal className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem onSelect={() => setDetailId(g.id)}>\n <Link2 className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.goals.actions.manageFunding', 'Manage funding')}\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={() => openEdit(g)}>\n <RefreshCw className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.goals.actions.editGoal', 'Edit goal')}\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n className=\"text-status-error-text focus:text-status-error-text\"\n disabled={archiveGoal.isPending}\n onSelect={() => archiveGoal.mutate(g.id)}\n >\n <Trash2 className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.goals.actions.archive', 'Archive goal')}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </CardHeader>\n <CardContent className=\"flex flex-1 flex-col gap-4\">\n <div>\n <p className=\"text-xs text-text-secondary\">\n {translate('brainyrich.goals.card.target', 'Target amount')}\n </p>\n <p className=\"text-2xl font-semibold text-text-primary\">\n {formatMoney(g.targetAmount, g.currency)}\n </p>\n <span\n className={`mt-1 inline-flex items-center gap-1 text-xs font-medium ${proj.tone}`}\n >\n <ProjIcon className=\"size-3.5\" aria-hidden=\"true\" />\n {humanize(g.projection)}\n </span>\n </div>\n\n <dl className=\"grid grid-cols-2 gap-3 rounded-lg bg-bg-sunken p-3 text-sm\">\n <div>\n <dt className=\"text-xs text-text-secondary\">\n {translate('brainyrich.goals.card.targetDate', 'Target date')}\n </dt>\n <dd className=\"flex items-center gap-1 font-medium text-text-primary\">\n <CalendarClock\n className=\"size-3.5 text-text-secondary\"\n aria-hidden=\"true\"\n />\n {formatDate(g.targetDate)}\n </dd>\n </div>\n <div>\n <dt className=\"text-xs text-text-secondary\">\n {translate('brainyrich.goals.card.monthly', 'Monthly')}\n </dt>\n <dd className=\"font-medium text-text-primary\">\n {formatMoney(g.monthlyContribution, g.currency)}\n </dd>\n </div>\n <div>\n <dt className=\"text-xs text-text-secondary\">\n {translate('brainyrich.goals.card.priority', 'Priority')}\n </dt>\n <dd className=\"font-medium text-text-primary\">{g.priority}</dd>\n </div>\n <div>\n <dt className=\"text-xs text-text-secondary\">\n {translate('brainyrich.goals.card.fundings', 'Funding links')}\n </dt>\n <dd className=\"font-medium text-text-primary\">{g.fundings.length}</dd>\n </div>\n </dl>\n\n <div className=\"mt-auto\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"w-full\"\n onClick={() => setDetailId(g.id)}\n >\n {translate('brainyrich.goals.actions.viewDetails', 'View details & funding')}\n </Button>\n </div>\n </CardContent>\n </Card>\n );\n })}\n </div>\n </>\n );\n };\n\n return (\n <>\n <SectionShell\n title={translate('brainyrich.goals.title', 'Financial Goals')}\n description={translate(\n 'brainyrich.goals.description',\n 'Track progress toward your wealth milestones and life objectives'\n )}\n actionLabel={translate('brainyrich.goals.actions.createGoal', 'New goal')}\n onAction={openCreate}\n >\n {body()}\n </SectionShell>\n\n <GoalFormDialog\n open={createOpen}\n mode=\"create\"\n form={form}\n setField={setField}\n households={households.map((h) => ({ id: h.id, name: h.name }))}\n valid={formValid}\n pending={createGoal.isPending}\n onSubmit={handleCreate}\n onOpenChange={(v) => setCreateOpen(v)}\n translate={translate}\n />\n\n <GoalFormDialog\n open={Boolean(editing)}\n mode=\"edit\"\n form={form}\n setField={setField}\n households={households.map((h) => ({ id: h.id, name: h.name }))}\n valid={formValid}\n pending={updateGoal.isPending}\n onSubmit={handleUpdate}\n onOpenChange={(v) => {\n if (!v) setEditing(null);\n }}\n translate={translate}\n />\n\n <GoalDetailSheet\n goalId={detailId}\n onClose={() => setDetailId(null)}\n translate={translate}\n />\n </>\n );\n}\n\ntype Translate = (key: string, fallback: string, params?: Record<string, string | number>) => string;\n\ninterface GoalFormDialogProps {\n open: boolean;\n mode: 'create' | 'edit';\n form: GoalFormState;\n setField: <K extends keyof GoalFormState>(key: K, value: GoalFormState[K]) => void;\n households: { id: string; name: string }[];\n valid: boolean;\n pending: boolean;\n onSubmit: () => void;\n onOpenChange: (open: boolean) => void;\n translate: Translate;\n}\n\nfunction GoalFormDialog({\n open,\n mode,\n form,\n setField,\n households,\n valid,\n pending,\n onSubmit,\n onOpenChange,\n translate,\n}: GoalFormDialogProps) {\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 {mode === 'create'\n ? translate('brainyrich.goals.form.createTitle', 'New goal')\n : translate('brainyrich.goals.form.editTitle', 'Edit goal')}\n </DialogTitle>\n <DialogDescription>\n {translate(\n 'brainyrich.goals.form.subtitle',\n 'Define the milestone, target and contribution plan.'\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=\"goal-name\">\n {translate('brainyrich.goals.form.name', 'Name')}\n </Label>\n <Input\n id=\"goal-name\"\n value={form.name}\n onChange={(e) => setField('name', e.target.value)}\n placeholder={translate('brainyrich.goals.form.namePlaceholder', 'e.g. Retirement fund')}\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=\"goal-type\">\n {translate('brainyrich.goals.form.type', 'Type')}\n </Label>\n <Select value={form.type} onValueChange={(v) => setField('type', v as BraGoalType)}>\n <SelectTrigger id=\"goal-type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {GOAL_TYPES.map((tpe) => (\n <SelectItem key={tpe} value={tpe}>\n {humanize(tpe)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n {mode === 'edit' ? (\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"goal-status\">\n {translate('brainyrich.goals.form.status', 'Status')}\n </Label>\n <Select\n value={form.status}\n onValueChange={(v) => setField('status', v as BraGoalStatus)}\n >\n <SelectTrigger id=\"goal-status\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {GOAL_STATUSES.map((st) => (\n <SelectItem key={st} value={st}>\n {humanize(st)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n ) : (\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"goal-priority\">\n {translate('brainyrich.goals.form.priority', 'Priority')}\n </Label>\n <Input\n id=\"goal-priority\"\n type=\"number\"\n min={1}\n value={form.priority}\n onChange={(e) => setField('priority', e.target.value)}\n />\n </div>\n )}\n </div>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"goal-target\">\n {translate('brainyrich.goals.form.targetAmount', 'Target amount')}\n </Label>\n <Input\n id=\"goal-target\"\n type=\"number\"\n min={0}\n step=\"0.01\"\n value={form.targetAmount}\n onChange={(e) => setField('targetAmount', e.target.value)}\n required\n />\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"goal-date\">\n {translate('brainyrich.goals.form.targetDate', 'Target date')}\n </Label>\n <Input\n id=\"goal-date\"\n type=\"date\"\n value={form.targetDate}\n onChange={(e) => setField('targetDate', e.target.value)}\n required\n />\n </div>\n </div>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"goal-monthly\">\n {translate('brainyrich.goals.form.monthly', 'Monthly contribution')}\n </Label>\n <Input\n id=\"goal-monthly\"\n type=\"number\"\n min={0}\n step=\"0.01\"\n value={form.monthlyContribution}\n onChange={(e) => setField('monthlyContribution', e.target.value)}\n />\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"goal-currency\">\n {translate('brainyrich.goals.form.currency', 'Currency')}\n </Label>\n <Input\n id=\"goal-currency\"\n value={form.currency}\n onChange={(e) => setField('currency', e.target.value.toUpperCase())}\n maxLength={3}\n />\n </div>\n </div>\n\n {mode === 'edit' ? (\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"goal-priority-edit\">\n {translate('brainyrich.goals.form.priority', 'Priority')}\n </Label>\n <Input\n id=\"goal-priority-edit\"\n type=\"number\"\n min={1}\n value={form.priority}\n onChange={(e) => setField('priority', e.target.value)}\n />\n </div>\n ) : null}\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"goal-household\">\n {translate('brainyrich.goals.form.household', 'Household (optional)')}\n </Label>\n <Select\n value={form.householdId || HOUSEHOLD_NONE}\n onValueChange={(v) => setField('householdId', v === HOUSEHOLD_NONE ? '' : v)}\n >\n <SelectTrigger id=\"goal-household\">\n <SelectValue\n placeholder={translate('brainyrich.goals.form.householdNone', 'None')}\n />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={HOUSEHOLD_NONE}>\n {translate('brainyrich.goals.form.householdNone', 'None')}\n </SelectItem>\n {households.map((h) => (\n <SelectItem key={h.id} value={h.id}>\n {h.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"goal-tags\">\n {translate('brainyrich.goals.form.tags', 'Tags (comma separated)')}\n </Label>\n <Input\n id=\"goal-tags\"\n value={form.tags}\n onChange={(e) => setField('tags', e.target.value)}\n placeholder={translate('brainyrich.goals.form.tagsPlaceholder', 'e.g. long-term, family')}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"goal-notes\">\n {translate('brainyrich.goals.form.notes', 'Notes')}\n </Label>\n <Textarea\n id=\"goal-notes\"\n value={form.notes}\n onChange={(e) => setField('notes', e.target.value)}\n rows={3}\n />\n </div>\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => onOpenChange(false)}\n disabled={pending}\n >\n {translate('brainyrich.goals.form.cancel', 'Cancel')}\n </Button>\n <Button type=\"submit\" disabled={!valid || pending}>\n {pending\n ? translate('brainyrich.goals.form.saving', 'Saving…')\n : mode === 'create'\n ? translate('brainyrich.goals.form.create', 'Create goal')\n : translate('brainyrich.goals.form.save', 'Save changes')}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n\ntype FundingMode = 'PERCENT' | 'FIXED';\n\ninterface GoalDetailSheetProps {\n goalId: string | null;\n onClose: () => void;\n translate: Translate;\n}\n\nfunction GoalDetailSheet({ goalId, onClose, translate }: GoalDetailSheetProps) {\n const { data: goal, isLoading, isError, refetch } = useGoal(goalId ?? undefined);\n const { data: fundings } = useGoalFundings(goalId ?? undefined);\n const { data: accounts } = useAccounts();\n\n const linkFunding = useLinkGoalFunding();\n const unlinkFunding = useUnlinkGoalFunding();\n const recalc = useRecalcGoalProjection();\n\n const [accountId, setAccountId] = useState('');\n const [fundingMode, setFundingMode] = useState<FundingMode>('PERCENT');\n const [fundingValue, setFundingValue] = useState('');\n const [fundedAmount, setFundedAmount] = useState('');\n\n const fixedFunded = fundings.reduce((s, f) => s + (f.fixedAmount ?? 0), 0);\n const currency = goal?.currency ?? 'USD';\n\n const accountName = (id: string) => accounts.find((a) => a.id === id)?.name ?? id;\n\n const handleLink = () => {\n if (!goalId || !accountId) return;\n const numeric = Number(fundingValue);\n if (!Number.isFinite(numeric) || numeric <= 0) return;\n linkFunding.mutate(\n {\n goalId,\n accountId,\n ...(fundingMode === 'PERCENT'\n ? { allocationPct: numeric }\n : { fixedAmount: numeric }),\n },\n {\n onSuccess: () => {\n setAccountId('');\n setFundingValue('');\n },\n }\n );\n };\n\n const handleRecalc = () => {\n if (!goalId) return;\n const amount = fundedAmount === '' ? fixedFunded : Number(fundedAmount);\n if (!Number.isFinite(amount)) return;\n recalc.mutate({ id: goalId, fundedAmount: amount });\n };\n\n const linkValid = Boolean(accountId) && Number(fundingValue) > 0;\n\n return (\n <Sheet\n open={Boolean(goalId)}\n onOpenChange={(v) => {\n if (!v) onClose();\n }}\n >\n <SheetContent className=\"flex w-full flex-col gap-0 overflow-y-auto sm:max-w-md\">\n <SheetHeader>\n <SheetTitle>{goal?.name ?? translate('brainyrich.goals.detail.title', 'Goal')}</SheetTitle>\n <SheetDescription>\n {translate('brainyrich.goals.detail.subtitle', 'Manage funding links and projection.')}\n </SheetDescription>\n </SheetHeader>\n\n <div className=\"space-y-6 p-4\">\n {isLoading ? (\n <LoadingState rows={3} />\n ) : isError ? (\n <ErrorState\n title={translate('brainyrich.goals.detail.error', 'Could not load goal')}\n onRetry={() => refetch()}\n />\n ) : !goal ? (\n <EmptyState\n icon={<Target className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.goals.detail.notFound', 'Goal not found')}\n />\n ) : (\n <>\n <div className=\"grid grid-cols-2 gap-3\">\n <SummaryTile\n label={translate('brainyrich.goals.detail.target', 'Target')}\n value={formatMoney(goal.targetAmount, currency)}\n />\n <SummaryTile\n label={translate('brainyrich.goals.detail.funded', 'Funded (fixed)')}\n value={formatMoney(fixedFunded, currency)}\n />\n <SummaryTile\n label={translate('brainyrich.goals.detail.projection', 'Projection')}\n value={humanize(goal.projection)}\n tone={projectionMeta(goal.projection).tone}\n />\n <SummaryTile\n label={translate('brainyrich.goals.detail.targetDate', 'Target date')}\n value={formatDate(goal.targetDate)}\n />\n </div>\n\n {/* Fundings list */}\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {translate('brainyrich.goals.detail.fundingLinks', 'Funding links')}\n </h3>\n {fundings.length === 0 ? (\n <p className=\"rounded-lg border border-dashed border-border-subtle bg-bg-surface px-4 py-6 text-center text-sm text-text-secondary\">\n {translate(\n 'brainyrich.goals.detail.noFundings',\n 'No accounts linked to fund this goal yet.'\n )}\n </p>\n ) : (\n <ul className=\"space-y-2\">\n {fundings.map((f) => (\n <li\n key={f.id}\n className=\"flex items-center justify-between gap-2 rounded-lg border border-border-subtle bg-bg-surface px-3 py-2\"\n >\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {accountName(f.accountId)}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {f.fixedAmount != null\n ? formatMoney(f.fixedAmount, currency)\n : translate('brainyrich.goals.detail.pctOfAccount', '{pct}% of account', {\n pct: f.allocationPct,\n })}\n </p>\n </div>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={translate('brainyrich.goals.detail.unlink', 'Unlink funding')}\n disabled={unlinkFunding.isPending}\n onClick={() => unlinkFunding.mutate(f.id)}\n >\n <Unlink className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </li>\n ))}\n </ul>\n )}\n </section>\n\n {/* Link a new funding */}\n <section className=\"space-y-3 rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {translate('brainyrich.goals.detail.linkTitle', 'Link an account')}\n </h3>\n {accounts.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">\n {translate(\n 'brainyrich.goals.detail.noAccounts',\n 'No accounts available to link.'\n )}\n </p>\n ) : (\n <>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"funding-account\">\n {translate('brainyrich.goals.detail.account', 'Account')}\n </Label>\n <Select value={accountId} onValueChange={setAccountId}>\n <SelectTrigger id=\"funding-account\">\n <SelectValue\n placeholder={translate(\n 'brainyrich.goals.detail.selectAccount',\n 'Select account'\n )}\n />\n </SelectTrigger>\n <SelectContent>\n {accounts.map((a) => (\n <SelectItem key={a.id} value={a.id}>\n {a.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"funding-mode\">\n {translate('brainyrich.goals.detail.mode', 'Method')}\n </Label>\n <Select\n value={fundingMode}\n onValueChange={(v) => setFundingMode(v as FundingMode)}\n >\n <SelectTrigger id=\"funding-mode\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"PERCENT\">\n {translate('brainyrich.goals.detail.percent', 'Percentage')}\n </SelectItem>\n <SelectItem value=\"FIXED\">\n {translate('brainyrich.goals.detail.fixed', 'Fixed amount')}\n </SelectItem>\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"funding-value\">\n {fundingMode === 'PERCENT'\n ? translate('brainyrich.goals.detail.pct', 'Percent')\n : translate('brainyrich.goals.detail.amount', 'Amount')}\n </Label>\n <Input\n id=\"funding-value\"\n type=\"number\"\n min={0}\n step=\"0.01\"\n value={fundingValue}\n onChange={(e) => setFundingValue(e.target.value)}\n />\n </div>\n </div>\n <Button\n size=\"sm\"\n className=\"w-full\"\n disabled={!linkValid || linkFunding.isPending}\n onClick={handleLink}\n >\n <Link2 className=\"size-4\" aria-hidden=\"true\" />\n {linkFunding.isPending\n ? translate('brainyrich.goals.detail.linking', 'Linking…')\n : translate('brainyrich.goals.detail.link', 'Link funding')}\n </Button>\n </>\n )}\n </section>\n\n {/* Recalc projection */}\n <section className=\"space-y-3 rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {translate('brainyrich.goals.detail.recalcTitle', 'Recalculate projection')}\n </h3>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"recalc-funded\">\n {translate('brainyrich.goals.detail.fundedAmount', 'Funded amount')}\n </Label>\n <Input\n id=\"recalc-funded\"\n type=\"number\"\n min={0}\n step=\"0.01\"\n value={fundedAmount}\n placeholder={String(fixedFunded)}\n onChange={(e) => setFundedAmount(e.target.value)}\n />\n <p className=\"text-xs text-text-secondary\">\n {translate(\n 'brainyrich.goals.detail.recalcHint',\n 'Defaults to the sum of fixed fundings when left blank.'\n )}\n </p>\n </div>\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"w-full\"\n disabled={recalc.isPending}\n onClick={handleRecalc}\n >\n <RefreshCw className=\"size-4\" aria-hidden=\"true\" />\n {recalc.isPending\n ? translate('brainyrich.goals.detail.recalculating', 'Recalculating…')\n : translate('brainyrich.goals.detail.recalc', 'Recalculate')}\n </Button>\n </section>\n </>\n )}\n </div>\n </SheetContent>\n </Sheet>\n );\n}\n\nfunction SummaryTile({ label, value, tone }: { label: string; value: string; tone?: string }) {\n return (\n <div className=\"rounded-lg bg-bg-sunken p-3\">\n <p className=\"text-xs text-text-secondary\">{label}</p>\n <p className={`text-sm font-semibold ${tone ?? 'text-text-primary'}`}>{value}</p>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"GoalsPage.js","names":[],"sources":["../../../src/brainyrich/pages/GoalsPage.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 Sheet,\n SheetContent,\n SheetDescription,\n SheetHeader,\n SheetTitle,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n AlertTriangle,\n CalendarClock,\n Link2,\n MoreHorizontal,\n Plus,\n RefreshCw,\n Target,\n Trash2,\n TrendingDown,\n TrendingUp,\n Unlink,\n} from 'lucide-react';\nimport { tWithFallback } from '../utils/i18n';\nimport { ConfirmDialog, LoadMore } from '../components';\nimport { TagField } from '../components/reuse/TagField';\nimport {\n useAccounts,\n useArchiveGoal,\n useCreateGoal,\n useGoal,\n useGoalFundings,\n useHouseholds,\n useLinkGoalFunding,\n usePagedGoals,\n useRecalcGoalProjection,\n useUnlinkGoalFunding,\n useUpdateGoal,\n} from '../hooks/useBrainyRichApi';\nimport type {\n BraCreateGoalInput,\n BraGoal,\n BraGoalFunding,\n BraGoalProjection,\n BraGoalStatus,\n BraGoalType,\n BraUpdateGoalInput,\n} from '../types/bra';\nimport {\n EmptyState,\n ErrorState,\n KpiGrid,\n LoadingState,\n SectionShell,\n formatDate,\n formatMoney,\n statusBadgeVariant,\n} from './_shared';\n\nconst GOAL_TYPES: BraGoalType[] = [\n 'RETIREMENT',\n 'EDUCATION',\n 'HOME',\n 'EMERGENCY_FUND',\n 'MAJOR_PURCHASE',\n 'WEALTH_GROWTH',\n 'CUSTOM',\n];\n\nconst GOAL_STATUSES: BraGoalStatus[] = ['ACTIVE', 'ACHIEVED', 'ON_HOLD', 'ABANDONED'];\n\ninterface ProjectionMeta {\n icon: typeof TrendingUp;\n tone: string;\n}\n\nfunction projectionMeta(projection: BraGoalProjection): ProjectionMeta {\n switch (projection) {\n case 'AHEAD':\n case 'ON_TRACK':\n return { icon: TrendingUp, tone: 'text-status-success-text' };\n case 'BEHIND':\n return { icon: TrendingDown, tone: 'text-status-warning-text' };\n case 'AT_RISK':\n default:\n return { icon: AlertTriangle, tone: 'text-status-error-text' };\n }\n}\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\n/** yyyy-mm-dd for a date input, guarded against absent/invalid ISO strings. */\nfunction toDateInput(iso?: string | null): string {\n if (!iso) return '';\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return '';\n return d.toISOString().slice(0, 10);\n}\n\ninterface GoalFormState {\n name: string;\n type: BraGoalType;\n status: BraGoalStatus;\n targetAmount: string;\n targetDate: string;\n monthlyContribution: string;\n priority: string;\n currency: string;\n householdId: string;\n notes: string;\n}\n\nfunction emptyForm(): GoalFormState {\n return {\n name: '',\n type: 'CUSTOM',\n status: 'ACTIVE',\n targetAmount: '',\n targetDate: '',\n monthlyContribution: '',\n priority: '1',\n currency: 'USD',\n householdId: '',\n notes: '',\n };\n}\n\nfunction formFromGoal(goal: BraGoal): GoalFormState {\n return {\n name: goal.name,\n type: goal.type,\n status: goal.status,\n targetAmount: String(goal.targetAmount),\n targetDate: toDateInput(goal.targetDate),\n monthlyContribution: String(goal.monthlyContribution),\n priority: String(goal.priority),\n currency: goal.currency,\n householdId: goal.householdId ?? '',\n notes: goal.notes ?? '',\n };\n}\n\nconst HOUSEHOLD_NONE = '__none__';\n\nexport function GoalsPage() {\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 {\n items: goals,\n hasMore,\n loadMore,\n isFetchingNextPage,\n isLoading,\n isError,\n refetch,\n } = usePagedGoals();\n const { data: households } = useHouseholds();\n\n const createGoal = useCreateGoal();\n const updateGoal = useUpdateGoal();\n const archiveGoal = useArchiveGoal();\n\n const [createOpen, setCreateOpen] = useState(false);\n const [editing, setEditing] = useState<BraGoal | null>(null);\n const [detailId, setDetailId] = useState<string | null>(null);\n const [archiving, setArchiving] = useState<BraGoal | null>(null);\n const [form, setForm] = useState<GoalFormState>(emptyForm);\n\n const setField = <K extends keyof GoalFormState>(key: K, value: GoalFormState[K]) =>\n setForm((prev) => ({ ...prev, [key]: value }));\n\n const totals = useMemo(() => {\n const totalTarget = goals.reduce((s, g) => s + g.targetAmount, 0);\n const totalMonthly = goals.reduce((s, g) => s + g.monthlyContribution, 0);\n const atRisk = goals.filter(\n (g) => g.projection === 'AT_RISK' || g.projection === 'BEHIND'\n ).length;\n return { totalTarget, totalMonthly, atRisk };\n }, [goals]);\n\n const currency = goals[0]?.currency ?? 'USD';\n\n const openCreate = () => {\n setForm(emptyForm());\n setCreateOpen(true);\n };\n\n const openEdit = (goal: BraGoal) => {\n setForm(formFromGoal(goal));\n setEditing(goal);\n };\n\n const formValid =\n form.name.trim().length > 0 && Number(form.targetAmount) > 0 && form.targetDate.length > 0;\n\n const handleCreate = () => {\n if (!formValid) return;\n const input: BraCreateGoalInput = {\n name: form.name.trim(),\n type: form.type,\n targetAmount: Number(form.targetAmount),\n targetDate: new Date(form.targetDate).toISOString(),\n monthlyContribution: Number(form.monthlyContribution) || 0,\n priority: Number(form.priority) || 1,\n currency: form.currency.trim() || 'USD',\n notes: form.notes.trim() || null,\n tags: [],\n ...(form.householdId ? { householdId: form.householdId } : {}),\n };\n createGoal.mutate(input, { onSuccess: () => setCreateOpen(false) });\n };\n\n const handleUpdate = () => {\n if (!editing || !formValid) return;\n const input: BraUpdateGoalInput = {\n name: form.name.trim(),\n type: form.type,\n status: form.status,\n targetAmount: Number(form.targetAmount),\n targetDate: new Date(form.targetDate).toISOString(),\n monthlyContribution: Number(form.monthlyContribution) || 0,\n priority: Number(form.priority) || 1,\n currency: form.currency.trim() || 'USD',\n notes: form.notes.trim() || null,\n // Legacy `tags` scalar preserved as-is; the canonical tag surface is <TagField>.\n tags: editing.tags,\n };\n updateGoal.mutate({ id: editing.id, input }, { onSuccess: () => setEditing(null) });\n };\n\n const body = () => {\n if (isLoading) return <LoadingState rows={4} />;\n if (isError)\n return (\n <ErrorState\n title={translate('brainyrich.goals.error.title', 'Could not load goals')}\n description={translate(\n 'brainyrich.goals.error.description',\n 'We could not reach the goals service. Please try again.'\n )}\n onRetry={() => refetch()}\n />\n );\n if (goals.length === 0)\n return (\n <EmptyState\n icon={<Target className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.goals.empty.title', 'No financial goals yet')}\n description={translate(\n 'brainyrich.goals.empty.description',\n 'Create your first goal to start tracking progress toward a milestone.'\n )}\n action={\n <Button size=\"sm\" onClick={openCreate}>\n <Plus className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.goals.actions.createGoal', 'New goal')}\n </Button>\n }\n />\n );\n\n return (\n <>\n <KpiGrid\n items={[\n {\n label: translate('brainyrich.goals.metrics.activeGoals', 'Goals'),\n value: String(goals.length),\n trend: translate('brainyrich.goals.metrics.activeGoalsTrend', 'Being tracked'),\n },\n {\n label: translate('brainyrich.goals.metrics.totalTarget', 'Total target'),\n value: formatMoney(totals.totalTarget, currency),\n },\n {\n label: translate('brainyrich.goals.metrics.monthly', 'Monthly contributions'),\n value: formatMoney(totals.totalMonthly, currency),\n trend: translate('brainyrich.goals.metrics.monthlyTrend', 'Across all goals'),\n },\n {\n label: translate('brainyrich.goals.metrics.atRisk', 'Needs attention'),\n value: String(totals.atRisk),\n trend: translate('brainyrich.goals.metrics.atRiskTrend', 'Behind or at risk'),\n deltaTone: totals.atRisk > 0 ? 'negative' : 'positive',\n },\n ]}\n />\n\n <div className=\"grid gap-4 md:grid-cols-2 xl:grid-cols-3\">\n {goals.map((g) => {\n const proj = projectionMeta(g.projection);\n const ProjIcon = proj.icon;\n return (\n <Card key={g.id} className=\"flex flex-col\">\n <CardHeader className=\"pb-3\">\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <Target\n className=\"size-4 shrink-0 text-text-secondary\"\n aria-hidden=\"true\"\n />\n <span className=\"truncate\">{g.name}</span>\n </CardTitle>\n <CardDescription className=\"mt-1 flex flex-wrap items-center gap-2\">\n <Badge variant=\"outline\">{humanize(g.type)}</Badge>\n <Badge variant={statusBadgeVariant(g.status)}>{humanize(g.status)}</Badge>\n </CardDescription>\n </div>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={translate('brainyrich.goals.actions.menu', 'Goal actions')}\n >\n <MoreHorizontal className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem onSelect={() => setDetailId(g.id)}>\n <Link2 className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.goals.actions.manageFunding', 'Manage funding')}\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={() => openEdit(g)}>\n <RefreshCw className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.goals.actions.editGoal', 'Edit goal')}\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n className=\"text-status-error-text focus:text-status-error-text\"\n onSelect={() => setArchiving(g)}\n >\n <Trash2 className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.goals.actions.archive', 'Archive goal')}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </CardHeader>\n <CardContent className=\"flex flex-1 flex-col gap-4\">\n <div>\n <p className=\"text-xs text-text-secondary\">\n {translate('brainyrich.goals.card.target', 'Target amount')}\n </p>\n <p className=\"text-2xl font-semibold text-text-primary\">\n {formatMoney(g.targetAmount, g.currency)}\n </p>\n <span\n className={`mt-1 inline-flex items-center gap-1 text-xs font-medium ${proj.tone}`}\n >\n <ProjIcon className=\"size-3.5\" aria-hidden=\"true\" />\n {humanize(g.projection)}\n </span>\n </div>\n\n <dl className=\"grid grid-cols-2 gap-3 rounded-lg bg-bg-sunken p-3 text-sm\">\n <div>\n <dt className=\"text-xs text-text-secondary\">\n {translate('brainyrich.goals.card.targetDate', 'Target date')}\n </dt>\n <dd className=\"flex items-center gap-1 font-medium text-text-primary\">\n <CalendarClock\n className=\"size-3.5 text-text-secondary\"\n aria-hidden=\"true\"\n />\n {formatDate(g.targetDate)}\n </dd>\n </div>\n <div>\n <dt className=\"text-xs text-text-secondary\">\n {translate('brainyrich.goals.card.monthly', 'Monthly')}\n </dt>\n <dd className=\"font-medium text-text-primary\">\n {formatMoney(g.monthlyContribution, g.currency)}\n </dd>\n </div>\n <div>\n <dt className=\"text-xs text-text-secondary\">\n {translate('brainyrich.goals.card.priority', 'Priority')}\n </dt>\n <dd className=\"font-medium text-text-primary\">{g.priority}</dd>\n </div>\n <div>\n <dt className=\"text-xs text-text-secondary\">\n {translate('brainyrich.goals.card.fundings', 'Funding links')}\n </dt>\n <dd className=\"font-medium text-text-primary\">{g.fundings.length}</dd>\n </div>\n </dl>\n\n <div className=\"mt-auto\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"w-full\"\n onClick={() => setDetailId(g.id)}\n >\n {translate('brainyrich.goals.actions.viewDetails', 'View details & funding')}\n </Button>\n </div>\n </CardContent>\n </Card>\n );\n })}\n </div>\n\n <LoadMore\n hasMore={hasMore}\n loading={isFetchingNextPage}\n onClick={loadMore}\n label={translate('brainyrich.goals.actions.loadMore', 'Load more goals')}\n loadingLabel={translate('brainyrich.goals.actions.loadingMore', 'Loading…')}\n />\n </>\n );\n };\n\n return (\n <>\n <SectionShell\n title={translate('brainyrich.goals.title', 'Financial Goals')}\n description={translate(\n 'brainyrich.goals.description',\n 'Track progress toward your wealth milestones and life objectives'\n )}\n actionLabel={translate('brainyrich.goals.actions.createGoal', 'New goal')}\n onAction={openCreate}\n >\n {body()}\n </SectionShell>\n\n <GoalFormDialog\n open={createOpen}\n mode=\"create\"\n form={form}\n setField={setField}\n households={households.map((h) => ({ id: h.id, name: h.name }))}\n valid={formValid}\n pending={createGoal.isPending}\n onSubmit={handleCreate}\n onOpenChange={(v) => setCreateOpen(v)}\n translate={translate}\n />\n\n <GoalFormDialog\n open={Boolean(editing)}\n mode=\"edit\"\n goalId={editing?.id}\n form={form}\n setField={setField}\n households={households.map((h) => ({ id: h.id, name: h.name }))}\n valid={formValid}\n pending={updateGoal.isPending}\n onSubmit={handleUpdate}\n onOpenChange={(v) => {\n if (!v) setEditing(null);\n }}\n translate={translate}\n />\n\n <GoalDetailSheet goalId={detailId} onClose={() => setDetailId(null)} translate={translate} />\n\n <ConfirmDialog\n open={Boolean(archiving)}\n onOpenChange={(o) => {\n if (!o) setArchiving(null);\n }}\n title={translate('brainyrich.goals.archive.title', 'Archive goal?')}\n description={translate(\n 'brainyrich.goals.archive.description',\n 'This removes “{name}” from your active goals. You can no longer track its progress.',\n { name: archiving?.name ?? '' }\n )}\n confirmLabel={translate('brainyrich.goals.archive.confirm', 'Archive goal')}\n pendingLabel={translate('brainyrich.goals.archive.pending', 'Archiving…')}\n destructive\n pending={archiveGoal.isPending}\n onConfirm={() => {\n if (!archiving) return;\n archiveGoal.mutate(archiving.id, { onSuccess: () => setArchiving(null) });\n }}\n />\n </>\n );\n}\n\ntype Translate = (\n key: string,\n fallback: string,\n params?: Record<string, string | number>\n) => string;\n\ninterface GoalFormDialogProps {\n open: boolean;\n mode: 'create' | 'edit';\n goalId?: string;\n form: GoalFormState;\n setField: <K extends keyof GoalFormState>(key: K, value: GoalFormState[K]) => void;\n households: { id: string; name: string }[];\n valid: boolean;\n pending: boolean;\n onSubmit: () => void;\n onOpenChange: (open: boolean) => void;\n translate: Translate;\n}\n\nfunction GoalFormDialog({\n open,\n mode,\n goalId,\n form,\n setField,\n households,\n valid,\n pending,\n onSubmit,\n onOpenChange,\n translate,\n}: GoalFormDialogProps) {\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 {mode === 'create'\n ? translate('brainyrich.goals.form.createTitle', 'New goal')\n : translate('brainyrich.goals.form.editTitle', 'Edit goal')}\n </DialogTitle>\n <DialogDescription>\n {translate(\n 'brainyrich.goals.form.subtitle',\n 'Define the milestone, target and contribution plan.'\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=\"goal-name\">{translate('brainyrich.goals.form.name', 'Name')}</Label>\n <Input\n id=\"goal-name\"\n value={form.name}\n onChange={(e) => setField('name', e.target.value)}\n placeholder={translate(\n 'brainyrich.goals.form.namePlaceholder',\n 'e.g. Retirement fund'\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=\"goal-type\">{translate('brainyrich.goals.form.type', 'Type')}</Label>\n <Select value={form.type} onValueChange={(v) => setField('type', v as BraGoalType)}>\n <SelectTrigger id=\"goal-type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {GOAL_TYPES.map((tpe) => (\n <SelectItem key={tpe} value={tpe}>\n {humanize(tpe)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n {mode === 'edit' ? (\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"goal-status\">\n {translate('brainyrich.goals.form.status', 'Status')}\n </Label>\n <Select\n value={form.status}\n onValueChange={(v) => setField('status', v as BraGoalStatus)}\n >\n <SelectTrigger id=\"goal-status\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {GOAL_STATUSES.map((st) => (\n <SelectItem key={st} value={st}>\n {humanize(st)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n ) : (\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"goal-priority\">\n {translate('brainyrich.goals.form.priority', 'Priority')}\n </Label>\n <Input\n id=\"goal-priority\"\n type=\"number\"\n min={1}\n value={form.priority}\n onChange={(e) => setField('priority', e.target.value)}\n />\n </div>\n )}\n </div>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"goal-target\">\n {translate('brainyrich.goals.form.targetAmount', 'Target amount')}\n </Label>\n <Input\n id=\"goal-target\"\n type=\"number\"\n min={0}\n step=\"0.01\"\n value={form.targetAmount}\n onChange={(e) => setField('targetAmount', e.target.value)}\n required\n />\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"goal-date\">\n {translate('brainyrich.goals.form.targetDate', 'Target date')}\n </Label>\n <Input\n id=\"goal-date\"\n type=\"date\"\n value={form.targetDate}\n onChange={(e) => setField('targetDate', e.target.value)}\n required\n />\n </div>\n </div>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"goal-monthly\">\n {translate('brainyrich.goals.form.monthly', 'Monthly contribution')}\n </Label>\n <Input\n id=\"goal-monthly\"\n type=\"number\"\n min={0}\n step=\"0.01\"\n value={form.monthlyContribution}\n onChange={(e) => setField('monthlyContribution', e.target.value)}\n />\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"goal-currency\">\n {translate('brainyrich.goals.form.currency', 'Currency')}\n </Label>\n <Input\n id=\"goal-currency\"\n value={form.currency}\n onChange={(e) => setField('currency', e.target.value.toUpperCase())}\n maxLength={3}\n />\n </div>\n </div>\n\n {mode === 'edit' ? (\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"goal-priority-edit\">\n {translate('brainyrich.goals.form.priority', 'Priority')}\n </Label>\n <Input\n id=\"goal-priority-edit\"\n type=\"number\"\n min={1}\n value={form.priority}\n onChange={(e) => setField('priority', e.target.value)}\n />\n </div>\n ) : null}\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"goal-household\">\n {translate('brainyrich.goals.form.household', 'Household (optional)')}\n </Label>\n <Select\n value={form.householdId || HOUSEHOLD_NONE}\n onValueChange={(v) => setField('householdId', v === HOUSEHOLD_NONE ? '' : v)}\n >\n <SelectTrigger id=\"goal-household\">\n <SelectValue\n placeholder={translate('brainyrich.goals.form.householdNone', 'None')}\n />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={HOUSEHOLD_NONE}>\n {translate('brainyrich.goals.form.householdNone', 'None')}\n </SelectItem>\n {households.map((h) => (\n <SelectItem key={h.id} value={h.id}>\n {h.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {mode === 'edit' && goalId ? (\n <TagField\n entityType=\"brainyrich-goal\"\n entityId={goalId}\n label={translate('brainyrich.goals.form.tags', 'Tags')}\n />\n ) : (\n <div className=\"space-y-1.5\">\n <Label>{translate('brainyrich.goals.form.tags', 'Tags')}</Label>\n <p className=\"text-sm text-text-secondary\">\n {translate(\n 'brainyrich.goals.form.tagsAfterCreate',\n 'You can add tags after creating the goal.'\n )}\n </p>\n </div>\n )}\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"goal-notes\">{translate('brainyrich.goals.form.notes', 'Notes')}</Label>\n <Textarea\n id=\"goal-notes\"\n value={form.notes}\n onChange={(e) => setField('notes', e.target.value)}\n rows={3}\n />\n </div>\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => onOpenChange(false)}\n disabled={pending}\n >\n {translate('brainyrich.goals.form.cancel', 'Cancel')}\n </Button>\n <Button type=\"submit\" disabled={!valid || pending}>\n {pending\n ? translate('brainyrich.goals.form.saving', 'Saving…')\n : mode === 'create'\n ? translate('brainyrich.goals.form.create', 'Create goal')\n : translate('brainyrich.goals.form.save', 'Save changes')}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n\ntype FundingMode = 'PERCENT' | 'FIXED';\n\ninterface GoalDetailSheetProps {\n goalId: string | null;\n onClose: () => void;\n translate: Translate;\n}\n\nfunction GoalDetailSheet({ goalId, onClose, translate }: GoalDetailSheetProps) {\n const { data: goal, isLoading, isError, refetch } = useGoal(goalId ?? undefined);\n const { data: fundings } = useGoalFundings(goalId ?? undefined);\n const { data: accounts } = useAccounts();\n\n const linkFunding = useLinkGoalFunding();\n const unlinkFunding = useUnlinkGoalFunding();\n const recalc = useRecalcGoalProjection();\n\n const [accountId, setAccountId] = useState('');\n const [fundingMode, setFundingMode] = useState<FundingMode>('PERCENT');\n const [fundingValue, setFundingValue] = useState('');\n const [fundedAmount, setFundedAmount] = useState('');\n const [unlinking, setUnlinking] = useState<BraGoalFunding | null>(null);\n\n const fixedFunded = fundings.reduce((s, f) => s + (f.fixedAmount ?? 0), 0);\n const currency = goal?.currency ?? 'USD';\n\n const accountName = (id: string) => accounts.find((a) => a.id === id)?.name ?? id;\n\n const handleLink = () => {\n if (!goalId || !accountId) return;\n const numeric = Number(fundingValue);\n if (!Number.isFinite(numeric) || numeric <= 0) return;\n linkFunding.mutate(\n {\n goalId,\n accountId,\n ...(fundingMode === 'PERCENT' ? { allocationPct: numeric } : { fixedAmount: numeric }),\n },\n {\n onSuccess: () => {\n setAccountId('');\n setFundingValue('');\n },\n }\n );\n };\n\n const handleRecalc = () => {\n if (!goalId) return;\n const amount = fundedAmount === '' ? fixedFunded : Number(fundedAmount);\n if (!Number.isFinite(amount)) return;\n recalc.mutate({ id: goalId, fundedAmount: amount });\n };\n\n const linkValid = Boolean(accountId) && Number(fundingValue) > 0;\n\n const unlinkingLabel = unlinking\n ? unlinking.fixedAmount != null\n ? formatMoney(unlinking.fixedAmount, currency)\n : accountName(unlinking.accountId)\n : '';\n\n return (\n <>\n <Sheet\n open={Boolean(goalId)}\n onOpenChange={(v) => {\n if (!v) onClose();\n }}\n >\n <SheetContent className=\"flex w-full flex-col gap-0 overflow-y-auto sm:max-w-md\">\n <SheetHeader>\n <SheetTitle>\n {goal?.name ?? translate('brainyrich.goals.detail.title', 'Goal')}\n </SheetTitle>\n <SheetDescription>\n {translate('brainyrich.goals.detail.subtitle', 'Manage funding links and projection.')}\n </SheetDescription>\n </SheetHeader>\n\n <div className=\"space-y-6 p-4\">\n {isLoading ? (\n <LoadingState rows={3} />\n ) : isError ? (\n <ErrorState\n title={translate('brainyrich.goals.detail.error', 'Could not load goal')}\n onRetry={() => refetch()}\n />\n ) : !goal ? (\n <EmptyState\n icon={<Target className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.goals.detail.notFound', 'Goal not found')}\n />\n ) : (\n <>\n <div className=\"grid grid-cols-2 gap-3\">\n <SummaryTile\n label={translate('brainyrich.goals.detail.target', 'Target')}\n value={formatMoney(goal.targetAmount, currency)}\n />\n <SummaryTile\n label={translate('brainyrich.goals.detail.funded', 'Funded (fixed)')}\n value={formatMoney(fixedFunded, currency)}\n />\n <SummaryTile\n label={translate('brainyrich.goals.detail.projection', 'Projection')}\n value={humanize(goal.projection)}\n tone={projectionMeta(goal.projection).tone}\n />\n <SummaryTile\n label={translate('brainyrich.goals.detail.targetDate', 'Target date')}\n value={formatDate(goal.targetDate)}\n />\n </div>\n\n {/* Fundings list */}\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {translate('brainyrich.goals.detail.fundingLinks', 'Funding links')}\n </h3>\n {fundings.length === 0 ? (\n <p className=\"rounded-lg border border-dashed border-border-subtle bg-bg-surface px-4 py-6 text-center text-sm text-text-secondary\">\n {translate(\n 'brainyrich.goals.detail.noFundings',\n 'No accounts linked to fund this goal yet.'\n )}\n </p>\n ) : (\n <ul className=\"space-y-2\">\n {fundings.map((f) => (\n <li\n key={f.id}\n className=\"flex items-center justify-between gap-2 rounded-lg border border-border-subtle bg-bg-surface px-3 py-2\"\n >\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {accountName(f.accountId)}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {f.fixedAmount != null\n ? formatMoney(f.fixedAmount, currency)\n : translate(\n 'brainyrich.goals.detail.pctOfAccount',\n '{pct}% of account',\n {\n pct: f.allocationPct,\n }\n )}\n </p>\n </div>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={translate('brainyrich.goals.detail.unlink', 'Unlink funding')}\n onClick={() => setUnlinking(f)}\n >\n <Unlink className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </li>\n ))}\n </ul>\n )}\n </section>\n\n {/* Link a new funding */}\n <section className=\"space-y-3 rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {translate('brainyrich.goals.detail.linkTitle', 'Link an account')}\n </h3>\n {accounts.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">\n {translate(\n 'brainyrich.goals.detail.noAccounts',\n 'No accounts available to link.'\n )}\n </p>\n ) : (\n <>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"funding-account\">\n {translate('brainyrich.goals.detail.account', 'Account')}\n </Label>\n <Select value={accountId} onValueChange={setAccountId}>\n <SelectTrigger id=\"funding-account\">\n <SelectValue\n placeholder={translate(\n 'brainyrich.goals.detail.selectAccount',\n 'Select account'\n )}\n />\n </SelectTrigger>\n <SelectContent>\n {accounts.map((a) => (\n <SelectItem key={a.id} value={a.id}>\n {a.name}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"funding-mode\">\n {translate('brainyrich.goals.detail.mode', 'Method')}\n </Label>\n <Select\n value={fundingMode}\n onValueChange={(v) => setFundingMode(v as FundingMode)}\n >\n <SelectTrigger id=\"funding-mode\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"PERCENT\">\n {translate('brainyrich.goals.detail.percent', 'Percentage')}\n </SelectItem>\n <SelectItem value=\"FIXED\">\n {translate('brainyrich.goals.detail.fixed', 'Fixed amount')}\n </SelectItem>\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"funding-value\">\n {fundingMode === 'PERCENT'\n ? translate('brainyrich.goals.detail.pct', 'Percent')\n : translate('brainyrich.goals.detail.amount', 'Amount')}\n </Label>\n <Input\n id=\"funding-value\"\n type=\"number\"\n min={0}\n step=\"0.01\"\n value={fundingValue}\n onChange={(e) => setFundingValue(e.target.value)}\n />\n </div>\n </div>\n <Button\n size=\"sm\"\n className=\"w-full\"\n disabled={!linkValid || linkFunding.isPending}\n onClick={handleLink}\n >\n <Link2 className=\"size-4\" aria-hidden=\"true\" />\n {linkFunding.isPending\n ? translate('brainyrich.goals.detail.linking', 'Linking…')\n : translate('brainyrich.goals.detail.link', 'Link funding')}\n </Button>\n </>\n )}\n </section>\n\n {/* Recalc projection */}\n <section className=\"space-y-3 rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {translate('brainyrich.goals.detail.recalcTitle', 'Recalculate projection')}\n </h3>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"recalc-funded\">\n {translate('brainyrich.goals.detail.fundedAmount', 'Funded amount')}\n </Label>\n <Input\n id=\"recalc-funded\"\n type=\"number\"\n min={0}\n step=\"0.01\"\n value={fundedAmount}\n placeholder={String(fixedFunded)}\n onChange={(e) => setFundedAmount(e.target.value)}\n />\n <p className=\"text-xs text-text-secondary\">\n {translate(\n 'brainyrich.goals.detail.recalcHint',\n 'Defaults to the sum of fixed fundings when left blank.'\n )}\n </p>\n </div>\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"w-full\"\n disabled={recalc.isPending}\n onClick={handleRecalc}\n >\n <RefreshCw className=\"size-4\" aria-hidden=\"true\" />\n {recalc.isPending\n ? translate('brainyrich.goals.detail.recalculating', 'Recalculating…')\n : translate('brainyrich.goals.detail.recalc', 'Recalculate')}\n </Button>\n </section>\n </>\n )}\n </div>\n </SheetContent>\n </Sheet>\n\n <ConfirmDialog\n open={Boolean(unlinking)}\n onOpenChange={(o) => {\n if (!o) setUnlinking(null);\n }}\n title={translate('brainyrich.goals.detail.unlinkTitle', 'Unlink funding?')}\n description={translate(\n 'brainyrich.goals.detail.unlinkConfirm',\n 'This removes the “{name}” funding link from this goal.',\n { name: unlinkingLabel }\n )}\n confirmLabel={translate('brainyrich.goals.detail.unlink', 'Unlink funding')}\n pendingLabel={translate('brainyrich.goals.detail.unlinking', 'Unlinking…')}\n destructive\n pending={unlinkFunding.isPending}\n onConfirm={() => {\n if (!unlinking) return;\n unlinkFunding.mutate(unlinking.id, { onSuccess: () => setUnlinking(null) });\n }}\n />\n </>\n );\n}\n\nfunction SummaryTile({ label, value, tone }: { label: string; value: string; tone?: string }) {\n return (\n <div className=\"rounded-lg bg-bg-sunken p-3\">\n <p className=\"text-xs text-text-secondary\">{label}</p>\n <p className={`text-sm font-semibold ${tone ?? 'text-text-primary'}`}>{value}</p>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"InvestmentsPage.js","names":[],"sources":["../../../src/brainyrich/pages/InvestmentsPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n CardDescription,\n Badge,\n Button,\n Input,\n Label,\n Textarea,\n Select,\n SelectTrigger,\n SelectValue,\n SelectContent,\n SelectItem,\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogDescription,\n DialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { PieChart, Plus, Trash2, X } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../utils/i18n';\nimport {\n useModelPortfolios,\n useModelPortfolio,\n useCreateModelPortfolio,\n} from '../hooks/useBrainyRichApi';\nimport type {\n BraAssetClass,\n BraRiskProfile,\n BraModelAllocationInput,\n} from '../types/bra';\nimport {\n SectionShell,\n KpiGrid,\n AllocationBars,\n EmptyState,\n LoadingState,\n ErrorState,\n formatDate,\n statusBadgeVariant,\n type AllocationDatum,\n} from './_shared';\n\n// ----------------------------------------------------------------------------\n// Enum option sets (mirror the SDL enums in ../types/bra) + humanizers.\n// No fabricated data: these are the exact allowed input values.\n// ----------------------------------------------------------------------------\n\nconst RISK_PROFILES: BraRiskProfile[] = [\n 'CONSERVATIVE',\n 'MODERATE',\n 'BALANCED',\n 'GROWTH',\n 'AGGRESSIVE',\n];\n\nconst ASSET_CLASSES: BraAssetClass[] = [\n 'EQUITY',\n 'FIXED_INCOME',\n 'CASH',\n 'REAL_ESTATE',\n 'COMMODITY',\n 'CRYPTO',\n 'ALTERNATIVE',\n];\n\n/** Turn an UPPER_SNAKE enum member into a readable label (derived, not invented). */\nfunction humanize(value: string): string {\n return value\n .toLowerCase()\n .split('_')\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(' ');\n}\n\nconst ALLOCATION_TONES: AllocationDatum['tone'][] = [\n 'accent',\n 'default',\n 'positive',\n 'warning',\n 'negative',\n];\n\ninterface AllocationRow {\n assetClass: BraAssetClass;\n targetPct: string;\n}\n\nconst emptyRow = (): AllocationRow => ({ assetClass: 'EQUITY', targetPct: '' });\n\nexport function InvestmentsPage() {\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 { data: models, isLoading, isError, refetch } = useModelPortfolios();\n const createModel = useCreateModelPortfolio();\n\n const [createOpen, setCreateOpen] = useState(false);\n const [detailId, setDetailId] = useState<string | null>(null);\n\n // -------- Create form state --------\n const [name, setName] = useState('');\n const [riskProfile, setRiskProfile] = useState<BraRiskProfile>('BALANCED');\n const [baseCurrency, setBaseCurrency] = useState('USD');\n const [description, setDescription] = useState('');\n const [rows, setRows] = useState<AllocationRow[]>([emptyRow()]);\n const [formError, setFormError] = useState<string | null>(null);\n\n const resetForm = () => {\n setName('');\n setRiskProfile('BALANCED');\n setBaseCurrency('USD');\n setDescription('');\n setRows([emptyRow()]);\n setFormError(null);\n };\n\n const allocationSum = useMemo(\n () => rows.reduce((s, r) => s + (Number.isFinite(parseFloat(r.targetPct)) ? parseFloat(r.targetPct) : 0), 0),\n [rows]\n );\n\n const updateRow = (index: number, patch: Partial<AllocationRow>) => {\n setRows((prev) => prev.map((r, i) => (i === index ? { ...r, ...patch } : r)));\n };\n const addRow = () => setRows((prev) => [...prev, emptyRow()]);\n const removeRow = (index: number) =>\n setRows((prev) => (prev.length > 1 ? prev.filter((_, i) => i !== index) : prev));\n\n const handleSubmit = () => {\n setFormError(null);\n const trimmedName = name.trim();\n if (!trimmedName) {\n setFormError(translate('brainyrich.investments.form.errorName', 'A model name is required.'));\n return;\n }\n const allocations: BraModelAllocationInput[] = [];\n for (const r of rows) {\n const pct = parseFloat(r.targetPct);\n if (!r.targetPct.trim() || !Number.isFinite(pct)) {\n setFormError(\n translate(\n 'brainyrich.investments.form.errorPct',\n 'Every allocation row needs a numeric target %.'\n )\n );\n return;\n }\n if (pct < 0) {\n setFormError(\n translate('brainyrich.investments.form.errorNegative', 'Target % cannot be negative.')\n );\n return;\n }\n allocations.push({ assetClass: r.assetClass, targetPct: pct });\n }\n if (Math.abs(allocationSum - 100) > 0.5) {\n setFormError(\n translate('brainyrich.investments.form.errorSum', 'Allocation targets must sum to ~100% (currently {sum}%).', {\n sum: allocationSum.toFixed(1),\n })\n );\n return;\n }\n\n createModel.mutate(\n {\n name: trimmedName,\n riskProfile,\n baseCurrency: baseCurrency.trim() || 'USD',\n description: description.trim() ? description.trim() : null,\n allocations,\n },\n {\n onSuccess: () => {\n setCreateOpen(false);\n resetForm();\n },\n onError: (err: unknown) => {\n setFormError(\n err instanceof Error\n ? err.message\n : translate('brainyrich.investments.form.errorGeneric', 'Could not create the model.')\n );\n },\n }\n );\n };\n\n const title = translate('brainyrich.investments.title', 'Model Portfolios');\n const description2 = translate(\n 'brainyrich.investments.description',\n 'Reusable target allocations you can benchmark and drive rebalancing against'\n );\n\n const activeCount = models.filter((m) => m.isActive).length;\n const riskCount = new Set(models.map((m) => m.riskProfile)).size;\n const classCount = new Set(models.flatMap((m) => m.allocations.map((a) => a.assetClass))).size;\n const kpis = [\n {\n label: translate('brainyrich.investments.kpi.total', 'Model portfolios'),\n value: String(models.length),\n },\n {\n label: translate('brainyrich.investments.kpi.active', 'Active'),\n value: String(activeCount),\n },\n {\n label: translate('brainyrich.investments.kpi.risk', 'Risk profiles'),\n value: String(riskCount),\n },\n {\n label: translate('brainyrich.investments.kpi.classes', 'Asset classes'),\n value: String(classCount),\n },\n ];\n\n const newModelLabel = translate('brainyrich.investments.actions.newModel', 'New model');\n\n const renderBody = () => {\n if (isLoading) return <LoadingState rows={4} />;\n if (isError)\n return (\n <ErrorState\n title={translate('brainyrich.investments.error.title', 'Could not load model portfolios')}\n onRetry={() => refetch()}\n />\n );\n if (models.length === 0)\n return (\n <EmptyState\n icon={<PieChart className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.investments.empty.title', 'No model portfolios yet')}\n description={translate(\n 'brainyrich.investments.empty.description',\n 'Create a target allocation model to benchmark portfolios and drive rebalancing.'\n )}\n action={\n <Button size=\"sm\" onClick={() => setCreateOpen(true)}>\n <Plus className=\"mr-1 size-4\" aria-hidden=\"true\" />\n {newModelLabel}\n </Button>\n }\n />\n );\n\n return (\n <div className=\"grid gap-4 md:grid-cols-2 xl:grid-cols-3\">\n {models.map((m) => {\n const bars: AllocationDatum[] = m.allocations.map((a, i) => ({\n label: humanize(a.assetClass),\n value: a.targetPct,\n tone: ALLOCATION_TONES[i % ALLOCATION_TONES.length],\n }));\n return (\n <Card key={m.id} className=\"flex flex-col\">\n <CardHeader className=\"space-y-2\">\n <div className=\"flex items-start justify-between gap-2\">\n <CardTitle className=\"text-base text-text-primary\">{m.name}</CardTitle>\n <Badge variant={m.isActive ? statusBadgeVariant('ACTIVE') : 'secondary'}>\n {m.isActive\n ? translate('brainyrich.investments.badge.active', 'Active')\n : translate('brainyrich.investments.badge.inactive', 'Inactive')}\n </Badge>\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n <Badge variant=\"outline\">{humanize(m.riskProfile)}</Badge>\n <Badge variant=\"outline\">{m.baseCurrency}</Badge>\n </div>\n {m.description ? (\n <CardDescription className=\"text-text-secondary\">{m.description}</CardDescription>\n ) : null}\n </CardHeader>\n <CardContent className=\"mt-auto space-y-4\">\n {bars.length > 0 ? (\n <AllocationBars data={bars} />\n ) : (\n <p className=\"text-sm text-text-secondary\">\n {translate('brainyrich.investments.card.noAllocations', 'No target allocations set.')}\n </p>\n )}\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"w-full\"\n onClick={() => setDetailId(m.id)}\n >\n {translate('brainyrich.investments.actions.viewDetails', 'View details')}\n </Button>\n </CardContent>\n </Card>\n );\n })}\n </div>\n );\n };\n\n return (\n <>\n <SectionShell\n title={title}\n description={description2}\n actionLabel={newModelLabel}\n onAction={() => setCreateOpen(true)}\n badges={\n !isLoading && !isError\n ? [\n translate('brainyrich.investments.badges.count', '{count} models', {\n count: models.length,\n }),\n ]\n : []\n }\n >\n {!isLoading && !isError && models.length > 0 ? <KpiGrid items={kpis} /> : null}\n {renderBody()}\n </SectionShell>\n\n {/* ---------------- Create model dialog ---------------- */}\n <Dialog\n open={createOpen}\n onOpenChange={(open) => {\n setCreateOpen(open);\n if (!open) resetForm();\n }}\n >\n <DialogContent className=\"max-h-[90vh] overflow-y-auto sm:max-w-lg\">\n <DialogHeader>\n <DialogTitle>{newModelLabel}</DialogTitle>\n <DialogDescription>\n {translate(\n 'brainyrich.investments.form.subtitle',\n 'Define a target allocation. Targets should sum to about 100%.'\n )}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-4 py-2\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-model-name\">\n {translate('brainyrich.investments.form.name', 'Name')}\n </Label>\n <Input\n id=\"bra-model-name\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder={translate('brainyrich.investments.form.namePlaceholder', 'Balanced Growth 60/40')}\n />\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-model-risk\">\n {translate('brainyrich.investments.form.risk', 'Risk profile')}\n </Label>\n <Select\n value={riskProfile}\n onValueChange={(v) => setRiskProfile(v as BraRiskProfile)}\n >\n <SelectTrigger id=\"bra-model-risk\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {RISK_PROFILES.map((r) => (\n <SelectItem key={r} value={r}>\n {humanize(r)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-model-currency\">\n {translate('brainyrich.investments.form.currency', 'Base currency')}\n </Label>\n <Input\n id=\"bra-model-currency\"\n value={baseCurrency}\n onChange={(e) => setBaseCurrency(e.target.value.toUpperCase().slice(0, 3))}\n placeholder=\"USD\"\n />\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-model-desc\">\n {translate('brainyrich.investments.form.description', 'Description')}\n </Label>\n <Textarea\n id=\"bra-model-desc\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n rows={2}\n placeholder={translate(\n 'brainyrich.investments.form.descriptionPlaceholder',\n 'Who this model is for and how it is used'\n )}\n />\n </div>\n\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between\">\n <Label>{translate('brainyrich.investments.form.allocations', 'Target allocations')}</Label>\n <span\n className={\n Math.abs(allocationSum - 100) <= 0.5\n ? 'text-xs font-medium text-status-success-text'\n : 'text-xs font-medium text-status-warning-text'\n }\n >\n {translate('brainyrich.investments.form.sum', 'Sum: {sum}%', {\n sum: allocationSum.toFixed(1),\n })}\n </span>\n </div>\n <div className=\"space-y-2\">\n {rows.map((r, i) => (\n <div key={i} className=\"flex items-center gap-2\">\n <Select\n value={r.assetClass}\n onValueChange={(v) => updateRow(i, { assetClass: v as BraAssetClass })}\n >\n <SelectTrigger className=\"flex-1\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {ASSET_CLASSES.map((c) => (\n <SelectItem key={c} value={c}>\n {humanize(c)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Input\n type=\"number\"\n inputMode=\"decimal\"\n min={0}\n max={100}\n step=\"0.1\"\n className=\"w-24\"\n value={r.targetPct}\n onChange={(e) => updateRow(i, { targetPct: e.target.value })}\n placeholder=\"%\"\n aria-label={translate('brainyrich.investments.form.targetPct', 'Target percent')}\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => removeRow(i)}\n disabled={rows.length <= 1}\n aria-label={translate('brainyrich.investments.form.removeRow', 'Remove allocation row')}\n >\n <Trash2 className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </div>\n ))}\n </div>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={addRow}>\n <Plus className=\"mr-1 size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.investments.form.addRow', 'Add asset class')}\n </Button>\n </div>\n\n {formError ? (\n <p className=\"text-sm text-status-error-text\" role=\"alert\">\n {formError}\n </p>\n ) : null}\n </div>\n\n <DialogFooter>\n <Button\n variant=\"outline\"\n onClick={() => {\n setCreateOpen(false);\n resetForm();\n }}\n disabled={createModel.isPending}\n >\n {translate('brainyrich.investments.form.cancel', 'Cancel')}\n </Button>\n <Button onClick={handleSubmit} disabled={createModel.isPending}>\n {createModel.isPending\n ? translate('brainyrich.investments.form.saving', 'Creating…')\n : translate('brainyrich.investments.form.create', 'Create model')}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n\n {/* ---------------- Detail dialog ---------------- */}\n <ModelDetailDialog\n id={detailId}\n onClose={() => setDetailId(null)}\n translate={translate}\n />\n </>\n );\n}\n\n// ----------------------------------------------------------------------------\n// Detail dialog — reads the single model via useModelPortfolio(id).\n// ----------------------------------------------------------------------------\n\nfunction ModelDetailDialog({\n id,\n onClose,\n translate,\n}: {\n id: string | null;\n onClose: () => void;\n translate: (key: string, fallback: string, params?: Record<string, string | number>) => string;\n}) {\n const { data: model, isLoading, isError, refetch } = useModelPortfolio(id ?? undefined);\n\n const bars: AllocationDatum[] = (model?.allocations ?? []).map((a, i) => ({\n label: humanize(a.assetClass),\n value: a.targetPct,\n tone: ALLOCATION_TONES[i % ALLOCATION_TONES.length],\n }));\n\n return (\n <Dialog open={Boolean(id)} onOpenChange={(open) => (!open ? onClose() : undefined)}>\n <DialogContent className=\"max-h-[90vh] overflow-y-auto sm:max-w-lg\">\n <DialogHeader>\n <DialogTitle className=\"flex items-center justify-between gap-2 pr-6\">\n {model?.name ??\n translate('brainyrich.investments.detail.title', 'Model portfolio')}\n </DialogTitle>\n {model?.description ? (\n <DialogDescription>{model.description}</DialogDescription>\n ) : null}\n </DialogHeader>\n\n {isLoading ? (\n <LoadingState rows={3} />\n ) : isError ? (\n <ErrorState\n title={translate('brainyrich.investments.detail.error', 'Could not load this model')}\n onRetry={() => refetch()}\n />\n ) : !model ? (\n <EmptyState\n icon={<X className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.investments.detail.notFound', 'Model not found')}\n />\n ) : (\n <div className=\"space-y-5 py-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <Badge variant={model.isActive ? statusBadgeVariant('ACTIVE') : 'secondary'}>\n {model.isActive\n ? translate('brainyrich.investments.badge.active', 'Active')\n : translate('brainyrich.investments.badge.inactive', 'Inactive')}\n </Badge>\n <Badge variant=\"outline\">{humanize(model.riskProfile)}</Badge>\n <Badge variant=\"outline\">{model.baseCurrency}</Badge>\n </div>\n\n <div>\n <p className=\"mb-2 text-sm font-medium text-text-primary\">\n {translate('brainyrich.investments.detail.allocations', 'Target allocations')}\n </p>\n {bars.length > 0 ? (\n <AllocationBars data={bars} />\n ) : (\n <p className=\"text-sm text-text-secondary\">\n {translate('brainyrich.investments.card.noAllocations', 'No target allocations set.')}\n </p>\n )}\n </div>\n\n <dl className=\"grid grid-cols-2 gap-4 border-t border-border-subtle pt-4 text-sm\">\n <div>\n <dt className=\"text-text-secondary\">\n {translate('brainyrich.investments.detail.created', 'Created')}\n </dt>\n <dd className=\"text-text-primary\">{formatDate(model.createdAt)}</dd>\n </div>\n <div>\n <dt className=\"text-text-secondary\">\n {translate('brainyrich.investments.detail.updated', 'Updated')}\n </dt>\n <dd className=\"text-text-primary\">{formatDate(model.updatedAt)}</dd>\n </div>\n </dl>\n </div>\n )}\n\n <DialogFooter>\n <Button variant=\"outline\" onClick={onClose}>\n {translate('brainyrich.investments.detail.close', 'Close')}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"InvestmentsPage.js","names":[],"sources":["../../../src/brainyrich/pages/InvestmentsPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n CardDescription,\n Badge,\n Button,\n Input,\n Label,\n Textarea,\n Select,\n SelectTrigger,\n SelectValue,\n SelectContent,\n SelectItem,\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogDescription,\n DialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { PieChart, Plus, Trash2, X } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../utils/i18n';\nimport {\n useModelPortfolios,\n useModelPortfolio,\n useCreateModelPortfolio,\n} from '../hooks/useBrainyRichApi';\nimport type { BraAssetClass, BraRiskProfile, BraModelAllocationInput } from '../types/bra';\nimport {\n SectionShell,\n KpiGrid,\n AllocationBars,\n EmptyState,\n LoadingState,\n ErrorState,\n formatDate,\n statusBadgeVariant,\n type AllocationDatum,\n} from './_shared';\n\n// ----------------------------------------------------------------------------\n// Enum option sets (mirror the SDL enums in ../types/bra) + humanizers.\n// No fabricated data: these are the exact allowed input values.\n// ----------------------------------------------------------------------------\n\nconst RISK_PROFILES: BraRiskProfile[] = [\n 'CONSERVATIVE',\n 'MODERATE',\n 'BALANCED',\n 'GROWTH',\n 'AGGRESSIVE',\n];\n\nconst ASSET_CLASSES: BraAssetClass[] = [\n 'EQUITY',\n 'FIXED_INCOME',\n 'CASH',\n 'REAL_ESTATE',\n 'COMMODITY',\n 'CRYPTO',\n 'ALTERNATIVE',\n];\n\n/** Turn an UPPER_SNAKE enum member into a readable label (derived, not invented). */\nfunction humanize(value: string): string {\n return value\n .toLowerCase()\n .split('_')\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(' ');\n}\n\nconst ALLOCATION_TONES: AllocationDatum['tone'][] = [\n 'accent',\n 'default',\n 'positive',\n 'warning',\n 'negative',\n];\n\ninterface AllocationRow {\n assetClass: BraAssetClass;\n targetPct: string;\n}\n\nconst emptyRow = (): AllocationRow => ({ assetClass: 'EQUITY', targetPct: '' });\n\nexport function InvestmentsPage() {\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 { data: models, isLoading, isError, refetch } = useModelPortfolios();\n const createModel = useCreateModelPortfolio();\n\n const [createOpen, setCreateOpen] = useState(false);\n const [detailId, setDetailId] = useState<string | null>(null);\n\n // -------- Create form state --------\n const [name, setName] = useState('');\n const [riskProfile, setRiskProfile] = useState<BraRiskProfile>('BALANCED');\n const [baseCurrency, setBaseCurrency] = useState('USD');\n const [description, setDescription] = useState('');\n const [rows, setRows] = useState<AllocationRow[]>([emptyRow()]);\n const [formError, setFormError] = useState<string | null>(null);\n\n const resetForm = () => {\n setName('');\n setRiskProfile('BALANCED');\n setBaseCurrency('USD');\n setDescription('');\n setRows([emptyRow()]);\n setFormError(null);\n };\n\n const allocationSum = useMemo(\n () =>\n rows.reduce(\n (s, r) => s + (Number.isFinite(parseFloat(r.targetPct)) ? parseFloat(r.targetPct) : 0),\n 0\n ),\n [rows]\n );\n\n const updateRow = (index: number, patch: Partial<AllocationRow>) => {\n setRows((prev) => prev.map((r, i) => (i === index ? { ...r, ...patch } : r)));\n };\n const addRow = () => setRows((prev) => [...prev, emptyRow()]);\n const removeRow = (index: number) =>\n setRows((prev) => (prev.length > 1 ? prev.filter((_, i) => i !== index) : prev));\n\n const handleSubmit = () => {\n setFormError(null);\n const trimmedName = name.trim();\n if (!trimmedName) {\n setFormError(translate('brainyrich.investments.form.errorName', 'A model name is required.'));\n return;\n }\n const allocations: BraModelAllocationInput[] = [];\n for (const r of rows) {\n const pct = parseFloat(r.targetPct);\n if (!r.targetPct.trim() || !Number.isFinite(pct)) {\n setFormError(\n translate(\n 'brainyrich.investments.form.errorPct',\n 'Every allocation row needs a numeric target %.'\n )\n );\n return;\n }\n if (pct < 0) {\n setFormError(\n translate('brainyrich.investments.form.errorNegative', 'Target % cannot be negative.')\n );\n return;\n }\n allocations.push({ assetClass: r.assetClass, targetPct: pct });\n }\n if (Math.abs(allocationSum - 100) > 0.5) {\n setFormError(\n translate(\n 'brainyrich.investments.form.errorSum',\n 'Allocation targets must sum to ~100% (currently {sum}%).',\n {\n sum: allocationSum.toFixed(1),\n }\n )\n );\n return;\n }\n\n createModel.mutate(\n {\n name: trimmedName,\n riskProfile,\n baseCurrency: baseCurrency.trim() || 'USD',\n description: description.trim() ? description.trim() : null,\n allocations,\n },\n {\n onSuccess: () => {\n setCreateOpen(false);\n resetForm();\n },\n onError: (err: unknown) => {\n setFormError(\n err instanceof Error\n ? err.message\n : translate('brainyrich.investments.form.errorGeneric', 'Could not create the model.')\n );\n },\n }\n );\n };\n\n const title = translate('brainyrich.investments.title', 'Model Portfolios');\n const description2 = translate(\n 'brainyrich.investments.description',\n 'Reusable target allocations you can benchmark and drive rebalancing against'\n );\n\n const activeCount = models.filter((m) => m.isActive).length;\n const riskCount = new Set(models.map((m) => m.riskProfile)).size;\n const classCount = new Set(models.flatMap((m) => m.allocations.map((a) => a.assetClass))).size;\n const kpis = [\n {\n label: translate('brainyrich.investments.kpi.total', 'Model portfolios'),\n value: String(models.length),\n },\n {\n label: translate('brainyrich.investments.kpi.active', 'Active'),\n value: String(activeCount),\n },\n {\n label: translate('brainyrich.investments.kpi.risk', 'Risk profiles'),\n value: String(riskCount),\n },\n {\n label: translate('brainyrich.investments.kpi.classes', 'Asset classes'),\n value: String(classCount),\n },\n ];\n\n const newModelLabel = translate('brainyrich.investments.actions.newModel', 'New model');\n\n const renderBody = () => {\n if (isLoading) return <LoadingState rows={4} />;\n if (isError)\n return (\n <ErrorState\n title={translate('brainyrich.investments.error.title', 'Could not load model portfolios')}\n onRetry={() => refetch()}\n />\n );\n if (models.length === 0)\n return (\n <EmptyState\n icon={<PieChart className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.investments.empty.title', 'No model portfolios yet')}\n description={translate(\n 'brainyrich.investments.empty.description',\n 'Create a target allocation model to benchmark portfolios and drive rebalancing.'\n )}\n action={\n <Button size=\"sm\" onClick={() => setCreateOpen(true)}>\n <Plus className=\"mr-1 size-4\" aria-hidden=\"true\" />\n {newModelLabel}\n </Button>\n }\n />\n );\n\n return (\n <div className=\"grid gap-4 md:grid-cols-2 xl:grid-cols-3\">\n {models.map((m) => {\n const bars: AllocationDatum[] = m.allocations.map((a, i) => ({\n label: humanize(a.assetClass),\n value: a.targetPct,\n tone: ALLOCATION_TONES[i % ALLOCATION_TONES.length],\n }));\n return (\n <Card key={m.id} className=\"flex flex-col\">\n <CardHeader className=\"space-y-2\">\n <div className=\"flex items-start justify-between gap-2\">\n <CardTitle className=\"text-base text-text-primary\">{m.name}</CardTitle>\n <Badge variant={m.isActive ? statusBadgeVariant('ACTIVE') : 'secondary'}>\n {m.isActive\n ? translate('brainyrich.investments.badge.active', 'Active')\n : translate('brainyrich.investments.badge.inactive', 'Inactive')}\n </Badge>\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n <Badge variant=\"outline\">{humanize(m.riskProfile)}</Badge>\n <Badge variant=\"outline\">{m.baseCurrency}</Badge>\n </div>\n {m.description ? (\n <CardDescription className=\"text-text-secondary\">{m.description}</CardDescription>\n ) : null}\n </CardHeader>\n <CardContent className=\"mt-auto space-y-4\">\n {bars.length > 0 ? (\n <AllocationBars data={bars} />\n ) : (\n <p className=\"text-sm text-text-secondary\">\n {translate(\n 'brainyrich.investments.card.noAllocations',\n 'No target allocations set.'\n )}\n </p>\n )}\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"w-full\"\n onClick={() => setDetailId(m.id)}\n >\n {translate('brainyrich.investments.actions.viewDetails', 'View details')}\n </Button>\n </CardContent>\n </Card>\n );\n })}\n </div>\n );\n };\n\n return (\n <>\n <SectionShell\n title={title}\n description={description2}\n actionLabel={newModelLabel}\n onAction={() => setCreateOpen(true)}\n badges={\n !isLoading && !isError\n ? [\n translate('brainyrich.investments.badges.count', '{count} models', {\n count: models.length,\n }),\n ]\n : []\n }\n >\n {!isLoading && !isError && models.length > 0 ? <KpiGrid items={kpis} /> : null}\n {renderBody()}\n </SectionShell>\n\n {/* ---------------- Create model dialog ---------------- */}\n <Dialog\n open={createOpen}\n onOpenChange={(open) => {\n setCreateOpen(open);\n if (!open) resetForm();\n }}\n >\n <DialogContent className=\"max-h-[90vh] overflow-y-auto sm:max-w-lg\">\n <DialogHeader>\n <DialogTitle>{newModelLabel}</DialogTitle>\n <DialogDescription>\n {translate(\n 'brainyrich.investments.form.subtitle',\n 'Define a target allocation. Targets should sum to about 100%.'\n )}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-4 py-2\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-model-name\">\n {translate('brainyrich.investments.form.name', 'Name')}\n </Label>\n <Input\n id=\"bra-model-name\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder={translate(\n 'brainyrich.investments.form.namePlaceholder',\n 'Balanced Growth 60/40'\n )}\n />\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-model-risk\">\n {translate('brainyrich.investments.form.risk', 'Risk profile')}\n </Label>\n <Select\n value={riskProfile}\n onValueChange={(v) => setRiskProfile(v as BraRiskProfile)}\n >\n <SelectTrigger id=\"bra-model-risk\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {RISK_PROFILES.map((r) => (\n <SelectItem key={r} value={r}>\n {humanize(r)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-model-currency\">\n {translate('brainyrich.investments.form.currency', 'Base currency')}\n </Label>\n <Input\n id=\"bra-model-currency\"\n value={baseCurrency}\n onChange={(e) => setBaseCurrency(e.target.value.toUpperCase().slice(0, 3))}\n placeholder=\"USD\"\n />\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-model-desc\">\n {translate('brainyrich.investments.form.description', 'Description')}\n </Label>\n <Textarea\n id=\"bra-model-desc\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n rows={2}\n placeholder={translate(\n 'brainyrich.investments.form.descriptionPlaceholder',\n 'Who this model is for and how it is used'\n )}\n />\n </div>\n\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between\">\n <Label>\n {translate('brainyrich.investments.form.allocations', 'Target allocations')}\n </Label>\n <span\n className={\n Math.abs(allocationSum - 100) <= 0.5\n ? 'text-xs font-medium text-status-success-text'\n : 'text-xs font-medium text-status-warning-text'\n }\n >\n {translate('brainyrich.investments.form.sum', 'Sum: {sum}%', {\n sum: allocationSum.toFixed(1),\n })}\n </span>\n </div>\n <div className=\"space-y-2\">\n {rows.map((r, i) => (\n <div key={i} className=\"flex items-center gap-2\">\n <Select\n value={r.assetClass}\n onValueChange={(v) => updateRow(i, { assetClass: v as BraAssetClass })}\n >\n <SelectTrigger className=\"flex-1\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {ASSET_CLASSES.map((c) => (\n <SelectItem key={c} value={c}>\n {humanize(c)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Input\n type=\"number\"\n inputMode=\"decimal\"\n min={0}\n max={100}\n step=\"0.1\"\n className=\"w-24\"\n value={r.targetPct}\n onChange={(e) => updateRow(i, { targetPct: e.target.value })}\n placeholder=\"%\"\n aria-label={translate(\n 'brainyrich.investments.form.targetPct',\n 'Target percent'\n )}\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => removeRow(i)}\n disabled={rows.length <= 1}\n aria-label={translate(\n 'brainyrich.investments.form.removeRow',\n 'Remove allocation row'\n )}\n >\n <Trash2 className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </div>\n ))}\n </div>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={addRow}>\n <Plus className=\"mr-1 size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.investments.form.addRow', 'Add asset class')}\n </Button>\n </div>\n\n {formError ? (\n <p className=\"text-sm text-status-error-text\" role=\"alert\">\n {formError}\n </p>\n ) : null}\n </div>\n\n <DialogFooter>\n <Button\n variant=\"outline\"\n onClick={() => {\n setCreateOpen(false);\n resetForm();\n }}\n disabled={createModel.isPending}\n >\n {translate('brainyrich.investments.form.cancel', 'Cancel')}\n </Button>\n <Button onClick={handleSubmit} disabled={createModel.isPending}>\n {createModel.isPending\n ? translate('brainyrich.investments.form.saving', 'Creating…')\n : translate('brainyrich.investments.form.create', 'Create model')}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n\n {/* ---------------- Detail dialog ---------------- */}\n <ModelDetailDialog id={detailId} onClose={() => setDetailId(null)} translate={translate} />\n </>\n );\n}\n\n// ----------------------------------------------------------------------------\n// Detail dialog — reads the single model via useModelPortfolio(id).\n// ----------------------------------------------------------------------------\n\nfunction ModelDetailDialog({\n id,\n onClose,\n translate,\n}: {\n id: string | null;\n onClose: () => void;\n translate: (key: string, fallback: string, params?: Record<string, string | number>) => string;\n}) {\n const { data: model, isLoading, isError, refetch } = useModelPortfolio(id ?? undefined);\n\n const bars: AllocationDatum[] = (model?.allocations ?? []).map((a, i) => ({\n label: humanize(a.assetClass),\n value: a.targetPct,\n tone: ALLOCATION_TONES[i % ALLOCATION_TONES.length],\n }));\n\n return (\n <Dialog open={Boolean(id)} onOpenChange={(open) => (!open ? onClose() : undefined)}>\n <DialogContent className=\"max-h-[90vh] overflow-y-auto sm:max-w-lg\">\n <DialogHeader>\n <DialogTitle className=\"flex items-center justify-between gap-2 pr-6\">\n {model?.name ?? translate('brainyrich.investments.detail.title', 'Model portfolio')}\n </DialogTitle>\n {model?.description ? <DialogDescription>{model.description}</DialogDescription> : null}\n </DialogHeader>\n\n {isLoading ? (\n <LoadingState rows={3} />\n ) : isError ? (\n <ErrorState\n title={translate('brainyrich.investments.detail.error', 'Could not load this model')}\n onRetry={() => refetch()}\n />\n ) : !model ? (\n <EmptyState\n icon={<X className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.investments.detail.notFound', 'Model not found')}\n />\n ) : (\n <div className=\"space-y-5 py-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <Badge variant={model.isActive ? statusBadgeVariant('ACTIVE') : 'secondary'}>\n {model.isActive\n ? translate('brainyrich.investments.badge.active', 'Active')\n : translate('brainyrich.investments.badge.inactive', 'Inactive')}\n </Badge>\n <Badge variant=\"outline\">{humanize(model.riskProfile)}</Badge>\n <Badge variant=\"outline\">{model.baseCurrency}</Badge>\n </div>\n\n <div>\n <p className=\"mb-2 text-sm font-medium text-text-primary\">\n {translate('brainyrich.investments.detail.allocations', 'Target allocations')}\n </p>\n {bars.length > 0 ? (\n <AllocationBars data={bars} />\n ) : (\n <p className=\"text-sm text-text-secondary\">\n {translate(\n 'brainyrich.investments.card.noAllocations',\n 'No target allocations set.'\n )}\n </p>\n )}\n </div>\n\n <dl className=\"grid grid-cols-2 gap-4 border-t border-border-subtle pt-4 text-sm\">\n <div>\n <dt className=\"text-text-secondary\">\n {translate('brainyrich.investments.detail.created', 'Created')}\n </dt>\n <dd className=\"text-text-primary\">{formatDate(model.createdAt)}</dd>\n </div>\n <div>\n <dt className=\"text-text-secondary\">\n {translate('brainyrich.investments.detail.updated', 'Updated')}\n </dt>\n <dd className=\"text-text-primary\">{formatDate(model.updatedAt)}</dd>\n </div>\n </dl>\n </div>\n )}\n\n <DialogFooter>\n <Button variant=\"outline\" onClick={onClose}>\n {translate('brainyrich.investments.detail.close', 'Close')}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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"}