removed expense and income vs outflow and inflow

This commit is contained in:
2026-05-18 07:58:35 +05:30
parent 58271584ce
commit fff304ad1e
13 changed files with 48 additions and 53 deletions

View File

@@ -18,13 +18,8 @@ import {
prepareReport, prepareReport,
} from "./features/report"; } from "./features/report";
/** Map the internal UI mode to the API flow param */
function modeToFlow(mode: "expense" | "income"): "outflows" | "inflows" {
return mode === "expense" ? "outflows" : "inflows";
}
export default function Dashboard() { export default function Dashboard() {
const [mode, setMode] = React.useState<"expense" | "income">("expense"); const [flow, setFlow] = React.useState<"outflows" | "inflows">("outflows");
const [appliedPayees, setAppliedPayees] = React.useState<string[]>([]); const [appliedPayees, setAppliedPayees] = React.useState<string[]>([]);
const [appliedTags, setAppliedTags] = React.useState<string[]>([]); const [appliedTags, setAppliedTags] = React.useState<string[]>([]);
@@ -37,7 +32,7 @@ export default function Dashboard() {
const report = useReport({ const report = useReport({
periods: ["daily", "weekly", "monthly", "all"], periods: ["daily", "weekly", "monthly", "all"],
flow: modeToFlow(mode), flow: flow,
payee: appliedPayees.length > 0 ? appliedPayees : undefined, payee: appliedPayees.length > 0 ? appliedPayees : undefined,
tags: appliedTags.length > 0 ? appliedTags : undefined, tags: appliedTags.length > 0 ? appliedTags : undefined,
}); });
@@ -77,9 +72,9 @@ export default function Dashboard() {
const isLoading = report.isLoading; const isLoading = report.isLoading;
const error = report.error; const error = report.error;
/** Callback for the ConfigurableDashboard's mode toggle */ /** Callback for the ConfigurableDashboard's flow toggle */
const handleModeChange = React.useCallback((newState: DashboardState) => { const handleFlowChange = React.useCallback((newState: DashboardState) => {
setMode(newState.mode); setFlow(newState.flow);
}, []); }, []);
if (isLoading && !report.data) { if (isLoading && !report.data) {
@@ -166,7 +161,7 @@ export default function Dashboard() {
config={configuration} config={configuration}
data={data} data={data}
isFetching={report.isFetching} isFetching={report.isFetching}
onModeChange={handleModeChange} onFlowChange={handleFlowChange}
/> />
</Box> </Box>
); );

View File

@@ -4,12 +4,12 @@ import {
GroupKey, GroupKey,
} from "../../features/report"; } from "../../features/report";
export type DashboardMode = "expense" | "income"; export type DashboardFlow = "outflows" | "inflows";
export type DashboardPeriodType = "rolling" | "calendar"; export type DashboardPeriodType = "rolling" | "calendar";
export type DashboardSelectedPeriodId = string | null; export type DashboardSelectedPeriodId = string | null;
export interface DashboardState { export interface DashboardState {
mode: DashboardMode; flow: DashboardFlow;
periodType: DashboardPeriodType; periodType: DashboardPeriodType;
selectedPeriodId: DashboardSelectedPeriodId; selectedPeriodId: DashboardSelectedPeriodId;
selectedGroupKey: GroupKey | null; selectedGroupKey: GroupKey | null;
@@ -43,7 +43,7 @@ export interface ThemeAwarePalette {
export interface DashboardConfig { export interface DashboardConfig {
sections: DashboardSection[]; sections: DashboardSection[];
style?: { style?: {
palette?: Record<DashboardMode, ThemeAwarePalette>; palette?: Record<DashboardFlow, ThemeAwarePalette>;
}; };
} }
@@ -51,5 +51,5 @@ export interface DashboardProps {
config: DashboardConfig; config: DashboardConfig;
data: ReportData; data: ReportData;
isFetching?: boolean; isFetching?: boolean;
onModeChange?: (state: DashboardState) => void; onFlowChange?: (state: DashboardState) => void;
} }

View File

@@ -4,24 +4,24 @@ import { DashboardProps, DashboardState } from "./Dashboard.models";
export default function Dashboard(props: DashboardProps) { export default function Dashboard(props: DashboardProps) {
const [state, setState] = React.useState<DashboardState>({ const [state, setState] = React.useState<DashboardState>({
mode: "expense", flow: "outflows",
periodType: "rolling", periodType: "rolling",
selectedPeriodId: null, selectedPeriodId: null,
selectedGroupKey: null, selectedGroupKey: null,
comparison: false, comparison: false,
}); });
const toggleMode = ( const toggleFlow = (
event: React.MouseEvent<HTMLElement>, event: React.MouseEvent<HTMLElement>,
newMode: "expense" | "income" | null newFlow: "outflows" | "inflows" | null
) => { ) => {
if (newMode !== null && newMode !== state.mode) { if (newFlow !== null && newFlow !== state.flow) {
setState(prev => { setState(prev => {
const next = { const next = {
...prev, ...prev,
mode: newMode, flow: newFlow,
}; };
props.onModeChange?.(next); props.onFlowChange?.(next);
return next; return next;
}); });
} }
@@ -54,7 +54,7 @@ export default function Dashboard(props: DashboardProps) {
{...props} {...props}
state={state} state={state}
setState={setState} setState={setState}
toggleMode={toggleMode} toggleFlow={toggleFlow}
togglePeriodType={togglePeriodType} togglePeriodType={togglePeriodType}
toggleComparison={toggleComparison} toggleComparison={toggleComparison}
setSelectedPeriodId={setSelectedPeriodId} setSelectedPeriodId={setSelectedPeriodId}

View File

@@ -14,7 +14,7 @@ import { DashboardProps, DashboardState } from "./Dashboard.models";
interface ViewProps extends DashboardProps { interface ViewProps extends DashboardProps {
state: DashboardState; state: DashboardState;
setState: React.Dispatch<React.SetStateAction<DashboardState>>; setState: React.Dispatch<React.SetStateAction<DashboardState>>;
toggleMode: (event: React.MouseEvent<HTMLElement>, newMode: "expense" | "income" | null) => void; toggleFlow: (event: React.MouseEvent<HTMLElement>, newFlow: "outflows" | "inflows" | null) => void;
togglePeriodType: () => void; togglePeriodType: () => void;
setSelectedPeriodId: (id: string | null) => void; setSelectedPeriodId: (id: string | null) => void;
setSelectedGroupKey: (groupKey: GroupKey | null) => void; setSelectedGroupKey: (groupKey: GroupKey | null) => void;
@@ -26,7 +26,7 @@ export default function DashboardView({
data, data,
state, state,
setState, setState,
toggleMode, toggleFlow,
togglePeriodType, togglePeriodType,
toggleComparison, toggleComparison,
setSelectedPeriodId, setSelectedPeriodId,
@@ -34,11 +34,11 @@ export default function DashboardView({
}: ViewProps) { }: ViewProps) {
const theme = useTheme(); const theme = useTheme();
const themeMode = theme.palette.mode; const themeMode = theme.palette.mode;
const { mode, periodType, comparison, selectedPeriodId, selectedGroupKey } = state; const { flow, periodType, comparison, selectedPeriodId, selectedGroupKey } = state;
// Resolve colors with fallbacks // Resolve colors with fallbacks
const colors = React.useMemo(() => { const colors = React.useMemo(() => {
const palette = config.style?.palette?.[mode]; const palette = config.style?.palette?.[flow];
const modeColors = palette ? palette[themeMode] : null; const modeColors = palette ? palette[themeMode] : null;
if (modeColors) { if (modeColors) {
@@ -50,13 +50,13 @@ export default function DashboardView({
} }
// Fallback to standard theme colors // Fallback to standard theme colors
const themeColor = mode === 'expense' ? theme.palette.error : theme.palette.success; const themeColor = flow === 'outflows' ? theme.palette.error : theme.palette.success;
return { return {
primary: themeColor.main, primary: themeColor.main,
light: alpha(themeColor.main, themeMode === 'light' ? 0.08 : 0.15), light: alpha(themeColor.main, themeMode === 'light' ? 0.08 : 0.15),
text: themeColor.main text: themeColor.main
}; };
}, [config.style?.palette, mode, themeMode, theme.palette]); }, [config.style?.palette, flow, themeMode, theme.palette]);
return ( return (
<Container <Container
@@ -71,9 +71,9 @@ export default function DashboardView({
> >
<Box sx={{ display: "flex", justifyContent: "center", mb: 3 }}> <Box sx={{ display: "flex", justifyContent: "center", mb: 3 }}>
<ToggleButtonGroup <ToggleButtonGroup
value={mode} value={flow}
exclusive exclusive
onChange={toggleMode} onChange={toggleFlow}
sx={{ sx={{
borderRadius: 3, borderRadius: 3,
overflow: "hidden", overflow: "hidden",
@@ -89,8 +89,8 @@ export default function DashboardView({
}, },
}} }}
> >
<ToggleButton value="expense">Expenses</ToggleButton> <ToggleButton value="outflows">Outflows</ToggleButton>
<ToggleButton value="income">Income</ToggleButton> <ToggleButton value="inflows">Inflows</ToggleButton>
</ToggleButtonGroup> </ToggleButtonGroup>
</Box> </Box>
@@ -118,7 +118,7 @@ export default function DashboardView({
colorScheme={colors} colorScheme={colors}
// State management // State management
mode={mode} flow={flow}
periodType={periodType} periodType={periodType}
comparison={comparison} comparison={comparison}

View File

@@ -54,7 +54,7 @@ function attachComparison(
export function buildChartData( export function buildChartData(
reportData: ReportData, reportData: ReportData,
key: PeriodKey, key: PeriodKey,
mode: "expense" | "income", flow: "outflows" | "inflows",
comparison: boolean comparison: boolean
): ChartDataPoint[] { ): ChartDataPoint[] {
const merged = mergeBucketPeriods(reportData.buckets, key); const merged = mergeBucketPeriods(reportData.buckets, key);

View File

@@ -1,5 +1,5 @@
import { import {
DashboardMode, DashboardFlow,
DashboardPeriodType, DashboardPeriodType,
DashboardSelectedPeriodId DashboardSelectedPeriodId
} from "../Dashboard"; } from "../Dashboard";
@@ -29,7 +29,7 @@ export interface HistoryChartProps {
text: string; text: string;
}; };
mode: DashboardMode; flow: DashboardFlow;
periodType: DashboardPeriodType; periodType: DashboardPeriodType;
selectedPeriodId: DashboardSelectedPeriodId; selectedPeriodId: DashboardSelectedPeriodId;
comparison: boolean; comparison: boolean;

View File

@@ -7,7 +7,7 @@ export default function HistoryChart(props: HistoryChartProps) {
const { const {
tabs, tabs,
reportData, reportData,
mode, flow,
comparison, comparison,
selectedPeriodId, selectedPeriodId,
setSelectedPeriodId setSelectedPeriodId
@@ -19,8 +19,8 @@ export default function HistoryChart(props: HistoryChartProps) {
const activeDataKey = tabToKey(activeTab); const activeDataKey = tabToKey(activeTab);
const currentData = React.useMemo(() => { const currentData = React.useMemo(() => {
return buildChartData(reportData, activeDataKey, mode, comparison); return buildChartData(reportData, activeDataKey, flow, comparison);
}, [reportData, activeDataKey, mode, comparison]); }, [reportData, activeDataKey, flow, comparison]);
const maxAmount = const maxAmount =
currentData.length > 0 currentData.length > 0

View File

@@ -35,7 +35,7 @@ export default function HistoryChartView(props: ViewProps) {
tabs, tabs,
colorScheme, colorScheme,
mode, flow,
periodType, periodType,
selectedPeriodId, selectedPeriodId,
comparison, comparison,

View File

@@ -47,7 +47,7 @@ export function buildLatestItems(
reportData: ReportData, reportData: ReportData,
selectedPeriodId: string | null, selectedPeriodId: string | null,
selectedGroupKey: GroupKey | null, selectedGroupKey: GroupKey | null,
mode: "expense" | "income" flow: "outflows" | "inflows"
): LatestItem[] { ): LatestItem[] {
const txns = extractTransactions(reportData, selectedPeriodId, selectedGroupKey); const txns = extractTransactions(reportData, selectedPeriodId, selectedGroupKey);

View File

@@ -5,7 +5,7 @@ import LatestItemsView from "./LatestItems.view";
type Props = { type Props = {
reportData: ReportData; reportData: ReportData;
mode: "expense" | "income"; flow: "outflows" | "inflows";
selectedPeriodId: string | null; selectedPeriodId: string | null;
selectedGroupKey?: GroupKey | null; selectedGroupKey?: GroupKey | null;
accentColor: string; accentColor: string;
@@ -14,7 +14,7 @@ type Props = {
export default function LatestItems({ export default function LatestItems({
reportData, reportData,
mode, flow,
selectedPeriodId, selectedPeriodId,
selectedGroupKey = null, selectedGroupKey = null,
accentColor, accentColor,
@@ -23,8 +23,8 @@ export default function LatestItems({
const [visibleCount, setVisibleCount] = React.useState(5); const [visibleCount, setVisibleCount] = React.useState(5);
const allItems = React.useMemo(() => { const allItems = React.useMemo(() => {
return buildLatestItems(reportData, selectedPeriodId, selectedGroupKey, mode); return buildLatestItems(reportData, selectedPeriodId, selectedGroupKey, flow);
}, [reportData, selectedPeriodId, selectedGroupKey, mode]); }, [reportData, selectedPeriodId, selectedGroupKey, flow]);
const visibleItems = React.useMemo(() => { const visibleItems = React.useMemo(() => {
return allItems.slice(0, visibleCount); return allItems.slice(0, visibleCount);

View File

@@ -11,7 +11,7 @@ export interface TagItem {
export function extractTopTags( export function extractTopTags(
reportData: ReportData, reportData: ReportData,
mode: "expense" | "income", flow: "outflows" | "inflows",
selectedPeriodId?: string | null selectedPeriodId?: string | null
): { items: TagItem[]; total: number } { ): { items: TagItem[]; total: number } {
const tagMap = new Map<string, number>(); const tagMap = new Map<string, number>();

View File

@@ -6,7 +6,7 @@ import { extractTopTags } from "./TopTags.adapter";
type Props = { type Props = {
reportData: ReportData; reportData: ReportData;
mode: "expense" | "income"; flow: "outflows" | "inflows";
selectedPeriodId?: string | null; selectedPeriodId?: string | null;
selectedGroupKey?: GroupKey | null; selectedGroupKey?: GroupKey | null;
setSelectedGroupKey?: (key: GroupKey | null) => void; setSelectedGroupKey?: (key: GroupKey | null) => void;
@@ -16,7 +16,7 @@ type Props = {
export default function TopTags({ export default function TopTags({
reportData, reportData,
mode, flow,
selectedPeriodId, selectedPeriodId,
selectedGroupKey, selectedGroupKey,
setSelectedGroupKey, setSelectedGroupKey,
@@ -24,8 +24,8 @@ export default function TopTags({
isFetching, isFetching,
}: Props) { }: Props) {
const { items, total } = React.useMemo(() => { const { items, total } = React.useMemo(() => {
return extractTopTags(reportData, mode, selectedPeriodId); return extractTopTags(reportData, flow, selectedPeriodId);
}, [reportData, mode, selectedPeriodId]); }, [reportData, flow, selectedPeriodId]);
return ( return (
<Box <Box
@@ -48,7 +48,7 @@ export default function TopTags({
progressAmount={item.amount} progressAmount={item.amount}
totalAmount={total} totalAmount={total}
compact={compact} compact={compact}
colorTheme={mode === "expense" ? "error" : "success"} colorTheme={flow === "outflows" ? "error" : "success"}
selected={isSelected} selected={isSelected}
isFetching={isFetching} isFetching={isFetching}
onClick={() => { onClick={() => {

View File

@@ -39,7 +39,7 @@ export const configuration: DashboardConfig = {
], ],
style: { style: {
palette: { palette: {
expense: { outflows: {
light: { light: {
primary: "#d32f2f", primary: "#d32f2f",
background: "#fdecea", background: "#fdecea",
@@ -51,7 +51,7 @@ export const configuration: DashboardConfig = {
text: "#ffcdd2" text: "#ffcdd2"
} }
}, },
income: { inflows: {
light: { light: {
primary: "#2e7d32", primary: "#2e7d32",
background: "#e8f5e9", background: "#e8f5e9",