top category working
This commit is contained in:
@@ -11,15 +11,20 @@ export default function Dashboard(props: DashboardProps) {
|
||||
comparison: false,
|
||||
});
|
||||
|
||||
const toggleMode = () => {
|
||||
const toggleMode = (
|
||||
event: React.MouseEvent<HTMLElement>,
|
||||
newMode: "expense" | "income" | null
|
||||
) => {
|
||||
if (newMode !== null && newMode !== state.mode) {
|
||||
setState(prev => {
|
||||
const next = {
|
||||
...prev,
|
||||
mode: prev.mode === "expense" ? "income" as const : "expense" as const,
|
||||
mode: newMode,
|
||||
};
|
||||
props.onModeChange?.(next);
|
||||
return next;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const togglePeriodType = () => {
|
||||
|
||||
@@ -14,7 +14,7 @@ import { DashboardProps, DashboardState } from "./Dashboard.models";
|
||||
interface ViewProps extends DashboardProps {
|
||||
state: DashboardState;
|
||||
setState: React.Dispatch<React.SetStateAction<DashboardState>>;
|
||||
toggleMode: () => void;
|
||||
toggleMode: (event: React.MouseEvent<HTMLElement>, newMode: "expense" | "income" | null) => void;
|
||||
togglePeriodType: () => void;
|
||||
setSelectedPeriodId: (id: string | null) => void;
|
||||
setSelectedGroupKey: (groupKey: GroupKey | null) => void;
|
||||
|
||||
@@ -1,32 +1,9 @@
|
||||
import { ReportData } from "../../features/report";
|
||||
import {
|
||||
getAmount,
|
||||
DecoratedPeriod,
|
||||
mergeBucketPeriods,
|
||||
periodIdToKey,
|
||||
} from "../report.helpers";
|
||||
|
||||
// ─── Helpers ─────────────────────────────────────────────────
|
||||
|
||||
function findPeriod(
|
||||
periods: DecoratedPeriod[],
|
||||
selectedPeriodId?: string | null
|
||||
) {
|
||||
if (!periods.length) return null;
|
||||
|
||||
if (selectedPeriodId) {
|
||||
const match = periods.find((p) => p.id === selectedPeriodId);
|
||||
if (match) return match;
|
||||
}
|
||||
|
||||
// fallback → latest
|
||||
return periods.reduce((latest, p) =>
|
||||
new Date(p.start).getTime() > new Date(latest.start).getTime()
|
||||
? p
|
||||
: latest
|
||||
);
|
||||
}
|
||||
|
||||
// ─── Main adapter ────────────────────────────────────────────
|
||||
|
||||
export interface TagItem {
|
||||
tag: string;
|
||||
amount: number;
|
||||
@@ -39,24 +16,34 @@ export function extractTopTags(
|
||||
): { items: TagItem[]; total: number } {
|
||||
const tagMap = new Map<string, number>();
|
||||
|
||||
for (const bucket of reportData.buckets) {
|
||||
const tags = bucket.group_key.tags;
|
||||
if (!tags || tags.length === 0) continue;
|
||||
let periodKey: ReturnType<typeof periodIdToKey> = "all";
|
||||
if (selectedPeriodId) {
|
||||
periodKey = periodIdToKey(selectedPeriodId);
|
||||
}
|
||||
|
||||
// Prefer ALL if available
|
||||
const allPeriods = (bucket.periods.all || []) as DecoratedPeriod[];
|
||||
const periods = mergeBucketPeriods(reportData.buckets, periodKey);
|
||||
|
||||
const periodsToUse = selectedPeriodId
|
||||
? (Object.values(bucket.periods).flat() as DecoratedPeriod[])
|
||||
: allPeriods;
|
||||
let period = periods[0];
|
||||
if (selectedPeriodId) {
|
||||
period = periods.find(p => p.id === selectedPeriodId) || period;
|
||||
} else if (periods.length > 0) {
|
||||
period = periods.reduce((latest, p) =>
|
||||
new Date(p.start).getTime() > new Date(latest.start).getTime()
|
||||
? p
|
||||
: latest
|
||||
);
|
||||
}
|
||||
|
||||
const period = findPeriod(periodsToUse, selectedPeriodId);
|
||||
if (!period) continue;
|
||||
|
||||
const amount = getAmount(period);
|
||||
|
||||
for (const tag of tags) {
|
||||
tagMap.set(tag, (tagMap.get(tag) || 0) + amount);
|
||||
if (period && period.metric && period.metric.transactions) {
|
||||
for (const txn of period.metric.transactions) {
|
||||
if (txn.tags && txn.tags.length > 0) {
|
||||
for (const tagObj of txn.tags) {
|
||||
const tagName = typeof tagObj === "string" ? tagObj : tagObj.name;
|
||||
tagMap.set(tagName, (tagMap.get(tagName) || 0) + txn.amount);
|
||||
}
|
||||
} else {
|
||||
tagMap.set("Untagged", (tagMap.get("Untagged") || 0) + txn.amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user