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

@@ -53,7 +53,11 @@ async function fetcher<T>(url: string): Promise<T> {
return res.json();
}
async function mutator<T>(url: string, method: string, body?: unknown): Promise<T> {
async function mutator<T>(
url: string,
method: string,
body?: unknown,
): Promise<T> {
const res = await fetch(url, {
method,
headers: { "Content-Type": "application/json" },
@@ -154,11 +158,16 @@ export function getPeriodicExpenses(): Promise<PeriodicExpense[]> {
return fetcher<PeriodicExpense[]>("/api/periodic-expenses");
}
export function createPeriodicExpense(data: CreatePeriodicExpenseInput): Promise<PeriodicExpense> {
export function createPeriodicExpense(
data: CreatePeriodicExpenseInput,
): Promise<PeriodicExpense> {
return mutator<PeriodicExpense>("/api/periodic-expenses", "POST", data);
}
export function updatePeriodicExpense(id: number, data: CreatePeriodicExpenseInput): Promise<PeriodicExpense> {
export function updatePeriodicExpense(
id: number,
data: CreatePeriodicExpenseInput,
): Promise<PeriodicExpense> {
return mutator<PeriodicExpense>(`/api/periodic-expenses/${id}`, "PUT", data);
}
@@ -167,12 +176,18 @@ export function deletePeriodicExpense(id: number): Promise<void> {
}
export function generateMonthlyExpense(id: number): Promise<Expense> {
return mutator<Expense>(`/api/periodic-expenses/${id}/generate-month`, "POST");
return mutator<Expense>(
`/api/periodic-expenses/${id}/generate-month`,
"POST",
);
}
export type MonthlyExpensesTotal = { total: number };
export function getMonthlyPayedTotal(year?: number, month?: number): Promise<MonthlyExpensesTotal> {
export function getMonthlyPayedTotal(
year?: number,
month?: number,
): Promise<MonthlyExpensesTotal> {
const params = new URLSearchParams();
if (year) params.set("year", String(year));
if (month) params.set("month", String(month));
@@ -202,17 +217,22 @@ export function getExpenses(
if (status) params.set("status", status);
if (page) params.set("page", String(page));
if (pageSize) params.set("pageSize", String(pageSize));
if (periodicExpenseId) params.set("periodicExpenseId", String(periodicExpenseId));
if (periodicExpenseId)
params.set("periodicExpenseId", String(periodicExpenseId));
if (search) params.set("search", search);
const qs = params.toString();
return fetcher<PaginatedResponse<Expense>>(`/api/expenses${qs ? `?${qs}` : ""}`);
return fetcher<PaginatedResponse<Expense>>(
`/api/expenses${qs ? `?${qs}` : ""}`,
);
}
export type PendingUpcomingExpense = Expense & {
dueType: "overdue" | "upcoming";
};
export function getPendingUpcomingExpenses(): Promise<PendingUpcomingExpense[]> {
export function getPendingUpcomingExpenses(): Promise<
PendingUpcomingExpense[]
> {
return fetcher<PendingUpcomingExpense[]>("/api/expenses/pending-upcoming");
}
@@ -220,18 +240,26 @@ export function getTotalPending(): Promise<MonthlyExpensesTotal> {
return fetcher<MonthlyExpensesTotal>("/api/expenses/pending-total");
}
export function getMonthlyTotals(year?: number, month?: number): Promise<MonthlyTotals> {
export function getMonthlyTotals(
year?: number,
month?: number,
): Promise<MonthlyTotals> {
const params = new URLSearchParams();
if (year) params.set("year", String(year));
if (month) params.set("month", String(month));
return fetcher<MonthlyTotals>(`/api/expenses/totals?${params}`);
}
export function createNonPeriodicExpense(data: CreateNonPeriodicExpenseInput): Promise<Expense> {
export function createNonPeriodicExpense(
data: CreateNonPeriodicExpenseInput,
): Promise<Expense> {
return mutator<Expense>("/api/expenses", "POST", data);
}
export function payExpense(id: number, data: PayExpenseInput): Promise<Expense> {
export function payExpense(
id: number,
data: PayExpenseInput,
): Promise<Expense> {
return mutator<Expense>(`/api/expenses/${id}/pay`, "PUT", data);
}