refactor(reports/trends): rename chart type from 'line' to 'bar' to match actual rendering
All checks were successful
PR Check / rust (push) Successful in 21m44s
PR Check / frontend (push) Successful in 2m18s
PR Check / rust (pull_request) Successful in 21m27s
PR Check / frontend (pull_request) Successful in 2m11s

The legacy chart was a stacked BarChart, not a LineChart — the initial 'line'
naming was misleading. Rename internal type, i18n key (chartLine -> chartBar,
Lignes -> Barres, Lines -> Bars) and icon. Legacy 'line' in localStorage is
migrated to 'bar' on read.
This commit is contained in:
le king fu 2026-04-19 07:26:22 -04:00
parent 02efc75542
commit 94104c4223
5 changed files with 23 additions and 16 deletions

View file

@ -27,7 +27,7 @@ function formatMonth(month: string): string {
return date.toLocaleDateString("default", { month: "short", year: "2-digit" }); return date.toLocaleDateString("default", { month: "short", year: "2-digit" });
} }
export type CategoryOverTimeChartType = "line" | "area"; export type CategoryOverTimeChartType = "bar" | "area";
interface CategoryOverTimeChartProps { interface CategoryOverTimeChartProps {
data: CategoryOverTimeData; data: CategoryOverTimeData;
@ -37,10 +37,10 @@ interface CategoryOverTimeChartProps {
onViewDetails: (item: CategoryBreakdownItem) => void; onViewDetails: (item: CategoryBreakdownItem) => void;
showAmounts?: boolean; showAmounts?: boolean;
/** /**
* Visual rendering mode. `line` (default) keeps the legacy stacked bars * Visual rendering mode. `bar` (default) keeps the legacy stacked-bar
* preserved for backward compatibility. `area` stacks Recharts <Area> layers * composition. `area` stacks Recharts <Area> layers (stackId="1") for a
* (stackId="1") showing total composition over time. Both modes share the * smoother flow view. Both modes share the same palette and SVG grayscale
* same palette and SVG grayscale patterns (existing signature visual). * patterns (existing signature visual).
*/ */
chartType?: CategoryOverTimeChartType; chartType?: CategoryOverTimeChartType;
} }
@ -52,7 +52,7 @@ export default function CategoryOverTimeChart({
onShowAll, onShowAll,
onViewDetails, onViewDetails,
showAmounts, showAmounts,
chartType = "line", chartType = "bar",
}: CategoryOverTimeChartProps) { }: CategoryOverTimeChartProps) {
const { t } = useTranslation(); const { t } = useTranslation();
const hoveredRef = useRef<string | null>(null); const hoveredRef = useRef<string | null>(null);

View file

@ -21,13 +21,18 @@ describe("readTrendsChartType", () => {
vi.stubGlobal("localStorage", mockLocalStorage); vi.stubGlobal("localStorage", mockLocalStorage);
}); });
it("returns 'line' fallback when key is missing", () => { it("returns 'bar' fallback when key is missing", () => {
expect(readTrendsChartType()).toBe("line"); expect(readTrendsChartType()).toBe("bar");
}); });
it("returns 'line' when stored value is 'line'", () => { it("returns 'bar' when stored value is 'bar'", () => {
store.set(TRENDS_CHART_TYPE_STORAGE_KEY, "bar");
expect(readTrendsChartType()).toBe("bar");
});
it("migrates legacy 'line' stored value to 'bar'", () => {
store.set(TRENDS_CHART_TYPE_STORAGE_KEY, "line"); store.set(TRENDS_CHART_TYPE_STORAGE_KEY, "line");
expect(readTrendsChartType()).toBe("line"); expect(readTrendsChartType()).toBe("bar");
}); });
it("returns 'area' when stored value is 'area'", () => { it("returns 'area' when stored value is 'area'", () => {

View file

@ -1,6 +1,6 @@
import { useEffect } from "react"; import { useEffect } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { LineChart as LineIcon, AreaChart as AreaIcon } from "lucide-react"; import { BarChart3 as BarIcon, AreaChart as AreaIcon } from "lucide-react";
import type { CategoryOverTimeChartType } from "./CategoryOverTimeChart"; import type { CategoryOverTimeChartType } from "./CategoryOverTimeChart";
export const TRENDS_CHART_TYPE_STORAGE_KEY = "reports-trends-category-charttype"; export const TRENDS_CHART_TYPE_STORAGE_KEY = "reports-trends-category-charttype";
@ -14,11 +14,13 @@ export interface TrendsChartTypeToggleProps {
export function readTrendsChartType( export function readTrendsChartType(
storageKey: string = TRENDS_CHART_TYPE_STORAGE_KEY, storageKey: string = TRENDS_CHART_TYPE_STORAGE_KEY,
fallback: CategoryOverTimeChartType = "line", fallback: CategoryOverTimeChartType = "bar",
): CategoryOverTimeChartType { ): CategoryOverTimeChartType {
if (typeof localStorage === "undefined") return fallback; if (typeof localStorage === "undefined") return fallback;
const saved = localStorage.getItem(storageKey); const saved = localStorage.getItem(storageKey);
return saved === "line" || saved === "area" ? saved : fallback; // Back-compat: "line" was the historical key for the bar chart.
if (saved === "line") return "bar";
return saved === "bar" || saved === "area" ? saved : fallback;
} }
export default function TrendsChartTypeToggle({ export default function TrendsChartTypeToggle({
@ -33,7 +35,7 @@ export default function TrendsChartTypeToggle({
}, [value, storageKey]); }, [value, storageKey]);
const options: { type: CategoryOverTimeChartType; icon: React.ReactNode; label: string }[] = [ const options: { type: CategoryOverTimeChartType; icon: React.ReactNode; label: string }[] = [
{ type: "line", icon: <LineIcon size={14} />, label: t("reports.trends.chartLine") }, { type: "bar", icon: <BarIcon size={14} />, label: t("reports.trends.chartBar") },
{ type: "area", icon: <AreaIcon size={14} />, label: t("reports.trends.chartArea") }, { type: "area", icon: <AreaIcon size={14} />, label: t("reports.trends.chartArea") },
]; ];

View file

@ -361,7 +361,7 @@
"trends": { "trends": {
"subviewGlobal": "Global flow", "subviewGlobal": "Global flow",
"subviewByCategory": "By category", "subviewByCategory": "By category",
"chartLine": "Lines", "chartBar": "Bars",
"chartArea": "Stacked area", "chartArea": "Stacked area",
"chartTypeAria": "Chart type" "chartTypeAria": "Chart type"
}, },

View file

@ -361,7 +361,7 @@
"trends": { "trends": {
"subviewGlobal": "Flux global", "subviewGlobal": "Flux global",
"subviewByCategory": "Par catégorie", "subviewByCategory": "Par catégorie",
"chartLine": "Lignes", "chartBar": "Barres",
"chartArea": "Surface empilée", "chartArea": "Surface empilée",
"chartTypeAria": "Type de graphique" "chartTypeAria": "Type de graphique"
}, },