diff --git a/src/components/transactions/TransactionFilterBar.tsx b/src/components/transactions/TransactionFilterBar.tsx index 1fcad90..baaf002 100644 --- a/src/components/transactions/TransactionFilterBar.tsx +++ b/src/components/transactions/TransactionFilterBar.tsx @@ -1,9 +1,44 @@ -import { useMemo } from "react"; +import { useMemo, useCallback } from "react"; import { useTranslation } from "react-i18next"; import { Search } from "lucide-react"; import type { TransactionFilters, Category, ImportSource } from "../../shared/types"; import CategoryCombobox from "../shared/CategoryCombobox"; +type QuickPeriod = "month" | "3months" | "6months" | "year" | "all"; +const PERIODS: QuickPeriod[] = ["month", "3months", "6months", "year", "all"]; + +function computePeriodDates(period: QuickPeriod): { dateFrom: string | null; dateTo: string | null } { + if (period === "all") return { dateFrom: null, dateTo: null }; + const now = new Date(); + const year = now.getFullYear(); + const month = now.getMonth(); + if (period === "year") return { dateFrom: `${year}-01-01`, dateTo: null }; + let from: Date; + switch (period) { + case "month": + from = new Date(year, month, 1); + break; + case "3months": + from = new Date(year, month - 2, 1); + break; + case "6months": + from = new Date(year, month - 5, 1); + break; + } + const dateFrom = `${from.getFullYear()}-${String(from.getMonth() + 1).padStart(2, "0")}-${String(from.getDate()).padStart(2, "0")}`; + return { dateFrom, dateTo: null }; +} + +function detectActivePeriod(filters: TransactionFilters): QuickPeriod | null { + if (filters.dateTo) return null; + if (!filters.dateFrom) return "all"; + for (const p of PERIODS) { + const { dateFrom } = computePeriodDates(p); + if (dateFrom === filters.dateFrom) return p; + } + return null; +} + interface TransactionFilterBarProps { filters: TransactionFilters; categories: Category[]; @@ -19,6 +54,17 @@ export default function TransactionFilterBar({ }: TransactionFilterBarProps) { const { t } = useTranslation(); + const activePeriod = detectActivePeriod(filters); + + const handlePeriodChange = useCallback( + (period: QuickPeriod) => { + const { dateFrom, dateTo } = computePeriodDates(period); + onFilterChange("dateFrom", dateFrom); + onFilterChange("dateTo", dateTo); + }, + [onFilterChange] + ); + const categoryExtras = useMemo( () => [ { value: "", label: t("transactions.filters.allCategories") }, @@ -37,6 +83,23 @@ export default function TransactionFilterBar({ return (
+ {/* Period quick-select */} +
+ {PERIODS.map((p) => ( + + ))} +
+
{/* Search */}
diff --git a/src/hooks/useTransactions.ts b/src/hooks/useTransactions.ts index 5d7ad3d..56a2e61 100644 --- a/src/hooks/useTransactions.ts +++ b/src/hooks/useTransactions.ts @@ -51,7 +51,7 @@ const initialFilters: TransactionFilters = { search: "", categoryId: null, sourceId: null, - dateFrom: null, + dateFrom: `${new Date().getFullYear()}-01-01`, dateTo: null, uncategorizedOnly: false, }; diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index 9a37b7f..29cf1aa 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -25,6 +25,7 @@ "3months": "3 months", "6months": "6 months", "12months": "12 months", + "year": "This year", "all": "All" }, "help": { diff --git a/src/i18n/locales/fr.json b/src/i18n/locales/fr.json index addba46..f8096e7 100644 --- a/src/i18n/locales/fr.json +++ b/src/i18n/locales/fr.json @@ -25,6 +25,7 @@ "3months": "3 mois", "6months": "6 mois", "12months": "12 mois", + "year": "Cette année", "all": "Tout" }, "help": {