mirror of
https://github.com/felipegcoutinho/openmonetis.git
synced 2026-05-09 19:01:47 +00:00
fix: média em category-trends ignora meses sem gastos
Corrige o cálculo da coluna Média para dividir apenas pelo número de meses com valores > 0, evitando distorção causada por meses sem movimentação. Adiciona ícone de informação com tooltip explicativo no cabeçalho da coluna. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import { RiInformationLine } from "@remixicon/react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
import { formatPeriodLabel } from "@/features/reports/utils";
|
import { formatPeriodLabel } from "@/features/reports/utils";
|
||||||
@@ -15,6 +16,11 @@ import {
|
|||||||
TableHeader,
|
TableHeader,
|
||||||
TableRow,
|
TableRow,
|
||||||
} from "@/shared/components/ui/table";
|
} from "@/shared/components/ui/table";
|
||||||
|
import {
|
||||||
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipTrigger,
|
||||||
|
} from "@/shared/components/ui/tooltip";
|
||||||
import type { CategoryReportItem } from "@/shared/lib/types/reports";
|
import type { CategoryReportItem } from "@/shared/lib/types/reports";
|
||||||
import { formatCurrency } from "@/shared/utils/currency";
|
import { formatCurrency } from "@/shared/utils/currency";
|
||||||
import { formatPeriodForUrl } from "@/shared/utils/period";
|
import { formatPeriodForUrl } from "@/shared/utils/period";
|
||||||
@@ -35,7 +41,6 @@ export function CategoryTable({
|
|||||||
const sectionTotals = useMemo(() => {
|
const sectionTotals = useMemo(() => {
|
||||||
const totalsMap = new Map<string, number>();
|
const totalsMap = new Map<string, number>();
|
||||||
let grandTotal = 0;
|
let grandTotal = 0;
|
||||||
const periodCount = Math.max(periods.length, 1);
|
|
||||||
|
|
||||||
for (const category of categories) {
|
for (const category of categories) {
|
||||||
grandTotal += category.total;
|
grandTotal += category.total;
|
||||||
@@ -46,10 +51,15 @@ export function CategoryTable({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const nonZeroPeriodCount = periods.filter(
|
||||||
|
(p) => (totalsMap.get(p) ?? 0) > 0,
|
||||||
|
).length;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
totalsMap,
|
totalsMap,
|
||||||
grandTotal,
|
grandTotal,
|
||||||
averageMonthlyTotal: grandTotal / periodCount,
|
averageMonthlyTotal:
|
||||||
|
nonZeroPeriodCount > 0 ? grandTotal / nonZeroPeriodCount : 0,
|
||||||
};
|
};
|
||||||
}, [categories, periods]);
|
}, [categories, periods]);
|
||||||
|
|
||||||
@@ -74,7 +84,21 @@ export function CategoryTable({
|
|||||||
</TableHead>
|
</TableHead>
|
||||||
))}
|
))}
|
||||||
<TableHead className="text-right min-w-[140px] font-bold">
|
<TableHead className="text-right min-w-[140px] font-bold">
|
||||||
Média
|
<div className="flex items-center justify-end gap-1">
|
||||||
|
Média
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<span className="cursor-default inline-flex">
|
||||||
|
<RiInformationLine className="size-3.5 text-muted-foreground" />
|
||||||
|
</span>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent side="top" className="max-w-[280px]">
|
||||||
|
A média considera apenas os meses com gastos registrados
|
||||||
|
(valores maiores que zero). Meses sem movimentação não
|
||||||
|
entram no cálculo.
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
<TableHead className="text-right min-w-[120px] font-bold">
|
<TableHead className="text-right min-w-[120px] font-bold">
|
||||||
Total
|
Total
|
||||||
@@ -126,7 +150,14 @@ export function CategoryTable({
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
<TableCell className="text-right font-semibold text-info">
|
<TableCell className="text-right font-semibold text-info">
|
||||||
{formatCurrency(category.total / Math.max(periods.length, 1))}
|
{(() => {
|
||||||
|
const nonZeroCount = periods.filter(
|
||||||
|
(p) => (category.monthlyData.get(p)?.amount ?? 0) > 0,
|
||||||
|
).length;
|
||||||
|
return formatCurrency(
|
||||||
|
nonZeroCount > 0 ? category.total / nonZeroCount : 0,
|
||||||
|
);
|
||||||
|
})()}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="text-right font-semibold">
|
<TableCell className="text-right font-semibold">
|
||||||
{formatCurrency(category.total)}
|
{formatCurrency(category.total)}
|
||||||
|
|||||||
Reference in New Issue
Block a user