import { useState } from 'react'; import { Title, Text, Stack, Group, Button, Table, Badge, Card, ActionIcon, Loader, Center, Select, Modal, TextInput, Alert, SimpleGrid, Tooltip, } from '@mantine/core'; import { DateInput } from '@mantine/dates'; import { IconPlus, IconArrowLeft, IconTrash, IconEdit, IconPlayerPlay, IconCoin, IconTrendingUp, } from '@tabler/icons-react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useParams, useNavigate } from 'react-router-dom'; import { notifications } from '@mantine/notifications'; import api from '../../services/api'; import { InvestmentForm } from './components/InvestmentForm'; import { ProjectionChart } from './components/ProjectionChart'; import { InvestmentTimeline } from './components/InvestmentTimeline'; const fmt = (v: number) => v.toLocaleString('en-US', { style: 'currency', currency: 'USD', maximumFractionDigits: 0 }); const fmtDec = (v: number) => v.toLocaleString('en-US', { style: 'currency', currency: 'USD', minimumFractionDigits: 2, maximumFractionDigits: 2 }); const statusColors: Record = { draft: 'gray', active: 'blue', approved: 'green', archived: 'red', }; export function InvestmentScenarioDetailPage() { const { id } = useParams<{ id: string }>(); const navigate = useNavigate(); const queryClient = useQueryClient(); const [addOpen, setAddOpen] = useState(false); const [editInv, setEditInv] = useState(null); const [executeInv, setExecuteInv] = useState(null); const [executionDate, setExecutionDate] = useState(new Date()); const { data: scenario, isLoading } = useQuery({ queryKey: ['board-planning-scenario', id], queryFn: async () => { const { data } = await api.get(`/board-planning/scenarios/${id}`); return data; }, }); const { data: projection, isLoading: projLoading } = useQuery({ queryKey: ['board-planning-projection', id], queryFn: async () => { const { data } = await api.get(`/board-planning/scenarios/${id}/projection`); return data; }, enabled: !!id, }); const addMutation = useMutation({ mutationFn: (dto: any) => api.post(`/board-planning/scenarios/${id}/investments`, dto), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['board-planning-scenario', id] }); queryClient.invalidateQueries({ queryKey: ['board-planning-projection', id] }); setAddOpen(false); notifications.show({ message: 'Investment added', color: 'green' }); }, }); const updateMutation = useMutation({ mutationFn: ({ invId, ...dto }: any) => api.put(`/board-planning/investments/${invId}`, dto), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['board-planning-scenario', id] }); queryClient.invalidateQueries({ queryKey: ['board-planning-projection', id] }); setEditInv(null); notifications.show({ message: 'Investment updated', color: 'green' }); }, }); const removeMutation = useMutation({ mutationFn: (invId: string) => api.delete(`/board-planning/investments/${invId}`), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['board-planning-scenario', id] }); queryClient.invalidateQueries({ queryKey: ['board-planning-projection', id] }); notifications.show({ message: 'Investment removed', color: 'orange' }); }, }); const executeMutation = useMutation({ mutationFn: ({ invId, executionDate }: { invId: string; executionDate: string }) => api.post(`/board-planning/investments/${invId}/execute`, { executionDate }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['board-planning-scenario', id] }); queryClient.invalidateQueries({ queryKey: ['board-planning-projection', id] }); setExecuteInv(null); notifications.show({ message: 'Investment executed and recorded', color: 'green' }); }, onError: (err: any) => { notifications.show({ message: err.response?.data?.message || 'Execution failed', color: 'red' }); }, }); const statusMutation = useMutation({ mutationFn: (status: string) => api.put(`/board-planning/scenarios/${id}`, { status }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['board-planning-scenario', id] }); queryClient.invalidateQueries({ queryKey: ['board-planning-scenarios'] }); }, }); if (isLoading) return
; if (!scenario) return
Scenario not found
; const investments = scenario.investments || []; const summary = projection?.summary; // Build a lookup of per-investment interest from the projection const interestDetailMap: Record = {}; if (summary?.investment_interest_details) { for (const d of summary.investment_interest_details) { interestDetailMap[d.id] = { interest: d.interest, principal: d.principal }; } } return ( {/* Header */} navigate('/board-planning/investments')}>
{scenario.name} {scenario.status} {scenario.description && {scenario.description}}