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,7 +1,7 @@
import { z } from "zod";
import { prisma } from "../../lib/prisma";
import { cache } from "../../lib/cache";
import { PaymentStatus } from "../../generated/prisma/client";
import { cache } from "../../lib/cache";
import { prisma } from "../../lib/prisma";
export const createPeriodicExpenseSchema = z.object({
description: z.string().min(1).max(50),
@@ -27,7 +27,11 @@ function lastDayOfMonth(year: number, month: number): number {
return new Date(year, month, 0).getDate();
}
export function buildDueDate(year: number, month: number, dueDay: number): Date {
export function buildDueDate(
year: number,
month: number,
dueDay: number,
): Date {
const clampedDay = Math.min(dueDay, lastDayOfMonth(year, month));
return new Date(Date.UTC(year, month - 1, clampedDay, 0, 0, 0, 0));
}
@@ -49,15 +53,20 @@ export async function listPeriodicExpenses() {
return data;
}
export async function createPeriodicExpense(data: z.infer<typeof createPeriodicExpenseSchema>) {
export async function createPeriodicExpense(
data: z.infer<typeof createPeriodicExpenseSchema>,
) {
const result = await prisma.periodicExpense.create({ data });
const { year, month } = getCurrentYearMonthUTC();
const { month } = getCurrentYearMonthUTC();
const currentMonthApplicable = data.periods.includes(month);
cache.invalidateByPrefix("expenses:");
return { ...result, currentMonthApplicable };
}
export async function updatePeriodicExpense(id: number, data: z.infer<typeof updatePeriodicExpenseSchema>) {
export async function updatePeriodicExpense(
id: number,
data: z.infer<typeof updatePeriodicExpenseSchema>,
) {
const result = await prisma.periodicExpense.update({ where: { id }, data });
cache.invalidateByPrefix("expenses:");
return result;
@@ -73,7 +82,9 @@ export async function softDeletePeriodicExpense(id: number) {
}
export async function generateMonthlyExpense(id: number) {
const periodic = await prisma.periodicExpense.findUniqueOrThrow({ where: { id } });
const periodic = await prisma.periodicExpense.findUniqueOrThrow({
where: { id },
});
const { year, month } = getCurrentYearMonthUTC();
const existing = await prisma.expense.findFirst({
@@ -135,7 +146,9 @@ export async function listExpenses(params: {
return result;
}
export async function createNonPeriodicExpense(data: z.infer<typeof createNonPeriodicExpenseSchema>) {
export async function createNonPeriodicExpense(
data: z.infer<typeof createNonPeriodicExpenseSchema>,
) {
const dueDate = new Date(data.dueDate);
const year = dueDate.getUTCFullYear();
const month = dueDate.getUTCMonth() + 1;
@@ -155,8 +168,13 @@ export async function createNonPeriodicExpense(data: z.infer<typeof createNonPer
return result;
}
export async function payExpense(id: number, data: z.infer<typeof payExpenseSchema>) {
const paymentDate = data.paymentDate ? new Date(data.paymentDate) : new Date();
export async function payExpense(
id: number,
data: z.infer<typeof payExpenseSchema>,
) {
const paymentDate = data.paymentDate
? new Date(data.paymentDate)
: new Date();
const result = await prisma.expense.update({
where: { id },
data: {
@@ -189,7 +207,9 @@ export async function getMonthlyTotals(year: number, month: number) {
const cached = cache.get(cacheKey);
if (cached) return cached;
const result = await prisma.$queryRaw<Array<{ payed: string | null; pending: string | null }>>`
const result = await prisma.$queryRaw<
Array<{ payed: string | null; pending: string | null }>
>`
SELECT
(SELECT CAST(SUM("amountPayed") AS NUMERIC) FROM expenses WHERE year = ${year} AND month = ${month} AND status = ${PaymentStatus.PAYED}::"PaymentStatus") as payed,
(SELECT CAST(SUM(amount) AS NUMERIC) FROM expenses WHERE year = ${year} AND month = ${month} AND status = ${PaymentStatus.PENDING}::"PaymentStatus") as pending
@@ -218,7 +238,17 @@ export async function getTotalPending() {
export async function listPendingUpcomingExpenses() {
const now = new Date();
const today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), 0, 0, 0, 0));
const today = new Date(
Date.UTC(
now.getUTCFullYear(),
now.getUTCMonth(),
now.getUTCDate(),
0,
0,
0,
0,
),
);
const fiveDaysLater = new Date(today);
fiveDaysLater.setUTCDate(fiveDaysLater.getUTCDate() + 5);
@@ -233,7 +263,8 @@ export async function listPendingUpcomingExpenses() {
return data.map((expense) => ({
...expense,
dueType: expense.dueDate < today ? "overdue" as const : "upcoming" as const,
dueType:
expense.dueDate < today ? ("overdue" as const) : ("upcoming" as const),
}));
}