@burdenoff/microfe-brainyrich 2026.512.1 → 2026.705.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 +53 -88
- package/dist/brainyrich/BrainyRichRoot.js.map +1 -1
- package/dist/brainyrich/BrainyRichRoutes.js +15 -35
- package/dist/brainyrich/BrainyRichRoutes.js.map +1 -1
- package/dist/brainyrich/hooks/useBrainyRichApi.js +543 -0
- package/dist/brainyrich/hooks/useBrainyRichApi.js.map +1 -0
- package/dist/brainyrich/index.js +0 -1
- package/dist/brainyrich/pages/AccountsPage.js +690 -160
- package/dist/brainyrich/pages/AccountsPage.js.map +1 -1
- package/dist/brainyrich/pages/AiAssistantPage.js +537 -363
- package/dist/brainyrich/pages/AiAssistantPage.js.map +1 -1
- package/dist/brainyrich/pages/AnalyticsPage.js +587 -268
- package/dist/brainyrich/pages/AnalyticsPage.js.map +1 -1
- package/dist/brainyrich/pages/DashboardPage.js +350 -232
- package/dist/brainyrich/pages/DashboardPage.js.map +1 -1
- package/dist/brainyrich/pages/FamilyPage.js +550 -337
- package/dist/brainyrich/pages/FamilyPage.js.map +1 -1
- package/dist/brainyrich/pages/GoalsPage.js +775 -142
- package/dist/brainyrich/pages/GoalsPage.js.map +1 -1
- package/dist/brainyrich/pages/InvestmentsPage.js +410 -311
- package/dist/brainyrich/pages/InvestmentsPage.js.map +1 -1
- package/dist/brainyrich/pages/PortfoliosPage.js +823 -154
- package/dist/brainyrich/pages/PortfoliosPage.js.map +1 -1
- package/dist/brainyrich/pages/ReportsPage.js +388 -251
- package/dist/brainyrich/pages/ReportsPage.js.map +1 -1
- package/dist/brainyrich/pages/RiskPage.js +411 -196
- package/dist/brainyrich/pages/RiskPage.js.map +1 -1
- package/dist/brainyrich/pages/TaxPage.js +622 -221
- package/dist/brainyrich/pages/TaxPage.js.map +1 -1
- package/dist/brainyrich/pages/_shared.js +222 -41
- package/dist/brainyrich/pages/_shared.js.map +1 -1
- package/dist/index.js +2 -3
- package/package.json +1 -1
- package/dist/brainyrich/BrainyRichRoot.d.ts +0 -5
- package/dist/brainyrich/BrainyRichRoot.d.ts.map +0 -1
- package/dist/brainyrich/BrainyRichRoutes.d.ts +0 -2
- package/dist/brainyrich/BrainyRichRoutes.d.ts.map +0 -1
- package/dist/brainyrich/index.d.ts +0 -5
- package/dist/brainyrich/index.d.ts.map +0 -1
- package/dist/brainyrich/pages/AccountsPage.d.ts +0 -2
- package/dist/brainyrich/pages/AccountsPage.d.ts.map +0 -1
- package/dist/brainyrich/pages/AdvisorsPage.d.ts +0 -2
- package/dist/brainyrich/pages/AdvisorsPage.d.ts.map +0 -1
- package/dist/brainyrich/pages/AdvisorsPage.js +0 -375
- package/dist/brainyrich/pages/AdvisorsPage.js.map +0 -1
- package/dist/brainyrich/pages/AiAssistantPage.d.ts +0 -2
- package/dist/brainyrich/pages/AiAssistantPage.d.ts.map +0 -1
- package/dist/brainyrich/pages/AnalyticsPage.d.ts +0 -2
- package/dist/brainyrich/pages/AnalyticsPage.d.ts.map +0 -1
- package/dist/brainyrich/pages/AssistantPage.d.ts +0 -2
- package/dist/brainyrich/pages/AssistantPage.d.ts.map +0 -1
- package/dist/brainyrich/pages/AssistantPage.js +0 -332
- package/dist/brainyrich/pages/AssistantPage.js.map +0 -1
- package/dist/brainyrich/pages/DashboardPage.d.ts +0 -2
- package/dist/brainyrich/pages/DashboardPage.d.ts.map +0 -1
- package/dist/brainyrich/pages/EstatePage.d.ts +0 -2
- package/dist/brainyrich/pages/EstatePage.d.ts.map +0 -1
- package/dist/brainyrich/pages/EstatePage.js +0 -269
- package/dist/brainyrich/pages/EstatePage.js.map +0 -1
- package/dist/brainyrich/pages/FamilyPage.d.ts +0 -2
- package/dist/brainyrich/pages/FamilyPage.d.ts.map +0 -1
- package/dist/brainyrich/pages/GoalsPage.d.ts +0 -2
- package/dist/brainyrich/pages/GoalsPage.d.ts.map +0 -1
- package/dist/brainyrich/pages/InsurancePage.d.ts +0 -2
- package/dist/brainyrich/pages/InsurancePage.d.ts.map +0 -1
- package/dist/brainyrich/pages/InsurancePage.js +0 -181
- package/dist/brainyrich/pages/InsurancePage.js.map +0 -1
- package/dist/brainyrich/pages/InvestmentsPage.d.ts +0 -2
- package/dist/brainyrich/pages/InvestmentsPage.d.ts.map +0 -1
- package/dist/brainyrich/pages/MarketplacePage.d.ts +0 -2
- package/dist/brainyrich/pages/MarketplacePage.d.ts.map +0 -1
- package/dist/brainyrich/pages/MarketplacePage.js +0 -450
- package/dist/brainyrich/pages/MarketplacePage.js.map +0 -1
- package/dist/brainyrich/pages/PortfoliosPage.d.ts +0 -2
- package/dist/brainyrich/pages/PortfoliosPage.d.ts.map +0 -1
- package/dist/brainyrich/pages/ReportsPage.d.ts +0 -2
- package/dist/brainyrich/pages/ReportsPage.d.ts.map +0 -1
- package/dist/brainyrich/pages/RiskPage.d.ts +0 -2
- package/dist/brainyrich/pages/RiskPage.d.ts.map +0 -1
- package/dist/brainyrich/pages/TaxPage.d.ts +0 -2
- package/dist/brainyrich/pages/TaxPage.d.ts.map +0 -1
- package/dist/brainyrich/pages/_shared.d.ts +0 -21
- package/dist/brainyrich/pages/_shared.d.ts.map +0 -1
- package/dist/brainyrich/providers/BrainyRichProvider.d.ts +0 -6
- package/dist/brainyrich/providers/BrainyRichProvider.d.ts.map +0 -1
- package/dist/brainyrich/store/brainyrichStore.d.ts +0 -19
- package/dist/brainyrich/store/brainyrichStore.d.ts.map +0 -1
- package/dist/brainyrich/store/brainyrichStore.js +0 -272
- package/dist/brainyrich/store/brainyrichStore.js.map +0 -1
- package/dist/brainyrich/types/index.d.ts +0 -116
- package/dist/brainyrich/types/index.d.ts.map +0 -1
- package/dist/brainyrich/utils/cn.d.ts +0 -4
- package/dist/brainyrich/utils/cn.d.ts.map +0 -1
- package/dist/brainyrich/utils/i18n.d.ts +0 -6
- package/dist/brainyrich/utils/i18n.d.ts.map +0 -1
- package/dist/brainyrich/utils/navigation.d.ts +0 -2
- package/dist/brainyrich/utils/navigation.d.ts.map +0 -1
- package/dist/dev/main.d.ts +0 -2
- package/dist/dev/main.d.ts.map +0 -1
- package/dist/generated/global-operations.d.ts +0 -2
- package/dist/generated/global-operations.d.ts.map +0 -1
- package/dist/generated/global-types.d.ts +0 -18199
- package/dist/generated/global-types.d.ts.map +0 -1
- package/dist/generated/wspace-operations.d.ts +0 -2
- package/dist/generated/wspace-operations.d.ts.map +0 -1
- package/dist/generated/wspace-types.d.ts +0 -43046
- package/dist/generated/wspace-types.d.ts.map +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiAssistantPage.js","names":[],"sources":["../../../src/brainyrich/pages/AiAssistantPage.tsx"],"sourcesContent":["import { useState, useRef, useEffect } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n Input,\n} from '@burdenoff/fe-libs/ui';\nimport {\n Bot,\n Send,\n Mic,\n Paperclip,\n Sparkles,\n TrendingUp,\n Calculator,\n PieChart,\n FileText,\n Lightbulb,\n Clock,\n Plus,\n User,\n} from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useBrainyRichStore } from '../store/brainyrichStore';\nimport { tWithFallback } from '../utils/i18n';\nimport { SectionShell, formatMoney } from './_shared';\n\nlet messageCounter = 0;\n\nfunction nextMessageId() {\n messageCounter += 1;\n return `msg-${messageCounter}`;\n}\n\ninterface ChatMessage {\n id: string;\n content: string;\n sender: 'user' | 'assistant';\n timestamp: Date;\n type?: 'text' | 'analysis' | 'recommendation';\n metadata?: {\n confidence?: number;\n sources?: string[];\n relatedTopics?: string[];\n };\n}\n\ninterface ChatSession {\n id: string;\n titleKey: string;\n titleFallback: string;\n title: string;\n lastMessage: Date;\n messageCount: number;\n}\n\nconst chatSessions: ChatSession[] = [\n {\n id: '1',\n titleKey: 'brainyrich.aiAssistant.sessions.taxPlanningStrategy',\n titleFallback: 'Tax Planning Strategy',\n title: 'Tax Planning Strategy',\n lastMessage: new Date(Date.now() - 1000 * 60 * 30),\n messageCount: 12,\n },\n {\n id: '2',\n titleKey: 'brainyrich.aiAssistant.sessions.portfolioRebalancingQ2',\n titleFallback: 'Portfolio Rebalancing Q2',\n title: 'Portfolio Rebalancing Q2',\n lastMessage: new Date(Date.now() - 1000 * 60 * 60 * 2),\n messageCount: 8,\n },\n {\n id: '3',\n titleKey: 'brainyrich.aiAssistant.sessions.estateNomineeUpdate',\n titleFallback: 'Estate Nominee Update',\n title: 'Estate Nominee Update',\n lastMessage: new Date(Date.now() - 1000 * 60 * 60 * 24),\n messageCount: 15,\n },\n {\n id: '4',\n titleKey: 'brainyrich.aiAssistant.sessions.retirementCorpusReview',\n titleFallback: 'Retirement Corpus Review',\n title: 'Retirement Corpus Review',\n lastMessage: new Date(Date.now() - 1000 * 60 * 60 * 48),\n messageCount: 6,\n },\n];\n\nconst quickSuggestions = [\n {\n key: 'brainyrich.aiAssistant.suggestions.portfolioPerformance',\n fallback: 'Analyze my portfolio performance',\n icon: TrendingUp,\n },\n {\n key: 'brainyrich.aiAssistant.suggestions.taxOptimization',\n fallback: 'Tax optimization strategies for FY 2026-27',\n icon: Calculator,\n },\n {\n key: 'brainyrich.aiAssistant.suggestions.retirementCorpus',\n fallback: 'Review my retirement corpus projections',\n icon: PieChart,\n },\n {\n key: 'brainyrich.aiAssistant.suggestions.estateChecklist',\n fallback: 'Estate planning checklist for nominees',\n icon: FileText,\n },\n];\n\nfunction formatTimeAgo(date: Date): string {\n const diffMs = Date.now() - date.getTime();\n const mins = Math.floor(diffMs / 60000);\n if (mins < 60) return `${mins}m ago`;\n const hrs = Math.floor(mins / 60);\n if (hrs < 24) return `${hrs}h ago`;\n const days = Math.floor(hrs / 24);\n return `${days}d ago`;\n}\n\nfunction generateAIResponse(\n input: string,\n ctx: { netWorth: string; portfolioValue: string }\n): string {\n const lower = input.toLowerCase();\n if (lower.includes('tax') || lower.includes('80c') || lower.includes('deduction')) {\n return `Based on your current tax documents, you have room to optimize Section 80C and 80D deductions. With your net worth of ${ctx.netWorth}, I recommend maximizing ELSS investments and NPS contributions. Your capital gains statement shows opportunities for tax-loss harvesting worth approximately $3,200. Shall I generate a detailed FY 2026-27 tax plan?`;\n }\n if (\n lower.includes('portfolio') ||\n lower.includes('invest') ||\n lower.includes('stock') ||\n lower.includes('rebalanc')\n ) {\n return `Your total portfolio value stands at ${ctx.portfolioValue} across three strategies. The Growth Portfolio leads YTD returns at 12.4%, but technology concentration has exceeded the 34% threshold. I suggest trimming AAPL/MSFT positions by 5% and rotating into international diversified ETFs. Want me to model a rebalancing scenario?`;\n }\n if (lower.includes('retire') || lower.includes('corpus') || lower.includes('pension')) {\n return `Your Retirement Corpus goal is 61.6% funded ($1.54M of $2.5M target by 2035). At your current savings rate, you'll reach 82% by deadline. Increasing SIP contributions by $500/month and utilizing catch-up NPS deposits could close the gap entirely. Shall I run a Monte Carlo simulation for different scenarios?`;\n }\n if (\n lower.includes('estate') ||\n lower.includes('nominee') ||\n lower.includes('will') ||\n lower.includes('trust')\n ) {\n return `Your estate planning workflow has a pending nominee update task. Based on your assets, I recommend reviewing beneficiary designations across all linked accounts and updating your healthcare directive. Your current life cover of $200K (2Cr) from HDFC Life may need reassessment given dependents. Would you like a comprehensive estate planning checklist?`;\n }\n return `I can help with investment analysis, tax optimization, retirement planning, estate strategies, and general wealth management. With your current net worth of ${ctx.netWorth} and active risk alerts to address, there are several areas we can focus on. What specific aspect of your finances would you like to explore?`;\n}\n\nexport function AiAssistantPage() {\n const { t } = useI18n();\n const { metrics, portfolios, risks } = useBrainyRichStore();\n const totalPortfolioValue = portfolios.reduce((s, p) => s + p.value, 0);\n const translate = (key: string, fallback: string, params?: Record<string, string | number>) =>\n tWithFallback(t, key, fallback, params);\n const highRiskCount = risks.filter((r) => r.severity === 'High').length;\n const translatedSessions = chatSessions.map((session) => ({\n ...session,\n title: translate(session.titleKey, session.titleFallback),\n }));\n const translatedSuggestions = quickSuggestions.map((suggestion) => ({\n ...suggestion,\n text: translate(suggestion.key, suggestion.fallback),\n }));\n const netWorth =\n metrics.find((m) => m.label === 'Net Worth')?.value ?? formatMoney(totalPortfolioValue);\n\n const [messages, setMessages] = useState<ChatMessage[]>([\n {\n id: '1',\n content: translate(\n 'brainyrich.aiAssistant.welcomeMessage',\n \"Welcome back! I'm your AI wealth assistant. Your portfolio is at {portfolioValue} with {highRiskCount} high-priority risk alert{sSuffix} needing attention. How can I help you today?\",\n {\n portfolioValue: formatMoney(totalPortfolioValue),\n highRiskCount,\n sSuffix: highRiskCount !== 1 ? 's' : '',\n }\n ),\n sender: 'assistant',\n timestamp: new Date(),\n type: 'text',\n },\n ]);\n const [inputValue, setInputValue] = useState('');\n const [isTyping, setIsTyping] = useState(false);\n const [activeSession, setActiveSession] = useState('new');\n\n const messagesEndRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\n }, [messages]);\n\n const handleSendMessage = () => {\n if (!inputValue.trim() || isTyping) return;\n\n const userMessage: ChatMessage = {\n id: nextMessageId(),\n content: inputValue,\n sender: 'user',\n timestamp: new Date(0),\n type: 'text',\n };\n\n setMessages((prev) => [...prev, userMessage]);\n setInputValue('');\n setIsTyping(true);\n\n setTimeout(() => {\n const response = generateAIResponse(inputValue, {\n netWorth,\n portfolioValue: formatMoney(totalPortfolioValue),\n });\n const assistantMessage: ChatMessage = {\n id: (Date.now() + 1).toString(),\n content: response,\n sender: 'assistant',\n timestamp: new Date(),\n type: 'text',\n metadata: {\n confidence: 0.92,\n sources: ['Financial Planning Standards', 'Portfolio Analytics Engine'],\n relatedTopics: ['Tax Planning', 'Retirement Planning', 'Risk Management'],\n },\n };\n setMessages((prev) => [...prev, assistantMessage]);\n setIsTyping(false);\n }, 1500);\n };\n\n const handleSuggestionClick = (text: string) => {\n setInputValue(text);\n inputRef.current?.focus();\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleSendMessage();\n }\n };\n\n return (\n <SectionShell\n title={translate('brainyrich.aiAssistant.title', 'AI Wealth Assistant')}\n description={translate(\n 'brainyrich.aiAssistant.description',\n 'Personalized financial advice powered by artificial intelligence'\n )}\n badges={[translate('brainyrich.aiAssistant.badges.aiPowered', 'AI Powered')]}\n actionLabel={translate('brainyrich.aiAssistant.actions.exportChat', 'Export Chat')}\n >\n <div\n className=\"grid grid-cols-1 gap-6 lg:grid-cols-4\"\n style={{ minHeight: 'calc(100vh - 280px)' }}\n >\n {/* Session sidebar */}\n <div className=\"space-y-3 lg:col-span-1\">\n <Button\n variant=\"outline\"\n className=\"w-full justify-start gap-2\"\n onClick={() => setActiveSession('new')}\n >\n <Plus className=\"h-4 w-4\" />\n {translate('brainyrich.aiAssistant.actions.newConversation', 'New Conversation')}\n </Button>\n\n <Card>\n <CardHeader className=\"pb-2\">\n <CardTitle className=\"flex items-center gap-2 text-sm\">\n <Clock className=\"h-4 w-4\" />\n {translate('brainyrich.aiAssistant.sections.recentSessions', 'Recent Sessions')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-1 p-3 pt-0\">\n {translatedSessions.map((session) => (\n <button\n key={session.id}\n type=\"button\"\n className={`w-full rounded-md p-2 text-left transition-colors hover:bg-accent ${activeSession === session.id ? 'bg-accent' : ''}`}\n onClick={() => setActiveSession(session.id)}\n >\n <p className=\"truncate text-sm font-medium\">{session.title}</p>\n <div className=\"mt-0.5 flex items-center justify-between text-xs text-muted-foreground\">\n <span>\n {translate('brainyrich.aiAssistant.session.messageCount', '{count} msgs', {\n count: session.messageCount,\n })}\n </span>\n <span>{formatTimeAgo(session.lastMessage)}</span>\n </div>\n </button>\n ))}\n </CardContent>\n </Card>\n\n {/* Context card */}\n <Card>\n <CardHeader className=\"pb-2\">\n <CardTitle className=\"text-sm\">\n {translate('brainyrich.aiAssistant.sections.portfolioContext', 'Portfolio Context')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2 p-3 pt-0\">\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"text-muted-foreground\">\n {translate('brainyrich.aiAssistant.context.netWorth', 'Net Worth')}\n </span>\n <span className=\"font-medium\">{netWorth}</span>\n </div>\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"text-muted-foreground\">\n {translate('brainyrich.aiAssistant.context.invested', 'Invested')}\n </span>\n <span className=\"font-medium\">{formatMoney(totalPortfolioValue)}</span>\n </div>\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"text-muted-foreground\">\n {translate('brainyrich.aiAssistant.context.portfolios', 'Portfolios')}\n </span>\n <span className=\"font-medium\">{portfolios.length}</span>\n </div>\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"text-muted-foreground\">\n {translate('brainyrich.aiAssistant.context.riskAlerts', 'Risk Alerts')}\n </span>\n <Badge\n variant={risks.some((r) => r.severity === 'High') ? 'destructive' : 'secondary'}\n className=\"text-[10px]\"\n >\n {translate('brainyrich.aiAssistant.context.activeAlerts', '{count} active', {\n count: risks.length,\n })}\n </Badge>\n </div>\n </CardContent>\n </Card>\n </div>\n\n {/* Main chat */}\n <div className=\"flex flex-col lg:col-span-3\">\n <Card className=\"flex flex-1 flex-col\">\n <CardHeader className=\"border-b py-3\">\n <div className=\"flex items-center justify-between\">\n <div>\n <CardTitle className=\"flex items-center gap-2 text-base\">\n <Bot className=\"h-5 w-5 text-blue-600\" />\n {translate('brainyrich.aiAssistant.chat.title', 'Financial AI Assistant')}\n </CardTitle>\n <CardDescription>\n {translate(\n 'brainyrich.aiAssistant.chat.description',\n 'Real-time analysis and personalized wealth recommendations'\n )}\n </CardDescription>\n </div>\n <div className=\"flex items-center gap-2\">\n <Badge variant=\"outline\" className=\"border-green-200 text-green-600\">\n {translate('brainyrich.aiAssistant.status.online', 'Online')}\n </Badge>\n <div className=\"flex items-center gap-1 text-sm text-muted-foreground\">\n <div className=\"h-2 w-2 animate-pulse rounded-full bg-green-500\" />\n {translate('brainyrich.aiAssistant.status.active', 'Active')}\n </div>\n </div>\n </div>\n </CardHeader>\n\n {/* Messages area */}\n <CardContent\n className=\"flex-1 space-y-4 overflow-y-auto p-4\"\n style={{ maxHeight: 'calc(100vh - 520px)', minHeight: '300px' }}\n >\n {messages.map((msg) => (\n <div\n key={msg.id}\n className={`flex ${msg.sender === 'user' ? 'justify-end' : 'justify-start'}`}\n >\n <div\n className={`flex max-w-[80%] items-start gap-2 ${msg.sender === 'user' ? 'flex-row-reverse' : ''}`}\n >\n <div\n className={`rounded-full p-2 ${msg.sender === 'user' ? 'bg-primary/10' : 'bg-blue-100'}`}\n >\n {msg.sender === 'user' ? (\n <User className=\"h-4 w-4\" />\n ) : (\n <Bot className=\"h-4 w-4 text-blue-600\" />\n )}\n </div>\n <div\n className={`space-y-1 rounded-lg p-3 ${msg.sender === 'user' ? 'bg-primary text-primary-foreground' : 'bg-muted'}`}\n >\n <p className=\"text-sm\">{msg.content}</p>\n {msg.metadata?.relatedTopics ? (\n <div className=\"flex flex-wrap gap-1 pt-1\">\n {msg.metadata.relatedTopics.map((topic) => (\n <Badge key={topic} variant=\"outline\" className=\"text-[10px]\">\n {topic}\n </Badge>\n ))}\n </div>\n ) : null}\n <p className=\"text-[10px] opacity-60\">\n {msg.timestamp.toLocaleTimeString([], {\n hour: '2-digit',\n minute: '2-digit',\n })}\n {msg.metadata?.confidence\n ? ` · ${Math.round(msg.metadata.confidence * 100)}% confidence`\n : ''}\n </p>\n </div>\n </div>\n </div>\n ))}\n\n {isTyping ? (\n <div className=\"flex items-center gap-2\">\n <div className=\"rounded-full bg-blue-100 p-2\">\n <Bot className=\"h-4 w-4 text-blue-600\" />\n </div>\n <div className=\"rounded-lg bg-muted p-3\">\n <div className=\"flex space-x-1\">\n <div className=\"h-2 w-2 animate-bounce rounded-full bg-muted-foreground/40\" />\n <div\n className=\"h-2 w-2 animate-bounce rounded-full bg-muted-foreground/40\"\n style={{ animationDelay: '0.1s' }}\n />\n <div\n className=\"h-2 w-2 animate-bounce rounded-full bg-muted-foreground/40\"\n style={{ animationDelay: '0.2s' }}\n />\n </div>\n </div>\n </div>\n ) : null}\n <div ref={messagesEndRef} />\n </CardContent>\n\n {/* Quick suggestions - show only at start */}\n {messages.length <= 1 ? (\n <div className=\"border-t px-4 py-3\">\n <p className=\"mb-2 flex items-center gap-1 text-xs text-muted-foreground\">\n <Sparkles className=\"h-3 w-3\" />\n {translate(\n 'brainyrich.aiAssistant.sections.suggestedQuestions',\n 'Suggested questions'\n )}\n </p>\n <div className=\"grid gap-2 sm:grid-cols-2\">\n {translatedSuggestions.map((s) => (\n <button\n key={s.text}\n type=\"button\"\n className=\"flex items-center gap-2 rounded-md border p-2 text-left text-sm transition-colors hover:bg-accent\"\n onClick={() => handleSuggestionClick(s.text)}\n >\n <s.icon className=\"h-4 w-4 shrink-0 text-muted-foreground\" />\n {s.text}\n </button>\n ))}\n </div>\n </div>\n ) : null}\n\n {/* Input area */}\n <div className=\"border-t p-4\">\n <div className=\"flex items-center gap-2\">\n <div className=\"relative flex-1\">\n <Input\n ref={inputRef}\n value={inputValue}\n onChange={(e) => setInputValue(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={translate(\n 'brainyrich.aiAssistant.input.placeholder',\n 'Ask about investments, taxes, retirement, estate planning...'\n )}\n className=\"pr-20\"\n />\n <div className=\"absolute right-2 top-1/2 flex -translate-y-1/2 items-center gap-1\">\n <Button variant=\"ghost\" size=\"icon\" className=\"h-7 w-7\">\n <Paperclip className=\"h-4 w-4\" />\n </Button>\n <Button variant=\"ghost\" size=\"icon\" className=\"h-7 w-7\">\n <Mic className=\"h-4 w-4\" />\n </Button>\n </div>\n </div>\n <Button\n onClick={handleSendMessage}\n disabled={!inputValue.trim() || isTyping}\n size=\"sm\"\n >\n <Send className=\"h-4 w-4\" />\n </Button>\n </div>\n <div className=\"mt-2 flex items-center justify-between text-xs text-muted-foreground\">\n <span className=\"flex items-center gap-1\">\n <Lightbulb className=\"h-3 w-3\" />\n {translate(\n 'brainyrich.aiAssistant.disclaimer',\n 'AI can make mistakes. Always verify important financial information.'\n )}\n </span>\n <span className=\"flex items-center gap-1\">\n <kbd className=\"rounded bg-muted px-1.5 py-0.5 text-[10px]\">Enter</kbd>\n {translate('brainyrich.aiAssistant.input.toSend', 'to send')}\n </span>\n </div>\n </div>\n </Card>\n </div>\n </div>\n </SectionShell>\n );\n}\n"],"mappings":";;;;;;;;;AA+BA,IAAI,IAAiB;AAErB,SAAS,IAAgB;AAEvB,QADA,KAAkB,GACX,OAAO;;AAyBhB,IAAM,IAA8B;CAClC;EACE,IAAI;EACJ,UAAU;EACV,eAAe;EACf,OAAO;EACP,6BAAa,IAAI,KAAK,KAAK,KAAK,GAAG,MAAO,KAAK,GAAG;EAClD,cAAc;EACf;CACD;EACE,IAAI;EACJ,UAAU;EACV,eAAe;EACf,OAAO;EACP,6BAAa,IAAI,KAAK,KAAK,KAAK,GAAG,MAAO,KAAK,KAAK,EAAE;EACtD,cAAc;EACf;CACD;EACE,IAAI;EACJ,UAAU;EACV,eAAe;EACf,OAAO;EACP,6BAAa,IAAI,KAAK,KAAK,KAAK,GAAG,MAAO,KAAK,KAAK,GAAG;EACvD,cAAc;EACf;CACD;EACE,IAAI;EACJ,UAAU;EACV,eAAe;EACf,OAAO;EACP,6BAAa,IAAI,KAAK,KAAK,KAAK,GAAG,MAAO,KAAK,KAAK,GAAG;EACvD,cAAc;EACf;CACF,EAEK,IAAmB;CACvB;EACE,KAAK;EACL,UAAU;EACV,MAAM;EACP;CACD;EACE,KAAK;EACL,UAAU;EACV,MAAM;EACP;CACD;EACE,KAAK;EACL,UAAU;EACV,MAAM;EACP;CACD;EACE,KAAK;EACL,UAAU;EACV,MAAM;EACP;CACF;AAED,SAAS,EAAc,GAAoB;CACzC,IAAM,IAAS,KAAK,KAAK,GAAG,EAAK,SAAS,EACpC,IAAO,KAAK,MAAM,IAAS,IAAM;AACvC,KAAI,IAAO,GAAI,QAAO,GAAG,EAAK;CAC9B,IAAM,IAAM,KAAK,MAAM,IAAO,GAAG;AAGjC,QAFI,IAAM,KAAW,GAAG,EAAI,SAErB,GADM,KAAK,MAAM,IAAM,GAAG,CAClB;;AAGjB,SAAS,EACP,GACA,GACQ;CACR,IAAM,IAAQ,EAAM,aAAa;AAuBjC,QAtBI,EAAM,SAAS,MAAM,IAAI,EAAM,SAAS,MAAM,IAAI,EAAM,SAAS,YAAY,GACxE,yHAAyH,EAAI,SAAS,0NAG7I,EAAM,SAAS,YAAY,IAC3B,EAAM,SAAS,SAAS,IACxB,EAAM,SAAS,QAAQ,IACvB,EAAM,SAAS,WAAW,GAEnB,wCAAwC,EAAI,eAAe,mRAEhE,EAAM,SAAS,SAAS,IAAI,EAAM,SAAS,SAAS,IAAI,EAAM,SAAS,UAAU,GAC5E,yTAGP,EAAM,SAAS,SAAS,IACxB,EAAM,SAAS,UAAU,IACzB,EAAM,SAAS,OAAO,IACtB,EAAM,SAAS,QAAQ,GAEhB,qWAEF,gKAAgK,EAAI,SAAS;;AAGtL,SAAgB,IAAkB;CAChC,IAAM,EAAE,SAAM,GAAS,EACjB,EAAE,YAAS,eAAY,aAAU,GAAoB,EACrD,IAAsB,EAAW,QAAQ,GAAG,MAAM,IAAI,EAAE,OAAO,EAAE,EACjE,KAAa,GAAa,GAAkB,MAChD,EAAc,GAAG,GAAK,GAAU,EAAO,EACnC,IAAgB,EAAM,QAAQ,MAAM,EAAE,aAAa,OAAO,CAAC,QAC3D,IAAqB,EAAa,KAAK,OAAa;EACxD,GAAG;EACH,OAAO,EAAU,EAAQ,UAAU,EAAQ,cAAc;EAC1D,EAAE,EACG,IAAwB,EAAiB,KAAK,OAAgB;EAClE,GAAG;EACH,MAAM,EAAU,EAAW,KAAK,EAAW,SAAS;EACrD,EAAE,EACG,IACJ,EAAQ,MAAM,MAAM,EAAE,UAAU,YAAY,EAAE,SAAS,EAAY,EAAoB,EAEnF,CAAC,GAAU,KAAe,EAAwB,CACtD;EACE,IAAI;EACJ,SAAS,EACP,yCACA,yLACA;GACE,gBAAgB,EAAY,EAAoB;GAChD;GACA,SAAS,MAAkB,IAAU,KAAN;GAChC,CACF;EACD,QAAQ;EACR,2BAAW,IAAI,MAAM;EACrB,MAAM;EACP,CACF,CAAC,EACI,CAAC,GAAY,KAAiB,EAAS,GAAG,EAC1C,CAAC,GAAU,KAAe,EAAS,GAAM,EACzC,CAAC,GAAe,KAAoB,EAAS,MAAM,EAEnD,IAAiB,EAAuB,KAAK,EAC7C,IAAW,EAAyB,KAAK;AAE/C,SAAgB;AACd,IAAe,SAAS,eAAe,EAAE,UAAU,UAAU,CAAC;IAC7D,CAAC,EAAS,CAAC;CAEd,IAAM,UAA0B;AAC9B,MAAI,CAAC,EAAW,MAAM,IAAI,EAAU;EAEpC,IAAM,IAA2B;GAC/B,IAAI,GAAe;GACnB,SAAS;GACT,QAAQ;GACR,2BAAW,IAAI,KAAK,EAAE;GACtB,MAAM;GACP;AAMD,EAJA,GAAa,MAAS,CAAC,GAAG,GAAM,EAAY,CAAC,EAC7C,EAAc,GAAG,EACjB,EAAY,GAAK,EAEjB,iBAAiB;GACf,IAAM,IAAW,EAAmB,GAAY;IAC9C;IACA,gBAAgB,EAAY,EAAoB;IACjD,CAAC,EACI,IAAgC;IACpC,KAAK,KAAK,KAAK,GAAG,GAAG,UAAU;IAC/B,SAAS;IACT,QAAQ;IACR,2BAAW,IAAI,MAAM;IACrB,MAAM;IACN,UAAU;KACR,YAAY;KACZ,SAAS,CAAC,gCAAgC,6BAA6B;KACvE,eAAe;MAAC;MAAgB;MAAuB;MAAkB;KAC1E;IACF;AAED,GADA,GAAa,MAAS,CAAC,GAAG,GAAM,EAAiB,CAAC,EAClD,EAAY,GAAM;KACjB,KAAK;IAGJ,KAAyB,MAAiB;AAE9C,EADA,EAAc,EAAK,EACnB,EAAS,SAAS,OAAO;;AAU3B,QACE,kBAAC,GAAD;EACE,OAAO,EAAU,gCAAgC,sBAAsB;EACvE,aAAa,EACX,sCACA,mEACD;EACD,QAAQ,CAAC,EAAU,2CAA2C,aAAa,CAAC;EAC5E,aAAa,EAAU,6CAA6C,cAAc;YAElF,kBAAC,OAAD;GACE,WAAU;GACV,OAAO,EAAE,WAAW,uBAAuB;aAF7C,CAKE,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,GAAD;MACE,SAAQ;MACR,WAAU;MACV,eAAe,EAAiB,MAAM;gBAHxC,CAKE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAC3B,EAAU,kDAAkD,mBAAmB,CACzE;;KAET,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;MAAY,WAAU;gBACpB,kBAAC,GAAD;OAAW,WAAU;iBAArB,CACE,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA,EAC5B,EAAU,kDAAkD,kBAAkB,CACrE;;MACD,CAAA,EACb,kBAAC,GAAD;MAAa,WAAU;gBACpB,EAAmB,KAAK,MACvB,kBAAC,UAAD;OAEE,MAAK;OACL,WAAW,qEAAqE,MAAkB,EAAQ,KAAK,cAAc;OAC7H,eAAe,EAAiB,EAAQ,GAAG;iBAJ7C,CAME,kBAAC,KAAD;QAAG,WAAU;kBAAgC,EAAQ;QAAU,CAAA,EAC/D,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD,EAAA,UACG,EAAU,+CAA+C,gBAAgB,EACxE,OAAO,EAAQ,cAChB,CAAC,EACG,CAAA,EACP,kBAAC,QAAD,EAAA,UAAO,EAAc,EAAQ,YAAY,EAAQ,CAAA,CAC7C;UACC;SAdF,EAAQ,GAcN,CACT;MACU,CAAA,CACT,EAAA,CAAA;KAGP,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;MAAY,WAAU;gBACpB,kBAAC,GAAD;OAAW,WAAU;iBAClB,EAAU,oDAAoD,oBAAoB;OACzE,CAAA;MACD,CAAA,EACb,kBAAC,GAAD;MAAa,WAAU;gBAAvB;OACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBACb,EAAU,2CAA2C,YAAY;SAC7D,CAAA,EACP,kBAAC,QAAD;SAAM,WAAU;mBAAe;SAAgB,CAAA,CAC3C;;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBACb,EAAU,2CAA2C,WAAW;SAC5D,CAAA,EACP,kBAAC,QAAD;SAAM,WAAU;mBAAe,EAAY,EAAoB;SAAQ,CAAA,CACnE;;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBACb,EAAU,6CAA6C,aAAa;SAChE,CAAA,EACP,kBAAC,QAAD;SAAM,WAAU;mBAAe,EAAW;SAAc,CAAA,CACpD;;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBACb,EAAU,6CAA6C,cAAc;SACjE,CAAA,EACP,kBAAC,GAAD;SACE,SAAS,EAAM,MAAM,MAAM,EAAE,aAAa,OAAO,GAAG,gBAAgB;SACpE,WAAU;mBAET,EAAU,+CAA+C,kBAAkB,EAC1E,OAAO,EAAM,QACd,CAAC;SACI,CAAA,CACJ;;OACM;QACT,EAAA,CAAA;KACH;OAGN,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD;KAAM,WAAU;eAAhB;MACE,kBAAC,GAAD;OAAY,WAAU;iBACpB,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,GAAD;SAAW,WAAU;mBAArB,CACE,kBAAC,GAAD,EAAK,WAAU,yBAA0B,CAAA,EACxC,EAAU,qCAAqC,yBAAyB,CAC/D;YACZ,kBAAC,GAAD,EAAA,UACG,EACC,2CACA,6DACD,EACe,CAAA,CACd,EAAA,CAAA,EACN,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UAAO,SAAQ;UAAU,WAAU;oBAChC,EAAU,wCAAwC,SAAS;UACtD,CAAA,EACR,kBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,kBAAC,OAAD,EAAK,WAAU,mDAAoD,CAAA,EAClE,EAAU,wCAAwC,SAAS,CACxD;YACF;WACF;;OACK,CAAA;MAGb,kBAAC,GAAD;OACE,WAAU;OACV,OAAO;QAAE,WAAW;QAAuB,WAAW;QAAS;iBAFjE;QAIG,EAAS,KAAK,MACb,kBAAC,OAAD;SAEE,WAAW,QAAQ,EAAI,WAAW,SAAS,gBAAgB;mBAE3D,kBAAC,OAAD;UACE,WAAW,sCAAsC,EAAI,WAAW,SAAS,qBAAqB;oBADhG,CAGE,kBAAC,OAAD;WACE,WAAW,oBAAoB,EAAI,WAAW,SAAS,kBAAkB;qBAExE,EAAI,WAAW,SACd,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,GAE5B,kBAAC,GAAD,EAAK,WAAU,yBAA0B,CAAA;WAEvC,CAAA,EACN,kBAAC,OAAD;WACE,WAAW,4BAA4B,EAAI,WAAW,SAAS,uCAAuC;qBADxG;YAGE,kBAAC,KAAD;aAAG,WAAU;uBAAW,EAAI;aAAY,CAAA;YACvC,EAAI,UAAU,gBACb,kBAAC,OAAD;aAAK,WAAU;uBACZ,EAAI,SAAS,cAAc,KAAK,MAC/B,kBAAC,GAAD;cAAmB,SAAQ;cAAU,WAAU;wBAC5C;cACK,EAFI,EAEJ,CACR;aACE,CAAA,GACJ;YACJ,kBAAC,KAAD;aAAG,WAAU;uBAAb,CACG,EAAI,UAAU,mBAAmB,EAAE,EAAE;cACpC,MAAM;cACN,QAAQ;cACT,CAAC,EACD,EAAI,UAAU,aACX,MAAM,KAAK,MAAM,EAAI,SAAS,aAAa,IAAI,CAAC,gBAChD,GACF;;YACA;aACF;;SACF,EAvCC,EAAI,GAuCL,CACN;QAED,IACC,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,OAAD;UAAK,WAAU;oBACb,kBAAC,GAAD,EAAK,WAAU,yBAA0B,CAAA;UACrC,CAAA,EACN,kBAAC,OAAD;UAAK,WAAU;oBACb,kBAAC,OAAD;WAAK,WAAU;qBAAf;YACE,kBAAC,OAAD,EAAK,WAAU,8DAA+D,CAAA;YAC9E,kBAAC,OAAD;aACE,WAAU;aACV,OAAO,EAAE,gBAAgB,QAAQ;aACjC,CAAA;YACF,kBAAC,OAAD;aACE,WAAU;aACV,OAAO,EAAE,gBAAgB,QAAQ;aACjC,CAAA;YACE;;UACF,CAAA,CACF;aACJ;QACJ,kBAAC,OAAD,EAAK,KAAK,GAAkB,CAAA;QAChB;;MAGb,EAAS,UAAU,IAClB,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,KAAD;QAAG,WAAU;kBAAb,CACE,kBAAC,GAAD,EAAU,WAAU,WAAY,CAAA,EAC/B,EACC,sDACA,sBACD,CACC;WACJ,kBAAC,OAAD;QAAK,WAAU;kBACZ,EAAsB,KAAK,MAC1B,kBAAC,UAAD;SAEE,MAAK;SACL,WAAU;SACV,eAAe,EAAsB,EAAE,KAAK;mBAJ9C,CAME,kBAAC,EAAE,MAAH,EAAQ,WAAU,0CAA2C,CAAA,EAC5D,EAAE,KACI;WAPF,EAAE,KAOA,CACT;QACE,CAAA,CACF;WACJ;MAGJ,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UACE,KAAK;UACL,OAAO;UACP,WAAW,MAAM,EAAc,EAAE,OAAO,MAAM;UAC9C,YA/OK,MAA2B;AAChD,WAAI,EAAE,QAAQ,WAAW,CAAC,EAAE,aAC1B,EAAE,gBAAgB,EAClB,GAAmB;;UA6OL,aAAa,EACX,4CACA,+DACD;UACD,WAAU;UACV,CAAA,EACF,kBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,kBAAC,GAAD;WAAQ,SAAQ;WAAQ,MAAK;WAAO,WAAU;qBAC5C,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA;WAC1B,CAAA,EACT,kBAAC,GAAD;WAAQ,SAAQ;WAAQ,MAAK;WAAO,WAAU;qBAC5C,kBAAC,GAAD,EAAK,WAAU,WAAY,CAAA;WACpB,CAAA,CACL;YACF;YACN,kBAAC,GAAD;SACE,SAAS;SACT,UAAU,CAAC,EAAW,MAAM,IAAI;SAChC,MAAK;mBAEL,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA;SACrB,CAAA,CACL;WACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAhB,CACE,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA,EAChC,EACC,qCACA,uEACD,CACI;YACP,kBAAC,QAAD;SAAM,WAAU;mBAAhB,CACE,kBAAC,OAAD;UAAK,WAAU;oBAA6C;UAAW,CAAA,EACtE,EAAU,uCAAuC,UAAU,CACvD;WACH;UACF;;MACD;;IACH,CAAA,CACF;;EACO,CAAA"}
|
|
1
|
+
{"version":3,"file":"AiAssistantPage.js","names":[],"sources":["../../../src/brainyrich/pages/AiAssistantPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n Input,\n Label,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n AlertTriangle,\n BellRing,\n CheckCircle2,\n Info,\n Lightbulb,\n MoreHorizontal,\n Plus,\n ShieldAlert,\n XCircle,\n} from 'lucide-react';\nimport { tWithFallback } from '../utils/i18n';\nimport {\n useAcknowledgeInsight,\n useCreateInsight,\n useDismissInsight,\n useInsights,\n useResolveInsight,\n} from '../hooks/useBrainyRichApi';\nimport type {\n BraCreateInsightInput,\n BraInsight,\n BraInsightSeverity,\n BraInsightStatus,\n BraInsightType,\n} from '../types/bra';\nimport {\n EmptyState,\n ErrorState,\n KpiGrid,\n LoadingState,\n SectionShell,\n formatDate,\n statusBadgeVariant,\n} from './_shared';\n\nconst INSIGHT_TYPES: BraInsightType[] = [\n 'REBALANCE_DUE',\n 'DRIFT',\n 'CONCENTRATION_RISK',\n 'CASH_DRAG',\n 'FEE_ANOMALY',\n 'TAX_OPPORTUNITY',\n 'GOAL_AT_RISK',\n];\n\nconst INSIGHT_SEVERITIES: BraInsightSeverity[] = ['INFO', 'LOW', 'MEDIUM', 'HIGH', 'CRITICAL'];\n\nconst INSIGHT_STATUSES: BraInsightStatus[] = ['OPEN', 'ACKNOWLEDGED', 'RESOLVED', 'DISMISSED'];\n\nconst ALL = '__all__';\n\nfunction humanize(value: string): string {\n return value\n .toLowerCase()\n .split('_')\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(' ');\n}\n\ninterface SeverityMeta {\n icon: typeof Info;\n tone: string;\n}\n\nfunction severityMeta(severity: BraInsightSeverity): SeverityMeta {\n switch (severity) {\n case 'CRITICAL':\n return { icon: ShieldAlert, tone: 'text-status-error-text' };\n case 'HIGH':\n return { icon: AlertTriangle, tone: 'text-status-error-text' };\n case 'MEDIUM':\n return { icon: BellRing, tone: 'text-status-warning-text' };\n case 'LOW':\n return { icon: Lightbulb, tone: 'text-status-warning-text' };\n case 'INFO':\n default:\n return { icon: Info, tone: 'text-text-secondary' };\n }\n}\n\ninterface InsightFormState {\n title: string;\n type: BraInsightType;\n severity: BraInsightSeverity;\n subjectType: string;\n subjectId: string;\n detail: string;\n metrics: string;\n ownerId: string;\n}\n\nfunction emptyForm(): InsightFormState {\n return {\n title: '',\n type: 'DRIFT',\n severity: 'MEDIUM',\n subjectType: 'PORTFOLIO',\n subjectId: '',\n detail: '',\n metrics: '',\n ownerId: '',\n };\n}\n\nexport function AiAssistantPage() {\n const { t } = useI18n();\n const translate = (key: string, fallback: string, params?: Record<string, string | number>) =>\n tWithFallback(t, key, fallback, params);\n\n const [severityFilter, setSeverityFilter] = useState<string>(ALL);\n const [statusFilter, setStatusFilter] = useState<string>(ALL);\n const [typeFilter, setTypeFilter] = useState<string>(ALL);\n\n const {\n data: insights,\n isLoading,\n isError,\n refetch,\n } = useInsights({\n ...(severityFilter !== ALL ? { severity: severityFilter as BraInsightSeverity } : {}),\n ...(statusFilter !== ALL ? { status: statusFilter as BraInsightStatus } : {}),\n });\n\n const acknowledge = useAcknowledgeInsight();\n const dismiss = useDismissInsight();\n const resolve = useResolveInsight();\n const createInsight = useCreateInsight();\n\n const [createOpen, setCreateOpen] = useState(false);\n const [form, setForm] = useState<InsightFormState>(emptyForm);\n\n const setField = <K extends keyof InsightFormState>(key: K, value: InsightFormState[K]) =>\n setForm((prev) => ({ ...prev, [key]: value }));\n\n // Type is not a backend filter arg — narrow client-side.\n const filtered = useMemo(\n () => (typeFilter === ALL ? insights : insights.filter((i) => i.type === typeFilter)),\n [insights, typeFilter]\n );\n\n const counts = useMemo(() => {\n const open = insights.filter((i) => i.status === 'OPEN').length;\n const urgent = insights.filter(\n (i) => i.severity === 'HIGH' || i.severity === 'CRITICAL'\n ).length;\n const resolved = insights.filter((i) => i.status === 'RESOLVED').length;\n return { open, urgent, resolved };\n }, [insights]);\n\n const metricsValid = useMemo(() => {\n if (!form.metrics.trim()) return true;\n try {\n JSON.parse(form.metrics);\n return true;\n } catch {\n return false;\n }\n }, [form.metrics]);\n\n const formValid =\n form.title.trim().length > 0 &&\n form.subjectType.trim().length > 0 &&\n form.subjectId.trim().length > 0 &&\n metricsValid;\n\n const openCreate = () => {\n setForm(emptyForm());\n setCreateOpen(true);\n };\n\n const handleCreate = () => {\n if (!formValid) return;\n let metrics: Record<string, unknown> | undefined;\n if (form.metrics.trim()) {\n try {\n metrics = JSON.parse(form.metrics) as Record<string, unknown>;\n } catch {\n return;\n }\n }\n const input: BraCreateInsightInput = {\n title: form.title.trim(),\n type: form.type,\n severity: form.severity,\n subjectType: form.subjectType.trim(),\n subjectId: form.subjectId.trim(),\n detail: form.detail.trim() || null,\n ...(metrics ? { metrics } : {}),\n ...(form.ownerId.trim() ? { ownerId: form.ownerId.trim() } : {}),\n };\n createInsight.mutate(input, { onSuccess: () => setCreateOpen(false) });\n };\n\n const anyFilterActive = severityFilter !== ALL || statusFilter !== ALL || typeFilter !== ALL;\n\n const body = () => {\n if (isLoading) return <LoadingState rows={4} />;\n if (isError)\n return (\n <ErrorState\n title={translate('brainyrich.insights.error.title', 'Could not load insights')}\n description={translate(\n 'brainyrich.insights.error.description',\n 'We could not reach the insights service. Please try again.'\n )}\n onRetry={() => refetch()}\n />\n );\n\n return (\n <>\n <KpiGrid\n items={[\n {\n label: translate('brainyrich.insights.metrics.total', 'Insights'),\n value: String(insights.length),\n trend: translate('brainyrich.insights.metrics.totalTrend', 'In your inbox'),\n },\n {\n label: translate('brainyrich.insights.metrics.open', 'Open'),\n value: String(counts.open),\n trend: translate('brainyrich.insights.metrics.openTrend', 'Awaiting action'),\n deltaTone: counts.open > 0 ? 'negative' : 'positive',\n },\n {\n label: translate('brainyrich.insights.metrics.urgent', 'High priority'),\n value: String(counts.urgent),\n trend: translate('brainyrich.insights.metrics.urgentTrend', 'High or critical'),\n deltaTone: counts.urgent > 0 ? 'negative' : 'positive',\n },\n {\n label: translate('brainyrich.insights.metrics.resolved', 'Resolved'),\n value: String(counts.resolved),\n trend: translate('brainyrich.insights.metrics.resolvedTrend', 'Closed out'),\n deltaTone: 'positive',\n },\n ]}\n />\n\n {/* Filters */}\n <Card>\n <CardContent className=\"flex flex-col gap-3 p-4 sm:flex-row sm:items-end\">\n <div className=\"w-full space-y-1.5 sm:w-48\">\n <Label htmlFor=\"insight-filter-severity\">\n {translate('brainyrich.insights.filters.severity', 'Severity')}\n </Label>\n <Select value={severityFilter} onValueChange={setSeverityFilter}>\n <SelectTrigger id=\"insight-filter-severity\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={ALL}>\n {translate('brainyrich.insights.filters.all', 'All')}\n </SelectItem>\n {INSIGHT_SEVERITIES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"w-full space-y-1.5 sm:w-48\">\n <Label htmlFor=\"insight-filter-status\">\n {translate('brainyrich.insights.filters.status', 'Status')}\n </Label>\n <Select value={statusFilter} onValueChange={setStatusFilter}>\n <SelectTrigger id=\"insight-filter-status\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={ALL}>\n {translate('brainyrich.insights.filters.all', 'All')}\n </SelectItem>\n {INSIGHT_STATUSES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"w-full space-y-1.5 sm:w-56\">\n <Label htmlFor=\"insight-filter-type\">\n {translate('brainyrich.insights.filters.type', 'Type')}\n </Label>\n <Select value={typeFilter} onValueChange={setTypeFilter}>\n <SelectTrigger id=\"insight-filter-type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={ALL}>\n {translate('brainyrich.insights.filters.all', 'All')}\n </SelectItem>\n {INSIGHT_TYPES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </CardContent>\n </Card>\n\n {filtered.length === 0 ? (\n <EmptyState\n icon={<BellRing className=\"size-6\" aria-hidden=\"true\" />}\n title={\n anyFilterActive\n ? translate('brainyrich.insights.empty.filteredTitle', 'No matching insights')\n : translate('brainyrich.insights.empty.title', 'No advisory insights yet')\n }\n description={\n anyFilterActive\n ? translate(\n 'brainyrich.insights.empty.filteredDescription',\n 'No insights match the selected filters. Adjust or clear them to see more.'\n )\n : translate(\n 'brainyrich.insights.empty.description',\n 'Advisory insights flag rebalancing, drift, concentration and other opportunities. Create one to get started.'\n )\n }\n action={\n anyFilterActive ? (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => {\n setSeverityFilter(ALL);\n setStatusFilter(ALL);\n setTypeFilter(ALL);\n }}\n >\n {translate('brainyrich.insights.actions.clearFilters', 'Clear filters')}\n </Button>\n ) : (\n <Button size=\"sm\" onClick={openCreate}>\n <Plus className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.create', 'New insight')}\n </Button>\n )\n }\n />\n ) : (\n <div className=\"space-y-3\">\n {filtered.map((insight) => (\n <InsightCard\n key={insight.id}\n insight={insight}\n translate={translate}\n onAcknowledge={() => acknowledge.mutate(insight.id)}\n onDismiss={() => dismiss.mutate(insight.id)}\n onResolve={() => resolve.mutate(insight.id)}\n acknowledgePending={acknowledge.isPending}\n dismissPending={dismiss.isPending}\n resolvePending={resolve.isPending}\n />\n ))}\n </div>\n )}\n </>\n );\n };\n\n return (\n <>\n <SectionShell\n title={translate('brainyrich.insights.title', 'Insights')}\n description={translate(\n 'brainyrich.insights.description',\n 'Advisory insights across portfolios, accounts and goals — triage, acknowledge and resolve.'\n )}\n badges={[translate('brainyrich.insights.badges.advisory', 'Advisory')]}\n actionLabel={translate('brainyrich.insights.actions.create', 'New insight')}\n onAction={openCreate}\n >\n {body()}\n </SectionShell>\n\n <InsightFormDialog\n open={createOpen}\n form={form}\n setField={setField}\n metricsValid={metricsValid}\n valid={formValid}\n pending={createInsight.isPending}\n onSubmit={handleCreate}\n onOpenChange={(v) => setCreateOpen(v)}\n translate={translate}\n />\n </>\n );\n}\n\ntype Translate = (\n key: string,\n fallback: string,\n params?: Record<string, string | number>\n) => string;\n\ninterface InsightCardProps {\n insight: BraInsight;\n translate: Translate;\n onAcknowledge: () => void;\n onDismiss: () => void;\n onResolve: () => void;\n acknowledgePending: boolean;\n dismissPending: boolean;\n resolvePending: boolean;\n}\n\nfunction InsightCard({\n insight,\n translate,\n onAcknowledge,\n onDismiss,\n onResolve,\n acknowledgePending,\n dismissPending,\n resolvePending,\n}: InsightCardProps) {\n const meta = severityMeta(insight.severity);\n const SeverityIcon = meta.icon;\n const isClosed = insight.status === 'RESOLVED' || insight.status === 'DISMISSED';\n\n return (\n <Card>\n <CardHeader className=\"pb-3\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex min-w-0 items-start gap-3\">\n <span\n className={`mt-0.5 flex size-9 shrink-0 items-center justify-center rounded-full bg-bg-sunken ${meta.tone}`}\n >\n <SeverityIcon className=\"size-5\" aria-hidden=\"true\" />\n </span>\n <div className=\"min-w-0\">\n <CardTitle className=\"text-base\">{insight.title}</CardTitle>\n <CardDescription className=\"mt-1 flex flex-wrap items-center gap-2\">\n <Badge variant=\"outline\">{humanize(insight.type)}</Badge>\n <Badge variant={statusBadgeVariant(insight.severity)}>\n <span className={`inline-flex items-center gap-1 ${meta.tone}`}>\n <SeverityIcon className=\"size-3\" aria-hidden=\"true\" />\n {humanize(insight.severity)}\n </span>\n </Badge>\n <Badge variant={statusBadgeVariant(insight.status)}>\n {humanize(insight.status)}\n </Badge>\n </CardDescription>\n </div>\n </div>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={translate('brainyrich.insights.actions.menu', 'Insight actions')}\n >\n <MoreHorizontal className=\"size-4\" aria-hidden=\"true\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem\n disabled={acknowledgePending || insight.status === 'ACKNOWLEDGED' || isClosed}\n onSelect={onAcknowledge}\n >\n <CheckCircle2 className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.acknowledge', 'Acknowledge')}\n </DropdownMenuItem>\n <DropdownMenuItem\n disabled={resolvePending || insight.status === 'RESOLVED'}\n onSelect={onResolve}\n >\n <CheckCircle2 className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.resolve', 'Resolve')}\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n className=\"text-status-error-text focus:text-status-error-text\"\n disabled={dismissPending || insight.status === 'DISMISSED'}\n onSelect={onDismiss}\n >\n <XCircle className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.dismiss', 'Dismiss')}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {insight.detail ? (\n <p className=\"text-sm text-text-secondary\">{insight.detail}</p>\n ) : null}\n <dl className=\"grid grid-cols-2 gap-3 rounded-lg bg-bg-sunken p-3 text-sm sm:grid-cols-3\">\n <div>\n <dt className=\"text-xs text-text-secondary\">\n {translate('brainyrich.insights.card.subjectType', 'Subject')}\n </dt>\n <dd className=\"font-medium text-text-primary\">{humanize(insight.subjectType)}</dd>\n </div>\n <div className=\"min-w-0\">\n <dt className=\"text-xs text-text-secondary\">\n {translate('brainyrich.insights.card.subjectId', 'Subject ID')}\n </dt>\n <dd className=\"truncate font-medium text-text-primary\" title={insight.subjectId}>\n {insight.subjectId}\n </dd>\n </div>\n <div>\n <dt className=\"text-xs text-text-secondary\">\n {translate('brainyrich.insights.card.created', 'Created')}\n </dt>\n <dd className=\"font-medium text-text-primary\">{formatDate(insight.createdAt)}</dd>\n </div>\n </dl>\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={acknowledgePending || insight.status === 'ACKNOWLEDGED' || isClosed}\n onClick={onAcknowledge}\n >\n <CheckCircle2 className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.acknowledge', 'Acknowledge')}\n </Button>\n <Button\n size=\"sm\"\n disabled={resolvePending || insight.status === 'RESOLVED'}\n onClick={onResolve}\n >\n <CheckCircle2 className=\"size-4\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.actions.resolve', 'Resolve')}\n </Button>\n </div>\n </CardContent>\n </Card>\n );\n}\n\ninterface InsightFormDialogProps {\n open: boolean;\n form: InsightFormState;\n setField: <K extends keyof InsightFormState>(key: K, value: InsightFormState[K]) => void;\n metricsValid: boolean;\n valid: boolean;\n pending: boolean;\n onSubmit: () => void;\n onOpenChange: (open: boolean) => void;\n translate: Translate;\n}\n\nfunction InsightFormDialog({\n open,\n form,\n setField,\n metricsValid,\n valid,\n pending,\n onSubmit,\n onOpenChange,\n translate,\n}: InsightFormDialogProps) {\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"max-h-[90vh] overflow-y-auto sm:max-w-lg\">\n <DialogHeader>\n <DialogTitle>\n {translate('brainyrich.insights.form.createTitle', 'New insight')}\n </DialogTitle>\n <DialogDescription>\n {translate(\n 'brainyrich.insights.form.subtitle',\n 'Flag an advisory insight against a portfolio, account, goal or household.'\n )}\n </DialogDescription>\n </DialogHeader>\n\n <form\n className=\"space-y-4\"\n onSubmit={(e) => {\n e.preventDefault();\n onSubmit();\n }}\n >\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-title\">\n {translate('brainyrich.insights.form.title', 'Title')}\n </Label>\n <Input\n id=\"insight-title\"\n value={form.title}\n onChange={(e) => setField('title', e.target.value)}\n placeholder={translate(\n 'brainyrich.insights.form.titlePlaceholder',\n 'e.g. Technology concentration above threshold'\n )}\n required\n />\n </div>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-type\">\n {translate('brainyrich.insights.form.type', 'Type')}\n </Label>\n <Select\n value={form.type}\n onValueChange={(v) => setField('type', v as BraInsightType)}\n >\n <SelectTrigger id=\"insight-type\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {INSIGHT_TYPES.map((tpe) => (\n <SelectItem key={tpe} value={tpe}>\n {humanize(tpe)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-severity\">\n {translate('brainyrich.insights.form.severity', 'Severity')}\n </Label>\n <Select\n value={form.severity}\n onValueChange={(v) => setField('severity', v as BraInsightSeverity)}\n >\n <SelectTrigger id=\"insight-severity\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {INSIGHT_SEVERITIES.map((s) => (\n <SelectItem key={s} value={s}>\n {humanize(s)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-subject-type\">\n {translate('brainyrich.insights.form.subjectType', 'Subject type')}\n </Label>\n <Input\n id=\"insight-subject-type\"\n value={form.subjectType}\n onChange={(e) => setField('subjectType', e.target.value)}\n placeholder={translate(\n 'brainyrich.insights.form.subjectTypePlaceholder',\n 'e.g. PORTFOLIO'\n )}\n required\n />\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-subject-id\">\n {translate('brainyrich.insights.form.subjectId', 'Subject ID')}\n </Label>\n <Input\n id=\"insight-subject-id\"\n value={form.subjectId}\n onChange={(e) => setField('subjectId', e.target.value)}\n placeholder={translate(\n 'brainyrich.insights.form.subjectIdPlaceholder',\n 'Referenced entity ID'\n )}\n required\n />\n </div>\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-owner\">\n {translate('brainyrich.insights.form.ownerId', 'Owner ID (optional)')}\n </Label>\n <Input\n id=\"insight-owner\"\n value={form.ownerId}\n onChange={(e) => setField('ownerId', e.target.value)}\n placeholder={translate(\n 'brainyrich.insights.form.ownerIdPlaceholder',\n 'Defaults to the current owner'\n )}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-detail\">\n {translate('brainyrich.insights.form.detail', 'Detail')}\n </Label>\n <Textarea\n id=\"insight-detail\"\n value={form.detail}\n onChange={(e) => setField('detail', e.target.value)}\n rows={3}\n placeholder={translate(\n 'brainyrich.insights.form.detailPlaceholder',\n 'Explain the finding and recommended action.'\n )}\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"insight-metrics\">\n {translate('brainyrich.insights.form.metrics', 'Metrics JSON (optional)')}\n </Label>\n <Textarea\n id=\"insight-metrics\"\n value={form.metrics}\n onChange={(e) => setField('metrics', e.target.value)}\n rows={3}\n className=\"font-mono text-xs\"\n placeholder='{ \"driftPct\": 8.2 }'\n aria-invalid={!metricsValid}\n />\n {!metricsValid ? (\n <p className=\"flex items-center gap-1 text-xs text-status-error-text\">\n <AlertTriangle className=\"size-3.5\" aria-hidden=\"true\" />\n {translate('brainyrich.insights.form.metricsInvalid', 'Enter valid JSON or leave blank.')}\n </p>\n ) : null}\n </div>\n\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => onOpenChange(false)}\n disabled={pending}\n >\n {translate('brainyrich.insights.form.cancel', 'Cancel')}\n </Button>\n <Button type=\"submit\" disabled={!valid || pending}>\n {pending\n ? translate('brainyrich.insights.form.saving', 'Saving…')\n : translate('brainyrich.insights.form.create', 'Create insight')}\n </Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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"}
|