@burdenoff/microfe-brainyrich 2026.828.1 → 2026.828.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/brainyrich/BrainyRichRoot.d.ts.map +1 -1
- package/dist/brainyrich/BrainyRichRoot.js +59 -59
- package/dist/brainyrich/BrainyRichRoot.js.map +1 -1
- package/dist/brainyrich/components/viz.d.ts.map +1 -1
- package/dist/brainyrich/components/viz.js +1 -1
- package/dist/brainyrich/components/viz.js.map +1 -1
- package/dist/brainyrich/pages/AiAssistantPage.js +192 -192
- package/dist/brainyrich/pages/AiAssistantPage.js.map +1 -1
- package/dist/brainyrich/pages/AnalyticsPage.js +9 -9
- package/dist/brainyrich/pages/AnalyticsPage.js.map +1 -1
- package/dist/brainyrich/pages/DashboardPage.js +115 -115
- package/dist/brainyrich/pages/DashboardPage.js.map +1 -1
- package/dist/brainyrich/pages/FamilyPage.js +59 -59
- package/dist/brainyrich/pages/FamilyPage.js.map +1 -1
- package/dist/brainyrich/pages/GoalsPage.js +285 -285
- package/dist/brainyrich/pages/GoalsPage.js.map +1 -1
- package/dist/brainyrich/pages/InvestmentsPage.js +18 -18
- package/dist/brainyrich/pages/InvestmentsPage.js.map +1 -1
- package/dist/brainyrich/pages/PortfoliosPage.d.ts.map +1 -1
- package/dist/brainyrich/pages/PortfoliosPage.js +322 -322
- package/dist/brainyrich/pages/PortfoliosPage.js.map +1 -1
- package/dist/brainyrich/pages/ReportsPage.js +17 -17
- package/dist/brainyrich/pages/ReportsPage.js.map +1 -1
- package/dist/brainyrich/pages/RiskPage.js +16 -16
- package/dist/brainyrich/pages/RiskPage.js.map +1 -1
- package/dist/brainyrich/pages/TaxPage.d.ts.map +1 -1
- package/dist/brainyrich/pages/TaxPage.js +14 -14
- package/dist/brainyrich/pages/TaxPage.js.map +1 -1
- package/dist/brainyrich/types/bra.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -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 Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n AlertTriangle,\n CalendarClock,\n Coins,\n Link2,\n LineChart,\n MoreHorizontal,\n PiggyBank,\n Plus,\n RefreshCw,\n Target,\n Trash2,\n TrendingDown,\n TrendingUp,\n Unlink,\n Wallet,\n} from 'lucide-react';\nimport { tWithFallback } from '../utils/i18n';\nimport {\n ConfirmDialog,\n FadeIn,\n GlassCard,\n LoadMore,\n MiniAreaChart,\n ProgressRing,\n StatTile,\n type AreaDatum,\n type VizTone,\n} from '../components';\nimport { TagField } from '../components/reuse/TagField';\nimport { hapticSuccess, showToast } from '../utils/nativeControls';\nimport { useTrackBrainyRichPageView } from '../hooks/useBrainyRichAnalytics';\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 LoadingState,\n SectionShell,\n formatCompact,\n formatDate,\n formatMoney,\n formatPct,\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/** Sum of the fixed-amount funding links wired to a goal (real backend value). */\nfunction goalFixedFunded(goal: Pick<BraGoal, 'fundings'>): number {\n return goal.fundings.reduce((s, f) => s + (f.fixedAmount ?? 0), 0);\n}\n\n/**\n * Funded-progress percentage for a goal. ACHIEVED goals read 100%; otherwise the\n * sum of fixed funding links over the target — every input is wired backend data,\n * never fabricated.\n */\nfunction fundedPercent(goal: Pick<BraGoal, 'fundings' | 'targetAmount' | 'status'>): number {\n if (goal.status === 'ACHIEVED') return 100;\n if (!(goal.targetAmount > 0)) return 0;\n return Math.max(0, Math.min(100, (goalFixedFunded(goal) / goal.targetAmount) * 100));\n}\n\n/** Ring/accent tone derived from the goal's real status + projection. */\nfunction goalTone(status: BraGoalStatus, projection: BraGoalProjection): VizTone {\n if (status === 'ACHIEVED') return 'success';\n switch (projection) {\n case 'AHEAD':\n case 'ON_TRACK':\n return 'brand';\n case 'BEHIND':\n return 'warning';\n case 'AT_RISK':\n default:\n return 'error';\n }\n}\n\n/**\n * A deterministic contribution trajectory from today to the target date, computed\n * purely from wired fields: starting funded balance + monthly contribution × month.\n * No randomness, no fabricated series — just the arithmetic funding path the user\n * has configured. Returns [] when there is nothing meaningful to chart.\n */\nfunction buildProjectionSeries(\n funded: number,\n monthly: number,\n targetIso?: string | null\n): AreaDatum[] {\n if (!targetIso) return [];\n const target = new Date(targetIso);\n if (Number.isNaN(target.getTime())) return [];\n const now = new Date();\n const totalMonths =\n (target.getFullYear() - now.getFullYear()) * 12 + (target.getMonth() - now.getMonth());\n if (totalMonths <= 0) return [];\n const steps = Math.min(Math.max(totalMonths, 2), 12);\n const fmt = new Intl.DateTimeFormat('en-US', { month: 'short', year: '2-digit' });\n const points: AreaDatum[] = [];\n for (let i = 0; i <= steps; i += 1) {\n const m = Math.round((totalMonths / steps) * i);\n const at = new Date(now.getFullYear(), now.getMonth() + m, 1);\n points.push({ x: fmt.format(at), y: Math.round(funded + monthly * m) });\n }\n return points;\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 useTrackBrainyRichPageView('brainyrich.goals.viewed');\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, {\n onSuccess: () => {\n hapticSuccess();\n void showToast(translate('brainyrich.goals.created', 'Goal created'));\n setCreateOpen(false);\n },\n });\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(\n { id: editing.id, input },\n {\n onSuccess: () => {\n hapticSuccess();\n void showToast(translate('brainyrich.goals.saved', 'Goal saved'));\n setEditing(null);\n },\n }\n );\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 <div className=\"grid gap-4 sm:grid-cols-2 xl:grid-cols-4\">\n <FadeIn index={0}>\n <StatTile\n glow\n icon={<Target className=\"size-4\" aria-hidden=\"true\" />}\n label={translate('brainyrich.goals.metrics.activeGoals', 'Goals')}\n value={String(goals.length)}\n />\n </FadeIn>\n <FadeIn index={1}>\n <StatTile\n icon={<PiggyBank className=\"size-4\" aria-hidden=\"true\" />}\n label={translate('brainyrich.goals.metrics.totalTarget', 'Total target')}\n value={formatMoney(totals.totalTarget, currency)}\n />\n </FadeIn>\n <FadeIn index={2}>\n <StatTile\n icon={<Coins className=\"size-4\" aria-hidden=\"true\" />}\n label={translate('brainyrich.goals.metrics.monthly', 'Monthly contributions')}\n value={formatMoney(totals.totalMonthly, currency)}\n />\n </FadeIn>\n <FadeIn index={3}>\n <StatTile\n icon={<AlertTriangle className=\"size-4\" aria-hidden=\"true\" />}\n label={translate('brainyrich.goals.metrics.atRisk', 'Needs attention')}\n value={String(totals.atRisk)}\n className={totals.atRisk > 0 ? 'ring-1 ring-status-error-text/30' : undefined}\n />\n </FadeIn>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2 xl:grid-cols-3\">\n {goals.map((g, i) => {\n const proj = projectionMeta(g.projection);\n const ProjIcon = proj.icon;\n const tone = goalTone(g.status, g.projection);\n const pct = fundedPercent(g);\n const achieved = g.status === 'ACHIEVED';\n return (\n <FadeIn key={g.id} index={i}>\n <Card\n className={`group flex h-full flex-col transition-shadow motion-safe:hover:shadow-[var(--shadow-pop-hover,var(--shadow-elevation-2))] ${\n achieved ? 'ring-1 ring-status-success-text/30' : ''\n }`}\n >\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 className=\"flex items-center gap-4\">\n <ProgressRing\n value={pct}\n tone={tone}\n size={92}\n strokeWidth={9}\n label={translate('brainyrich.goals.card.funded', 'funded')}\n />\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-xs text-text-secondary\">\n {translate('brainyrich.goals.card.target', 'Target amount')}\n </p>\n <p className=\"truncate 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 rounded-full bg-bg-sunken px-2 py-0.5 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 </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(\n 'brainyrich.goals.actions.viewDetails',\n 'View details & funding'\n )}\n </Button>\n </div>\n </CardContent>\n </Card>\n </FadeIn>\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 <div data-tour=\"brainyrich-page-goals\" className=\"contents\">\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, {\n onSuccess: () => {\n hapticSuccess();\n void showToast(\n translate('brainyrich.goals.archived', 'Goal archived', { name: archiving.name })\n );\n setArchiving(null);\n },\n });\n }}\n />\n </div>\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 const fundedPct = goal ? fundedPercent(goal) : 0;\n const tone: VizTone = goal ? goalTone(goal.status, goal.projection) : 'brand';\n const projectionSeries = goal\n ? buildProjectionSeries(fixedFunded, goal.monthlyContribution, goal.targetDate)\n : [];\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-xl\">\n <SheetHeader>\n <SheetTitle>\n {goal?.name ?? translate('brainyrich.goals.detail.title', 'Goal')}\n </SheetTitle>\n <SheetDescription>\n {translate(\n 'brainyrich.goals.detail.subtitle',\n 'Manage funding links and projection.'\n )}\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 {/* Hero: funded progress ring + headline */}\n <GlassCard glow className=\"flex items-center gap-5\">\n <ProgressRing\n value={fundedPct}\n tone={tone}\n size={116}\n strokeWidth={11}\n label={translate('brainyrich.goals.detail.funded', 'funded')}\n />\n <div className=\"min-w-0 flex-1 space-y-1\">\n <Badge variant={statusBadgeVariant(goal.projection)}>\n {humanize(goal.projection)}\n </Badge>\n <p className=\"text-2xl font-semibold text-text-primary\">\n {formatMoney(fixedFunded, currency)}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {translate('brainyrich.goals.detail.ofTarget', 'of {target} target', {\n target: formatCompact(goal.targetAmount, currency),\n })}\n </p>\n </div>\n </GlassCard>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <StatTile\n icon={<Target className=\"size-4\" aria-hidden=\"true\" />}\n label={translate('brainyrich.goals.detail.target', 'Target')}\n value={formatMoney(goal.targetAmount, currency)}\n />\n <StatTile\n icon={<Wallet className=\"size-4\" aria-hidden=\"true\" />}\n label={translate('brainyrich.goals.detail.funded', 'Funded (fixed)')}\n value={formatMoney(fixedFunded, currency)}\n />\n <StatTile\n icon={<Coins className=\"size-4\" aria-hidden=\"true\" />}\n label={translate('brainyrich.goals.detail.monthly', 'Monthly')}\n value={formatMoney(goal.monthlyContribution, currency)}\n />\n <StatTile\n icon={<CalendarClock className=\"size-4\" aria-hidden=\"true\" />}\n label={translate('brainyrich.goals.detail.targetDate', 'Target date')}\n value={formatDate(goal.targetDate)}\n />\n </div>\n\n {/* Projection trajectory toward the target line */}\n {projectionSeries.length >= 2 ? (\n <section className=\"space-y-3 rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <div className=\"flex items-center gap-2\">\n <LineChart className=\"size-4 text-text-secondary\" aria-hidden=\"true\" />\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {translate(\n 'brainyrich.goals.detail.projectionChart',\n 'Contribution projection'\n )}\n </h3>\n </div>\n <MiniAreaChart\n data={projectionSeries}\n target={goal.targetAmount}\n tone={tone}\n height={180}\n valueFormatter={(v) => formatCompact(v, currency)}\n />\n <p className=\"text-xs text-text-secondary\">\n {translate(\n 'brainyrich.goals.detail.projectionHint',\n 'Starting balance plus {monthly}/mo through {date}.',\n {\n monthly: formatMoney(goal.monthlyContribution, currency),\n date: formatDate(goal.targetDate),\n }\n )}\n </p>\n </section>\n ) : null}\n\n {/* Funding sources table */}\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {translate('brainyrich.goals.detail.fundingLinks', 'Funding sources')}\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 <div className=\"overflow-x-auto rounded-lg border border-border-subtle\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>\n {translate('brainyrich.goals.detail.account', 'Account')}\n </TableHead>\n <TableHead className=\"text-right\">\n {translate('brainyrich.goals.detail.allocation', 'Allocation')}\n </TableHead>\n <TableHead className=\"text-right\">\n {translate('brainyrich.goals.detail.fixedAmount', 'Fixed amount')}\n </TableHead>\n <TableHead className=\"w-10\" />\n </TableRow>\n </TableHeader>\n <TableBody>\n {fundings.map((f) => (\n <TableRow key={f.id}>\n <TableCell className=\"font-medium text-text-primary\">\n {accountName(f.accountId)}\n </TableCell>\n <TableCell className=\"text-right tabular-nums text-text-secondary\">\n {f.fixedAmount == null ? formatPct(f.allocationPct) : '—'}\n </TableCell>\n <TableCell className=\"text-right tabular-nums text-text-secondary\">\n {f.fixedAmount != null ? formatMoney(f.fixedAmount, currency) : '—'}\n </TableCell>\n <TableCell className=\"text-right\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={translate(\n 'brainyrich.goals.detail.unlink',\n 'Unlink funding'\n )}\n onClick={() => setUnlinking(f)}\n >\n <Unlink className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\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 {/* Tags */}\n <Card>\n <CardContent className=\"p-4\">\n <TagField\n entityType=\"brainyrich-goal\"\n entityId={goal.id}\n label={translate('brainyrich.goals.detail.tags', 'Tags')}\n />\n </CardContent>\n </Card>\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"],"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 ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\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 Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n AlertTriangle,\n CalendarClock,\n Coins,\n Link2,\n LineChart,\n MoreHorizontal,\n PiggyBank,\n Plus,\n RefreshCw,\n Target,\n Trash2,\n TrendingDown,\n TrendingUp,\n Unlink,\n Wallet,\n} from 'lucide-react';\nimport { tWithFallback } from '../utils/i18n';\nimport {\n ConfirmDialog,\n FadeIn,\n GlassCard,\n LoadMore,\n MiniAreaChart,\n ProgressRing,\n StatTile,\n type AreaDatum,\n type VizTone,\n} from '../components';\nimport { TagField } from '../components/reuse/TagField';\nimport { hapticSuccess, showToast } from '../utils/nativeControls';\nimport { useTrackBrainyRichPageView } from '../hooks/useBrainyRichAnalytics';\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 LoadingState,\n SectionShell,\n formatCompact,\n formatDate,\n formatMoney,\n formatPct,\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/** Sum of the fixed-amount funding links wired to a goal (real backend value). */\nfunction goalFixedFunded(goal: Pick<BraGoal, 'fundings'>): number {\n return goal.fundings.reduce((s, f) => s + (f.fixedAmount ?? 0), 0);\n}\n\n/**\n * Funded-progress percentage for a goal. ACHIEVED goals read 100%; otherwise the\n * sum of fixed funding links over the target — every input is wired backend data,\n * never fabricated.\n */\nfunction fundedPercent(goal: Pick<BraGoal, 'fundings' | 'targetAmount' | 'status'>): number {\n if (goal.status === 'ACHIEVED') return 100;\n if (!(goal.targetAmount > 0)) return 0;\n return Math.max(0, Math.min(100, (goalFixedFunded(goal) / goal.targetAmount) * 100));\n}\n\n/** Ring/accent tone derived from the goal's real status + projection. */\nfunction goalTone(status: BraGoalStatus, projection: BraGoalProjection): VizTone {\n if (status === 'ACHIEVED') return 'success';\n switch (projection) {\n case 'AHEAD':\n case 'ON_TRACK':\n return 'brand';\n case 'BEHIND':\n return 'warning';\n case 'AT_RISK':\n default:\n return 'error';\n }\n}\n\n/**\n * A deterministic contribution trajectory from today to the target date, computed\n * purely from wired fields: starting funded balance + monthly contribution × month.\n * No randomness, no fabricated series — just the arithmetic funding path the user\n * has configured. Returns [] when there is nothing meaningful to chart.\n */\nfunction buildProjectionSeries(\n funded: number,\n monthly: number,\n targetIso?: string | null\n): AreaDatum[] {\n if (!targetIso) return [];\n const target = new Date(targetIso);\n if (Number.isNaN(target.getTime())) return [];\n const now = new Date();\n const totalMonths =\n (target.getFullYear() - now.getFullYear()) * 12 + (target.getMonth() - now.getMonth());\n if (totalMonths <= 0) return [];\n const steps = Math.min(Math.max(totalMonths, 2), 12);\n const fmt = new Intl.DateTimeFormat('en-US', { month: 'short', year: '2-digit' });\n const points: AreaDatum[] = [];\n for (let i = 0; i <= steps; i += 1) {\n const m = Math.round((totalMonths / steps) * i);\n const at = new Date(now.getFullYear(), now.getMonth() + m, 1);\n points.push({ x: fmt.format(at), y: Math.round(funded + monthly * m) });\n }\n return points;\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 useTrackBrainyRichPageView('brainyrich.goals.viewed');\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, {\n onSuccess: () => {\n hapticSuccess();\n void showToast(translate('brainyrich.goals.created', 'Goal created'));\n setCreateOpen(false);\n },\n });\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(\n { id: editing.id, input },\n {\n onSuccess: () => {\n hapticSuccess();\n void showToast(translate('brainyrich.goals.saved', 'Goal saved'));\n setEditing(null);\n },\n }\n );\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 <div className=\"grid gap-4 sm:grid-cols-2 xl:grid-cols-4\">\n <FadeIn index={0}>\n <StatTile\n glow\n icon={<Target className=\"size-4\" aria-hidden=\"true\" />}\n label={translate('brainyrich.goals.metrics.activeGoals', 'Goals')}\n value={String(goals.length)}\n />\n </FadeIn>\n <FadeIn index={1}>\n <StatTile\n icon={<PiggyBank className=\"size-4\" aria-hidden=\"true\" />}\n label={translate('brainyrich.goals.metrics.totalTarget', 'Total target')}\n value={formatMoney(totals.totalTarget, currency)}\n />\n </FadeIn>\n <FadeIn index={2}>\n <StatTile\n icon={<Coins className=\"size-4\" aria-hidden=\"true\" />}\n label={translate('brainyrich.goals.metrics.monthly', 'Monthly contributions')}\n value={formatMoney(totals.totalMonthly, currency)}\n />\n </FadeIn>\n <FadeIn index={3}>\n <StatTile\n icon={<AlertTriangle className=\"size-4\" aria-hidden=\"true\" />}\n label={translate('brainyrich.goals.metrics.atRisk', 'Needs attention')}\n value={String(totals.atRisk)}\n className={totals.atRisk > 0 ? 'ring-1 ring-status-error-text/30' : undefined}\n />\n </FadeIn>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2 xl:grid-cols-3\">\n {goals.map((g, i) => {\n const proj = projectionMeta(g.projection);\n const ProjIcon = proj.icon;\n const tone = goalTone(g.status, g.projection);\n const pct = fundedPercent(g);\n const achieved = g.status === 'ACHIEVED';\n return (\n <FadeIn key={g.id} index={i}>\n <Card\n className={`group flex h-full flex-col transition-shadow motion-safe:hover:shadow-[var(--shadow-pop-hover,var(--shadow-elevation-2))] ${\n achieved ? 'ring-1 ring-status-success-text/30' : ''\n }`}\n >\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 className=\"flex items-center gap-4\">\n <ProgressRing\n value={pct}\n tone={tone}\n size={92}\n strokeWidth={9}\n label={translate('brainyrich.goals.card.funded', 'funded')}\n />\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-xs text-text-secondary\">\n {translate('brainyrich.goals.card.target', 'Target amount')}\n </p>\n <p className=\"truncate 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 rounded-full bg-bg-sunken px-2 py-0.5 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 </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(\n 'brainyrich.goals.actions.viewDetails',\n 'View details & funding'\n )}\n </Button>\n </div>\n </CardContent>\n </Card>\n </FadeIn>\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 <div data-tour=\"brainyrich-page-goals\" className=\"contents\">\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, {\n onSuccess: () => {\n hapticSuccess();\n void showToast(\n translate('brainyrich.goals.archived', 'Goal archived', { name: archiving.name })\n );\n setArchiving(null);\n },\n });\n }}\n />\n </div>\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 <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"max-h-[90vh] overflow-y-auto sm:max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>\n {mode === 'create'\n ? translate('brainyrich.goals.form.createTitle', 'New goal')\n : translate('brainyrich.goals.form.editTitle', 'Edit goal')}\n </ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n {translate(\n 'brainyrich.goals.form.subtitle',\n 'Define the milestone, target and contribution plan.'\n )}\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\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 <ResponsiveDialogFooter>\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 </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\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 const fundedPct = goal ? fundedPercent(goal) : 0;\n const tone: VizTone = goal ? goalTone(goal.status, goal.projection) : 'brand';\n const projectionSeries = goal\n ? buildProjectionSeries(fixedFunded, goal.monthlyContribution, goal.targetDate)\n : [];\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-xl\">\n <SheetHeader>\n <SheetTitle>\n {goal?.name ?? translate('brainyrich.goals.detail.title', 'Goal')}\n </SheetTitle>\n <SheetDescription>\n {translate(\n 'brainyrich.goals.detail.subtitle',\n 'Manage funding links and projection.'\n )}\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 {/* Hero: funded progress ring + headline */}\n <GlassCard glow className=\"flex items-center gap-5\">\n <ProgressRing\n value={fundedPct}\n tone={tone}\n size={116}\n strokeWidth={11}\n label={translate('brainyrich.goals.detail.funded', 'funded')}\n />\n <div className=\"min-w-0 flex-1 space-y-1\">\n <Badge variant={statusBadgeVariant(goal.projection)}>\n {humanize(goal.projection)}\n </Badge>\n <p className=\"text-2xl font-semibold text-text-primary\">\n {formatMoney(fixedFunded, currency)}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {translate('brainyrich.goals.detail.ofTarget', 'of {target} target', {\n target: formatCompact(goal.targetAmount, currency),\n })}\n </p>\n </div>\n </GlassCard>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <StatTile\n icon={<Target className=\"size-4\" aria-hidden=\"true\" />}\n label={translate('brainyrich.goals.detail.target', 'Target')}\n value={formatMoney(goal.targetAmount, currency)}\n />\n <StatTile\n icon={<Wallet className=\"size-4\" aria-hidden=\"true\" />}\n label={translate('brainyrich.goals.detail.funded', 'Funded (fixed)')}\n value={formatMoney(fixedFunded, currency)}\n />\n <StatTile\n icon={<Coins className=\"size-4\" aria-hidden=\"true\" />}\n label={translate('brainyrich.goals.detail.monthly', 'Monthly')}\n value={formatMoney(goal.monthlyContribution, currency)}\n />\n <StatTile\n icon={<CalendarClock className=\"size-4\" aria-hidden=\"true\" />}\n label={translate('brainyrich.goals.detail.targetDate', 'Target date')}\n value={formatDate(goal.targetDate)}\n />\n </div>\n\n {/* Projection trajectory toward the target line */}\n {projectionSeries.length >= 2 ? (\n <section className=\"space-y-3 rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <div className=\"flex items-center gap-2\">\n <LineChart className=\"size-4 text-text-secondary\" aria-hidden=\"true\" />\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {translate(\n 'brainyrich.goals.detail.projectionChart',\n 'Contribution projection'\n )}\n </h3>\n </div>\n <MiniAreaChart\n data={projectionSeries}\n target={goal.targetAmount}\n tone={tone}\n height={180}\n valueFormatter={(v) => formatCompact(v, currency)}\n />\n <p className=\"text-xs text-text-secondary\">\n {translate(\n 'brainyrich.goals.detail.projectionHint',\n 'Starting balance plus {monthly}/mo through {date}.',\n {\n monthly: formatMoney(goal.monthlyContribution, currency),\n date: formatDate(goal.targetDate),\n }\n )}\n </p>\n </section>\n ) : null}\n\n {/* Funding sources table */}\n <section className=\"space-y-3\">\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {translate('brainyrich.goals.detail.fundingLinks', 'Funding sources')}\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 <div className=\"overflow-x-auto rounded-lg border border-border-subtle\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>\n {translate('brainyrich.goals.detail.account', 'Account')}\n </TableHead>\n <TableHead className=\"text-right\">\n {translate('brainyrich.goals.detail.allocation', 'Allocation')}\n </TableHead>\n <TableHead className=\"text-right\">\n {translate('brainyrich.goals.detail.fixedAmount', 'Fixed amount')}\n </TableHead>\n <TableHead className=\"w-10\" />\n </TableRow>\n </TableHeader>\n <TableBody>\n {fundings.map((f) => (\n <TableRow key={f.id}>\n <TableCell className=\"font-medium text-text-primary\">\n {accountName(f.accountId)}\n </TableCell>\n <TableCell className=\"text-right tabular-nums text-text-secondary\">\n {f.fixedAmount == null ? formatPct(f.allocationPct) : '—'}\n </TableCell>\n <TableCell className=\"text-right tabular-nums text-text-secondary\">\n {f.fixedAmount != null ? formatMoney(f.fixedAmount, currency) : '—'}\n </TableCell>\n <TableCell className=\"text-right\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={translate(\n 'brainyrich.goals.detail.unlink',\n 'Unlink funding'\n )}\n onClick={() => setUnlinking(f)}\n >\n <Unlink className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\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 {/* Tags */}\n <Card>\n <CardContent className=\"p-4\">\n <TagField\n entityType=\"brainyrich-goal\"\n entityId={goal.id}\n label={translate('brainyrich.goals.detail.tags', 'Tags')}\n />\n </CardContent>\n </Card>\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"],"mappings":";;;;;;;;;;;;;;;;AA2GA,IAAM,KAA4B;CAChC;CACA;CACA;CACA;CACA;CACA;CACA;AACF,GAEM,KAAiC;CAAC;CAAU;CAAY;CAAW;AAAW;AAOpF,SAAS,GAAe,GAA+C;CACrE,QAAQ,GAAR;EACE,KAAK;EACL,KAAK,YACH,OAAO;GAAE,MAAM;GAAY,MAAM;EAA2B;EAC9D,KAAK,UACH,OAAO;GAAE,MAAM;GAAc,MAAM;EAA2B;EAEhE,SACE,OAAO;GAAE,MAAM;GAAe,MAAM;EAAyB;CACjE;AACF;AAEA,SAAS,EAAS,GAAuB;CACvC,OAAO,EACJ,YAAY,EACZ,MAAM,GAAG,EACT,KAAK,MAAS,EAAK,OAAO,CAAC,EAAE,YAAY,IAAI,EAAK,MAAM,CAAC,CAAC,EAC1D,KAAK,GAAG;AACb;AAGA,SAAS,GAAgB,GAAyC;CAChE,OAAO,EAAK,SAAS,QAAQ,GAAG,MAAM,KAAK,EAAE,eAAe,IAAI,CAAC;AACnE;AAOA,SAAS,GAAc,GAAqE;CAG1F,OAFI,EAAK,WAAW,aAAmB,MACjC,EAAK,eAAe,IACnB,KAAK,IAAI,GAAG,KAAK,IAAI,KAAM,GAAgB,CAAI,IAAI,EAAK,eAAgB,GAAG,CAAC,IAD9C;AAEvC;AAGA,SAAS,GAAS,GAAuB,GAAwC;CAC/E,IAAI,MAAW,YAAY,OAAO;CAClC,QAAQ,GAAR;EACE,KAAK;EACL,KAAK,YACH,OAAO;EACT,KAAK,UACH,OAAO;EAET,SACE,OAAO;CACX;AACF;AAQA,SAAS,GACP,GACA,GACA,GACa;CACb,IAAI,CAAC,GAAW,OAAO,CAAC;CACxB,IAAM,IAAS,IAAI,KAAK,CAAS;CACjC,IAAI,OAAO,MAAM,EAAO,QAAQ,CAAC,GAAG,OAAO,CAAC;CAC5C,IAAM,oBAAM,IAAI,KAAK,GACf,KACH,EAAO,YAAY,IAAI,EAAI,YAAY,KAAK,MAAM,EAAO,SAAS,IAAI,EAAI,SAAS;CACtF,IAAI,KAAe,GAAG,OAAO,CAAC;CAC9B,IAAM,IAAQ,KAAK,IAAI,KAAK,IAAI,GAAa,CAAC,GAAG,EAAE,GAC7C,IAAM,IAAI,KAAK,eAAe,SAAS;EAAE,OAAO;EAAS,MAAM;CAAU,CAAC,GAC1E,IAAsB,CAAC;CAC7B,KAAK,IAAI,IAAI,GAAG,KAAK,GAAO,KAAK,GAAG;EAClC,IAAM,IAAI,KAAK,MAAO,IAAc,IAAS,CAAC,GACxC,IAAK,IAAI,KAAK,EAAI,YAAY,GAAG,EAAI,SAAS,IAAI,GAAG,CAAC;EAC5D,EAAO,KAAK;GAAE,GAAG,EAAI,OAAO,CAAE;GAAG,GAAG,KAAK,MAAM,IAAS,IAAU,CAAC;EAAE,CAAC;CACxE;CACA,OAAO;AACT;AAGA,SAAS,GAAY,GAA6B;CAChD,IAAI,CAAC,GAAK,OAAO;CACjB,IAAM,IAAI,IAAI,KAAK,CAAG;CAEtB,OADI,OAAO,MAAM,EAAE,QAAQ,CAAC,IAAU,KAC/B,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AACpC;AAeA,SAAS,KAA2B;CAClC,OAAO;EACL,MAAM;EACN,MAAM;EACN,QAAQ;EACR,cAAc;EACd,YAAY;EACZ,qBAAqB;EACrB,UAAU;EACV,UAAU;EACV,aAAa;EACb,OAAO;CACT;AACF;AAEA,SAAS,GAAa,GAA8B;CAClD,OAAO;EACL,MAAM,EAAK;EACX,MAAM,EAAK;EACX,QAAQ,EAAK;EACb,cAAc,OAAO,EAAK,YAAY;EACtC,YAAY,GAAY,EAAK,UAAU;EACvC,qBAAqB,OAAO,EAAK,mBAAmB;EACpD,UAAU,OAAO,EAAK,QAAQ;EAC9B,UAAU,EAAK;EACf,aAAa,EAAK,eAAe;EACjC,OAAO,EAAK,SAAS;CACvB;AACF;AAEA,IAAM,KAAiB;AAEvB,SAAgB,KAAY;CAC1B,IAAM,EAAE,MAAM,EAAQ,GAChB,KAAa,GAAa,GAAkB,MAChD,EAAc,GAAG,GAAK,GAAU,CAAM;CAExC,EAA2B,yBAAyB;CAEpD,IAAM,EACJ,OAAO,GACP,YACA,aACA,uBACA,eACA,aACA,gBACE,EAAc,GACZ,EAAE,MAAM,MAAe,EAAc,GAErC,IAAa,EAAc,GAC3B,KAAa,GAAc,GAC3B,IAAc,EAAe,GAE7B,CAAC,IAAY,KAAiB,EAAS,EAAK,GAC5C,CAAC,GAAS,KAAc,EAAyB,IAAI,GACrD,CAAC,GAAU,KAAe,EAAwB,IAAI,GACtD,CAAC,GAAW,KAAgB,EAAyB,IAAI,GACzD,CAAC,GAAM,KAAW,EAAwB,EAAS,GAEnD,MAA2C,GAAQ,MACvD,GAAS,OAAU;EAAE,GAAG;GAAO,IAAM;CAAM,EAAE,GAEzC,IAAS,SAMN;EAAE,aALW,EAAM,QAAQ,GAAG,MAAM,IAAI,EAAE,cAAc,CAKtD;EAAa,cAJD,EAAM,QAAQ,GAAG,MAAM,IAAI,EAAE,qBAAqB,CAIjD;EAAc,QAHrB,EAAM,QAClB,MAAM,EAAE,eAAe,aAAa,EAAE,eAAe,QACxD,EAAE;CACyC,IAC1C,CAAC,CAAK,CAAC,GAEJ,IAAW,EAAM,IAAI,YAAY,OAEjC,UAAmB;EAEvB,AADA,EAAQ,GAAU,CAAC,GACnB,EAAc,EAAI;CACpB,GAEM,KAAY,MAAkB;EAElC,AADA,EAAQ,GAAa,CAAI,CAAC,GAC1B,EAAW,CAAI;CACjB,GAEM,IACJ,EAAK,KAAK,KAAK,EAAE,SAAS,KAAK,OAAO,EAAK,YAAY,IAAI,KAAK,EAAK,WAAW,SAAS;CA6Q3F,OACE,kBAAC,OAAD;EAAK,aAAU;EAAwB,WAAU;YAAjD;GACE,kBAAC,GAAD;IACE,OAAO,EAAU,0BAA0B,iBAAiB;IAC5D,aAAa,EACX,gCACA,kEACF;IACA,aAAa,EAAU,uCAAuC,UAAU;IACxE,UAAU;cAjOV,KAAkB,kBAAC,IAAD,EAAc,MAAM,EAAI,CAAA,IAC1C,KAEA,kBAAC,IAAD;KACE,OAAO,EAAU,gCAAgC,sBAAsB;KACvE,aAAa,EACX,sCACA,yDACF;KACA,eAAe,GAAQ;IACxB,CAAA,IAED,EAAM,WAAW,IAEjB,kBAAC,IAAD;KACE,MAAM,kBAAC,GAAD;MAAQ,WAAU;MAAS,eAAY;KAAQ,CAAA;KACrD,OAAO,EAAU,gCAAgC,wBAAwB;KACzE,aAAa,EACX,sCACA,uEACF;KACA,QACE,kBAAC,GAAD;MAAQ,MAAK;MAAK,SAAS;gBAA3B,CACE,kBAAC,GAAD;OAAM,WAAU;OAAS,eAAY;MAAQ,CAAA,GAC5C,EAAU,uCAAuC,UAAU,CACtD;;IAEX,CAAA,IAIH,kBAAA,GAAA,EAAA,UAAA;KACE,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,GAAD;QAAQ,OAAO;kBACb,kBAAC,GAAD;SACE,MAAA;SACA,MAAM,kBAAC,GAAD;UAAQ,WAAU;UAAS,eAAY;SAAQ,CAAA;SACrD,OAAO,EAAU,wCAAwC,OAAO;SAChE,OAAO,OAAO,EAAM,MAAM;QAC3B,CAAA;OACK,CAAA;OACR,kBAAC,GAAD;QAAQ,OAAO;kBACb,kBAAC,GAAD;SACE,MAAM,kBAAC,IAAD;UAAW,WAAU;UAAS,eAAY;SAAQ,CAAA;SACxD,OAAO,EAAU,wCAAwC,cAAc;SACvE,OAAO,EAAY,EAAO,aAAa,CAAQ;QAChD,CAAA;OACK,CAAA;OACR,kBAAC,GAAD;QAAQ,OAAO;kBACb,kBAAC,GAAD;SACE,MAAM,kBAAC,IAAD;UAAO,WAAU;UAAS,eAAY;SAAQ,CAAA;SACpD,OAAO,EAAU,oCAAoC,uBAAuB;SAC5E,OAAO,EAAY,EAAO,cAAc,CAAQ;QACjD,CAAA;OACK,CAAA;OACR,kBAAC,GAAD;QAAQ,OAAO;kBACb,kBAAC,GAAD;SACE,MAAM,kBAAC,GAAD;UAAe,WAAU;UAAS,eAAY;SAAQ,CAAA;SAC5D,OAAO,EAAU,mCAAmC,iBAAiB;SACrE,OAAO,OAAO,EAAO,MAAM;SAC3B,WAAW,EAAO,SAAS,IAAI,qCAAqC,KAAA;QACrE,CAAA;OACK,CAAA;MACL;;KAEL,kBAAC,OAAD;MAAK,WAAU;gBACZ,EAAM,KAAK,GAAG,MAAM;OACnB,IAAM,IAAO,GAAe,EAAE,UAAU,GAClC,IAAW,EAAK,MAChB,IAAO,GAAS,EAAE,QAAQ,EAAE,UAAU,GACtC,IAAM,GAAc,CAAC;OAE3B,OACE,kBAAC,GAAD;QAAmB,OAAO;kBACxB,kBAAC,IAAD;SACE,WAAW,6HAJA,EAAE,WAAW,aAKX,uCAAuC;mBAFtD,CAKE,kBAAC,GAAD;UAAY,WAAU;oBACpB,kBAAC,OAAD;WAAK,WAAU;qBAAf,CACE,kBAAC,OAAD;YAAK,WAAU;sBAAf,CACE,kBAAC,GAAD;aAAW,WAAU;uBAArB,CACE,kBAAC,GAAD;cACE,WAAU;cACV,eAAY;aACb,CAAA,GACD,kBAAC,QAAD;cAAM,WAAU;wBAAY,EAAE;aAAW,CAAA,CAChC;gBACX,kBAAC,GAAD;aAAiB,WAAU;uBAA3B,CACE,kBAAC,GAAD;cAAO,SAAQ;wBAAW,EAAS,EAAE,IAAI;aAAS,CAAA,GAClD,kBAAC,GAAD;cAAO,SAAS,GAAmB,EAAE,MAAM;wBAAI,EAAS,EAAE,MAAM;aAAS,CAAA,CAC1D;cACd;eACL,kBAAC,IAAD,EAAA,UAAA,CACE,kBAAC,IAAD;YAAqB,SAAA;sBACnB,kBAAC,GAAD;aACE,SAAQ;aACR,MAAK;aACL,cAAY,EAAU,iCAAiC,cAAc;uBAErE,kBAAC,GAAD;cAAgB,WAAU;cAAS,eAAY;aAAQ,CAAA;YACjD,CAAA;WACW,CAAA,GACrB,kBAAC,IAAD;YAAqB,OAAM;sBAA3B;aACE,kBAAC,GAAD;cAAkB,gBAAgB,EAAY,EAAE,EAAE;wBAAlD,CACE,kBAAC,IAAD;eAAO,WAAU;eAAS,eAAY;cAAQ,CAAA,GAC7C,EAAU,0CAA0C,gBAAgB,CACrD;;aAClB,kBAAC,GAAD;cAAkB,gBAAgB,EAAS,CAAC;wBAA5C,CACE,kBAAC,IAAD;eAAW,WAAU;eAAS,eAAY;cAAQ,CAAA,GACjD,EAAU,qCAAqC,WAAW,CAC3C;;aAClB,kBAAC,IAAD,CAAwB,CAAA;aACxB,kBAAC,GAAD;cACE,WAAU;cACV,gBAAgB,EAAa,CAAC;wBAFhC,CAIE,kBAAC,IAAD;eAAQ,WAAU;eAAS,eAAY;cAAQ,CAAA,GAC9C,EAAU,oCAAoC,cAAc,CAC7C;;YACC;aACT,EAAA,CAAA,CACX;;SACK,CAAA,GACZ,kBAAC,IAAD;UAAa,WAAU;oBAAvB;WACE,kBAAC,OAAD;YAAK,WAAU;sBAAf,CACE,kBAAC,IAAD;aACE,OAAO;aACD;aACN,MAAM;aACN,aAAa;aACb,OAAO,EAAU,gCAAgC,QAAQ;YAC1D,CAAA,GACD,kBAAC,OAAD;aAAK,WAAU;uBAAf;cACE,kBAAC,KAAD;eAAG,WAAU;yBACV,EAAU,gCAAgC,eAAe;cACzD,CAAA;cACH,kBAAC,KAAD;eAAG,WAAU;yBACV,EAAY,EAAE,cAAc,EAAE,QAAQ;cACtC,CAAA;cACH,kBAAC,QAAD;eACE,WAAW,iGAAiG,EAAK;yBADnH,CAGE,kBAAC,GAAD;gBAAU,WAAU;gBAAW,eAAY;eAAQ,CAAA,GAClD,EAAS,EAAE,UAAU,CAClB;;aACH;cACF;;WAEL,kBAAC,MAAD;YAAI,WAAU;sBAAd;aACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;cAAI,WAAU;wBACX,EAAU,oCAAoC,aAAa;aAC1D,CAAA,GACJ,kBAAC,MAAD;cAAI,WAAU;wBAAd,CACE,kBAAC,IAAD;eACE,WAAU;eACV,eAAY;cACb,CAAA,GACA,GAAW,EAAE,UAAU,CACtB;eACD,EAAA,CAAA;aACL,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;cAAI,WAAU;wBACX,EAAU,iCAAiC,SAAS;aACnD,CAAA,GACJ,kBAAC,MAAD;cAAI,WAAU;wBACX,EAAY,EAAE,qBAAqB,EAAE,QAAQ;aAC5C,CAAA,CACD,EAAA,CAAA;aACL,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;cAAI,WAAU;wBACX,EAAU,kCAAkC,UAAU;aACrD,CAAA,GACJ,kBAAC,MAAD;cAAI,WAAU;wBAAiC,EAAE;aAAa,CAAA,CAC3D,EAAA,CAAA;aACL,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;cAAI,WAAU;wBACX,EAAU,kCAAkC,eAAe;aAC1D,CAAA,GACJ,kBAAC,MAAD;cAAI,WAAU;wBAAiC,EAAE,SAAS;aAAW,CAAA,CAClE,EAAA,CAAA;YACH;;WAEJ,kBAAC,OAAD;YAAK,WAAU;sBACb,kBAAC,GAAD;aACE,SAAQ;aACR,MAAK;aACL,WAAU;aACV,eAAe,EAAY,EAAE,EAAE;uBAE9B,EACC,wCACA,wBACF;YACM,CAAA;WACL,CAAA;UACM;WACT;;OACA,GA/HK,EAAE,EA+HP;MAEZ,CAAC;KACE,CAAA;KAEL,kBAAC,IAAD;MACW;MACT,SAAS;MACT,SAAS;MACT,OAAO,EAAU,qCAAqC,iBAAiB;MACvE,cAAc,EAAU,wCAAwC,UAAU;KAC3E,CAAA;IACD,EAAA,CAAA;GAgBY,CAAA;GAEd,kBAAC,IAAD;IACE,MAAM;IACN,MAAK;IACC;IACI;IACV,YAAY,EAAW,KAAK,OAAO;KAAE,IAAI,EAAE;KAAI,MAAM,EAAE;IAAK,EAAE;IAC9D,OAAO;IACP,SAAS,EAAW;IACpB,gBAjSqB;KACzB,IAAI,CAAC,GAAW;KAChB,IAAM,IAA4B;MAChC,MAAM,EAAK,KAAK,KAAK;MACrB,MAAM,EAAK;MACX,cAAc,OAAO,EAAK,YAAY;MACtC,YAAY,IAAI,KAAK,EAAK,UAAU,EAAE,YAAY;MAClD,qBAAqB,OAAO,EAAK,mBAAmB,KAAK;MACzD,UAAU,OAAO,EAAK,QAAQ,KAAK;MACnC,UAAU,EAAK,SAAS,KAAK,KAAK;MAClC,OAAO,EAAK,MAAM,KAAK,KAAK;MAC5B,MAAM,CAAC;MACP,GAAI,EAAK,cAAc,EAAE,aAAa,EAAK,YAAY,IAAI,CAAC;KAC9D;KACA,EAAW,OAAO,GAAO,EACvB,iBAAiB;MAGf,AAFA,EAAc,GACd,EAAe,EAAU,4BAA4B,cAAc,CAAC,GACpE,EAAc,EAAK;KACrB,EACF,CAAC;IACH;IA6QM,eAAe,MAAM,EAAc,CAAC;IACzB;GACZ,CAAA;GAED,kBAAC,IAAD;IACE,MAAM,EAAQ;IACd,MAAK;IACL,QAAQ,GAAS;IACX;IACI;IACV,YAAY,EAAW,KAAK,OAAO;KAAE,IAAI,EAAE;KAAI,MAAM,EAAE;IAAK,EAAE;IAC9D,OAAO;IACP,SAAS,GAAW;IACpB,gBAxRqB;KACzB,IAAI,CAAC,KAAW,CAAC,GAAW;KAC5B,IAAM,IAA4B;MAChC,MAAM,EAAK,KAAK,KAAK;MACrB,MAAM,EAAK;MACX,QAAQ,EAAK;MACb,cAAc,OAAO,EAAK,YAAY;MACtC,YAAY,IAAI,KAAK,EAAK,UAAU,EAAE,YAAY;MAClD,qBAAqB,OAAO,EAAK,mBAAmB,KAAK;MACzD,UAAU,OAAO,EAAK,QAAQ,KAAK;MACnC,UAAU,EAAK,SAAS,KAAK,KAAK;MAClC,OAAO,EAAK,MAAM,KAAK,KAAK;MAE5B,MAAM,EAAQ;KAChB;KACA,GAAW,OACT;MAAE,IAAI,EAAQ;MAAI;KAAM,GACxB,EACE,iBAAiB;MAGf,AAFA,EAAc,GACd,EAAe,EAAU,0BAA0B,YAAY,CAAC,GAChE,EAAW,IAAI;KACjB,EACF,CACF;IACF;IAgQM,eAAe,MAAM;KACnB,AAAK,KAAG,EAAW,IAAI;IACzB;IACW;GACZ,CAAA;GAED,kBAAC,IAAD;IAAiB,QAAQ;IAAU,eAAe,EAAY,IAAI;IAAc;GAAY,CAAA;GAE5F,kBAAC,IAAD;IACE,MAAM,EAAQ;IACd,eAAe,MAAM;KACnB,AAAK,KAAG,EAAa,IAAI;IAC3B;IACA,OAAO,EAAU,kCAAkC,eAAe;IAClE,aAAa,EACX,wCACA,uFACA,EAAE,MAAM,GAAW,QAAQ,GAAG,CAChC;IACA,cAAc,EAAU,oCAAoC,cAAc;IAC1E,cAAc,EAAU,oCAAoC,YAAY;IACxE,aAAA;IACA,SAAS,EAAY;IACrB,iBAAiB;KACV,KACL,EAAY,OAAO,EAAU,IAAI,EAC/B,iBAAiB;MAKf,AAJA,EAAc,GACd,EACE,EAAU,6BAA6B,iBAAiB,EAAE,MAAM,EAAU,KAAK,CAAC,CAClF,GACA,EAAa,IAAI;KACnB,EACF,CAAC;IACH;GACD,CAAA;EACE;;AAET;AAsBA,SAAS,GAAe,EACtB,SACA,SACA,WACA,SACA,aACA,eACA,UACA,YACA,aACA,iBACA,gBACsB;CACtB,OACE,kBAAC,GAAD;EAAwB;EAAoB;YAC1C,kBAAC,GAAD;GAAyB,WAAU;aAAnC,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,IAAD,EAAA,UACG,MAAS,WACN,EAAU,qCAAqC,UAAU,IACzD,EAAU,mCAAmC,WAAW,EACvC,CAAA,GACvB,kBAAC,GAAD,EAAA,UACG,EACC,kCACA,qDACF,EAC2B,CAAA,CACP,EAAA,CAAA,GAExB,kBAAC,QAAD;IACE,WAAU;IACV,WAAW,MAAM;KAEf,AADA,EAAE,eAAe,GACjB,EAAS;IACX;cALF;KAOE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD;OAAO,SAAQ;iBAAa,EAAU,8BAA8B,MAAM;MAAS,CAAA,GACnF,kBAAC,GAAD;OACE,IAAG;OACH,OAAO,EAAK;OACZ,WAAW,MAAM,EAAS,QAAQ,EAAE,OAAO,KAAK;OAChD,aAAa,EACX,yCACA,sBACF;OACA,UAAA;MACD,CAAA,CACE;;KAEL,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD;QAAO,SAAQ;kBAAa,EAAU,8BAA8B,MAAM;OAAS,CAAA,GACnF,kBAAC,GAAD;QAAQ,OAAO,EAAK;QAAM,gBAAgB,MAAM,EAAS,QAAQ,CAAgB;kBAAjF,CACE,kBAAC,GAAD;SAAe,IAAG;mBAChB,kBAAC,GAAD,CAAc,CAAA;QACD,CAAA,GACf,kBAAC,GAAD,EAAA,UACG,GAAW,KAAK,MACf,kBAAC,GAAD;SAAsB,OAAO;mBAC1B,EAAS,CAAG;QACH,GAFK,CAEL,CACb,EACY,CAAA,CACT;SACL;UACJ,MAAS,SACR,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD;QAAO,SAAQ;kBACZ,EAAU,gCAAgC,QAAQ;OAC9C,CAAA,GACP,kBAAC,GAAD;QACE,OAAO,EAAK;QACZ,gBAAgB,MAAM,EAAS,UAAU,CAAkB;kBAF7D,CAIE,kBAAC,GAAD;SAAe,IAAG;mBAChB,kBAAC,GAAD,CAAc,CAAA;QACD,CAAA,GACf,kBAAC,GAAD,EAAA,UACG,GAAc,KAAK,MAClB,kBAAC,GAAD;SAAqB,OAAO;mBACzB,EAAS,CAAE;QACF,GAFK,CAEL,CACb,EACY,CAAA,CACT;SACL;WAEL,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD;QAAO,SAAQ;kBACZ,EAAU,kCAAkC,UAAU;OAClD,CAAA,GACP,kBAAC,GAAD;QACE,IAAG;QACH,MAAK;QACL,KAAK;QACL,OAAO,EAAK;QACZ,WAAW,MAAM,EAAS,YAAY,EAAE,OAAO,KAAK;OACrD,CAAA,CACE;QAEJ;;KAEL,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD;QAAO,SAAQ;kBACZ,EAAU,sCAAsC,eAAe;OAC3D,CAAA,GACP,kBAAC,GAAD;QACE,IAAG;QACH,MAAK;QACL,KAAK;QACL,MAAK;QACL,OAAO,EAAK;QACZ,WAAW,MAAM,EAAS,gBAAgB,EAAE,OAAO,KAAK;QACxD,UAAA;OACD,CAAA,CACE;UACL,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD;QAAO,SAAQ;kBACZ,EAAU,oCAAoC,aAAa;OACvD,CAAA,GACP,kBAAC,GAAD;QACE,IAAG;QACH,MAAK;QACL,OAAO,EAAK;QACZ,WAAW,MAAM,EAAS,cAAc,EAAE,OAAO,KAAK;QACtD,UAAA;OACD,CAAA,CACE;QACF;;KAEL,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD;QAAO,SAAQ;kBACZ,EAAU,iCAAiC,sBAAsB;OAC7D,CAAA,GACP,kBAAC,GAAD;QACE,IAAG;QACH,MAAK;QACL,KAAK;QACL,MAAK;QACL,OAAO,EAAK;QACZ,WAAW,MAAM,EAAS,uBAAuB,EAAE,OAAO,KAAK;OAChE,CAAA,CACE;UACL,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD;QAAO,SAAQ;kBACZ,EAAU,kCAAkC,UAAU;OAClD,CAAA,GACP,kBAAC,GAAD;QACE,IAAG;QACH,OAAO,EAAK;QACZ,WAAW,MAAM,EAAS,YAAY,EAAE,OAAO,MAAM,YAAY,CAAC;QAClE,WAAW;OACZ,CAAA,CACE;QACF;;KAEJ,MAAS,SACR,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD;OAAO,SAAQ;iBACZ,EAAU,kCAAkC,UAAU;MAClD,CAAA,GACP,kBAAC,GAAD;OACE,IAAG;OACH,MAAK;OACL,KAAK;OACL,OAAO,EAAK;OACZ,WAAW,MAAM,EAAS,YAAY,EAAE,OAAO,KAAK;MACrD,CAAA,CACE;UACH;KAEJ,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD;OAAO,SAAQ;iBACZ,EAAU,mCAAmC,sBAAsB;MAC/D,CAAA,GACP,kBAAC,GAAD;OACE,OAAO,EAAK,eAAe;OAC3B,gBAAgB,MAAM,EAAS,eAAe,MAAM,KAAiB,KAAK,CAAC;iBAF7E,CAIE,kBAAC,GAAD;QAAe,IAAG;kBAChB,kBAAC,GAAD,EACE,aAAa,EAAU,uCAAuC,MAAM,EACrE,CAAA;OACY,CAAA,GACf,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;QAAY,OAAO;kBAChB,EAAU,uCAAuC,MAAM;OAC9C,CAAA,GACX,EAAW,KAAK,MACf,kBAAC,GAAD;QAAuB,OAAO,EAAE;kBAC7B,EAAE;OACO,GAFK,EAAE,EAEP,CACb,CACY,EAAA,CAAA,CACT;QACL;;KAEJ,MAAS,UAAU,IAClB,kBAAC,GAAD;MACE,YAAW;MACX,UAAU;MACV,OAAO,EAAU,8BAA8B,MAAM;KACtD,CAAA,IAED,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD,EAAA,UAAQ,EAAU,8BAA8B,MAAM,EAAS,CAAA,GAC/D,kBAAC,KAAD;OAAG,WAAU;iBACV,EACC,yCACA,2CACF;MACC,CAAA,CACA;;KAGP,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD;OAAO,SAAQ;iBAAc,EAAU,+BAA+B,OAAO;MAAS,CAAA,GACtF,kBAAC,IAAD;OACE,IAAG;OACH,OAAO,EAAK;OACZ,WAAW,MAAM,EAAS,SAAS,EAAE,OAAO,KAAK;OACjD,MAAM;MACP,CAAA,CACE;;KAEL,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;MACE,MAAK;MACL,SAAQ;MACR,eAAe,EAAa,EAAK;MACjC,UAAU;gBAET,EAAU,gCAAgC,QAAQ;KAC7C,CAAA,GACR,kBAAC,GAAD;MAAQ,MAAK;MAAS,UAAU,CAAC,KAAS;gBACvC,IACG,EAAU,gCAAgC,SAAS,IACnD,MAAS,WACP,EAAU,gCAAgC,aAAa,IACvD,EAAU,8BAA8B,cAAc;KACtD,CAAA,CACc,EAAA,CAAA;IACpB;KACiB;;CACT,CAAA;AAEtB;AAUA,SAAS,GAAgB,EAAE,WAAQ,YAAS,gBAAmC;CAC7E,IAAM,EAAE,MAAM,GAAM,cAAW,aAAS,gBAAY,EAAQ,KAAU,KAAA,CAAS,GACzE,EAAE,MAAM,MAAa,EAAgB,KAAU,KAAA,CAAS,GACxD,EAAE,MAAM,MAAa,EAAY,GAEjC,IAAc,EAAmB,GACjC,IAAgB,EAAqB,GACrC,IAAS,EAAwB,GAEjC,CAAC,GAAW,KAAgB,EAAS,EAAE,GACvC,CAAC,GAAa,MAAkB,EAAsB,SAAS,GAC/D,CAAC,GAAc,MAAmB,EAAS,EAAE,GAC7C,CAAC,GAAc,MAAmB,EAAS,EAAE,GAC7C,CAAC,GAAW,KAAgB,EAAgC,IAAI,GAEhE,IAAc,EAAS,QAAQ,GAAG,MAAM,KAAK,EAAE,eAAe,IAAI,CAAC,GACnE,IAAW,GAAM,YAAY,OAC7B,KAAY,IAAO,GAAc,CAAI,IAAI,GACzC,KAAgB,IAAO,GAAS,EAAK,QAAQ,EAAK,UAAU,IAAI,SAChE,IAAmB,IACrB,GAAsB,GAAa,EAAK,qBAAqB,EAAK,UAAU,IAC5E,CAAC,GAEC,MAAe,MAAe,EAAS,MAAM,MAAM,EAAE,OAAO,CAAE,GAAG,QAAQ,GAEzE,WAAmB;EACvB,IAAI,CAAC,KAAU,CAAC,GAAW;EAC3B,IAAM,IAAU,OAAO,CAAY;EAC/B,CAAC,OAAO,SAAS,CAAO,KAAK,KAAW,KAC5C,EAAY,OACV;GACE;GACA;GACA,GAAI,MAAgB,YAAY,EAAE,eAAe,EAAQ,IAAI,EAAE,aAAa,EAAQ;EACtF,GACA,EACE,iBAAiB;GAEf,AADA,EAAa,EAAE,GACf,GAAgB,EAAE;EACpB,EACF,CACF;CACF,GAEM,UAAqB;EACzB,IAAI,CAAC,GAAQ;EACb,IAAM,IAAS,MAAiB,KAAK,IAAc,OAAO,CAAY;EACjE,OAAO,SAAS,CAAM,KAC3B,EAAO,OAAO;GAAE,IAAI;GAAQ,cAAc;EAAO,CAAC;CACpD,GAEM,IAAY,EAAQ,KAAc,OAAO,CAAY,IAAI,GAEzD,IAAiB,IACnB,EAAU,eAAe,OAEvB,GAAY,EAAU,SAAS,IAD/B,EAAY,EAAU,aAAa,CAAQ,IAE7C;CAEJ,OACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,IAAD;EACE,MAAM,EAAQ;EACd,eAAe,MAAM;GACnB,AAAK,KAAG,EAAQ;EAClB;YAEA,kBAAC,IAAD;GAAc,WAAU;aAAxB,CACE,kBAAC,IAAD,EAAA,UAAA,CACE,kBAAC,IAAD,EAAA,UACG,GAAM,QAAQ,EAAU,iCAAiC,MAAM,EACtD,CAAA,GACZ,kBAAC,IAAD,EAAA,UACG,EACC,oCACA,sCACF,EACgB,CAAA,CACP,EAAA,CAAA,GAEb,kBAAC,OAAD;IAAK,WAAU;cACZ,IACC,kBAAC,IAAD,EAAc,MAAM,EAAI,CAAA,IACtB,KACF,kBAAC,IAAD;KACE,OAAO,EAAU,iCAAiC,qBAAqB;KACvE,eAAe,GAAQ;IACxB,CAAA,IACE,IAMH,kBAAA,GAAA,EAAA,UAAA;KAEE,kBAAC,IAAD;MAAW,MAAA;MAAK,WAAU;gBAA1B,CACE,kBAAC,IAAD;OACE,OAAO;OACD;OACN,MAAM;OACN,aAAa;OACb,OAAO,EAAU,kCAAkC,QAAQ;MAC5D,CAAA,GACD,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,GAAD;SAAO,SAAS,GAAmB,EAAK,UAAU;mBAC/C,EAAS,EAAK,UAAU;QACpB,CAAA;QACP,kBAAC,KAAD;SAAG,WAAU;mBACV,EAAY,GAAa,CAAQ;QACjC,CAAA;QACH,kBAAC,KAAD;SAAG,WAAU;mBACV,EAAU,oCAAoC,sBAAsB,EACnE,QAAQ,GAAc,EAAK,cAAc,CAAQ,EACnD,CAAC;QACA,CAAA;OACA;QACI;;KAEX,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,GAAD;QACE,MAAM,kBAAC,GAAD;SAAQ,WAAU;SAAS,eAAY;QAAQ,CAAA;QACrD,OAAO,EAAU,kCAAkC,QAAQ;QAC3D,OAAO,EAAY,EAAK,cAAc,CAAQ;OAC/C,CAAA;OACD,kBAAC,GAAD;QACE,MAAM,kBAAC,GAAD;SAAQ,WAAU;SAAS,eAAY;QAAQ,CAAA;QACrD,OAAO,EAAU,kCAAkC,gBAAgB;QACnE,OAAO,EAAY,GAAa,CAAQ;OACzC,CAAA;OACD,kBAAC,GAAD;QACE,MAAM,kBAAC,IAAD;SAAO,WAAU;SAAS,eAAY;QAAQ,CAAA;QACpD,OAAO,EAAU,mCAAmC,SAAS;QAC7D,OAAO,EAAY,EAAK,qBAAqB,CAAQ;OACtD,CAAA;OACD,kBAAC,GAAD;QACE,MAAM,kBAAC,IAAD;SAAe,WAAU;SAAS,eAAY;QAAQ,CAAA;QAC5D,OAAO,EAAU,sCAAsC,aAAa;QACpE,OAAO,GAAW,EAAK,UAAU;OAClC,CAAA;MACE;;KAGJ,EAAiB,UAAU,IAC1B,kBAAC,WAAD;MAAS,WAAU;gBAAnB;OACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,IAAD;SAAW,WAAU;SAA6B,eAAY;QAAQ,CAAA,GACtE,kBAAC,MAAD;SAAI,WAAU;mBACX,EACC,2CACA,yBACF;QACE,CAAA,CACD;;OACL,kBAAC,IAAD;QACE,MAAM;QACN,QAAQ,EAAK;QACP;QACN,QAAQ;QACR,iBAAiB,MAAM,GAAc,GAAG,CAAQ;OACjD,CAAA;OACD,kBAAC,KAAD;QAAG,WAAU;kBACV,EACC,0CACA,sDACA;SACE,SAAS,EAAY,EAAK,qBAAqB,CAAQ;SACvD,MAAM,GAAW,EAAK,UAAU;QAClC,CACF;OACC,CAAA;MACI;UACP;KAGJ,kBAAC,WAAD;MAAS,WAAU;gBAAnB,CACE,kBAAC,MAAD;OAAI,WAAU;iBACX,EAAU,wCAAwC,iBAAiB;MAClE,CAAA,GACH,EAAS,WAAW,IACnB,kBAAC,KAAD;OAAG,WAAU;iBACV,EACC,sCACA,2CACF;MACC,CAAA,IAEH,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,IAAD,EAAA,UAAA,CACE,kBAAC,IAAD,EAAA,UACE,kBAAC,IAAD,EAAA,UAAA;QACE,kBAAC,GAAD,EAAA,UACG,EAAU,mCAAmC,SAAS,EAC9C,CAAA;QACX,kBAAC,GAAD;SAAW,WAAU;mBAClB,EAAU,sCAAsC,YAAY;QACpD,CAAA;QACX,kBAAC,GAAD;SAAW,WAAU;mBAClB,EAAU,uCAAuC,cAAc;QACvD,CAAA;QACX,kBAAC,GAAD,EAAW,WAAU,OAAQ,CAAA;OACrB,EAAA,CAAA,EACC,CAAA,GACb,kBAAC,IAAD,EAAA,UACG,EAAS,KAAK,MACb,kBAAC,IAAD,EAAA,UAAA;QACE,kBAAC,GAAD;SAAW,WAAU;mBAClB,GAAY,EAAE,SAAS;QACf,CAAA;QACX,kBAAC,GAAD;SAAW,WAAU;mBAClB,EAAE,eAAe,OAAO,EAAU,EAAE,aAAa,IAAI;QAC7C,CAAA;QACX,kBAAC,GAAD;SAAW,WAAU;mBAClB,EAAE,eAAe,OAA8C,MAAvC,EAAY,EAAE,aAAa,CAAQ;QACnD,CAAA;QACX,kBAAC,GAAD;SAAW,WAAU;mBACnB,kBAAC,GAAD;UACE,SAAQ;UACR,MAAK;UACL,cAAY,EACV,kCACA,gBACF;UACA,eAAe,EAAa,CAAC;oBAE7B,kBAAC,GAAD;WAAQ,WAAU;WAAS,eAAY;UAAQ,CAAA;SACzC,CAAA;QACC,CAAA;OACH,EAAA,GAvBK,EAAE,EAuBP,CACX,EACQ,CAAA,CACN,EAAA,CAAA;MACJ,CAAA,CAEA;;KAGT,kBAAC,WAAD;MAAS,WAAU;gBAAnB,CACE,kBAAC,MAAD;OAAI,WAAU;iBACX,EAAU,qCAAqC,iBAAiB;MAC/D,CAAA,GACH,EAAS,WAAW,IACnB,kBAAC,KAAD;OAAG,WAAU;iBACV,EACC,sCACA,gCACF;MACC,CAAA,IAEH,kBAAA,GAAA,EAAA,UAAA;OACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD;SAAO,SAAQ;mBACZ,EAAU,mCAAmC,SAAS;QAClD,CAAA,GACP,kBAAC,GAAD;SAAQ,OAAO;SAAW,eAAe;mBAAzC,CACE,kBAAC,GAAD;UAAe,IAAG;oBAChB,kBAAC,GAAD,EACE,aAAa,EACX,yCACA,gBACF,EACD,CAAA;SACY,CAAA,GACf,kBAAC,GAAD,EAAA,UACG,EAAS,KAAK,MACb,kBAAC,GAAD;UAAuB,OAAO,EAAE;oBAC7B,EAAE;SACO,GAFK,EAAE,EAEP,CACb,EACY,CAAA,CACT;UACL;;OACL,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UAAO,SAAQ;oBACZ,EAAU,gCAAgC,QAAQ;SAC9C,CAAA,GACP,kBAAC,GAAD;UACE,OAAO;UACP,gBAAgB,MAAM,GAAe,CAAgB;oBAFvD,CAIE,kBAAC,GAAD;WAAe,IAAG;qBAChB,kBAAC,GAAD,CAAc,CAAA;UACD,CAAA,GACf,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;WAAY,OAAM;qBACf,EAAU,mCAAmC,YAAY;UAChD,CAAA,GACZ,kBAAC,GAAD;WAAY,OAAM;qBACf,EAAU,iCAAiC,cAAc;UAChD,CAAA,CACC,EAAA,CAAA,CACT;WACL;YACL,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UAAO,SAAQ;oBACZ,MAAgB,YACb,EAAU,+BAA+B,SAAS,IAClD,EAAU,kCAAkC,QAAQ;SACnD,CAAA,GACP,kBAAC,GAAD;UACE,IAAG;UACH,MAAK;UACL,KAAK;UACL,MAAK;UACL,OAAO;UACP,WAAW,MAAM,GAAgB,EAAE,OAAO,KAAK;SAChD,CAAA,CACE;UACF;;OACL,kBAAC,GAAD;QACE,MAAK;QACL,WAAU;QACV,UAAU,CAAC,KAAa,EAAY;QACpC,SAAS;kBAJX,CAME,kBAAC,IAAD;SAAO,WAAU;SAAS,eAAY;QAAQ,CAAA,GAC7C,EAAY,YACT,EAAU,mCAAmC,UAAU,IACvD,EAAU,gCAAgC,cAAc,CACtD;;MACR,EAAA,CAAA,CAEG;;KAGT,kBAAC,IAAD,EAAA,UACE,kBAAC,IAAD;MAAa,WAAU;gBACrB,kBAAC,GAAD;OACE,YAAW;OACX,UAAU,EAAK;OACf,OAAO,EAAU,gCAAgC,MAAM;MACxD,CAAA;KACU,CAAA,EACT,CAAA;KAGN,kBAAC,WAAD;MAAS,WAAU;gBAAnB;OACE,kBAAC,MAAD;QAAI,WAAU;kBACX,EAAU,uCAAuC,wBAAwB;OACxE,CAAA;OACJ,kBAAC,OAAD;QAAK,WAAU;kBAAf;SACE,kBAAC,GAAD;UAAO,SAAQ;oBACZ,EAAU,wCAAwC,eAAe;SAC7D,CAAA;SACP,kBAAC,GAAD;UACE,IAAG;UACH,MAAK;UACL,KAAK;UACL,MAAK;UACL,OAAO;UACP,aAAa,OAAO,CAAW;UAC/B,WAAW,MAAM,GAAgB,EAAE,OAAO,KAAK;SAChD,CAAA;SACD,kBAAC,KAAD;UAAG,WAAU;oBACV,EACC,sCACA,wDACF;SACC,CAAA;QACA;;OACL,kBAAC,GAAD;QACE,MAAK;QACL,SAAQ;QACR,WAAU;QACV,UAAU,EAAO;QACjB,SAAS;kBALX,CAOE,kBAAC,IAAD;SAAW,WAAU;SAAS,eAAY;QAAQ,CAAA,GACjD,EAAO,YACJ,EAAU,yCAAyC,gBAAgB,IACnE,EAAU,kCAAkC,aAAa,CACvD;;MACD;;IACT,EAAA,CAAA,IA7RF,kBAAC,IAAD;KACE,MAAM,kBAAC,GAAD;MAAQ,WAAU;MAAS,eAAY;KAAQ,CAAA;KACrD,OAAO,EAAU,oCAAoC,gBAAgB;IACtE,CAAA;GA4RA,CAAA,CACO;;CACT,CAAA,GAEP,kBAAC,IAAD;EACE,MAAM,EAAQ;EACd,eAAe,MAAM;GACnB,AAAK,KAAG,EAAa,IAAI;EAC3B;EACA,OAAO,EAAU,uCAAuC,iBAAiB;EACzE,aAAa,EACX,yCACA,0DACA,EAAE,MAAM,EAAe,CACzB;EACA,cAAc,EAAU,kCAAkC,gBAAgB;EAC1E,cAAc,EAAU,qCAAqC,YAAY;EACzE,aAAA;EACA,SAAS,EAAc;EACvB,iBAAiB;GACV,KACL,EAAc,OAAO,EAAU,IAAI,EAAE,iBAAiB,EAAa,IAAI,EAAE,CAAC;EAC5E;CACD,CAAA,CACD,EAAA,CAAA;AAEN"}
|
|
@@ -7,7 +7,7 @@ import { useMemo as p, useState as m } from "react";
|
|
|
7
7
|
import { CheckCircle2 as h, Gauge as g, Layers as ie, PieChart as _, Plus as v, ShieldCheck as ae, Trash2 as oe, X as y } from "lucide-react";
|
|
8
8
|
import { useI18n as se } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
9
9
|
import { Fragment as ce, jsx as b, jsxs as x } from "react/jsx-runtime";
|
|
10
|
-
import { Badge as S, Button as C, Card as le, CardContent as ue, CardDescription as de, CardHeader as fe, CardTitle as pe,
|
|
10
|
+
import { Badge as S, Button as C, Card as le, CardContent as ue, CardDescription as de, CardHeader as fe, CardTitle as pe, Input as w, Label as T, ResponsiveDialog as E, ResponsiveDialogContent as D, ResponsiveDialogDescription as O, ResponsiveDialogFooter as k, ResponsiveDialogHeader as A, ResponsiveDialogTitle as j, Select as M, SelectContent as N, SelectItem as P, SelectTrigger as F, SelectValue as I, Textarea as me } from "@burdenoff/fe-libs/ui";
|
|
11
11
|
//#region src/brainyrich/pages/InvestmentsPage.tsx
|
|
12
12
|
var he = [
|
|
13
13
|
"CONSERVATIVE",
|
|
@@ -290,24 +290,24 @@ function H() {
|
|
|
290
290
|
})
|
|
291
291
|
})]
|
|
292
292
|
}),
|
|
293
|
-
/* @__PURE__ */ b(
|
|
293
|
+
/* @__PURE__ */ b(E, {
|
|
294
294
|
open: ye,
|
|
295
295
|
onOpenChange: (e) => {
|
|
296
296
|
U(e), e || Y();
|
|
297
297
|
},
|
|
298
|
-
children: /* @__PURE__ */ x(
|
|
298
|
+
children: /* @__PURE__ */ x(D, {
|
|
299
299
|
className: "max-h-[90vh] overflow-y-auto sm:max-w-lg",
|
|
300
300
|
children: [
|
|
301
|
-
/* @__PURE__ */ x(
|
|
301
|
+
/* @__PURE__ */ x(A, { children: [/* @__PURE__ */ b(j, { children: $ }), /* @__PURE__ */ b(O, { children: c("brainyrich.investments.form.subtitle", "Define a target allocation. Targets should sum to about 100%.") })] }),
|
|
302
302
|
/* @__PURE__ */ x("div", {
|
|
303
303
|
className: "space-y-4 py-2",
|
|
304
304
|
children: [
|
|
305
305
|
/* @__PURE__ */ x("div", {
|
|
306
306
|
className: "space-y-2",
|
|
307
|
-
children: [/* @__PURE__ */ b(
|
|
307
|
+
children: [/* @__PURE__ */ b(T, {
|
|
308
308
|
htmlFor: "bra-model-name",
|
|
309
309
|
children: c("brainyrich.investments.form.name", "Name")
|
|
310
|
-
}), /* @__PURE__ */ b(
|
|
310
|
+
}), /* @__PURE__ */ b(w, {
|
|
311
311
|
id: "bra-model-name",
|
|
312
312
|
value: W,
|
|
313
313
|
onChange: (e) => Se(e.target.value),
|
|
@@ -318,7 +318,7 @@ function H() {
|
|
|
318
318
|
className: "grid gap-4 sm:grid-cols-2",
|
|
319
319
|
children: [/* @__PURE__ */ x("div", {
|
|
320
320
|
className: "space-y-2",
|
|
321
|
-
children: [/* @__PURE__ */ b(
|
|
321
|
+
children: [/* @__PURE__ */ b(T, {
|
|
322
322
|
htmlFor: "bra-model-risk",
|
|
323
323
|
children: c("brainyrich.investments.form.risk", "Risk profile")
|
|
324
324
|
}), /* @__PURE__ */ x(M, {
|
|
@@ -334,10 +334,10 @@ function H() {
|
|
|
334
334
|
})]
|
|
335
335
|
}), /* @__PURE__ */ x("div", {
|
|
336
336
|
className: "space-y-2",
|
|
337
|
-
children: [/* @__PURE__ */ b(
|
|
337
|
+
children: [/* @__PURE__ */ b(T, {
|
|
338
338
|
htmlFor: "bra-model-currency",
|
|
339
339
|
children: c("brainyrich.investments.form.currency", "Base currency")
|
|
340
|
-
}), /* @__PURE__ */ b(
|
|
340
|
+
}), /* @__PURE__ */ b(w, {
|
|
341
341
|
id: "bra-model-currency",
|
|
342
342
|
value: Te,
|
|
343
343
|
onChange: (e) => Ee(e.target.value.toUpperCase().slice(0, 3)),
|
|
@@ -347,7 +347,7 @@ function H() {
|
|
|
347
347
|
}),
|
|
348
348
|
/* @__PURE__ */ x("div", {
|
|
349
349
|
className: "space-y-2",
|
|
350
|
-
children: [/* @__PURE__ */ b(
|
|
350
|
+
children: [/* @__PURE__ */ b(T, {
|
|
351
351
|
htmlFor: "bra-model-desc",
|
|
352
352
|
children: c("brainyrich.investments.form.description", "Description")
|
|
353
353
|
}), /* @__PURE__ */ b(me, {
|
|
@@ -363,7 +363,7 @@ function H() {
|
|
|
363
363
|
children: [
|
|
364
364
|
/* @__PURE__ */ x("div", {
|
|
365
365
|
className: "flex items-center justify-between",
|
|
366
|
-
children: [/* @__PURE__ */ b(
|
|
366
|
+
children: [/* @__PURE__ */ b(T, { children: c("brainyrich.investments.form.allocations", "Target allocations") }), /* @__PURE__ */ x("span", {
|
|
367
367
|
className: `inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium ${Z ? "bg-status-success-bg text-status-success-text" : "bg-status-warning-bg text-status-warning-text"}`,
|
|
368
368
|
children: [Z ? /* @__PURE__ */ b(h, {
|
|
369
369
|
className: "size-3",
|
|
@@ -408,7 +408,7 @@ function H() {
|
|
|
408
408
|
children: L(e)
|
|
409
409
|
}, e)) })]
|
|
410
410
|
}),
|
|
411
|
-
/* @__PURE__ */ b(
|
|
411
|
+
/* @__PURE__ */ b(w, {
|
|
412
412
|
type: "number",
|
|
413
413
|
inputMode: "decimal",
|
|
414
414
|
min: 0,
|
|
@@ -454,7 +454,7 @@ function H() {
|
|
|
454
454
|
}) : null
|
|
455
455
|
]
|
|
456
456
|
}),
|
|
457
|
-
/* @__PURE__ */ x(
|
|
457
|
+
/* @__PURE__ */ x(k, { children: [/* @__PURE__ */ b(C, {
|
|
458
458
|
variant: "outline",
|
|
459
459
|
onClick: () => {
|
|
460
460
|
U(!1), Y();
|
|
@@ -482,16 +482,16 @@ function ve({ id: e, onClose: t, translate: r }) {
|
|
|
482
482
|
value: e.targetPct,
|
|
483
483
|
tone: R[t % R.length]
|
|
484
484
|
})), p = B(a?.allocations ?? []), m = [...a?.allocations ?? []].sort((e, t) => t.targetPct - e.targetPct)[0];
|
|
485
|
-
return /* @__PURE__ */ b(
|
|
485
|
+
return /* @__PURE__ */ b(E, {
|
|
486
486
|
open: !!e,
|
|
487
487
|
onOpenChange: (e) => e ? void 0 : t(),
|
|
488
|
-
children: /* @__PURE__ */ x(
|
|
488
|
+
children: /* @__PURE__ */ x(D, {
|
|
489
489
|
className: "max-h-[90vh] overflow-y-auto sm:max-w-lg",
|
|
490
490
|
children: [
|
|
491
|
-
/* @__PURE__ */ x(
|
|
491
|
+
/* @__PURE__ */ x(A, { children: [/* @__PURE__ */ b(j, {
|
|
492
492
|
className: "flex items-center justify-between gap-2 pr-6",
|
|
493
493
|
children: a?.name ?? r("brainyrich.investments.detail.title", "Model portfolio")
|
|
494
|
-
}), a?.description ? /* @__PURE__ */ b(
|
|
494
|
+
}), a?.description ? /* @__PURE__ */ b(O, { children: a.description }) : null] }),
|
|
495
495
|
o ? /* @__PURE__ */ b(l, { rows: 3 }) : ee ? /* @__PURE__ */ b(ne, {
|
|
496
496
|
title: r("brainyrich.investments.detail.error", "Could not load this model"),
|
|
497
497
|
onRetry: () => s()
|
|
@@ -558,7 +558,7 @@ function ve({ id: e, onClose: t, translate: r }) {
|
|
|
558
558
|
}),
|
|
559
559
|
title: r("brainyrich.investments.detail.notFound", "Model not found")
|
|
560
560
|
}),
|
|
561
|
-
/* @__PURE__ */ b(
|
|
561
|
+
/* @__PURE__ */ b(k, { children: /* @__PURE__ */ b(C, {
|
|
562
562
|
variant: "outline",
|
|
563
563
|
onClick: t,
|
|
564
564
|
children: r("brainyrich.investments.detail.close", "Close")
|