Compare commits
4 Commits
5f85abdf86
...
38f7416942
| Author | SHA1 | Date | |
|---|---|---|---|
| 38f7416942 | |||
| e82cad4f21 | |||
| 1daa90d091 | |||
| 2d0b0bc470 |
@@ -1,11 +1,11 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
|
||||||
export type DashboardMode = "expense" | "income";
|
export type DashboardMode = "expense" | "income";
|
||||||
export type DashboardPeriod = "rolling" | "calendar";
|
export type DashboardPeriodType = "rolling" | "calendar";
|
||||||
|
|
||||||
export interface DashboardState {
|
export interface DashboardState {
|
||||||
mode: DashboardMode;
|
mode: DashboardMode;
|
||||||
period: DashboardPeriod;
|
periodType: DashboardPeriodType;
|
||||||
comparison: boolean;
|
comparison: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ 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",
|
mode: "expense",
|
||||||
period: "rolling",
|
periodType: "rolling",
|
||||||
comparison: false,
|
comparison: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export default function DashboardView({
|
|||||||
}: ViewProps) {
|
}: ViewProps) {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const themeMode = theme.palette.mode;
|
const themeMode = theme.palette.mode;
|
||||||
const { mode, period, comparison } = state;
|
const { mode, periodType, comparison } = state;
|
||||||
|
|
||||||
// Resolve colors with fallbacks
|
// Resolve colors with fallbacks
|
||||||
const colors = React.useMemo(() => {
|
const colors = React.useMemo(() => {
|
||||||
@@ -139,8 +139,8 @@ export default function DashboardView({
|
|||||||
title={section.title}
|
title={section.title}
|
||||||
accentColor={colors.primary}
|
accentColor={colors.primary}
|
||||||
colorScheme={colors}
|
colorScheme={colors}
|
||||||
period={period}
|
periodType={periodType}
|
||||||
onPeriodChange={(p: any) => setState(prev => ({ ...prev, period: p }))}
|
onPeriodTypeChange={(p: any) => setState(prev => ({ ...prev, periodType: p }))}
|
||||||
comparison={comparison}
|
comparison={comparison}
|
||||||
setComparison={(c: any) => setState(prev => ({ ...prev, comparison: c }))}
|
setComparison={(c: any) => setState(prev => ({ ...prev, comparison: c }))}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ export interface HistoryChartProps {
|
|||||||
summary?: string;
|
summary?: string;
|
||||||
tabs: string[];
|
tabs: string[];
|
||||||
data: ChartData;
|
data: ChartData;
|
||||||
period: "rolling" | "calendar";
|
periodType: "rolling" | "calendar";
|
||||||
onPeriodChange: (p: "rolling" | "calendar") => void;
|
onPeriodTypeChange: (p: "rolling" | "calendar") => void;
|
||||||
comparison: boolean;
|
comparison: boolean;
|
||||||
setComparison: (v: boolean) => void;
|
setComparison: (v: boolean) => void;
|
||||||
colorScheme: {
|
colorScheme: {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { ChartDataPoint, HistoryChartProps, ChartData } from "./HistoryChart.mod
|
|||||||
import HistoryChartView from "./HistoryChart.view";
|
import HistoryChartView from "./HistoryChart.view";
|
||||||
|
|
||||||
export default function HistoryChart(props: HistoryChartProps) {
|
export default function HistoryChart(props: HistoryChartProps) {
|
||||||
const { tabs, data, period, comparison } = props;
|
const { tabs, data, periodType, comparison } = props;
|
||||||
|
|
||||||
const [activeTab, setActiveTab] = React.useState<string>(tabs[0] || "");
|
const [activeTab, setActiveTab] = React.useState<string>(tabs[0] || "");
|
||||||
const [startIndex, setStartIndex] = React.useState(0);
|
const [startIndex, setStartIndex] = React.useState(0);
|
||||||
@@ -16,7 +16,7 @@ export default function HistoryChart(props: HistoryChartProps) {
|
|||||||
rawData = data.daily || [];
|
rawData = data.daily || [];
|
||||||
} else {
|
} else {
|
||||||
const section = data[activeDataKey];
|
const section = data[activeDataKey];
|
||||||
rawData = section?.[period] || [];
|
rawData = section?.[periodType] || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentData = rawData;
|
const currentData = rawData;
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ export default function HistoryChartView(props: ViewProps) {
|
|||||||
header,
|
header,
|
||||||
summary,
|
summary,
|
||||||
tabs,
|
tabs,
|
||||||
period,
|
periodType,
|
||||||
onPeriodChange,
|
onPeriodTypeChange,
|
||||||
comparison,
|
comparison,
|
||||||
setComparison,
|
setComparison,
|
||||||
colorScheme,
|
colorScheme,
|
||||||
@@ -99,7 +99,7 @@ export default function HistoryChartView(props: ViewProps) {
|
|||||||
</ToggleButtonGroup>
|
</ToggleButtonGroup>
|
||||||
|
|
||||||
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "space-between", mb: 3 }}>
|
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "space-between", mb: 3 }}>
|
||||||
<ToggleButtonGroup value={period} exclusive onChange={(_, v) => v && onPeriodChange(v)} size="small">
|
<ToggleButtonGroup value={periodType} exclusive onChange={(_, v) => v && onPeriodTypeChange(v)} size="small">
|
||||||
<ToggleButton value="rolling">Rolling</ToggleButton>
|
<ToggleButton value="rolling">Rolling</ToggleButton>
|
||||||
<ToggleButton value="calendar" disabled={activeDataKey === "daily"}>
|
<ToggleButton value="calendar" disabled={activeDataKey === "daily"}>
|
||||||
Calendar
|
Calendar
|
||||||
|
|||||||
@@ -25,14 +25,57 @@ const toLabel = (start: string, end: string, type: "weekly" | "monthly") => {
|
|||||||
})}`;
|
})}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getWeekOfMonth = (date: Date) => {
|
||||||
|
const firstDay = new Date(date.getFullYear(), date.getMonth(), 1);
|
||||||
|
return Math.ceil((date.getDate() + firstDay.getDay()) / 7);
|
||||||
|
};
|
||||||
|
|
||||||
|
const findCompareBucket = (
|
||||||
|
current: ReportBucket,
|
||||||
|
buckets: ReportBucket[],
|
||||||
|
type: "weekly" | "monthly"
|
||||||
|
): ReportBucket | undefined => {
|
||||||
|
const start = new Date(current.start);
|
||||||
|
|
||||||
|
if (type === "monthly") {
|
||||||
|
const targetYear = start.getFullYear() - 1;
|
||||||
|
const targetMonth = start.getMonth();
|
||||||
|
|
||||||
|
return buckets.find(b => {
|
||||||
|
const d = new Date(b.start);
|
||||||
|
return (
|
||||||
|
d.getFullYear() === targetYear &&
|
||||||
|
d.getMonth() === targetMonth
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === "weekly") {
|
||||||
|
const weekIndex = getWeekOfMonth(start); // you must define this
|
||||||
|
const target = new Date(start);
|
||||||
|
target.setMonth(target.getMonth() - 1);
|
||||||
|
|
||||||
|
return buckets.find(b => {
|
||||||
|
const d = new Date(b.start);
|
||||||
|
return (
|
||||||
|
d.getFullYear() === target.getFullYear() &&
|
||||||
|
d.getMonth() === target.getMonth() &&
|
||||||
|
getWeekOfMonth(d) === weekIndex
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
|
||||||
const toPoints = (
|
const toPoints = (
|
||||||
buckets: ReportBucket[],
|
buckets: ReportBucket[],
|
||||||
type: "weekly" | "monthly",
|
type: "weekly" | "monthly",
|
||||||
flow: "expenses" | "incomes"
|
flow: "expenses" | "incomes"
|
||||||
): ChartDataPoint[] => {
|
): ChartDataPoint[] => {
|
||||||
return buckets.map((b, i) => {
|
return buckets.map((b) => {
|
||||||
const amount = sumBucket(b, flow);
|
const amount = sumBucket(b, flow);
|
||||||
const prev = buckets[i - 1];
|
const prev = findCompareBucket(b, buckets, type);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: toLabel(b.start, b.end, type),
|
id: toLabel(b.start, b.end, type),
|
||||||
|
|||||||
Reference in New Issue
Block a user