removed expense and income vs outflow and inflow
This commit is contained in:
@@ -18,13 +18,8 @@ import {
|
||||
prepareReport,
|
||||
} 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() {
|
||||
const [mode, setMode] = React.useState<"expense" | "income">("expense");
|
||||
const [flow, setFlow] = React.useState<"outflows" | "inflows">("outflows");
|
||||
|
||||
const [appliedPayees, setAppliedPayees] = React.useState<string[]>([]);
|
||||
const [appliedTags, setAppliedTags] = React.useState<string[]>([]);
|
||||
@@ -37,7 +32,7 @@ export default function Dashboard() {
|
||||
|
||||
const report = useReport({
|
||||
periods: ["daily", "weekly", "monthly", "all"],
|
||||
flow: modeToFlow(mode),
|
||||
flow: flow,
|
||||
payee: appliedPayees.length > 0 ? appliedPayees : undefined,
|
||||
tags: appliedTags.length > 0 ? appliedTags : undefined,
|
||||
});
|
||||
@@ -77,9 +72,9 @@ export default function Dashboard() {
|
||||
const isLoading = report.isLoading;
|
||||
const error = report.error;
|
||||
|
||||
/** Callback for the ConfigurableDashboard's mode toggle */
|
||||
const handleModeChange = React.useCallback((newState: DashboardState) => {
|
||||
setMode(newState.mode);
|
||||
/** Callback for the ConfigurableDashboard's flow toggle */
|
||||
const handleFlowChange = React.useCallback((newState: DashboardState) => {
|
||||
setFlow(newState.flow);
|
||||
}, []);
|
||||
|
||||
if (isLoading && !report.data) {
|
||||
@@ -166,7 +161,7 @@ export default function Dashboard() {
|
||||
config={configuration}
|
||||
data={data}
|
||||
isFetching={report.isFetching}
|
||||
onModeChange={handleModeChange}
|
||||
onFlowChange={handleFlowChange}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -4,12 +4,12 @@ import {
|
||||
GroupKey,
|
||||
} from "../../features/report";
|
||||
|
||||
export type DashboardMode = "expense" | "income";
|
||||
export type DashboardFlow = "outflows" | "inflows";
|
||||
export type DashboardPeriodType = "rolling" | "calendar";
|
||||
export type DashboardSelectedPeriodId = string | null;
|
||||
|
||||
export interface DashboardState {
|
||||
mode: DashboardMode;
|
||||
flow: DashboardFlow;
|
||||
periodType: DashboardPeriodType;
|
||||
selectedPeriodId: DashboardSelectedPeriodId;
|
||||
selectedGroupKey: GroupKey | null;
|
||||
@@ -43,7 +43,7 @@ export interface ThemeAwarePalette {
|
||||
export interface DashboardConfig {
|
||||
sections: DashboardSection[];
|
||||
style?: {
|
||||
palette?: Record<DashboardMode, ThemeAwarePalette>;
|
||||
palette?: Record<DashboardFlow, ThemeAwarePalette>;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -51,5 +51,5 @@ export interface DashboardProps {
|
||||
config: DashboardConfig;
|
||||
data: ReportData;
|
||||
isFetching?: boolean;
|
||||
onModeChange?: (state: DashboardState) => void;
|
||||
onFlowChange?: (state: DashboardState) => void;
|
||||
}
|
||||
|
||||
@@ -4,24 +4,24 @@ import { DashboardProps, DashboardState } from "./Dashboard.models";
|
||||
|
||||
export default function Dashboard(props: DashboardProps) {
|
||||
const [state, setState] = React.useState<DashboardState>({
|
||||
mode: "expense",
|
||||
flow: "outflows",
|
||||
periodType: "rolling",
|
||||
selectedPeriodId: null,
|
||||
selectedGroupKey: null,
|
||||
comparison: false,
|
||||
});
|
||||
|
||||
const toggleMode = (
|
||||
const toggleFlow = (
|
||||
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 => {
|
||||
const next = {
|
||||
...prev,
|
||||
mode: newMode,
|
||||
flow: newFlow,
|
||||
};
|
||||
props.onModeChange?.(next);
|
||||
props.onFlowChange?.(next);
|
||||
return next;
|
||||
});
|
||||
}
|
||||
@@ -54,7 +54,7 @@ export default function Dashboard(props: DashboardProps) {
|
||||
{...props}
|
||||
state={state}
|
||||
setState={setState}
|
||||
toggleMode={toggleMode}
|
||||
toggleFlow={toggleFlow}
|
||||
togglePeriodType={togglePeriodType}
|
||||
toggleComparison={toggleComparison}
|
||||
setSelectedPeriodId={setSelectedPeriodId}
|
||||
|
||||
@@ -14,7 +14,7 @@ import { DashboardProps, DashboardState } from "./Dashboard.models";
|
||||
interface ViewProps extends DashboardProps {
|
||||
state: 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;
|
||||
setSelectedPeriodId: (id: string | null) => void;
|
||||
setSelectedGroupKey: (groupKey: GroupKey | null) => void;
|
||||
@@ -26,7 +26,7 @@ export default function DashboardView({
|
||||
data,
|
||||
state,
|
||||
setState,
|
||||
toggleMode,
|
||||
toggleFlow,
|
||||
togglePeriodType,
|
||||
toggleComparison,
|
||||
setSelectedPeriodId,
|
||||
@@ -34,11 +34,11 @@ export default function DashboardView({
|
||||
}: ViewProps) {
|
||||
const theme = useTheme();
|
||||
const themeMode = theme.palette.mode;
|
||||
const { mode, periodType, comparison, selectedPeriodId, selectedGroupKey } = state;
|
||||
const { flow, periodType, comparison, selectedPeriodId, selectedGroupKey } = state;
|
||||
|
||||
// Resolve colors with fallbacks
|
||||
const colors = React.useMemo(() => {
|
||||
const palette = config.style?.palette?.[mode];
|
||||
const palette = config.style?.palette?.[flow];
|
||||
const modeColors = palette ? palette[themeMode] : null;
|
||||
|
||||
if (modeColors) {
|
||||
@@ -50,13 +50,13 @@ export default function DashboardView({
|
||||
}
|
||||
|
||||
// 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 {
|
||||
primary: themeColor.main,
|
||||
light: alpha(themeColor.main, themeMode === 'light' ? 0.08 : 0.15),
|
||||
text: themeColor.main
|
||||
};
|
||||
}, [config.style?.palette, mode, themeMode, theme.palette]);
|
||||
}, [config.style?.palette, flow, themeMode, theme.palette]);
|
||||
|
||||
return (
|
||||
<Container
|
||||
@@ -71,9 +71,9 @@ export default function DashboardView({
|
||||
>
|
||||
<Box sx={{ display: "flex", justifyContent: "center", mb: 3 }}>
|
||||
<ToggleButtonGroup
|
||||
value={mode}
|
||||
value={flow}
|
||||
exclusive
|
||||
onChange={toggleMode}
|
||||
onChange={toggleFlow}
|
||||
sx={{
|
||||
borderRadius: 3,
|
||||
overflow: "hidden",
|
||||
@@ -89,8 +89,8 @@ export default function DashboardView({
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ToggleButton value="expense">Expenses</ToggleButton>
|
||||
<ToggleButton value="income">Income</ToggleButton>
|
||||
<ToggleButton value="outflows">Outflows</ToggleButton>
|
||||
<ToggleButton value="inflows">Inflows</ToggleButton>
|
||||
</ToggleButtonGroup>
|
||||
</Box>
|
||||
|
||||
@@ -118,7 +118,7 @@ export default function DashboardView({
|
||||
colorScheme={colors}
|
||||
|
||||
// State management
|
||||
mode={mode}
|
||||
flow={flow}
|
||||
|
||||
periodType={periodType}
|
||||
comparison={comparison}
|
||||
|
||||
@@ -54,7 +54,7 @@ function attachComparison(
|
||||
export function buildChartData(
|
||||
reportData: ReportData,
|
||||
key: PeriodKey,
|
||||
mode: "expense" | "income",
|
||||
flow: "outflows" | "inflows",
|
||||
comparison: boolean
|
||||
): ChartDataPoint[] {
|
||||
const merged = mergeBucketPeriods(reportData.buckets, key);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {
|
||||
DashboardMode,
|
||||
DashboardFlow,
|
||||
DashboardPeriodType,
|
||||
DashboardSelectedPeriodId
|
||||
} from "../Dashboard";
|
||||
@@ -29,7 +29,7 @@ export interface HistoryChartProps {
|
||||
text: string;
|
||||
};
|
||||
|
||||
mode: DashboardMode;
|
||||
flow: DashboardFlow;
|
||||
periodType: DashboardPeriodType;
|
||||
selectedPeriodId: DashboardSelectedPeriodId;
|
||||
comparison: boolean;
|
||||
|
||||
@@ -7,7 +7,7 @@ export default function HistoryChart(props: HistoryChartProps) {
|
||||
const {
|
||||
tabs,
|
||||
reportData,
|
||||
mode,
|
||||
flow,
|
||||
comparison,
|
||||
selectedPeriodId,
|
||||
setSelectedPeriodId
|
||||
@@ -19,8 +19,8 @@ export default function HistoryChart(props: HistoryChartProps) {
|
||||
const activeDataKey = tabToKey(activeTab);
|
||||
|
||||
const currentData = React.useMemo(() => {
|
||||
return buildChartData(reportData, activeDataKey, mode, comparison);
|
||||
}, [reportData, activeDataKey, mode, comparison]);
|
||||
return buildChartData(reportData, activeDataKey, flow, comparison);
|
||||
}, [reportData, activeDataKey, flow, comparison]);
|
||||
|
||||
const maxAmount =
|
||||
currentData.length > 0
|
||||
|
||||
@@ -35,7 +35,7 @@ export default function HistoryChartView(props: ViewProps) {
|
||||
tabs,
|
||||
colorScheme,
|
||||
|
||||
mode,
|
||||
flow,
|
||||
periodType,
|
||||
selectedPeriodId,
|
||||
comparison,
|
||||
|
||||
@@ -47,7 +47,7 @@ export function buildLatestItems(
|
||||
reportData: ReportData,
|
||||
selectedPeriodId: string | null,
|
||||
selectedGroupKey: GroupKey | null,
|
||||
mode: "expense" | "income"
|
||||
flow: "outflows" | "inflows"
|
||||
): LatestItem[] {
|
||||
const txns = extractTransactions(reportData, selectedPeriodId, selectedGroupKey);
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import LatestItemsView from "./LatestItems.view";
|
||||
|
||||
type Props = {
|
||||
reportData: ReportData;
|
||||
mode: "expense" | "income";
|
||||
flow: "outflows" | "inflows";
|
||||
selectedPeriodId: string | null;
|
||||
selectedGroupKey?: GroupKey | null;
|
||||
accentColor: string;
|
||||
@@ -14,7 +14,7 @@ type Props = {
|
||||
|
||||
export default function LatestItems({
|
||||
reportData,
|
||||
mode,
|
||||
flow,
|
||||
selectedPeriodId,
|
||||
selectedGroupKey = null,
|
||||
accentColor,
|
||||
@@ -23,8 +23,8 @@ export default function LatestItems({
|
||||
const [visibleCount, setVisibleCount] = React.useState(5);
|
||||
|
||||
const allItems = React.useMemo(() => {
|
||||
return buildLatestItems(reportData, selectedPeriodId, selectedGroupKey, mode);
|
||||
}, [reportData, selectedPeriodId, selectedGroupKey, mode]);
|
||||
return buildLatestItems(reportData, selectedPeriodId, selectedGroupKey, flow);
|
||||
}, [reportData, selectedPeriodId, selectedGroupKey, flow]);
|
||||
|
||||
const visibleItems = React.useMemo(() => {
|
||||
return allItems.slice(0, visibleCount);
|
||||
|
||||
@@ -11,7 +11,7 @@ export interface TagItem {
|
||||
|
||||
export function extractTopTags(
|
||||
reportData: ReportData,
|
||||
mode: "expense" | "income",
|
||||
flow: "outflows" | "inflows",
|
||||
selectedPeriodId?: string | null
|
||||
): { items: TagItem[]; total: number } {
|
||||
const tagMap = new Map<string, number>();
|
||||
|
||||
@@ -6,7 +6,7 @@ import { extractTopTags } from "./TopTags.adapter";
|
||||
|
||||
type Props = {
|
||||
reportData: ReportData;
|
||||
mode: "expense" | "income";
|
||||
flow: "outflows" | "inflows";
|
||||
selectedPeriodId?: string | null;
|
||||
selectedGroupKey?: GroupKey | null;
|
||||
setSelectedGroupKey?: (key: GroupKey | null) => void;
|
||||
@@ -16,7 +16,7 @@ type Props = {
|
||||
|
||||
export default function TopTags({
|
||||
reportData,
|
||||
mode,
|
||||
flow,
|
||||
selectedPeriodId,
|
||||
selectedGroupKey,
|
||||
setSelectedGroupKey,
|
||||
@@ -24,8 +24,8 @@ export default function TopTags({
|
||||
isFetching,
|
||||
}: Props) {
|
||||
const { items, total } = React.useMemo(() => {
|
||||
return extractTopTags(reportData, mode, selectedPeriodId);
|
||||
}, [reportData, mode, selectedPeriodId]);
|
||||
return extractTopTags(reportData, flow, selectedPeriodId);
|
||||
}, [reportData, flow, selectedPeriodId]);
|
||||
|
||||
return (
|
||||
<Box
|
||||
@@ -48,7 +48,7 @@ export default function TopTags({
|
||||
progressAmount={item.amount}
|
||||
totalAmount={total}
|
||||
compact={compact}
|
||||
colorTheme={mode === "expense" ? "error" : "success"}
|
||||
colorTheme={flow === "outflows" ? "error" : "success"}
|
||||
selected={isSelected}
|
||||
isFetching={isFetching}
|
||||
onClick={() => {
|
||||
|
||||
@@ -39,7 +39,7 @@ export const configuration: DashboardConfig = {
|
||||
],
|
||||
style: {
|
||||
palette: {
|
||||
expense: {
|
||||
outflows: {
|
||||
light: {
|
||||
primary: "#d32f2f",
|
||||
background: "#fdecea",
|
||||
@@ -51,7 +51,7 @@ export const configuration: DashboardConfig = {
|
||||
text: "#ffcdd2"
|
||||
}
|
||||
},
|
||||
income: {
|
||||
inflows: {
|
||||
light: {
|
||||
primary: "#2e7d32",
|
||||
background: "#e8f5e9",
|
||||
|
||||
Reference in New Issue
Block a user