@burdenoff/microfe-brainyrich 2026.705.1 → 2026.706.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/brainyrich/BrainyRichRoot.js +13 -13
- package/dist/brainyrich/components/ActorName.js +38 -0
- package/dist/brainyrich/components/ActorName.js.map +1 -0
- package/dist/brainyrich/components/ConfirmDialog.js +25 -0
- package/dist/brainyrich/components/ConfirmDialog.js.map +1 -0
- package/dist/brainyrich/components/LoadMore.js +24 -0
- package/dist/brainyrich/components/LoadMore.js.map +1 -0
- package/dist/brainyrich/components/index.js +5 -0
- package/dist/brainyrich/components/notify.js +38 -0
- package/dist/brainyrich/components/notify.js.map +1 -0
- package/dist/brainyrich/components/pickers.js +232 -0
- package/dist/brainyrich/components/pickers.js.map +1 -0
- package/dist/brainyrich/components/reuse/CommentThread.js +208 -0
- package/dist/brainyrich/components/reuse/CommentThread.js.map +1 -0
- package/dist/brainyrich/components/reuse/DocumentsPanel.js +237 -0
- package/dist/brainyrich/components/reuse/DocumentsPanel.js.map +1 -0
- package/dist/brainyrich/components/reuse/TagField.js +206 -0
- package/dist/brainyrich/components/reuse/TagField.js.map +1 -0
- package/dist/brainyrich/components/reuse/transport.js +24 -0
- package/dist/brainyrich/components/reuse/transport.js.map +1 -0
- package/dist/brainyrich/hooks/useBrainyRichApi.js +644 -372
- package/dist/brainyrich/hooks/useBrainyRichApi.js.map +1 -1
- package/dist/brainyrich/pages/AccountsPage.js +346 -293
- package/dist/brainyrich/pages/AccountsPage.js.map +1 -1
- package/dist/brainyrich/pages/AiAssistantPage.js +339 -320
- package/dist/brainyrich/pages/AiAssistantPage.js.map +1 -1
- package/dist/brainyrich/pages/AnalyticsPage.js +178 -164
- package/dist/brainyrich/pages/AnalyticsPage.js.map +1 -1
- package/dist/brainyrich/pages/DashboardPage.js +195 -169
- package/dist/brainyrich/pages/DashboardPage.js.map +1 -1
- package/dist/brainyrich/pages/FamilyPage.js +247 -198
- package/dist/brainyrich/pages/FamilyPage.js.map +1 -1
- package/dist/brainyrich/pages/GoalsPage.js +478 -442
- package/dist/brainyrich/pages/GoalsPage.js.map +1 -1
- package/dist/brainyrich/pages/InvestmentsPage.js.map +1 -1
- package/dist/brainyrich/pages/PortfoliosPage.js +438 -396
- package/dist/brainyrich/pages/PortfoliosPage.js.map +1 -1
- package/dist/brainyrich/pages/ReportsPage.js +246 -213
- package/dist/brainyrich/pages/ReportsPage.js.map +1 -1
- package/dist/brainyrich/pages/RiskPage.js +321 -173
- package/dist/brainyrich/pages/RiskPage.js.map +1 -1
- package/dist/brainyrich/pages/TaxPage.js +258 -225
- package/dist/brainyrich/pages/TaxPage.js.map +1 -1
- package/dist/brainyrich/pages/_shared.js.map +1 -1
- package/dist/node_modules/sonner/dist/index.js +163 -0
- package/dist/node_modules/sonner/dist/index.js.map +1 -0
- package/package.json +3 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FamilyPage.js","names":[],"sources":["../../../src/brainyrich/pages/FamilyPage.tsx"],"sourcesContent":["import { useMemo, useState, type ReactNode } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n Dialog,\n DialogClose,\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 {\n Users,\n MoreHorizontal,\n Pencil,\n Archive,\n Eye,\n Mail,\n Wallet,\n Target,\n Briefcase,\n} from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../utils/i18n';\nimport {\n useHouseholds,\n useHousehold,\n useCreateHousehold,\n useUpdateHousehold,\n useArchiveHousehold,\n useAccounts,\n usePortfolios,\n useGoals,\n} from '../hooks/useBrainyRichApi';\nimport type {\n BraHousehold,\n BraHouseholdStatus,\n BraRiskProfile,\n BraCreateHouseholdInput,\n BraUpdateHouseholdInput,\n} from '../types/bra';\nimport {\n SectionShell,\n KpiGrid,\n EmptyState,\n LoadingState,\n ErrorState,\n formatMoney,\n formatDate,\n statusBadgeVariant,\n} from './_shared';\n\nconst STATUS_OPTIONS: BraHouseholdStatus[] = ['PROSPECT', 'ONBOARDING', 'ACTIVE', 'INACTIVE'];\nconst RISK_OPTIONS: BraRiskProfile[] = [\n 'CONSERVATIVE',\n 'MODERATE',\n 'BALANCED',\n 'GROWTH',\n 'AGGRESSIVE',\n];\nconst CURRENCY_OPTIONS = ['USD', 'EUR', 'GBP', 'INR', 'AED', 'SGD'];\n\ninterface HouseholdFormState {\n name: string;\n status: BraHouseholdStatus;\n riskProfile: BraRiskProfile;\n currency: string;\n advisorId: string;\n primaryContactName: string;\n primaryContactEmail: string;\n notes: string;\n tags: string;\n}\n\nconst emptyForm: HouseholdFormState = {\n name: '',\n status: 'PROSPECT',\n riskProfile: 'BALANCED',\n currency: 'USD',\n advisorId: '',\n primaryContactName: '',\n primaryContactEmail: '',\n notes: '',\n tags: '',\n};\n\nfunction toTags(raw: string): string[] {\n return raw\n .split(',')\n .map((t) => t.trim())\n .filter(Boolean);\n}\n\nexport function FamilyPage() {\n const { t } = useI18n();\n const tr = (key: string, fallback: string, params?: Record<string, string | number>) =>\n tWithFallback(t, key, fallback, params);\n\n const { data: households, isLoading, isError, refetch } = useHouseholds();\n\n const createHousehold = useCreateHousehold();\n const updateHousehold = useUpdateHousehold();\n const archiveHousehold = useArchiveHousehold();\n\n const [formOpen, setFormOpen] = useState(false);\n const [editing, setEditing] = useState<BraHousehold | null>(null);\n const [form, setForm] = useState<HouseholdFormState>(emptyForm);\n const [detailId, setDetailId] = useState<string | undefined>(undefined);\n\n const setField = <K extends keyof HouseholdFormState>(key: K, value: HouseholdFormState[K]) =>\n setForm((prev) => ({ ...prev, [key]: value }));\n\n const openCreate = () => {\n setEditing(null);\n setForm(emptyForm);\n setFormOpen(true);\n };\n\n const openEdit = (h: BraHousehold) => {\n setEditing(h);\n setForm({\n name: h.name,\n status: h.status,\n riskProfile: h.riskProfile,\n currency: h.currency,\n advisorId: h.advisorId ?? '',\n primaryContactName: h.primaryContactName ?? '',\n primaryContactEmail: h.primaryContactEmail ?? '',\n notes: h.notes ?? '',\n tags: h.tags.join(', '),\n });\n setFormOpen(true);\n };\n\n const kpis = useMemo(() => {\n const total = households.length;\n const active = households.filter((h) => h.status === 'ACTIVE').length;\n const pipeline = households.filter(\n (h) => h.status === 'PROSPECT' || h.status === 'ONBOARDING'\n ).length;\n const aum = households.reduce((sum, h) => sum + (Number.isFinite(h.aum) ? h.aum : 0), 0);\n const currency = households[0]?.currency ?? 'USD';\n return { total, active, pipeline, aum, currency };\n }, [households]);\n\n const submitting = createHousehold.isPending || updateHousehold.isPending;\n const canSubmit = form.name.trim().length > 0 && !submitting;\n\n const handleSubmit = () => {\n if (!canSubmit) return;\n if (editing) {\n const input: BraUpdateHouseholdInput = {\n name: form.name.trim(),\n status: form.status,\n riskProfile: form.riskProfile,\n currency: form.currency,\n primaryContactName: form.primaryContactName.trim() || null,\n primaryContactEmail: form.primaryContactEmail.trim() || null,\n notes: form.notes.trim() || null,\n tags: toTags(form.tags),\n };\n updateHousehold.mutate(\n { id: editing.id, input },\n { onSuccess: () => setFormOpen(false) }\n );\n } else {\n const input: BraCreateHouseholdInput = {\n name: form.name.trim(),\n status: form.status,\n riskProfile: form.riskProfile,\n currency: form.currency,\n primaryContactName: form.primaryContactName.trim() || null,\n primaryContactEmail: form.primaryContactEmail.trim() || null,\n notes: form.notes.trim() || null,\n tags: toTags(form.tags),\n };\n if (form.advisorId.trim()) input.advisorId = form.advisorId.trim();\n createHousehold.mutate(input, { onSuccess: () => setFormOpen(false) });\n }\n };\n\n return (\n <SectionShell\n title={tr('brainyrich.households.title', 'Households')}\n description={tr(\n 'brainyrich.households.description',\n 'Client households and family units under advisement'\n )}\n badges={\n households.length\n ? [tr('brainyrich.households.count', '{count} households', { count: households.length })]\n : []\n }\n actionLabel={tr('brainyrich.households.new', 'New household')}\n onAction={openCreate}\n >\n <KpiGrid\n items={[\n {\n label: tr('brainyrich.households.kpi.total', 'Households'),\n value: String(kpis.total),\n },\n {\n label: tr('brainyrich.households.kpi.active', 'Active'),\n value: String(kpis.active),\n },\n {\n label: tr('brainyrich.households.kpi.pipeline', 'In pipeline'),\n value: String(kpis.pipeline),\n trend: tr('brainyrich.households.kpi.pipelineHint', 'Prospect + onboarding'),\n },\n {\n label: tr('brainyrich.households.kpi.aum', 'Total AUM'),\n value: formatMoney(kpis.aum, kpis.currency),\n },\n ]}\n />\n\n {isLoading ? (\n <LoadingState rows={5} />\n ) : isError ? (\n <ErrorState\n title={tr('brainyrich.households.error.title', 'Could not load households')}\n onRetry={() => refetch()}\n />\n ) : households.length === 0 ? (\n <EmptyState\n icon={<Users className=\"size-6\" aria-hidden=\"true\" />}\n title={tr('brainyrich.households.empty.title', 'No households yet')}\n description={tr(\n 'brainyrich.households.empty.description',\n 'Create your first client household to start organizing accounts, portfolios and goals.'\n )}\n action={\n <Button size=\"sm\" onClick={openCreate}>\n {tr('brainyrich.households.new', 'New household')}\n </Button>\n }\n />\n ) : (\n <Card>\n <CardContent className=\"p-0\">\n <div className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>{tr('brainyrich.households.col.name', 'Household')}</TableHead>\n <TableHead>{tr('brainyrich.households.col.status', 'Status')}</TableHead>\n <TableHead>{tr('brainyrich.households.col.risk', 'Risk profile')}</TableHead>\n <TableHead>{tr('brainyrich.households.col.contact', 'Primary contact')}</TableHead>\n <TableHead className=\"text-right\">\n {tr('brainyrich.households.col.aum', 'AUM')}\n </TableHead>\n <TableHead className=\"w-12 text-right\">\n <span className=\"sr-only\">\n {tr('brainyrich.households.col.actions', 'Actions')}\n </span>\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {households.map((h) => (\n <TableRow key={h.id}>\n <TableCell>\n <button\n type=\"button\"\n className=\"text-left font-medium text-text-primary hover:underline\"\n onClick={() => setDetailId(h.id)}\n >\n {h.name}\n </button>\n {h.tags.length > 0 ? (\n <div className=\"mt-1 flex flex-wrap gap-1\">\n {h.tags.map((tag) => (\n <Badge key={tag} variant=\"outline\" className=\"text-xs\">\n {tag}\n </Badge>\n ))}\n </div>\n ) : null}\n </TableCell>\n <TableCell>\n <Badge variant={statusBadgeVariant(h.status)}>{h.status}</Badge>\n </TableCell>\n <TableCell>\n <Badge variant=\"secondary\">{h.riskProfile}</Badge>\n </TableCell>\n <TableCell>\n {h.primaryContactName ? (\n <div className=\"space-y-0.5\">\n <p className=\"text-sm text-text-primary\">{h.primaryContactName}</p>\n {h.primaryContactEmail ? (\n <p className=\"flex items-center gap-1 text-xs text-text-secondary\">\n <Mail className=\"size-3\" aria-hidden=\"true\" />\n {h.primaryContactEmail}\n </p>\n ) : null}\n </div>\n ) : (\n <span className=\"text-sm text-text-muted\">—</span>\n )}\n </TableCell>\n <TableCell className=\"text-right font-medium text-text-primary\">\n {formatMoney(h.aum, h.currency)}\n </TableCell>\n <TableCell className=\"text-right\">\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={tr('brainyrich.households.rowMenu', 'Household actions')}\n >\n <MoreHorizontal className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem onClick={() => setDetailId(h.id)}>\n <Eye className=\"size-4\" aria-hidden=\"true\" />\n {tr('brainyrich.households.action.view', 'View details')}\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => openEdit(h)}>\n <Pencil className=\"size-4\" aria-hidden=\"true\" />\n {tr('brainyrich.households.action.edit', 'Edit')}\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n className=\"text-status-error-text focus:text-status-error-text\"\n disabled={archiveHousehold.isPending}\n onClick={() => archiveHousehold.mutate(h.id)}\n >\n <Archive className=\"size-4\" aria-hidden=\"true\" />\n {tr('brainyrich.households.action.archive', 'Archive')}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n </CardContent>\n </Card>\n )}\n\n <HouseholdFormDialog\n open={formOpen}\n onOpenChange={setFormOpen}\n editing={editing}\n form={form}\n setField={setField}\n onSubmit={handleSubmit}\n canSubmit={canSubmit}\n submitting={submitting}\n tr={tr}\n />\n\n <HouseholdDetailSheet\n householdId={detailId}\n onClose={() => setDetailId(undefined)}\n onEdit={(h) => {\n setDetailId(undefined);\n openEdit(h);\n }}\n tr={tr}\n />\n </SectionShell>\n );\n}\n\n// ============================================================================\n// Create / edit dialog\n// ============================================================================\n\ninterface HouseholdFormDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n editing: BraHousehold | null;\n form: HouseholdFormState;\n setField: <K extends keyof HouseholdFormState>(key: K, value: HouseholdFormState[K]) => void;\n onSubmit: () => void;\n canSubmit: boolean;\n submitting: boolean;\n tr: (key: string, fallback: string, params?: Record<string, string | number>) => string;\n}\n\nfunction HouseholdFormDialog({\n open,\n onOpenChange,\n editing,\n form,\n setField,\n onSubmit,\n canSubmit,\n submitting,\n tr,\n}: HouseholdFormDialogProps) {\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 {editing\n ? tr('brainyrich.households.form.editTitle', 'Edit household')\n : tr('brainyrich.households.form.createTitle', 'New household')}\n </DialogTitle>\n <DialogDescription>\n {tr(\n 'brainyrich.households.form.subtitle',\n 'A household groups a client family’s accounts, portfolios and goals.'\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-2\">\n <Label htmlFor=\"hh-name\">{tr('brainyrich.households.form.name', 'Name')} *</Label>\n <Input\n id=\"hh-name\"\n value={form.name}\n onChange={(e) => setField('name', e.target.value)}\n placeholder={tr('brainyrich.households.form.namePh', 'e.g. The Raghavan Family')}\n required\n />\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>{tr('brainyrich.households.form.status', 'Status')}</Label>\n <Select\n value={form.status}\n onValueChange={(v) => setField('status', v as BraHouseholdStatus)}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {STATUS_OPTIONS.map((s) => (\n <SelectItem key={s} value={s}>\n {s}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"space-y-2\">\n <Label>{tr('brainyrich.households.form.risk', 'Risk profile')}</Label>\n <Select\n value={form.riskProfile}\n onValueChange={(v) => setField('riskProfile', v as BraRiskProfile)}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {RISK_OPTIONS.map((r) => (\n <SelectItem key={r} value={r}>\n {r}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"hh-contact-name\">\n {tr('brainyrich.households.form.contactName', 'Primary contact')}\n </Label>\n <Input\n id=\"hh-contact-name\"\n value={form.primaryContactName}\n onChange={(e) => setField('primaryContactName', e.target.value)}\n placeholder={tr('brainyrich.households.form.contactNamePh', 'Full name')}\n />\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"hh-contact-email\">\n {tr('brainyrich.households.form.contactEmail', 'Contact email')}\n </Label>\n <Input\n id=\"hh-contact-email\"\n type=\"email\"\n value={form.primaryContactEmail}\n onChange={(e) => setField('primaryContactEmail', e.target.value)}\n placeholder=\"name@example.com\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>{tr('brainyrich.households.form.currency', 'Currency')}</Label>\n <Select value={form.currency} onValueChange={(v) => setField('currency', v)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {CURRENCY_OPTIONS.map((c) => (\n <SelectItem key={c} value={c}>\n {c}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {!editing ? (\n <div className=\"space-y-2\">\n <Label htmlFor=\"hh-advisor\">\n {tr('brainyrich.households.form.advisor', 'Advisor ID')}\n </Label>\n <Input\n id=\"hh-advisor\"\n value={form.advisorId}\n onChange={(e) => setField('advisorId', e.target.value)}\n placeholder={tr('brainyrich.households.form.advisorPh', 'Optional')}\n />\n </div>\n ) : null}\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"hh-tags\">{tr('brainyrich.households.form.tags', 'Tags')}</Label>\n <Input\n id=\"hh-tags\"\n value={form.tags}\n onChange={(e) => setField('tags', e.target.value)}\n placeholder={tr('brainyrich.households.form.tagsPh', 'Comma-separated')}\n />\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"hh-notes\">{tr('brainyrich.households.form.notes', 'Notes')}</Label>\n <Textarea\n id=\"hh-notes\"\n value={form.notes}\n onChange={(e) => setField('notes', e.target.value)}\n rows={3}\n />\n </div>\n\n <DialogFooter>\n <DialogClose asChild>\n <Button type=\"button\" variant=\"outline\">\n {tr('brainyrich.common.cancel', 'Cancel')}\n </Button>\n </DialogClose>\n <Button type=\"submit\" disabled={!canSubmit}>\n {submitting\n ? tr('brainyrich.common.saving', 'Saving…')\n : editing\n ? tr('brainyrich.common.save', 'Save changes')\n : tr('brainyrich.households.form.create', 'Create household')}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n\n// ============================================================================\n// Detail sheet\n// ============================================================================\n\ninterface HouseholdDetailSheetProps {\n householdId: string | undefined;\n onClose: () => void;\n onEdit: (h: BraHousehold) => void;\n tr: (key: string, fallback: string, params?: Record<string, string | number>) => string;\n}\n\nfunction HouseholdDetailSheet({ householdId, onClose, onEdit, tr }: HouseholdDetailSheetProps) {\n const { data: household, isLoading, isError, refetch } = useHousehold(householdId);\n const { data: accounts } = useAccounts(householdId ? { householdId } : {});\n const { data: portfolios } = usePortfolios(householdId ? { householdId } : {});\n const { data: goals } = useGoals(householdId ? { householdId } : {});\n\n const open = Boolean(householdId);\n\n return (\n <Sheet open={open} onOpenChange={(o) => (!o ? onClose() : undefined)}>\n <SheetContent className=\"w-full overflow-y-auto sm:max-w-md\">\n {isLoading ? (\n <div className=\"p-2\">\n <LoadingState rows={4} />\n </div>\n ) : isError ? (\n <ErrorState\n title={tr('brainyrich.households.detail.error', 'Could not load household')}\n onRetry={() => refetch()}\n />\n ) : !household ? (\n <EmptyState\n icon={<Users className=\"size-6\" aria-hidden=\"true\" />}\n title={tr('brainyrich.households.detail.missing', 'Household not found')}\n />\n ) : (\n <div className=\"space-y-6\">\n <SheetHeader className=\"space-y-2\">\n <SheetTitle>{household.name}</SheetTitle>\n <SheetDescription>\n {tr('brainyrich.households.detail.subtitle', 'Household overview')}\n </SheetDescription>\n <div className=\"flex flex-wrap items-center gap-2 pt-1\">\n <Badge variant={statusBadgeVariant(household.status)}>{household.status}</Badge>\n <Badge variant=\"secondary\">{household.riskProfile}</Badge>\n </div>\n </SheetHeader>\n\n <div className=\"grid grid-cols-3 gap-3\">\n <SummaryTile\n icon={<Wallet className=\"size-4\" aria-hidden=\"true\" />}\n label={tr('brainyrich.households.detail.accounts', 'Accounts')}\n value={String(accounts.length)}\n />\n <SummaryTile\n icon={<Briefcase className=\"size-4\" aria-hidden=\"true\" />}\n label={tr('brainyrich.households.detail.portfolios', 'Portfolios')}\n value={String(portfolios.length)}\n />\n <SummaryTile\n icon={<Target className=\"size-4\" aria-hidden=\"true\" />}\n label={tr('brainyrich.households.detail.goals', 'Goals')}\n value={String(goals.length)}\n />\n </div>\n\n <Card>\n <CardContent className=\"space-y-3 p-4 text-sm\">\n <DetailRow\n label={tr('brainyrich.households.detail.aum', 'AUM')}\n value={formatMoney(household.aum, household.currency)}\n />\n <DetailRow\n label={tr('brainyrich.households.form.currency', 'Currency')}\n value={household.currency}\n />\n <DetailRow\n label={tr('brainyrich.households.detail.contact', 'Primary contact')}\n value={household.primaryContactName ?? '—'}\n />\n <DetailRow\n label={tr('brainyrich.households.form.contactEmail', 'Contact email')}\n value={household.primaryContactEmail ?? '—'}\n />\n <DetailRow\n label={tr('brainyrich.households.detail.created', 'Created')}\n value={formatDate(household.createdAt)}\n />\n <DetailRow\n label={tr('brainyrich.households.detail.updated', 'Last updated')}\n value={formatDate(household.updatedAt)}\n />\n </CardContent>\n </Card>\n\n {household.tags.length > 0 ? (\n <div className=\"flex flex-wrap gap-1\">\n {household.tags.map((tag) => (\n <Badge key={tag} variant=\"outline\">\n {tag}\n </Badge>\n ))}\n </div>\n ) : null}\n\n {household.notes ? (\n <div className=\"space-y-1\">\n <p className=\"text-xs font-medium text-text-secondary\">\n {tr('brainyrich.households.form.notes', 'Notes')}\n </p>\n <p className=\"text-sm text-text-primary\">{household.notes}</p>\n </div>\n ) : null}\n\n <Button variant=\"outline\" className=\"w-full\" onClick={() => onEdit(household)}>\n <Pencil className=\"size-4\" aria-hidden=\"true\" />\n {tr('brainyrich.households.action.edit', 'Edit')}\n </Button>\n </div>\n )}\n </SheetContent>\n </Sheet>\n );\n}\n\nfunction SummaryTile({\n icon,\n label,\n value,\n}: {\n icon: ReactNode;\n label: string;\n value: string;\n}) {\n return (\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-3 text-center\">\n <div className=\"mx-auto mb-1 flex size-8 items-center justify-center rounded-full bg-bg-sunken text-text-secondary\">\n {icon}\n </div>\n <p className=\"text-lg font-semibold text-text-primary\">{value}</p>\n <p className=\"text-xs text-text-secondary\">{label}</p>\n </div>\n );\n}\n\nfunction DetailRow({ label, value }: { label: string; value: string }) {\n return (\n <div className=\"flex items-center justify-between gap-4\">\n <span className=\"text-text-secondary\">{label}</span>\n <span className=\"text-right font-medium text-text-primary\">{value}</span>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FamilyPage.js","names":[],"sources":["../../../src/brainyrich/pages/FamilyPage.tsx"],"sourcesContent":["import { useMemo, useState, type ReactNode } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n Dialog,\n DialogClose,\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 {\n Users,\n MoreHorizontal,\n Pencil,\n Archive,\n Eye,\n Mail,\n Wallet,\n Target,\n Briefcase,\n} from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../utils/i18n';\nimport {\n usePagedHouseholds,\n useHousehold,\n useCreateHousehold,\n useUpdateHousehold,\n useArchiveHousehold,\n useAccounts,\n usePortfolios,\n useGoals,\n} from '../hooks/useBrainyRichApi';\nimport { ConfirmDialog, LoadMore, ActorName } from '../components';\nimport { TagField } from '../components/reuse/TagField';\nimport { DocumentsPanel } from '../components/reuse/DocumentsPanel';\nimport { CommentThread } from '../components/reuse/CommentThread';\nimport type {\n BraHousehold,\n BraHouseholdStatus,\n BraRiskProfile,\n BraCreateHouseholdInput,\n BraUpdateHouseholdInput,\n} from '../types/bra';\nimport {\n SectionShell,\n KpiGrid,\n EmptyState,\n LoadingState,\n ErrorState,\n formatMoney,\n formatDate,\n statusBadgeVariant,\n} from './_shared';\n\nconst STATUS_OPTIONS: BraHouseholdStatus[] = ['PROSPECT', 'ONBOARDING', 'ACTIVE', 'INACTIVE'];\nconst RISK_OPTIONS: BraRiskProfile[] = [\n 'CONSERVATIVE',\n 'MODERATE',\n 'BALANCED',\n 'GROWTH',\n 'AGGRESSIVE',\n];\nconst CURRENCY_OPTIONS = ['USD', 'EUR', 'GBP', 'INR', 'AED', 'SGD'];\n\ninterface HouseholdFormState {\n name: string;\n status: BraHouseholdStatus;\n riskProfile: BraRiskProfile;\n currency: string;\n advisorId: string;\n primaryContactName: string;\n primaryContactEmail: string;\n notes: string;\n tags: string;\n}\n\nconst emptyForm: HouseholdFormState = {\n name: '',\n status: 'PROSPECT',\n riskProfile: 'BALANCED',\n currency: 'USD',\n advisorId: '',\n primaryContactName: '',\n primaryContactEmail: '',\n notes: '',\n tags: '',\n};\n\nfunction toTags(raw: string): string[] {\n return raw\n .split(',')\n .map((t) => t.trim())\n .filter(Boolean);\n}\n\nexport function FamilyPage() {\n const { t } = useI18n();\n const tr = (key: string, fallback: string, params?: Record<string, string | number>) =>\n tWithFallback(t, key, fallback, params);\n\n const {\n items: households,\n hasMore,\n loadMore,\n isLoading,\n isFetchingNextPage,\n isError,\n refetch,\n } = usePagedHouseholds();\n\n const createHousehold = useCreateHousehold();\n const updateHousehold = useUpdateHousehold();\n const archiveHousehold = useArchiveHousehold();\n\n const [formOpen, setFormOpen] = useState(false);\n const [editing, setEditing] = useState<BraHousehold | null>(null);\n const [form, setForm] = useState<HouseholdFormState>(emptyForm);\n const [detailId, setDetailId] = useState<string | undefined>(undefined);\n const [archiveTarget, setArchiveTarget] = useState<BraHousehold | null>(null);\n\n const setField = <K extends keyof HouseholdFormState>(key: K, value: HouseholdFormState[K]) =>\n setForm((prev) => ({ ...prev, [key]: value }));\n\n const openCreate = () => {\n setEditing(null);\n setForm(emptyForm);\n setFormOpen(true);\n };\n\n const openEdit = (h: BraHousehold) => {\n setEditing(h);\n setForm({\n name: h.name,\n status: h.status,\n riskProfile: h.riskProfile,\n currency: h.currency,\n advisorId: h.advisorId ?? '',\n primaryContactName: h.primaryContactName ?? '',\n primaryContactEmail: h.primaryContactEmail ?? '',\n notes: h.notes ?? '',\n tags: h.tags.join(', '),\n });\n setFormOpen(true);\n };\n\n const kpis = useMemo(() => {\n const total = households.length;\n const active = households.filter((h) => h.status === 'ACTIVE').length;\n const pipeline = households.filter(\n (h) => h.status === 'PROSPECT' || h.status === 'ONBOARDING'\n ).length;\n const aum = households.reduce((sum, h) => sum + (Number.isFinite(h.aum) ? h.aum : 0), 0);\n const currency = households[0]?.currency ?? 'USD';\n return { total, active, pipeline, aum, currency };\n }, [households]);\n\n const submitting = createHousehold.isPending || updateHousehold.isPending;\n const canSubmit = form.name.trim().length > 0 && !submitting;\n\n const handleSubmit = () => {\n if (!canSubmit) return;\n if (editing) {\n const input: BraUpdateHouseholdInput = {\n name: form.name.trim(),\n status: form.status,\n riskProfile: form.riskProfile,\n currency: form.currency,\n primaryContactName: form.primaryContactName.trim() || null,\n primaryContactEmail: form.primaryContactEmail.trim() || null,\n notes: form.notes.trim() || null,\n tags: toTags(form.tags),\n };\n updateHousehold.mutate({ id: editing.id, input }, { onSuccess: () => setFormOpen(false) });\n } else {\n const input: BraCreateHouseholdInput = {\n name: form.name.trim(),\n status: form.status,\n riskProfile: form.riskProfile,\n currency: form.currency,\n primaryContactName: form.primaryContactName.trim() || null,\n primaryContactEmail: form.primaryContactEmail.trim() || null,\n notes: form.notes.trim() || null,\n tags: toTags(form.tags),\n };\n if (form.advisorId.trim()) input.advisorId = form.advisorId.trim();\n createHousehold.mutate(input, { onSuccess: () => setFormOpen(false) });\n }\n };\n\n return (\n <SectionShell\n title={tr('brainyrich.households.title', 'Households')}\n description={tr(\n 'brainyrich.households.description',\n 'Client households and family units under advisement'\n )}\n badges={\n households.length\n ? [tr('brainyrich.households.count', '{count} households', { count: households.length })]\n : []\n }\n actionLabel={tr('brainyrich.households.new', 'New household')}\n onAction={openCreate}\n >\n <KpiGrid\n items={[\n {\n label: tr('brainyrich.households.kpi.total', 'Households'),\n value: String(kpis.total),\n },\n {\n label: tr('brainyrich.households.kpi.active', 'Active'),\n value: String(kpis.active),\n },\n {\n label: tr('brainyrich.households.kpi.pipeline', 'In pipeline'),\n value: String(kpis.pipeline),\n trend: tr('brainyrich.households.kpi.pipelineHint', 'Prospect + onboarding'),\n },\n {\n label: tr('brainyrich.households.kpi.aum', 'Total AUM'),\n value: formatMoney(kpis.aum, kpis.currency),\n },\n ]}\n />\n\n {isLoading ? (\n <LoadingState rows={5} />\n ) : isError ? (\n <ErrorState\n title={tr('brainyrich.households.error.title', 'Could not load households')}\n onRetry={() => refetch()}\n />\n ) : households.length === 0 ? (\n <EmptyState\n icon={<Users className=\"size-6\" aria-hidden=\"true\" />}\n title={tr('brainyrich.households.empty.title', 'No households yet')}\n description={tr(\n 'brainyrich.households.empty.description',\n 'Create your first client household to start organizing accounts, portfolios and goals.'\n )}\n action={\n <Button size=\"sm\" onClick={openCreate}>\n {tr('brainyrich.households.new', 'New household')}\n </Button>\n }\n />\n ) : (\n <Card>\n <CardContent className=\"p-0\">\n <div className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>{tr('brainyrich.households.col.name', 'Household')}</TableHead>\n <TableHead>{tr('brainyrich.households.col.status', 'Status')}</TableHead>\n <TableHead>{tr('brainyrich.households.col.risk', 'Risk profile')}</TableHead>\n <TableHead>\n {tr('brainyrich.households.col.contact', 'Primary contact')}\n </TableHead>\n <TableHead className=\"text-right\">\n {tr('brainyrich.households.col.aum', 'AUM')}\n </TableHead>\n <TableHead className=\"w-12 text-right\">\n <span className=\"sr-only\">\n {tr('brainyrich.households.col.actions', 'Actions')}\n </span>\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {households.map((h) => (\n <TableRow key={h.id}>\n <TableCell>\n <button\n type=\"button\"\n className=\"text-left font-medium text-text-primary hover:underline\"\n onClick={() => setDetailId(h.id)}\n >\n {h.name}\n </button>\n {h.tags.length > 0 ? (\n <div className=\"mt-1 flex flex-wrap gap-1\">\n {h.tags.map((tag) => (\n <Badge key={tag} variant=\"outline\" className=\"text-xs\">\n {tag}\n </Badge>\n ))}\n </div>\n ) : null}\n </TableCell>\n <TableCell>\n <Badge variant={statusBadgeVariant(h.status)}>{h.status}</Badge>\n </TableCell>\n <TableCell>\n <Badge variant=\"secondary\">{h.riskProfile}</Badge>\n </TableCell>\n <TableCell>\n {h.primaryContactName ? (\n <div className=\"space-y-0.5\">\n <p className=\"text-sm text-text-primary\">{h.primaryContactName}</p>\n {h.primaryContactEmail ? (\n <p className=\"flex items-center gap-1 text-xs text-text-secondary\">\n <Mail className=\"size-3\" aria-hidden=\"true\" />\n {h.primaryContactEmail}\n </p>\n ) : null}\n </div>\n ) : (\n <span className=\"text-sm text-text-muted\">—</span>\n )}\n </TableCell>\n <TableCell className=\"text-right font-medium text-text-primary\">\n {formatMoney(h.aum, h.currency)}\n </TableCell>\n <TableCell className=\"text-right\">\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={tr('brainyrich.households.rowMenu', 'Household actions')}\n >\n <MoreHorizontal className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem onClick={() => setDetailId(h.id)}>\n <Eye className=\"size-4\" aria-hidden=\"true\" />\n {tr('brainyrich.households.action.view', 'View details')}\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => openEdit(h)}>\n <Pencil className=\"size-4\" aria-hidden=\"true\" />\n {tr('brainyrich.households.action.edit', 'Edit')}\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n className=\"text-status-error-text focus:text-status-error-text\"\n onClick={() => setArchiveTarget(h)}\n >\n <Archive className=\"size-4\" aria-hidden=\"true\" />\n {tr('brainyrich.households.action.archive', 'Archive')}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n </CardContent>\n </Card>\n )}\n\n {!isLoading && !isError && households.length > 0 ? (\n <LoadMore\n hasMore={hasMore}\n onClick={loadMore}\n loading={isFetchingNextPage}\n label={tr('brainyrich.households.loadMore', 'Load more households')}\n />\n ) : null}\n\n <HouseholdFormDialog\n open={formOpen}\n onOpenChange={setFormOpen}\n editing={editing}\n form={form}\n setField={setField}\n onSubmit={handleSubmit}\n canSubmit={canSubmit}\n submitting={submitting}\n tr={tr}\n />\n\n <HouseholdDetailSheet\n householdId={detailId}\n onClose={() => setDetailId(undefined)}\n onEdit={(h) => {\n setDetailId(undefined);\n openEdit(h);\n }}\n tr={tr}\n />\n\n <ConfirmDialog\n open={Boolean(archiveTarget)}\n onOpenChange={(o) => (!o ? setArchiveTarget(null) : undefined)}\n title={tr('brainyrich.households.archive.title', 'Archive household?')}\n description={tr(\n 'brainyrich.households.archive.description',\n 'Archiving “{name}” removes it from the active list. You can still access its records, but it will no longer appear here.',\n { name: archiveTarget?.name ?? '' }\n )}\n confirmLabel={tr('brainyrich.households.action.archive', 'Archive')}\n pendingLabel={tr('brainyrich.households.archive.pending', 'Archiving…')}\n destructive\n pending={archiveHousehold.isPending}\n onConfirm={() => {\n if (!archiveTarget) return;\n archiveHousehold.mutate(archiveTarget.id, {\n onSuccess: () => setArchiveTarget(null),\n });\n }}\n />\n </SectionShell>\n );\n}\n\n// ============================================================================\n// Create / edit dialog\n// ============================================================================\n\ninterface HouseholdFormDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n editing: BraHousehold | null;\n form: HouseholdFormState;\n setField: <K extends keyof HouseholdFormState>(key: K, value: HouseholdFormState[K]) => void;\n onSubmit: () => void;\n canSubmit: boolean;\n submitting: boolean;\n tr: (key: string, fallback: string, params?: Record<string, string | number>) => string;\n}\n\nfunction HouseholdFormDialog({\n open,\n onOpenChange,\n editing,\n form,\n setField,\n onSubmit,\n canSubmit,\n submitting,\n tr,\n}: HouseholdFormDialogProps) {\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 {editing\n ? tr('brainyrich.households.form.editTitle', 'Edit household')\n : tr('brainyrich.households.form.createTitle', 'New household')}\n </DialogTitle>\n <DialogDescription>\n {tr(\n 'brainyrich.households.form.subtitle',\n 'A household groups a client family’s accounts, portfolios and goals.'\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-2\">\n <Label htmlFor=\"hh-name\">{tr('brainyrich.households.form.name', 'Name')} *</Label>\n <Input\n id=\"hh-name\"\n value={form.name}\n onChange={(e) => setField('name', e.target.value)}\n placeholder={tr('brainyrich.households.form.namePh', 'e.g. The Raghavan Family')}\n required\n />\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>{tr('brainyrich.households.form.status', 'Status')}</Label>\n <Select\n value={form.status}\n onValueChange={(v) => setField('status', v as BraHouseholdStatus)}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {STATUS_OPTIONS.map((s) => (\n <SelectItem key={s} value={s}>\n {s}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n <div className=\"space-y-2\">\n <Label>{tr('brainyrich.households.form.risk', 'Risk profile')}</Label>\n <Select\n value={form.riskProfile}\n onValueChange={(v) => setField('riskProfile', v as BraRiskProfile)}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {RISK_OPTIONS.map((r) => (\n <SelectItem key={r} value={r}>\n {r}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"hh-contact-name\">\n {tr('brainyrich.households.form.contactName', 'Primary contact')}\n </Label>\n <Input\n id=\"hh-contact-name\"\n value={form.primaryContactName}\n onChange={(e) => setField('primaryContactName', e.target.value)}\n placeholder={tr('brainyrich.households.form.contactNamePh', 'Full name')}\n />\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"hh-contact-email\">\n {tr('brainyrich.households.form.contactEmail', 'Contact email')}\n </Label>\n <Input\n id=\"hh-contact-email\"\n type=\"email\"\n value={form.primaryContactEmail}\n onChange={(e) => setField('primaryContactEmail', e.target.value)}\n placeholder=\"name@example.com\"\n />\n </div>\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div className=\"space-y-2\">\n <Label>{tr('brainyrich.households.form.currency', 'Currency')}</Label>\n <Select value={form.currency} onValueChange={(v) => setField('currency', v)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {CURRENCY_OPTIONS.map((c) => (\n <SelectItem key={c} value={c}>\n {c}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {!editing ? (\n <div className=\"space-y-2\">\n <Label htmlFor=\"hh-advisor\">\n {tr('brainyrich.households.form.advisor', 'Advisor ID')}\n </Label>\n <Input\n id=\"hh-advisor\"\n value={form.advisorId}\n onChange={(e) => setField('advisorId', e.target.value)}\n placeholder={tr('brainyrich.households.form.advisorPh', 'Optional')}\n />\n </div>\n ) : null}\n </div>\n\n {editing ? (\n <TagField\n entityType=\"brainyrich-household\"\n entityId={editing.id}\n label={tr('brainyrich.households.form.tags', 'Tags')}\n />\n ) : (\n <div className=\"space-y-2\">\n <Label htmlFor=\"hh-tags\">{tr('brainyrich.households.form.tags', 'Tags')}</Label>\n <Input\n id=\"hh-tags\"\n value={form.tags}\n onChange={(e) => setField('tags', e.target.value)}\n placeholder={tr('brainyrich.households.form.tagsPh', 'Comma-separated')}\n />\n </div>\n )}\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"hh-notes\">{tr('brainyrich.households.form.notes', 'Notes')}</Label>\n <Textarea\n id=\"hh-notes\"\n value={form.notes}\n onChange={(e) => setField('notes', e.target.value)}\n rows={3}\n />\n </div>\n\n <DialogFooter>\n <DialogClose asChild>\n <Button type=\"button\" variant=\"outline\">\n {tr('brainyrich.common.cancel', 'Cancel')}\n </Button>\n </DialogClose>\n <Button type=\"submit\" disabled={!canSubmit}>\n {submitting\n ? tr('brainyrich.common.saving', 'Saving…')\n : editing\n ? tr('brainyrich.common.save', 'Save changes')\n : tr('brainyrich.households.form.create', 'Create household')}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n\n// ============================================================================\n// Detail sheet\n// ============================================================================\n\ninterface HouseholdDetailSheetProps {\n householdId: string | undefined;\n onClose: () => void;\n onEdit: (h: BraHousehold) => void;\n tr: (key: string, fallback: string, params?: Record<string, string | number>) => string;\n}\n\nfunction HouseholdDetailSheet({ householdId, onClose, onEdit, tr }: HouseholdDetailSheetProps) {\n const { data: household, isLoading, isError, refetch } = useHousehold(householdId);\n const { data: accounts } = useAccounts(householdId ? { householdId } : {});\n const { data: portfolios } = usePortfolios(householdId ? { householdId } : {});\n const { data: goals } = useGoals(householdId ? { householdId } : {});\n\n const open = Boolean(householdId);\n\n return (\n <Sheet open={open} onOpenChange={(o) => (!o ? onClose() : undefined)}>\n <SheetContent className=\"w-full overflow-y-auto sm:max-w-md\">\n {isLoading ? (\n <div className=\"p-2\">\n <LoadingState rows={4} />\n </div>\n ) : isError ? (\n <ErrorState\n title={tr('brainyrich.households.detail.error', 'Could not load household')}\n onRetry={() => refetch()}\n />\n ) : !household ? (\n <EmptyState\n icon={<Users className=\"size-6\" aria-hidden=\"true\" />}\n title={tr('brainyrich.households.detail.missing', 'Household not found')}\n />\n ) : (\n <div className=\"space-y-6\">\n <SheetHeader className=\"space-y-2\">\n <SheetTitle>{household.name}</SheetTitle>\n <SheetDescription>\n {tr('brainyrich.households.detail.subtitle', 'Household overview')}\n </SheetDescription>\n <div className=\"flex flex-wrap items-center gap-2 pt-1\">\n <Badge variant={statusBadgeVariant(household.status)}>{household.status}</Badge>\n <Badge variant=\"secondary\">{household.riskProfile}</Badge>\n </div>\n </SheetHeader>\n\n <div className=\"grid grid-cols-3 gap-3\">\n <SummaryTile\n icon={<Wallet className=\"size-4\" aria-hidden=\"true\" />}\n label={tr('brainyrich.households.detail.accounts', 'Accounts')}\n value={String(accounts.length)}\n />\n <SummaryTile\n icon={<Briefcase className=\"size-4\" aria-hidden=\"true\" />}\n label={tr('brainyrich.households.detail.portfolios', 'Portfolios')}\n value={String(portfolios.length)}\n />\n <SummaryTile\n icon={<Target className=\"size-4\" aria-hidden=\"true\" />}\n label={tr('brainyrich.households.detail.goals', 'Goals')}\n value={String(goals.length)}\n />\n </div>\n\n <Card>\n <CardContent className=\"space-y-3 p-4 text-sm\">\n <DetailRow\n label={tr('brainyrich.households.detail.aum', 'AUM')}\n value={formatMoney(household.aum, household.currency)}\n />\n <DetailRow\n label={tr('brainyrich.households.form.currency', 'Currency')}\n value={household.currency}\n />\n <DetailRow\n label={tr('brainyrich.households.detail.contact', 'Primary contact')}\n value={household.primaryContactName ?? '—'}\n />\n <DetailRow\n label={tr('brainyrich.households.form.contactEmail', 'Contact email')}\n value={household.primaryContactEmail ?? '—'}\n />\n <div className=\"flex items-center justify-between gap-4\">\n <span className=\"text-text-secondary\">\n {tr('brainyrich.households.detail.advisor', 'Advisor')}\n </span>\n <span className=\"text-right font-medium text-text-primary\">\n {household.advisorId ? (\n <ActorName id={household.advisorId} />\n ) : (\n tr('brainyrich.common.unassigned', 'Unassigned')\n )}\n </span>\n </div>\n <DetailRow\n label={tr('brainyrich.households.detail.created', 'Created')}\n value={formatDate(household.createdAt)}\n />\n <DetailRow\n label={tr('brainyrich.households.detail.updated', 'Last updated')}\n value={formatDate(household.updatedAt)}\n />\n </CardContent>\n </Card>\n\n {household.tags.length > 0 ? (\n <div className=\"flex flex-wrap gap-1\">\n {household.tags.map((tag) => (\n <Badge key={tag} variant=\"outline\">\n {tag}\n </Badge>\n ))}\n </div>\n ) : null}\n\n {household.notes ? (\n <div className=\"space-y-1\">\n <p className=\"text-xs font-medium text-text-secondary\">\n {tr('brainyrich.households.detail.summary', 'Summary')}\n </p>\n <p className=\"text-sm text-text-primary\">{household.notes}</p>\n </div>\n ) : null}\n\n <DocumentsPanel\n entityType=\"brainyrich-household\"\n entityId={household.id}\n heading={tr('brainyrich.households.detail.documents', 'Documents')}\n />\n\n <CommentThread\n entityType=\"brainyrich-household\"\n entityId={household.id}\n heading={tr('brainyrich.households.detail.discussion', 'Discussion')}\n />\n\n <Button variant=\"outline\" className=\"w-full\" onClick={() => onEdit(household)}>\n <Pencil className=\"size-4\" aria-hidden=\"true\" />\n {tr('brainyrich.households.action.edit', 'Edit')}\n </Button>\n </div>\n )}\n </SheetContent>\n </Sheet>\n );\n}\n\nfunction SummaryTile({ icon, label, value }: { icon: ReactNode; label: string; value: string }) {\n return (\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-3 text-center\">\n <div className=\"mx-auto mb-1 flex size-8 items-center justify-center rounded-full bg-bg-sunken text-text-secondary\">\n {icon}\n </div>\n <p className=\"text-lg font-semibold text-text-primary\">{value}</p>\n <p className=\"text-xs text-text-secondary\">{label}</p>\n </div>\n );\n}\n\nfunction DetailRow({ label, value }: { label: string; value: string }) {\n return (\n <div className=\"flex items-center justify-between gap-4\">\n <span className=\"text-text-secondary\">{label}</span>\n <span className=\"text-right font-medium text-text-primary\">{value}</span>\n </div>\n );\n}\n"],"mappings":"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"}
|