QoL tweaks: Cash Flow cards, auto-primary accounts, investment projections, Sankey filters
- Dashboard: Remove tenant name/role subtitle - Cash Flow: Replace Operating/Reserve net cards with inflow vs outflow breakdown showing In/Out amounts and signed net; replace Ending Cash card with AI Financial Health status from saved recommendation - Accounts: Auto-set first asset account per fund_type as primary on creation - Investments: Add 5th summary card for projected annual interest earnings - Sankey: Add Actuals/Budget/Forecast data source toggle and All Funds/Operating/Reserve fund filter SegmentedControls with backend support for budget-based and forecast (actuals+budget) queries Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { useState, useEffect, useRef, useCallback } from 'react';
|
||||
import {
|
||||
Title, Group, Stack, Text, Card, Loader, Center, Select, SimpleGrid,
|
||||
Title, Group, Stack, Text, Card, Loader, Center, Select, SimpleGrid, SegmentedControl,
|
||||
} from '@mantine/core';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import {
|
||||
@@ -52,6 +52,8 @@ export function SankeyPage() {
|
||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||
const [dimensions, setDimensions] = useState({ width: 900, height: 500 });
|
||||
const [year, setYear] = useState(new Date().getFullYear().toString());
|
||||
const [source, setSource] = useState('actuals');
|
||||
const [fundFilter, setFundFilter] = useState('all');
|
||||
|
||||
const yearOptions = Array.from({ length: 5 }, (_, i) => {
|
||||
const y = new Date().getFullYear() - 2 + i;
|
||||
@@ -59,9 +61,12 @@ export function SankeyPage() {
|
||||
});
|
||||
|
||||
const { data, isLoading, isError } = useQuery<CashFlowData>({
|
||||
queryKey: ['sankey', year],
|
||||
queryKey: ['sankey', year, source, fundFilter],
|
||||
queryFn: async () => {
|
||||
const { data } = await api.get(`/reports/cash-flow-sankey?year=${year}`);
|
||||
const params = new URLSearchParams({ year });
|
||||
if (source !== 'actuals') params.set('source', source);
|
||||
if (fundFilter !== 'all') params.set('fundType', fundFilter);
|
||||
const { data } = await api.get(`/reports/cash-flow-sankey?${params}`);
|
||||
return data;
|
||||
},
|
||||
});
|
||||
@@ -191,6 +196,31 @@ export function SankeyPage() {
|
||||
<Select data={yearOptions} value={year} onChange={(v) => v && setYear(v)} w={120} />
|
||||
</Group>
|
||||
|
||||
<Group>
|
||||
<Text size="sm" fw={500}>Data source:</Text>
|
||||
<SegmentedControl
|
||||
size="sm"
|
||||
value={source}
|
||||
onChange={setSource}
|
||||
data={[
|
||||
{ label: 'Actuals', value: 'actuals' },
|
||||
{ label: 'Budget', value: 'budget' },
|
||||
{ label: 'Forecast', value: 'forecast' },
|
||||
]}
|
||||
/>
|
||||
<Text size="sm" fw={500} ml="md">Fund:</Text>
|
||||
<SegmentedControl
|
||||
size="sm"
|
||||
value={fundFilter}
|
||||
onChange={setFundFilter}
|
||||
data={[
|
||||
{ label: 'All Funds', value: 'all' },
|
||||
{ label: 'Operating', value: 'operating' },
|
||||
{ label: 'Reserve', value: 'reserve' },
|
||||
]}
|
||||
/>
|
||||
</Group>
|
||||
|
||||
<SimpleGrid cols={{ base: 1, sm: 3 }}>
|
||||
<Card withBorder p="md">
|
||||
<Text size="xs" c="dimmed" tt="uppercase" fw={700}>Total Income</Text>
|
||||
|
||||
Reference in New Issue
Block a user