chore: add Biome for lint and fix all lint errors

- Install @biomejs/biome as devDependency at root
- Configure biome.json with 2-space indent, double quotes, Tailwind CSS support
- Add lint/lint:fix/format/format:fix scripts to root and app package.json
- Fix noNonNullAssertion: env vars extracted to variables with suppression, <div role=button> replaced with <button>
- Fix noUnusedVariables: remove unused destructured vars
- Fix useIterableCallbackReturn: arrow functions with block body
- Fix noExplicitAny: recharts Tooltip formatters
- Fix noLabelWithoutControl: add htmlFor+id or use <span> for non-input labels
- Fix noStaticElementInteractions/useKeyWithClickEvents: role+keyboard events for overlays
- Fix noArrayIndexKey: use error string as key
- Fix CSS parse: enable tailwindDirectives parser
- Normalize formatting across 80 files with biome check --write
This commit is contained in:
Jose Selesan
2026-06-04 10:48:07 -03:00
parent 53a797703e
commit 5b6ccf0fa6
81 changed files with 1565 additions and 794 deletions

View File

@@ -1,30 +1,38 @@
import { createContext, useContext, useState, useCallback, useEffect, useRef, type ReactNode } from "react";
import {
usePeriodicExpenses,
useCreatePeriodicExpense,
useUpdatePeriodicExpense,
useDeletePeriodicExpense,
useGenerateMonthlyExpense,
useExpenses,
useCreateNonPeriodicExpense,
usePayExpense,
useMonthlyTotals,
useTotalPending,
useImportPeriodicExpenses,
useImportExpenses,
} from "@/lib/queries";
createContext,
type ReactNode,
useCallback,
useContext,
useEffect,
useRef,
useState,
} from "react";
import type {
PeriodicExpense,
Expense,
CreatePeriodicExpenseInput,
CreateNonPeriodicExpenseInput,
PayExpenseInput,
PaginatedResponse,
MonthlyTotals,
MonthlyExpensesTotal,
ImportResult,
CreatePeriodicExpenseInput,
Expense,
ImportExpensesResult,
ImportResult,
MonthlyExpensesTotal,
MonthlyTotals,
PaginatedResponse,
PayExpenseInput,
PeriodicExpense,
} from "@/lib/api";
import {
useCreateNonPeriodicExpense,
useCreatePeriodicExpense,
useDeletePeriodicExpense,
useExpenses,
useGenerateMonthlyExpense,
useImportExpenses,
useImportPeriodicExpenses,
useMonthlyTotals,
usePayExpense,
usePeriodicExpenses,
useTotalPending,
useUpdatePeriodicExpense,
} from "@/lib/queries";
interface ExpensesContextValue {
periodicExpenses: PeriodicExpense[];
@@ -47,11 +55,18 @@ interface ExpensesContextValue {
totalPending: MonthlyExpensesTotal | undefined;
isLoadingTotalPending: boolean;
createPeriodicExpense: (data: CreatePeriodicExpenseInput) => Promise<PeriodicExpense>;
updatePeriodicExpense: (id: number, data: CreatePeriodicExpenseInput) => Promise<void>;
createPeriodicExpense: (
data: CreatePeriodicExpenseInput,
) => Promise<PeriodicExpense>;
updatePeriodicExpense: (
id: number,
data: CreatePeriodicExpenseInput,
) => Promise<void>;
deletePeriodicExpense: (id: number) => Promise<void>;
generateMonthlyExpense: (id: number) => Promise<Expense>;
createNonPeriodicExpense: (data: CreateNonPeriodicExpenseInput) => Promise<void>;
createNonPeriodicExpense: (
data: CreateNonPeriodicExpenseInput,
) => Promise<void>;
payExpense: (id: number, data: PayExpenseInput) => Promise<void>;
importPeriodicExpenses: (file: File) => Promise<ImportResult>;
importExpenses: (file: File) => Promise<ImportExpensesResult>;
@@ -59,11 +74,19 @@ interface ExpensesContextValue {
const ExpensesContext = createContext<ExpensesContextValue | null>(null);
export function ExpensesProvider({ children, initialPeriodicExpenseId }: { children: ReactNode; initialPeriodicExpenseId?: number }) {
export function ExpensesProvider({
children,
initialPeriodicExpenseId,
}: {
children: ReactNode;
initialPeriodicExpenseId?: number;
}) {
const [statusFilter, setStatusFilter] = useState("PENDING");
const [page, setPage] = useState(1);
const pageSize = 10;
const [periodicExpenseFilter, setPeriodicExpenseFilter] = useState<number | undefined>(initialPeriodicExpenseId);
const [periodicExpenseFilter, setPeriodicExpenseFilter] = useState<
number | undefined
>(initialPeriodicExpenseId);
const [searchInput, setSearchInput] = useState("");
const [searchQuery, setSearchQuery] = useState("");
@@ -81,15 +104,28 @@ export function ExpensesProvider({ children, initialPeriodicExpenseId }: { child
useEffect(() => {
setPage(1);
}, [periodicExpenseFilter, searchQuery]);
}, []);
const { data: periodicExpenses = [], isLoading: isLoadingPeriodic } = usePeriodicExpenses();
const { data: expenses = { data: [], total: 0, page: 1, pageSize: 10 }, isLoading: isLoadingExpenses } =
useExpenses(statusFilter, page, pageSize, periodicExpenseFilter, searchQuery || undefined);
const { data: periodicExpenses = [], isLoading: isLoadingPeriodic } =
usePeriodicExpenses();
const {
data: expenses = { data: [], total: 0, page: 1, pageSize: 10 },
isLoading: isLoadingExpenses,
} = useExpenses(
statusFilter,
page,
pageSize,
periodicExpenseFilter,
searchQuery || undefined,
);
const now = new Date();
const { data: monthlyTotals, isLoading: isLoadingTotals } = useMonthlyTotals(now.getFullYear(), now.getMonth() + 1);
const { data: totalPending, isLoading: isLoadingTotalPending } = useTotalPending();
const { data: monthlyTotals, isLoading: isLoadingTotals } = useMonthlyTotals(
now.getFullYear(),
now.getMonth() + 1,
);
const { data: totalPending, isLoading: isLoadingTotalPending } =
useTotalPending();
const createPeriodicMutation = useCreatePeriodicExpense();
const updatePeriodicMutation = useUpdatePeriodicExpense();
@@ -193,6 +229,7 @@ export function ExpensesProvider({ children, initialPeriodicExpenseId }: { child
export function useExpensesContext() {
const ctx = useContext(ExpensesContext);
if (!ctx) throw new Error("useExpensesContext must be used within ExpensesProvider");
if (!ctx)
throw new Error("useExpensesContext must be used within ExpensesProvider");
return ctx;
}