@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":"DashboardPage.js","names":[],"sources":["../../../src/brainyrich/pages/DashboardPage.tsx"],"sourcesContent":["import { useMemo, useState, type FormEvent, type ReactNode } from 'react';\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n CardDescription,\n Button,\n Badge,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport {\n Target,\n Bell,\n Briefcase,\n Wallet,\n PlusCircle,\n MoreHorizontal,\n Check,\n X,\n CircleCheck,\n TrendingUp,\n Coins,\n Landmark,\n TriangleAlert,\n Info,\n ShieldAlert,\n} from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../utils/i18n';\nimport {\n useNetWorthSummary,\n usePortfolios,\n useGoals,\n useInsights,\n useCreateAccount,\n useAcknowledgeInsight,\n useDismissInsight,\n useResolveInsight,\n} from '../hooks/useBrainyRichApi';\nimport type {\n BraAccountType,\n BraAssetClass,\n BraCreateAccountInput,\n BraInsight,\n BraInsightSeverity,\n} from '../types/bra';\nimport {\n HouseholdPicker,\n ConfirmDialog,\n DonutChart,\n StatTile,\n GlassCard,\n FadeIn,\n type VizTone,\n type DonutDatum,\n} from '../components';\nimport {\n SectionShell,\n EmptyState,\n LoadingState,\n ErrorState,\n formatMoney,\n formatCompact,\n formatDate,\n statusBadgeVariant,\n} from './_shared';\nimport { hapticSuccess, showToast } from '../utils/nativeControls';\nimport { useTrackBrainyRichPageView } from '../hooks/useBrainyRichAnalytics';\n\nconst ACCOUNT_TYPES: BraAccountType[] = [\n 'BANK',\n 'BROKERAGE',\n 'RETIREMENT',\n 'CASH',\n 'CRYPTO',\n 'REAL_ESTATE',\n 'ALTERNATIVE',\n 'LIABILITY',\n];\n\n/** Distinct, semantic tone per asset class so the donut stays legible + on-brand. */\nconst ASSET_TONE: Record<BraAssetClass, VizTone> = {\n EQUITY: 'brand',\n FIXED_INCOME: 'blue',\n CASH: 'teal',\n REAL_ESTATE: 'indigo',\n COMMODITY: 'warning',\n CRYPTO: 'purple',\n ALTERNATIVE: 'info',\n};\n\n/** Title-case an enum member: FIXED_INCOME → \"Fixed income\". */\nfunction prettyLabel(value: string): string {\n const spaced = value.replace(/_/g, ' ').toLowerCase();\n return spaced.charAt(0).toUpperCase() + spaced.slice(1);\n}\n\nexport function DashboardPage() {\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.dashboard.viewed');\n\n const summaryQuery = useNetWorthSummary();\n const portfoliosQuery = usePortfolios();\n const goalsQuery = useGoals();\n const insightsQuery = useInsights({ status: 'OPEN' });\n\n const summary = summaryQuery.data;\n const currency = summary?.currency ?? 'USD';\n\n const kpis: HeroStat[] = summary\n ? [\n {\n label: translate('brainyrich.dashboard.metrics.netWorth', 'Net Worth'),\n value: formatCompact(summary.totalNetWorth, currency),\n icon: <Wallet className=\"size-4\" aria-hidden=\"true\" />,\n glow: true,\n },\n {\n label: translate('brainyrich.dashboard.metrics.investedAssets', 'Invested Assets'),\n value: formatCompact(summary.totalMarketValue, currency),\n icon: <TrendingUp className=\"size-4\" aria-hidden=\"true\" />,\n },\n {\n label: translate('brainyrich.dashboard.metrics.liquidity', 'Cash & Liquidity'),\n value: formatCompact(summary.totalCash, currency),\n icon: <Coins className=\"size-4\" aria-hidden=\"true\" />,\n },\n {\n label: translate('brainyrich.dashboard.metrics.accounts', 'Linked Accounts'),\n value: String(summary.accountCount),\n icon: <Landmark className=\"size-4\" aria-hidden=\"true\" />,\n },\n ]\n : [];\n\n const donutData: DonutDatum[] = useMemo(() => {\n if (!summary) return [];\n return summary.byAssetClass\n .filter((row) => Number.isFinite(row.marketValue) && row.marketValue > 0)\n .slice()\n .sort((a, b) => b.marketValue - a.marketValue)\n .map((row) => ({\n label: prettyLabel(row.assetClass),\n value: row.marketValue,\n tone: ASSET_TONE[row.assetClass],\n }));\n }, [summary]);\n\n const topPortfolios = portfoliosQuery.data.slice(0, 5);\n const topGoals = goalsQuery.data.slice(0, 5);\n const openInsights = insightsQuery.data.slice(0, 6);\n\n return (\n <div data-tour=\"brainyrich-page-dashboard\" className=\"contents\">\n <SectionShell\n title={translate('brainyrich.dashboard.title', 'Wealth Dashboard')}\n description={translate(\n 'brainyrich.dashboard.description',\n 'Your consolidated financial overview at a glance'\n )}\n actions={<NewAccountDialog translate={translate} />}\n >\n {/* Hero KPI row — net-worth overview */}\n {summaryQuery.isLoading ? (\n <LoadingState rows={1} />\n ) : summaryQuery.isError ? (\n <ErrorState\n title={translate('brainyrich.dashboard.netWorthError', 'Could not load net worth')}\n onRetry={() => summaryQuery.refetch()}\n />\n ) : summary ? (\n <div className=\"grid gap-4 sm:grid-cols-2 xl:grid-cols-4\">\n {kpis.map((kpi, i) => (\n <FadeIn key={kpi.label} index={i}>\n <StatTile\n label={kpi.label}\n value={kpi.value}\n icon={kpi.icon}\n glow={kpi.glow}\n className=\"h-full\"\n />\n </FadeIn>\n ))}\n </div>\n ) : (\n <EmptyState\n icon={<Wallet className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.dashboard.noSummary', 'No financial data yet')}\n description={translate(\n 'brainyrich.dashboard.noSummaryDesc',\n 'Link your first account to see your net worth here.'\n )}\n />\n )}\n\n <div className=\"grid gap-6 lg:grid-cols-3\">\n {/* Net worth by asset class — donut hero */}\n <FadeIn index={0} className=\"lg:col-span-2\">\n <GlassCard className=\"h-full\">\n <div className=\"mb-4 space-y-1\">\n <h2 className=\"flex items-center gap-2 text-base font-semibold text-text-primary\">\n <Briefcase className=\"size-5\" aria-hidden=\"true\" />\n {translate(\n 'brainyrich.dashboard.sections.assetAllocation',\n 'Net worth by asset class'\n )}\n </h2>\n <p className=\"text-sm text-text-secondary\">\n {translate(\n 'brainyrich.dashboard.sections.assetAllocationDescription',\n 'Market value distributed across asset classes'\n )}\n </p>\n </div>\n {summaryQuery.isLoading ? (\n <LoadingState rows={3} />\n ) : summaryQuery.isError ? (\n <ErrorState onRetry={() => summaryQuery.refetch()} />\n ) : donutData.length > 0 ? (\n <DonutChart\n data={donutData}\n height={260}\n centerValue={formatCompact(summary?.totalMarketValue ?? 0, currency)}\n centerLabel={translate('brainyrich.dashboard.metrics.investedAssets', 'Invested')}\n valueFormatter={(v) => formatMoney(v, currency)}\n />\n ) : (\n <EmptyState\n icon={<Briefcase className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.dashboard.noAllocation', 'No holdings to allocate')}\n description={translate(\n 'brainyrich.dashboard.noAllocationDesc',\n 'Add holdings to your accounts to see how your wealth is allocated.'\n )}\n />\n )}\n </GlassCard>\n </FadeIn>\n\n {/* Right rail — needs attention + goals */}\n <div className=\"space-y-6\">\n {/* Needs attention — open insights */}\n <FadeIn index={1}>\n <Card className=\"motion-safe:transition-shadow motion-safe:hover:shadow-[var(--shadow-pop-hover,var(--shadow-elevation-2))]\">\n <CardHeader className=\"pb-3\">\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <Bell className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.sections.needsAttention', 'Needs attention')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2.5\">\n {insightsQuery.isLoading ? (\n <LoadingState rows={2} />\n ) : insightsQuery.isError ? (\n <ErrorState onRetry={() => insightsQuery.refetch()} />\n ) : openInsights.length > 0 ? (\n openInsights.map((insight) => (\n <InsightRow key={insight.id} insight={insight} translate={translate} />\n ))\n ) : (\n <EmptyState\n icon={<CircleCheck className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.dashboard.noInsights', 'All clear')}\n description={translate(\n 'brainyrich.dashboard.noInsightsDesc',\n 'There are no open insights that need your attention.'\n )}\n />\n )}\n </CardContent>\n </Card>\n </FadeIn>\n\n {/* Goals on track */}\n <FadeIn index={2}>\n <Card className=\"motion-safe:transition-shadow motion-safe:hover:shadow-[var(--shadow-pop-hover,var(--shadow-elevation-2))]\">\n <CardHeader className=\"pb-3\">\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <Target className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.sections.goals', 'Goals on track')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2.5\">\n {goalsQuery.isLoading ? (\n <LoadingState rows={3} />\n ) : goalsQuery.isError ? (\n <ErrorState onRetry={() => goalsQuery.refetch()} />\n ) : topGoals.length > 0 ? (\n topGoals.map((goal) => (\n <div\n key={goal.id}\n className=\"flex items-start justify-between gap-2 rounded-lg border border-border-subtle p-3 motion-safe:transition-colors hover:border-[var(--color-action-primary-border)]/50 hover:bg-bg-elevated\"\n >\n <div className=\"min-w-0 space-y-0.5\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {goal.name}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {formatMoney(goal.targetAmount, goal.currency)}\n {' · '}\n {formatDate(goal.targetDate)}\n </p>\n </div>\n <Badge variant={statusBadgeVariant(goal.projection)} className=\"shrink-0\">\n {prettyLabel(goal.projection)}\n </Badge>\n </div>\n ))\n ) : (\n <EmptyState\n icon={<Target className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.dashboard.noGoals', 'No goals yet')}\n description={translate(\n 'brainyrich.dashboard.noGoalsDesc',\n 'Set a financial goal to start tracking progress.'\n )}\n />\n )}\n </CardContent>\n </Card>\n </FadeIn>\n </div>\n </div>\n\n {/* Portfolios mini-list */}\n <FadeIn index={3}>\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <Wallet className=\"size-5\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.sections.portfolios', 'Portfolios')}\n </CardTitle>\n <CardDescription>\n {translate(\n 'brainyrich.dashboard.sections.portfoliosDescription',\n 'Your active investment strategies'\n )}\n </CardDescription>\n </CardHeader>\n <CardContent>\n {portfoliosQuery.isLoading ? (\n <LoadingState rows={3} />\n ) : portfoliosQuery.isError ? (\n <ErrorState onRetry={() => portfoliosQuery.refetch()} />\n ) : topPortfolios.length > 0 ? (\n <div className=\"grid gap-3 sm:grid-cols-2\">\n {topPortfolios.map((portfolio) => (\n <div\n key={portfolio.id}\n className=\"flex items-start justify-between gap-2 rounded-lg border border-border-subtle p-3 motion-safe:transition-colors hover:border-[var(--color-action-primary-border)]/50 hover:bg-bg-elevated\"\n >\n <div className=\"min-w-0 space-y-0.5\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {portfolio.name}\n </p>\n {portfolio.description ? (\n <p className=\"truncate text-xs text-text-secondary\">\n {portfolio.description}\n </p>\n ) : (\n <p className=\"text-xs text-text-secondary\">{portfolio.baseCurrency}</p>\n )}\n </div>\n <Badge variant={statusBadgeVariant(portfolio.status)} className=\"shrink-0\">\n {portfolio.status}\n </Badge>\n </div>\n ))}\n </div>\n ) : (\n <EmptyState\n icon={<Wallet className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.dashboard.noPortfolios', 'No portfolios yet')}\n description={translate(\n 'brainyrich.dashboard.noPortfoliosDesc',\n 'Create a portfolio to organize your investment strategy.'\n )}\n />\n )}\n </CardContent>\n </Card>\n </FadeIn>\n </SectionShell>\n </div>\n );\n}\n\ninterface HeroStat {\n label: string;\n value: string;\n icon: ReactNode;\n glow?: boolean;\n}\n\ntype Translate = (\n key: string,\n fallback: string,\n params?: Record<string, string | number>\n) => string;\n\n// ============================================================================\n// Severity chip — tinted, icon + label (colour is never the only signal)\n// ============================================================================\n\nconst SEVERITY_STYLE: Record<BraInsightSeverity, { chip: string; rail: string; icon: ReactNode }> =\n {\n CRITICAL: {\n chip: 'text-status-error-text bg-status-error-bg',\n rail: 'bg-status-error',\n icon: <ShieldAlert className=\"size-3\" aria-hidden=\"true\" />,\n },\n HIGH: {\n chip: 'text-status-error-text bg-status-error-bg',\n rail: 'bg-status-error',\n icon: <TriangleAlert className=\"size-3\" aria-hidden=\"true\" />,\n },\n MEDIUM: {\n chip: 'text-status-warning-text bg-status-warning-bg',\n rail: 'bg-status-warning',\n icon: <TriangleAlert className=\"size-3\" aria-hidden=\"true\" />,\n },\n LOW: {\n chip: 'text-status-info-text bg-status-info-bg',\n rail: 'bg-status-info',\n icon: <Info className=\"size-3\" aria-hidden=\"true\" />,\n },\n INFO: {\n chip: 'text-status-info-text bg-status-info-bg',\n rail: 'bg-status-info',\n icon: <Info className=\"size-3\" aria-hidden=\"true\" />,\n },\n };\n\nfunction SeverityChip({ severity }: { severity: BraInsightSeverity }) {\n const style = SEVERITY_STYLE[severity] ?? SEVERITY_STYLE.INFO;\n return (\n <span\n className={`inline-flex shrink-0 items-center gap-1 rounded-full px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide ${style.chip}`}\n >\n {style.icon}\n {severity}\n </span>\n );\n}\n\n// ============================================================================\n// Insight row with acknowledge / dismiss / resolve actions\n// ============================================================================\n\nfunction InsightRow({ insight, translate }: { insight: BraInsight; translate: Translate }) {\n const acknowledge = useAcknowledgeInsight();\n const dismiss = useDismissInsight();\n const resolve = useResolveInsight();\n const [confirmDismiss, setConfirmDismiss] = useState(false);\n const pending = acknowledge.isPending || dismiss.isPending || resolve.isPending;\n const rail = (SEVERITY_STYLE[insight.severity] ?? SEVERITY_STYLE.INFO).rail;\n\n return (\n <div className=\"relative flex items-start justify-between gap-3 overflow-hidden rounded-lg border border-border-subtle p-3 pl-4 motion-safe:transition-colors hover:border-[var(--color-action-primary-border)]/50 hover:bg-bg-elevated\">\n <span aria-hidden=\"true\" className={`absolute inset-y-0 left-0 w-1 ${rail}`} />\n <div className=\"min-w-0 space-y-1\">\n <div className=\"flex items-center gap-2\">\n <SeverityChip severity={insight.severity} />\n <span className=\"truncate text-xs text-text-secondary\">{prettyLabel(insight.type)}</span>\n </div>\n <p className=\"text-sm font-medium text-text-primary\">{insight.title}</p>\n {insight.detail ? <p className=\"text-xs text-text-secondary\">{insight.detail}</p> : null}\n </div>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"shrink-0\"\n disabled={pending}\n aria-label={translate('brainyrich.dashboard.insightActions', 'Insight actions')}\n >\n <MoreHorizontal className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem onSelect={() => acknowledge.mutate(insight.id)}>\n <Check className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.insight.acknowledge', 'Acknowledge')}\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={() => resolve.mutate(insight.id)}>\n <CircleCheck className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.insight.resolve', 'Resolve')}\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={() => setConfirmDismiss(true)}>\n <X className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.insight.dismiss', 'Dismiss')}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n\n <ConfirmDialog\n open={confirmDismiss}\n onOpenChange={setConfirmDismiss}\n title={translate('brainyrich.dashboard.insight.dismissTitle', 'Dismiss this insight?')}\n description={translate(\n 'brainyrich.dashboard.insight.dismissDescription',\n 'It will be removed from Needs Attention. You can still find it in the full insights list.'\n )}\n confirmLabel={translate('brainyrich.dashboard.insight.dismiss', 'Dismiss')}\n pendingLabel={translate('brainyrich.dashboard.insight.dismissing', 'Dismissing…')}\n destructive\n pending={dismiss.isPending}\n onConfirm={() =>\n dismiss.mutate(insight.id, {\n onSuccess: () => setConfirmDismiss(false),\n })\n }\n />\n </div>\n );\n}\n\n// ============================================================================\n// New account dialog — primary create action\n// ============================================================================\n\nfunction NewAccountDialog({ translate }: { translate: Translate }) {\n const [open, setOpen] = useState(false);\n const [name, setName] = useState('');\n const [type, setType] = useState<BraAccountType>('BROKERAGE');\n const [institution, setInstitution] = useState('');\n const [cashBalance, setCashBalance] = useState('');\n const [currency, setCurrency] = useState('USD');\n const [householdId, setHouseholdId] = useState<string | null>(null);\n\n const createAccount = useCreateAccount();\n const trimmedName = name.trim();\n const canSubmit = trimmedName.length > 0 && !createAccount.isPending;\n\n const reset = () => {\n setName('');\n setType('BROKERAGE');\n setInstitution('');\n setCashBalance('');\n setCurrency('USD');\n setHouseholdId(null);\n createAccount.reset();\n };\n\n const handleSubmit = (event: FormEvent) => {\n event.preventDefault();\n if (!canSubmit) return;\n const parsedCash = Number.parseFloat(cashBalance);\n const input: BraCreateAccountInput = {\n name: trimmedName,\n type,\n currency: currency.trim() || 'USD',\n isManual: true,\n ...(institution.trim() ? { institution: institution.trim() } : {}),\n ...(Number.isFinite(parsedCash) ? { cashBalance: parsedCash } : {}),\n ...(householdId ? { householdId } : {}),\n };\n createAccount.mutate(input, {\n onSuccess: () => {\n hapticSuccess();\n void showToast(translate('brainyrich.dashboard.newAccount.success', 'Account created'));\n reset();\n setOpen(false);\n },\n });\n };\n\n return (\n <Dialog\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (!next) reset();\n }}\n >\n <Button size=\"sm\" onClick={() => setOpen(true)}>\n <PlusCircle className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.actions.newAccount', 'New Account')}\n </Button>\n <DialogContent>\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n <DialogHeader>\n <DialogTitle>\n {translate('brainyrich.dashboard.newAccount.title', 'New Account')}\n </DialogTitle>\n <DialogDescription>\n {translate(\n 'brainyrich.dashboard.newAccount.description',\n 'Add a manual account to track alongside your linked institutions.'\n )}\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-account-name\">\n {translate('brainyrich.dashboard.newAccount.name', 'Account name')}\n </Label>\n <Input\n id=\"bra-account-name\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder={translate(\n 'brainyrich.dashboard.newAccount.namePlaceholder',\n 'e.g. Fidelity Brokerage'\n )}\n required\n autoFocus\n />\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-account-type\">\n {translate('brainyrich.dashboard.newAccount.type', 'Type')}\n </Label>\n <Select value={type} onValueChange={(value) => setType(value as BraAccountType)}>\n <SelectTrigger id=\"bra-account-type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {ACCOUNT_TYPES.map((accountType) => (\n <SelectItem key={accountType} value={accountType}>\n {accountType.replace(/_/g, ' ')}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-account-currency\">\n {translate('brainyrich.dashboard.newAccount.currency', 'Currency')}\n </Label>\n <Input\n id=\"bra-account-currency\"\n value={currency}\n onChange={(e) => setCurrency(e.target.value.toUpperCase())}\n maxLength={3}\n />\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-account-institution\">\n {translate('brainyrich.dashboard.newAccount.institution', 'Institution (optional)')}\n </Label>\n <Input\n id=\"bra-account-institution\"\n value={institution}\n onChange={(e) => setInstitution(e.target.value)}\n placeholder={translate(\n 'brainyrich.dashboard.newAccount.institutionPlaceholder',\n 'e.g. Fidelity'\n )}\n />\n </div>\n\n <HouseholdPicker\n id=\"bra-account-household\"\n value={householdId}\n onChange={setHouseholdId}\n label={translate('brainyrich.dashboard.newAccount.household', 'Household (optional)')}\n noneLabel={translate('brainyrich.dashboard.newAccount.noHousehold', 'No household')}\n disabled={createAccount.isPending}\n />\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-account-cash\">\n {translate('brainyrich.dashboard.newAccount.cash', 'Cash balance (optional)')}\n </Label>\n <Input\n id=\"bra-account-cash\"\n type=\"number\"\n inputMode=\"decimal\"\n step=\"0.01\"\n value={cashBalance}\n onChange={(e) => setCashBalance(e.target.value)}\n placeholder=\"0.00\"\n />\n </div>\n\n {createAccount.isError ? (\n <p className=\"text-sm text-status-error-text\">\n {createAccount.error instanceof Error\n ? createAccount.error.message\n : translate('brainyrich.dashboard.newAccount.error', 'Could not create account.')}\n </p>\n ) : null}\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => setOpen(false)}\n disabled={createAccount.isPending}\n >\n {translate('brainyrich.common.cancel', 'Cancel')}\n </Button>\n <Button type=\"submit\" disabled={!canSubmit}>\n {createAccount.isPending\n ? translate('brainyrich.dashboard.newAccount.creating', 'Creating…')\n : translate('brainyrich.dashboard.newAccount.create', 'Create account')}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DashboardPage.js","names":[],"sources":["../../../src/brainyrich/pages/DashboardPage.tsx"],"sourcesContent":["import { useMemo, useState, type FormEvent, type ReactNode } from 'react';\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n CardDescription,\n Button,\n Badge,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport {\n Target,\n Bell,\n Briefcase,\n Wallet,\n PlusCircle,\n MoreHorizontal,\n Check,\n X,\n CircleCheck,\n TrendingUp,\n Coins,\n Landmark,\n TriangleAlert,\n Info,\n ShieldAlert,\n} from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../utils/i18n';\nimport {\n useNetWorthSummary,\n usePortfolios,\n useGoals,\n useInsights,\n useCreateAccount,\n useAcknowledgeInsight,\n useDismissInsight,\n useResolveInsight,\n} from '../hooks/useBrainyRichApi';\nimport type {\n BraAccountType,\n BraAssetClass,\n BraCreateAccountInput,\n BraInsight,\n BraInsightSeverity,\n} from '../types/bra';\nimport {\n HouseholdPicker,\n ConfirmDialog,\n DonutChart,\n StatTile,\n GlassCard,\n FadeIn,\n type VizTone,\n type DonutDatum,\n} from '../components';\nimport {\n SectionShell,\n EmptyState,\n LoadingState,\n ErrorState,\n formatMoney,\n formatCompact,\n formatDate,\n statusBadgeVariant,\n} from './_shared';\nimport { hapticSuccess, showToast } from '../utils/nativeControls';\nimport { useTrackBrainyRichPageView } from '../hooks/useBrainyRichAnalytics';\n\nconst ACCOUNT_TYPES: BraAccountType[] = [\n 'BANK',\n 'BROKERAGE',\n 'RETIREMENT',\n 'CASH',\n 'CRYPTO',\n 'REAL_ESTATE',\n 'ALTERNATIVE',\n 'LIABILITY',\n];\n\n/** Distinct, semantic tone per asset class so the donut stays legible + on-brand. */\nconst ASSET_TONE: Record<BraAssetClass, VizTone> = {\n EQUITY: 'brand',\n FIXED_INCOME: 'blue',\n CASH: 'teal',\n REAL_ESTATE: 'indigo',\n COMMODITY: 'warning',\n CRYPTO: 'purple',\n ALTERNATIVE: 'info',\n};\n\n/** Title-case an enum member: FIXED_INCOME → \"Fixed income\". */\nfunction prettyLabel(value: string): string {\n const spaced = value.replace(/_/g, ' ').toLowerCase();\n return spaced.charAt(0).toUpperCase() + spaced.slice(1);\n}\n\nexport function DashboardPage() {\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.dashboard.viewed');\n\n const summaryQuery = useNetWorthSummary();\n const portfoliosQuery = usePortfolios();\n const goalsQuery = useGoals();\n const insightsQuery = useInsights({ status: 'OPEN' });\n\n const summary = summaryQuery.data;\n const currency = summary?.currency ?? 'USD';\n\n const kpis: HeroStat[] = summary\n ? [\n {\n label: translate('brainyrich.dashboard.metrics.netWorth', 'Net Worth'),\n value: formatCompact(summary.totalNetWorth, currency),\n icon: <Wallet className=\"size-4\" aria-hidden=\"true\" />,\n glow: true,\n },\n {\n label: translate('brainyrich.dashboard.metrics.investedAssets', 'Invested Assets'),\n value: formatCompact(summary.totalMarketValue, currency),\n icon: <TrendingUp className=\"size-4\" aria-hidden=\"true\" />,\n },\n {\n label: translate('brainyrich.dashboard.metrics.liquidity', 'Cash & Liquidity'),\n value: formatCompact(summary.totalCash, currency),\n icon: <Coins className=\"size-4\" aria-hidden=\"true\" />,\n },\n {\n label: translate('brainyrich.dashboard.metrics.accounts', 'Linked Accounts'),\n value: String(summary.accountCount),\n icon: <Landmark className=\"size-4\" aria-hidden=\"true\" />,\n },\n ]\n : [];\n\n const donutData: DonutDatum[] = useMemo(() => {\n if (!summary) return [];\n return summary.byAssetClass\n .filter((row) => Number.isFinite(row.marketValue) && row.marketValue > 0)\n .slice()\n .sort((a, b) => b.marketValue - a.marketValue)\n .map((row) => ({\n label: prettyLabel(row.assetClass),\n value: row.marketValue,\n tone: ASSET_TONE[row.assetClass],\n }));\n }, [summary]);\n\n const topPortfolios = portfoliosQuery.data.slice(0, 5);\n const topGoals = goalsQuery.data.slice(0, 5);\n const openInsights = insightsQuery.data.slice(0, 6);\n\n return (\n <div data-tour=\"brainyrich-page-dashboard\" className=\"contents\">\n <SectionShell\n title={translate('brainyrich.dashboard.title', 'Wealth Dashboard')}\n description={translate(\n 'brainyrich.dashboard.description',\n 'Your consolidated financial overview at a glance'\n )}\n actions={<NewAccountDialog translate={translate} />}\n >\n {/* Hero KPI row — net-worth overview */}\n {summaryQuery.isLoading ? (\n <LoadingState rows={1} />\n ) : summaryQuery.isError ? (\n <ErrorState\n title={translate('brainyrich.dashboard.netWorthError', 'Could not load net worth')}\n onRetry={() => summaryQuery.refetch()}\n />\n ) : summary ? (\n <div className=\"grid gap-4 sm:grid-cols-2 xl:grid-cols-4\">\n {kpis.map((kpi, i) => (\n <FadeIn key={kpi.label} index={i}>\n <StatTile\n label={kpi.label}\n value={kpi.value}\n icon={kpi.icon}\n glow={kpi.glow}\n className=\"h-full\"\n />\n </FadeIn>\n ))}\n </div>\n ) : (\n <EmptyState\n icon={<Wallet className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.dashboard.noSummary', 'No financial data yet')}\n description={translate(\n 'brainyrich.dashboard.noSummaryDesc',\n 'Link your first account to see your net worth here.'\n )}\n />\n )}\n\n <div className=\"grid gap-6 lg:grid-cols-3\">\n {/* Net worth by asset class — donut hero */}\n <FadeIn index={0} className=\"lg:col-span-2\">\n <GlassCard className=\"h-full\">\n <div className=\"mb-4 space-y-1\">\n <h2 className=\"flex items-center gap-2 text-base font-semibold text-text-primary\">\n <Briefcase className=\"size-5\" aria-hidden=\"true\" />\n {translate(\n 'brainyrich.dashboard.sections.assetAllocation',\n 'Net worth by asset class'\n )}\n </h2>\n <p className=\"text-sm text-text-secondary\">\n {translate(\n 'brainyrich.dashboard.sections.assetAllocationDescription',\n 'Market value distributed across asset classes'\n )}\n </p>\n </div>\n {summaryQuery.isLoading ? (\n <LoadingState rows={3} />\n ) : summaryQuery.isError ? (\n <ErrorState onRetry={() => summaryQuery.refetch()} />\n ) : donutData.length > 0 ? (\n <DonutChart\n data={donutData}\n height={260}\n centerValue={formatCompact(summary?.totalMarketValue ?? 0, currency)}\n centerLabel={translate('brainyrich.dashboard.metrics.investedAssets', 'Invested')}\n valueFormatter={(v) => formatMoney(v, currency)}\n />\n ) : (\n <EmptyState\n icon={<Briefcase className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.dashboard.noAllocation', 'No holdings to allocate')}\n description={translate(\n 'brainyrich.dashboard.noAllocationDesc',\n 'Add holdings to your accounts to see how your wealth is allocated.'\n )}\n />\n )}\n </GlassCard>\n </FadeIn>\n\n {/* Right rail — needs attention + goals */}\n <div className=\"space-y-6\">\n {/* Needs attention — open insights */}\n <FadeIn index={1}>\n <Card className=\"motion-safe:transition-shadow motion-safe:hover:shadow-[var(--shadow-pop-hover,var(--shadow-elevation-2))]\">\n <CardHeader className=\"pb-3\">\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <Bell className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.sections.needsAttention', 'Needs attention')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2.5\">\n {insightsQuery.isLoading ? (\n <LoadingState rows={2} />\n ) : insightsQuery.isError ? (\n <ErrorState onRetry={() => insightsQuery.refetch()} />\n ) : openInsights.length > 0 ? (\n openInsights.map((insight) => (\n <InsightRow key={insight.id} insight={insight} translate={translate} />\n ))\n ) : (\n <EmptyState\n icon={<CircleCheck className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.dashboard.noInsights', 'All clear')}\n description={translate(\n 'brainyrich.dashboard.noInsightsDesc',\n 'There are no open insights that need your attention.'\n )}\n />\n )}\n </CardContent>\n </Card>\n </FadeIn>\n\n {/* Goals on track */}\n <FadeIn index={2}>\n <Card className=\"motion-safe:transition-shadow motion-safe:hover:shadow-[var(--shadow-pop-hover,var(--shadow-elevation-2))]\">\n <CardHeader className=\"pb-3\">\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <Target className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.sections.goals', 'Goals on track')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2.5\">\n {goalsQuery.isLoading ? (\n <LoadingState rows={3} />\n ) : goalsQuery.isError ? (\n <ErrorState onRetry={() => goalsQuery.refetch()} />\n ) : topGoals.length > 0 ? (\n topGoals.map((goal) => (\n <div\n key={goal.id}\n className=\"flex items-start justify-between gap-2 rounded-lg border border-border-subtle p-3 motion-safe:transition-colors hover:border-[var(--color-action-primary-border)]/50 hover:bg-bg-elevated\"\n >\n <div className=\"min-w-0 space-y-0.5\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {goal.name}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {formatMoney(goal.targetAmount, goal.currency)}\n {' · '}\n {formatDate(goal.targetDate)}\n </p>\n </div>\n <Badge variant={statusBadgeVariant(goal.projection)} className=\"shrink-0\">\n {prettyLabel(goal.projection)}\n </Badge>\n </div>\n ))\n ) : (\n <EmptyState\n icon={<Target className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.dashboard.noGoals', 'No goals yet')}\n description={translate(\n 'brainyrich.dashboard.noGoalsDesc',\n 'Set a financial goal to start tracking progress.'\n )}\n />\n )}\n </CardContent>\n </Card>\n </FadeIn>\n </div>\n </div>\n\n {/* Portfolios mini-list */}\n <FadeIn index={3}>\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <Wallet className=\"size-5\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.sections.portfolios', 'Portfolios')}\n </CardTitle>\n <CardDescription>\n {translate(\n 'brainyrich.dashboard.sections.portfoliosDescription',\n 'Your active investment strategies'\n )}\n </CardDescription>\n </CardHeader>\n <CardContent>\n {portfoliosQuery.isLoading ? (\n <LoadingState rows={3} />\n ) : portfoliosQuery.isError ? (\n <ErrorState onRetry={() => portfoliosQuery.refetch()} />\n ) : topPortfolios.length > 0 ? (\n <div className=\"grid gap-3 sm:grid-cols-2\">\n {topPortfolios.map((portfolio) => (\n <div\n key={portfolio.id}\n className=\"flex items-start justify-between gap-2 rounded-lg border border-border-subtle p-3 motion-safe:transition-colors hover:border-[var(--color-action-primary-border)]/50 hover:bg-bg-elevated\"\n >\n <div className=\"min-w-0 space-y-0.5\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {portfolio.name}\n </p>\n {portfolio.description ? (\n <p className=\"truncate text-xs text-text-secondary\">\n {portfolio.description}\n </p>\n ) : (\n <p className=\"text-xs text-text-secondary\">{portfolio.baseCurrency}</p>\n )}\n </div>\n <Badge variant={statusBadgeVariant(portfolio.status)} className=\"shrink-0\">\n {portfolio.status}\n </Badge>\n </div>\n ))}\n </div>\n ) : (\n <EmptyState\n icon={<Wallet className=\"size-6\" aria-hidden=\"true\" />}\n title={translate('brainyrich.dashboard.noPortfolios', 'No portfolios yet')}\n description={translate(\n 'brainyrich.dashboard.noPortfoliosDesc',\n 'Create a portfolio to organize your investment strategy.'\n )}\n />\n )}\n </CardContent>\n </Card>\n </FadeIn>\n </SectionShell>\n </div>\n );\n}\n\ninterface HeroStat {\n label: string;\n value: string;\n icon: ReactNode;\n glow?: boolean;\n}\n\ntype Translate = (\n key: string,\n fallback: string,\n params?: Record<string, string | number>\n) => string;\n\n// ============================================================================\n// Severity chip — tinted, icon + label (colour is never the only signal)\n// ============================================================================\n\nconst SEVERITY_STYLE: Record<BraInsightSeverity, { chip: string; rail: string; icon: ReactNode }> =\n {\n CRITICAL: {\n chip: 'text-status-error-text bg-status-error-bg',\n rail: 'bg-status-error',\n icon: <ShieldAlert className=\"size-3\" aria-hidden=\"true\" />,\n },\n HIGH: {\n chip: 'text-status-error-text bg-status-error-bg',\n rail: 'bg-status-error',\n icon: <TriangleAlert className=\"size-3\" aria-hidden=\"true\" />,\n },\n MEDIUM: {\n chip: 'text-status-warning-text bg-status-warning-bg',\n rail: 'bg-status-warning',\n icon: <TriangleAlert className=\"size-3\" aria-hidden=\"true\" />,\n },\n LOW: {\n chip: 'text-status-info-text bg-status-info-bg',\n rail: 'bg-status-info',\n icon: <Info className=\"size-3\" aria-hidden=\"true\" />,\n },\n INFO: {\n chip: 'text-status-info-text bg-status-info-bg',\n rail: 'bg-status-info',\n icon: <Info className=\"size-3\" aria-hidden=\"true\" />,\n },\n };\n\nfunction SeverityChip({ severity }: { severity: BraInsightSeverity }) {\n const style = SEVERITY_STYLE[severity] ?? SEVERITY_STYLE.INFO;\n return (\n <span\n className={`inline-flex shrink-0 items-center gap-1 rounded-full px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide ${style.chip}`}\n >\n {style.icon}\n {severity}\n </span>\n );\n}\n\n// ============================================================================\n// Insight row with acknowledge / dismiss / resolve actions\n// ============================================================================\n\nfunction InsightRow({ insight, translate }: { insight: BraInsight; translate: Translate }) {\n const acknowledge = useAcknowledgeInsight();\n const dismiss = useDismissInsight();\n const resolve = useResolveInsight();\n const [confirmDismiss, setConfirmDismiss] = useState(false);\n const pending = acknowledge.isPending || dismiss.isPending || resolve.isPending;\n const rail = (SEVERITY_STYLE[insight.severity] ?? SEVERITY_STYLE.INFO).rail;\n\n return (\n <div className=\"relative flex items-start justify-between gap-3 overflow-hidden rounded-lg border border-border-subtle p-3 pl-4 motion-safe:transition-colors hover:border-[var(--color-action-primary-border)]/50 hover:bg-bg-elevated\">\n <span aria-hidden=\"true\" className={`absolute inset-y-0 left-0 w-1 ${rail}`} />\n <div className=\"min-w-0 space-y-1\">\n <div className=\"flex items-center gap-2\">\n <SeverityChip severity={insight.severity} />\n <span className=\"truncate text-xs text-text-secondary\">{prettyLabel(insight.type)}</span>\n </div>\n <p className=\"text-sm font-medium text-text-primary\">{insight.title}</p>\n {insight.detail ? <p className=\"text-xs text-text-secondary\">{insight.detail}</p> : null}\n </div>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"shrink-0\"\n disabled={pending}\n aria-label={translate('brainyrich.dashboard.insightActions', 'Insight actions')}\n >\n <MoreHorizontal className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem onSelect={() => acknowledge.mutate(insight.id)}>\n <Check className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.insight.acknowledge', 'Acknowledge')}\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={() => resolve.mutate(insight.id)}>\n <CircleCheck className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.insight.resolve', 'Resolve')}\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={() => setConfirmDismiss(true)}>\n <X className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.insight.dismiss', 'Dismiss')}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n\n <ConfirmDialog\n open={confirmDismiss}\n onOpenChange={setConfirmDismiss}\n title={translate('brainyrich.dashboard.insight.dismissTitle', 'Dismiss this insight?')}\n description={translate(\n 'brainyrich.dashboard.insight.dismissDescription',\n 'It will be removed from Needs Attention. You can still find it in the full insights list.'\n )}\n confirmLabel={translate('brainyrich.dashboard.insight.dismiss', 'Dismiss')}\n pendingLabel={translate('brainyrich.dashboard.insight.dismissing', 'Dismissing…')}\n destructive\n pending={dismiss.isPending}\n onConfirm={() =>\n dismiss.mutate(insight.id, {\n onSuccess: () => setConfirmDismiss(false),\n })\n }\n />\n </div>\n );\n}\n\n// ============================================================================\n// New account dialog — primary create action\n// ============================================================================\n\nfunction NewAccountDialog({ translate }: { translate: Translate }) {\n const [open, setOpen] = useState(false);\n const [name, setName] = useState('');\n const [type, setType] = useState<BraAccountType>('BROKERAGE');\n const [institution, setInstitution] = useState('');\n const [cashBalance, setCashBalance] = useState('');\n const [currency, setCurrency] = useState('USD');\n const [householdId, setHouseholdId] = useState<string | null>(null);\n\n const createAccount = useCreateAccount();\n const trimmedName = name.trim();\n const canSubmit = trimmedName.length > 0 && !createAccount.isPending;\n\n const reset = () => {\n setName('');\n setType('BROKERAGE');\n setInstitution('');\n setCashBalance('');\n setCurrency('USD');\n setHouseholdId(null);\n createAccount.reset();\n };\n\n const handleSubmit = (event: FormEvent) => {\n event.preventDefault();\n if (!canSubmit) return;\n const parsedCash = Number.parseFloat(cashBalance);\n const input: BraCreateAccountInput = {\n name: trimmedName,\n type,\n currency: currency.trim() || 'USD',\n isManual: true,\n ...(institution.trim() ? { institution: institution.trim() } : {}),\n ...(Number.isFinite(parsedCash) ? { cashBalance: parsedCash } : {}),\n ...(householdId ? { householdId } : {}),\n };\n createAccount.mutate(input, {\n onSuccess: () => {\n hapticSuccess();\n void showToast(translate('brainyrich.dashboard.newAccount.success', 'Account created'));\n reset();\n setOpen(false);\n },\n });\n };\n\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (!next) reset();\n }}\n >\n <Button size=\"sm\" onClick={() => setOpen(true)}>\n <PlusCircle className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.dashboard.actions.newAccount', 'New Account')}\n </Button>\n <ResponsiveDialogContent>\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>\n {translate('brainyrich.dashboard.newAccount.title', 'New Account')}\n </ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n {translate(\n 'brainyrich.dashboard.newAccount.description',\n 'Add a manual account to track alongside your linked institutions.'\n )}\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-account-name\">\n {translate('brainyrich.dashboard.newAccount.name', 'Account name')}\n </Label>\n <Input\n id=\"bra-account-name\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder={translate(\n 'brainyrich.dashboard.newAccount.namePlaceholder',\n 'e.g. Fidelity Brokerage'\n )}\n required\n autoFocus\n />\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-account-type\">\n {translate('brainyrich.dashboard.newAccount.type', 'Type')}\n </Label>\n <Select value={type} onValueChange={(value) => setType(value as BraAccountType)}>\n <SelectTrigger id=\"bra-account-type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {ACCOUNT_TYPES.map((accountType) => (\n <SelectItem key={accountType} value={accountType}>\n {accountType.replace(/_/g, ' ')}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-account-currency\">\n {translate('brainyrich.dashboard.newAccount.currency', 'Currency')}\n </Label>\n <Input\n id=\"bra-account-currency\"\n value={currency}\n onChange={(e) => setCurrency(e.target.value.toUpperCase())}\n maxLength={3}\n />\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-account-institution\">\n {translate('brainyrich.dashboard.newAccount.institution', 'Institution (optional)')}\n </Label>\n <Input\n id=\"bra-account-institution\"\n value={institution}\n onChange={(e) => setInstitution(e.target.value)}\n placeholder={translate(\n 'brainyrich.dashboard.newAccount.institutionPlaceholder',\n 'e.g. Fidelity'\n )}\n />\n </div>\n\n <HouseholdPicker\n id=\"bra-account-household\"\n value={householdId}\n onChange={setHouseholdId}\n label={translate('brainyrich.dashboard.newAccount.household', 'Household (optional)')}\n noneLabel={translate('brainyrich.dashboard.newAccount.noHousehold', 'No household')}\n disabled={createAccount.isPending}\n />\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"bra-account-cash\">\n {translate('brainyrich.dashboard.newAccount.cash', 'Cash balance (optional)')}\n </Label>\n <Input\n id=\"bra-account-cash\"\n type=\"number\"\n inputMode=\"decimal\"\n step=\"0.01\"\n value={cashBalance}\n onChange={(e) => setCashBalance(e.target.value)}\n placeholder=\"0.00\"\n />\n </div>\n\n {createAccount.isError ? (\n <p className=\"text-sm text-status-error-text\">\n {createAccount.error instanceof Error\n ? createAccount.error.message\n : translate('brainyrich.dashboard.newAccount.error', 'Could not create account.')}\n </p>\n ) : null}\n\n <ResponsiveDialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => setOpen(false)}\n disabled={createAccount.isPending}\n >\n {translate('brainyrich.common.cancel', 'Cancel')}\n </Button>\n <Button type=\"submit\" disabled={!canSubmit}>\n {createAccount.isPending\n ? translate('brainyrich.dashboard.newAccount.creating', 'Creating…')\n : translate('brainyrich.dashboard.newAccount.create', 'Create account')}\n </Button>\n </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":"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"}
|
|
@@ -15,7 +15,7 @@ import { useMemo as oe, useState as w } from "react";
|
|
|
15
15
|
import { Archive as T, Briefcase as E, Building2 as se, Eye as ce, Mail as le, MoreHorizontal as ue, Pencil as de, Target as D, TrendingUp as O, UserCircle2 as fe, Users as k, Wallet as A } from "lucide-react";
|
|
16
16
|
import { useI18n as pe } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
17
17
|
import { jsx as j, jsxs as M } from "react/jsx-runtime";
|
|
18
|
-
import { Badge as N, Button as P, Card as F, CardContent as I,
|
|
18
|
+
import { Badge as N, Button as P, Card as F, CardContent as I, DropdownMenu as me, DropdownMenuContent as he, DropdownMenuItem as L, DropdownMenuSeparator as ge, DropdownMenuTrigger as _e, Input as R, Label as z, ResponsiveDialog as ve, ResponsiveDialogClose as B, ResponsiveDialogContent as V, ResponsiveDialogDescription as H, ResponsiveDialogFooter as ye, ResponsiveDialogHeader as U, ResponsiveDialogTitle as W, Select as G, SelectContent as K, SelectItem as q, SelectTrigger as J, SelectValue as Y, Separator as be, Sheet as xe, SheetContent as Se, SheetDescription as Ce, SheetHeader as we, SheetTitle as Te, Table as Ee, TableBody as De, TableCell as X, TableHead as Z, TableHeader as Oe, TableRow as ke, Tabs as Ae, TabsContent as Q, TabsList as je, TabsTrigger as $, Textarea as Me } from "@burdenoff/fe-libs/ui";
|
|
19
19
|
//#region src/brainyrich/pages/FamilyPage.tsx
|
|
20
20
|
var Ne = [
|
|
21
21
|
"PROSPECT",
|
|
@@ -61,13 +61,13 @@ function ze(e) {
|
|
|
61
61
|
function Be() {
|
|
62
62
|
let { t } = pe(), i = (n, r, i) => e(t, n, r, i);
|
|
63
63
|
x("brainyrich.family.viewed");
|
|
64
|
-
let { items: a, hasMore: s, loadMore: u, isLoading: f, isFetchingNextPage: h, isError: g, refetch: ae } = o(), S = r(), C = c(), E = n(), [se, D] = w(!1), [O, A] = w(null), [
|
|
64
|
+
let { items: a, hasMore: s, loadMore: u, isLoading: f, isFetchingNextPage: h, isError: g, refetch: ae } = o(), S = r(), C = c(), E = n(), [se, D] = w(!1), [O, A] = w(null), [R, z] = w(Le), [ve, B] = w(void 0), [V, H] = w(null), ye = (e, t) => z((n) => ({
|
|
65
65
|
...n,
|
|
66
66
|
[e]: t
|
|
67
67
|
})), U = () => {
|
|
68
|
-
A(null),
|
|
68
|
+
A(null), z(Le), D(!0);
|
|
69
69
|
}, W = (e) => {
|
|
70
|
-
A(e),
|
|
70
|
+
A(e), z({
|
|
71
71
|
name: e.name,
|
|
72
72
|
status: e.status,
|
|
73
73
|
riskProfile: e.riskProfile,
|
|
@@ -104,17 +104,17 @@ function Be() {
|
|
|
104
104
|
tone: Ie[e]
|
|
105
105
|
})).filter((e) => e.value > 0)
|
|
106
106
|
};
|
|
107
|
-
}, [a]), K = S.isPending || C.isPending, q =
|
|
107
|
+
}, [a]), K = S.isPending || C.isPending, q = R.name.trim().length > 0 && !K, J = () => {
|
|
108
108
|
if (q) if (O) {
|
|
109
109
|
let e = {
|
|
110
|
-
name:
|
|
111
|
-
status:
|
|
112
|
-
riskProfile:
|
|
113
|
-
currency:
|
|
114
|
-
primaryContactName:
|
|
115
|
-
primaryContactEmail:
|
|
116
|
-
notes:
|
|
117
|
-
tags: Re(
|
|
110
|
+
name: R.name.trim(),
|
|
111
|
+
status: R.status,
|
|
112
|
+
riskProfile: R.riskProfile,
|
|
113
|
+
currency: R.currency,
|
|
114
|
+
primaryContactName: R.primaryContactName.trim() || null,
|
|
115
|
+
primaryContactEmail: R.primaryContactEmail.trim() || null,
|
|
116
|
+
notes: R.notes.trim() || null,
|
|
117
|
+
tags: Re(R.tags)
|
|
118
118
|
};
|
|
119
119
|
C.mutate({
|
|
120
120
|
id: O.id,
|
|
@@ -124,16 +124,16 @@ function Be() {
|
|
|
124
124
|
} });
|
|
125
125
|
} else {
|
|
126
126
|
let e = {
|
|
127
|
-
name:
|
|
128
|
-
status:
|
|
129
|
-
riskProfile:
|
|
130
|
-
currency:
|
|
131
|
-
primaryContactName:
|
|
132
|
-
primaryContactEmail:
|
|
133
|
-
notes:
|
|
134
|
-
tags: Re(
|
|
127
|
+
name: R.name.trim(),
|
|
128
|
+
status: R.status,
|
|
129
|
+
riskProfile: R.riskProfile,
|
|
130
|
+
currency: R.currency,
|
|
131
|
+
primaryContactName: R.primaryContactName.trim() || null,
|
|
132
|
+
primaryContactEmail: R.primaryContactEmail.trim() || null,
|
|
133
|
+
notes: R.notes.trim() || null,
|
|
134
|
+
tags: Re(R.tags)
|
|
135
135
|
};
|
|
136
|
-
|
|
136
|
+
R.advisorId.trim() && (e.advisorId = R.advisorId.trim()), S.mutate(e, { onSuccess: () => {
|
|
137
137
|
y(), b(i("brainyrich.households.created", "Household created")), D(!1);
|
|
138
138
|
} });
|
|
139
139
|
}
|
|
@@ -229,7 +229,7 @@ function Be() {
|
|
|
229
229
|
let t = G.aum > 0 ? Math.min(100, e.aum / G.aum * 100) : 0;
|
|
230
230
|
return /* @__PURE__ */ M(ke, {
|
|
231
231
|
className: "group cursor-pointer transition-colors",
|
|
232
|
-
onClick: () =>
|
|
232
|
+
onClick: () => B(e.id),
|
|
233
233
|
children: [
|
|
234
234
|
/* @__PURE__ */ M(X, { children: [/* @__PURE__ */ j("span", {
|
|
235
235
|
className: "font-medium text-text-primary transition-colors group-hover:text-[var(--color-action-primary-text)]",
|
|
@@ -309,7 +309,7 @@ function Be() {
|
|
|
309
309
|
/* @__PURE__ */ j(X, {
|
|
310
310
|
className: "text-right",
|
|
311
311
|
onClick: (e) => e.stopPropagation(),
|
|
312
|
-
children: /* @__PURE__ */ M(
|
|
312
|
+
children: /* @__PURE__ */ M(me, { children: [/* @__PURE__ */ j(_e, {
|
|
313
313
|
asChild: !0,
|
|
314
314
|
children: /* @__PURE__ */ j(P, {
|
|
315
315
|
variant: "ghost",
|
|
@@ -320,27 +320,27 @@ function Be() {
|
|
|
320
320
|
"aria-hidden": "true"
|
|
321
321
|
})
|
|
322
322
|
})
|
|
323
|
-
}), /* @__PURE__ */ M(
|
|
323
|
+
}), /* @__PURE__ */ M(he, {
|
|
324
324
|
align: "end",
|
|
325
325
|
children: [
|
|
326
|
-
/* @__PURE__ */ M(
|
|
327
|
-
onClick: () =>
|
|
326
|
+
/* @__PURE__ */ M(L, {
|
|
327
|
+
onClick: () => B(e.id),
|
|
328
328
|
children: [/* @__PURE__ */ j(ce, {
|
|
329
329
|
className: "size-4",
|
|
330
330
|
"aria-hidden": "true"
|
|
331
331
|
}), i("brainyrich.households.action.view", "View details")]
|
|
332
332
|
}),
|
|
333
|
-
/* @__PURE__ */ M(
|
|
333
|
+
/* @__PURE__ */ M(L, {
|
|
334
334
|
onClick: () => W(e),
|
|
335
335
|
children: [/* @__PURE__ */ j(de, {
|
|
336
336
|
className: "size-4",
|
|
337
337
|
"aria-hidden": "true"
|
|
338
338
|
}), i("brainyrich.households.action.edit", "Edit")]
|
|
339
339
|
}),
|
|
340
|
-
/* @__PURE__ */ j(
|
|
341
|
-
/* @__PURE__ */ M(
|
|
340
|
+
/* @__PURE__ */ j(ge, {}),
|
|
341
|
+
/* @__PURE__ */ M(L, {
|
|
342
342
|
className: "text-status-error-text focus:text-status-error-text",
|
|
343
|
-
onClick: () =>
|
|
343
|
+
onClick: () => H(e),
|
|
344
344
|
children: [/* @__PURE__ */ j(T, {
|
|
345
345
|
className: "size-4",
|
|
346
346
|
"aria-hidden": "true"
|
|
@@ -366,33 +366,33 @@ function Be() {
|
|
|
366
366
|
open: se,
|
|
367
367
|
onOpenChange: D,
|
|
368
368
|
editing: O,
|
|
369
|
-
form:
|
|
370
|
-
setField:
|
|
369
|
+
form: R,
|
|
370
|
+
setField: ye,
|
|
371
371
|
onSubmit: J,
|
|
372
372
|
canSubmit: q,
|
|
373
373
|
submitting: K,
|
|
374
374
|
tr: i
|
|
375
375
|
}),
|
|
376
376
|
/* @__PURE__ */ j(Ue, {
|
|
377
|
-
householdId:
|
|
378
|
-
onClose: () =>
|
|
377
|
+
householdId: ve,
|
|
378
|
+
onClose: () => B(void 0),
|
|
379
379
|
onEdit: (e) => {
|
|
380
|
-
|
|
380
|
+
B(void 0), W(e);
|
|
381
381
|
},
|
|
382
382
|
tr: i
|
|
383
383
|
}),
|
|
384
384
|
/* @__PURE__ */ j(te, {
|
|
385
|
-
open: !!
|
|
386
|
-
onOpenChange: (e) => e ? void 0 :
|
|
385
|
+
open: !!V,
|
|
386
|
+
onOpenChange: (e) => e ? void 0 : H(null),
|
|
387
387
|
title: i("brainyrich.households.archive.title", "Archive household?"),
|
|
388
|
-
description: i("brainyrich.households.archive.description", "Archiving “{name}” removes it from the active list. You can still access its records, but it will no longer appear here.", { name:
|
|
388
|
+
description: i("brainyrich.households.archive.description", "Archiving “{name}” removes it from the active list. You can still access its records, but it will no longer appear here.", { name: V?.name ?? "" }),
|
|
389
389
|
confirmLabel: i("brainyrich.households.action.archive", "Archive"),
|
|
390
390
|
pendingLabel: i("brainyrich.households.archive.pending", "Archiving…"),
|
|
391
391
|
destructive: !0,
|
|
392
392
|
pending: E.isPending,
|
|
393
393
|
onConfirm: () => {
|
|
394
|
-
|
|
395
|
-
y(), b(i("brainyrich.households.archived", "Household archived", { name:
|
|
394
|
+
V && E.mutate(V.id, { onSuccess: () => {
|
|
395
|
+
y(), b(i("brainyrich.households.archived", "Household archived", { name: V.name })), H(null);
|
|
396
396
|
} });
|
|
397
397
|
}
|
|
398
398
|
})
|
|
@@ -512,12 +512,12 @@ function Ve({ firm: e, tr: t }) {
|
|
|
512
512
|
});
|
|
513
513
|
}
|
|
514
514
|
function He({ open: e, onOpenChange: t, editing: n, form: r, setField: i, onSubmit: a, canSubmit: o, submitting: s, tr: c }) {
|
|
515
|
-
return /* @__PURE__ */ j(
|
|
515
|
+
return /* @__PURE__ */ j(ve, {
|
|
516
516
|
open: e,
|
|
517
517
|
onOpenChange: t,
|
|
518
|
-
children: /* @__PURE__ */ M(
|
|
518
|
+
children: /* @__PURE__ */ M(V, {
|
|
519
519
|
className: "max-h-[90vh] overflow-y-auto sm:max-w-lg",
|
|
520
|
-
children: [/* @__PURE__ */ M(
|
|
520
|
+
children: [/* @__PURE__ */ M(U, { children: [/* @__PURE__ */ j(W, { children: n ? c("brainyrich.households.form.editTitle", "Edit household") : c("brainyrich.households.form.createTitle", "New household") }), /* @__PURE__ */ j(H, { children: c("brainyrich.households.form.subtitle", "A household groups a client family’s accounts, portfolios and goals.") })] }), /* @__PURE__ */ M("form", {
|
|
521
521
|
className: "space-y-4",
|
|
522
522
|
onSubmit: (e) => {
|
|
523
523
|
e.preventDefault(), a();
|
|
@@ -525,10 +525,10 @@ function He({ open: e, onOpenChange: t, editing: n, form: r, setField: i, onSubm
|
|
|
525
525
|
children: [
|
|
526
526
|
/* @__PURE__ */ M("div", {
|
|
527
527
|
className: "space-y-2",
|
|
528
|
-
children: [/* @__PURE__ */ M(
|
|
528
|
+
children: [/* @__PURE__ */ M(z, {
|
|
529
529
|
htmlFor: "hh-name",
|
|
530
530
|
children: [c("brainyrich.households.form.name", "Name"), " *"]
|
|
531
|
-
}), /* @__PURE__ */ j(
|
|
531
|
+
}), /* @__PURE__ */ j(R, {
|
|
532
532
|
id: "hh-name",
|
|
533
533
|
value: r.name,
|
|
534
534
|
onChange: (e) => i("name", e.target.value),
|
|
@@ -540,7 +540,7 @@ function He({ open: e, onOpenChange: t, editing: n, form: r, setField: i, onSubm
|
|
|
540
540
|
className: "grid gap-4 sm:grid-cols-2",
|
|
541
541
|
children: [/* @__PURE__ */ M("div", {
|
|
542
542
|
className: "space-y-2",
|
|
543
|
-
children: [/* @__PURE__ */ j(
|
|
543
|
+
children: [/* @__PURE__ */ j(z, { children: c("brainyrich.households.form.status", "Status") }), /* @__PURE__ */ M(G, {
|
|
544
544
|
value: r.status,
|
|
545
545
|
onValueChange: (e) => i("status", e),
|
|
546
546
|
children: [/* @__PURE__ */ j(J, { children: /* @__PURE__ */ j(Y, {}) }), /* @__PURE__ */ j(K, { children: Ne.map((e) => /* @__PURE__ */ j(q, {
|
|
@@ -550,7 +550,7 @@ function He({ open: e, onOpenChange: t, editing: n, form: r, setField: i, onSubm
|
|
|
550
550
|
})]
|
|
551
551
|
}), /* @__PURE__ */ M("div", {
|
|
552
552
|
className: "space-y-2",
|
|
553
|
-
children: [/* @__PURE__ */ j(
|
|
553
|
+
children: [/* @__PURE__ */ j(z, { children: c("brainyrich.households.form.risk", "Risk profile") }), /* @__PURE__ */ M(G, {
|
|
554
554
|
value: r.riskProfile,
|
|
555
555
|
onValueChange: (e) => i("riskProfile", e),
|
|
556
556
|
children: [/* @__PURE__ */ j(J, { children: /* @__PURE__ */ j(Y, {}) }), /* @__PURE__ */ j(K, { children: Pe.map((e) => /* @__PURE__ */ j(q, {
|
|
@@ -564,10 +564,10 @@ function He({ open: e, onOpenChange: t, editing: n, form: r, setField: i, onSubm
|
|
|
564
564
|
className: "grid gap-4 sm:grid-cols-2",
|
|
565
565
|
children: [/* @__PURE__ */ M("div", {
|
|
566
566
|
className: "space-y-2",
|
|
567
|
-
children: [/* @__PURE__ */ j(
|
|
567
|
+
children: [/* @__PURE__ */ j(z, {
|
|
568
568
|
htmlFor: "hh-contact-name",
|
|
569
569
|
children: c("brainyrich.households.form.contactName", "Primary contact")
|
|
570
|
-
}), /* @__PURE__ */ j(
|
|
570
|
+
}), /* @__PURE__ */ j(R, {
|
|
571
571
|
id: "hh-contact-name",
|
|
572
572
|
value: r.primaryContactName,
|
|
573
573
|
onChange: (e) => i("primaryContactName", e.target.value),
|
|
@@ -575,10 +575,10 @@ function He({ open: e, onOpenChange: t, editing: n, form: r, setField: i, onSubm
|
|
|
575
575
|
})]
|
|
576
576
|
}), /* @__PURE__ */ M("div", {
|
|
577
577
|
className: "space-y-2",
|
|
578
|
-
children: [/* @__PURE__ */ j(
|
|
578
|
+
children: [/* @__PURE__ */ j(z, {
|
|
579
579
|
htmlFor: "hh-contact-email",
|
|
580
580
|
children: c("brainyrich.households.form.contactEmail", "Contact email")
|
|
581
|
-
}), /* @__PURE__ */ j(
|
|
581
|
+
}), /* @__PURE__ */ j(R, {
|
|
582
582
|
id: "hh-contact-email",
|
|
583
583
|
type: "email",
|
|
584
584
|
value: r.primaryContactEmail,
|
|
@@ -591,7 +591,7 @@ function He({ open: e, onOpenChange: t, editing: n, form: r, setField: i, onSubm
|
|
|
591
591
|
className: "grid gap-4 sm:grid-cols-2",
|
|
592
592
|
children: [/* @__PURE__ */ M("div", {
|
|
593
593
|
className: "space-y-2",
|
|
594
|
-
children: [/* @__PURE__ */ j(
|
|
594
|
+
children: [/* @__PURE__ */ j(z, { children: c("brainyrich.households.form.currency", "Currency") }), /* @__PURE__ */ M(G, {
|
|
595
595
|
value: r.currency,
|
|
596
596
|
onValueChange: (e) => i("currency", e),
|
|
597
597
|
children: [/* @__PURE__ */ j(J, { children: /* @__PURE__ */ j(Y, {}) }), /* @__PURE__ */ j(K, { children: Fe.map((e) => /* @__PURE__ */ j(q, {
|
|
@@ -601,10 +601,10 @@ function He({ open: e, onOpenChange: t, editing: n, form: r, setField: i, onSubm
|
|
|
601
601
|
})]
|
|
602
602
|
}), n ? null : /* @__PURE__ */ M("div", {
|
|
603
603
|
className: "space-y-2",
|
|
604
|
-
children: [/* @__PURE__ */ j(
|
|
604
|
+
children: [/* @__PURE__ */ j(z, {
|
|
605
605
|
htmlFor: "hh-advisor",
|
|
606
606
|
children: c("brainyrich.households.form.advisor", "Advisor ID")
|
|
607
|
-
}), /* @__PURE__ */ j(
|
|
607
|
+
}), /* @__PURE__ */ j(R, {
|
|
608
608
|
id: "hh-advisor",
|
|
609
609
|
value: r.advisorId,
|
|
610
610
|
onChange: (e) => i("advisorId", e.target.value),
|
|
@@ -618,10 +618,10 @@ function He({ open: e, onOpenChange: t, editing: n, form: r, setField: i, onSubm
|
|
|
618
618
|
label: c("brainyrich.households.form.tags", "Tags")
|
|
619
619
|
}) : /* @__PURE__ */ M("div", {
|
|
620
620
|
className: "space-y-2",
|
|
621
|
-
children: [/* @__PURE__ */ j(
|
|
621
|
+
children: [/* @__PURE__ */ j(z, {
|
|
622
622
|
htmlFor: "hh-tags",
|
|
623
623
|
children: c("brainyrich.households.form.tags", "Tags")
|
|
624
|
-
}), /* @__PURE__ */ j(
|
|
624
|
+
}), /* @__PURE__ */ j(R, {
|
|
625
625
|
id: "hh-tags",
|
|
626
626
|
value: r.tags,
|
|
627
627
|
onChange: (e) => i("tags", e.target.value),
|
|
@@ -630,7 +630,7 @@ function He({ open: e, onOpenChange: t, editing: n, form: r, setField: i, onSubm
|
|
|
630
630
|
}),
|
|
631
631
|
/* @__PURE__ */ M("div", {
|
|
632
632
|
className: "space-y-2",
|
|
633
|
-
children: [/* @__PURE__ */ j(
|
|
633
|
+
children: [/* @__PURE__ */ j(z, {
|
|
634
634
|
htmlFor: "hh-notes",
|
|
635
635
|
children: c("brainyrich.households.form.notes", "Notes")
|
|
636
636
|
}), /* @__PURE__ */ j(Me, {
|
|
@@ -640,7 +640,7 @@ function He({ open: e, onOpenChange: t, editing: n, form: r, setField: i, onSubm
|
|
|
640
640
|
rows: 3
|
|
641
641
|
})]
|
|
642
642
|
}),
|
|
643
|
-
/* @__PURE__ */ M(
|
|
643
|
+
/* @__PURE__ */ M(ye, { children: [/* @__PURE__ */ j(B, {
|
|
644
644
|
asChild: !0,
|
|
645
645
|
children: /* @__PURE__ */ j(P, {
|
|
646
646
|
type: "button",
|