refactor: migrate from ESLint to Biome and extract SQL queries to data.ts

- Replace ESLint with Biome for linting and formatting
- Configure Biome with tabs, double quotes, and organized imports
- Move all SQL/Drizzle queries from page.tsx files to data.ts files
- Create new data.ts files for: ajustes, dashboard, relatorios/categorias
- Update existing data.ts files: extrato, fatura (add lancamentos queries)
- Remove all drizzle-orm imports from page.tsx files
- Update README.md with new tooling info

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Felipe Coutinho
2026-01-27 13:15:37 +00:00
parent 8ffe61c59b
commit a7f63fb77a
442 changed files with 66141 additions and 69292 deletions

View File

@@ -8,29 +8,31 @@ import type { SelectOption } from "@/components/lancamentos/types";
* Capitalizes the first letter of a string
*/
function capitalize(value: string): string {
return value.length > 0 ? value[0]?.toUpperCase().concat(value.slice(1)) : value;
return value.length > 0
? value[0]?.toUpperCase().concat(value.slice(1))
: value;
}
/**
* Group label for categorias
*/
type CategoriaGroup = {
label: string;
options: SelectOption[];
label: string;
options: SelectOption[];
};
/**
* Normalizes category group labels (Despesa -> Despesas, Receita -> Receitas)
*/
function normalizeCategoryGroupLabel(value: string): string {
const lower = value.toLowerCase();
if (lower === "despesa") {
return "Despesas";
}
if (lower === "receita") {
return "Receitas";
}
return capitalize(value);
const lower = value.toLowerCase();
if (lower === "despesa") {
return "Despesas";
}
if (lower === "receita") {
return "Receitas";
}
return capitalize(value);
}
/**
@@ -39,45 +41,45 @@ function normalizeCategoryGroupLabel(value: string): string {
* @returns Array of grouped and sorted categoria options
*/
export function groupAndSortCategorias(
categoriaOptions: SelectOption[]
categoriaOptions: SelectOption[],
): CategoriaGroup[] {
// Group categorias by their group property
const groups = categoriaOptions.reduce<Record<string, SelectOption[]>>(
(acc, option) => {
const key = option.group ?? "Outros";
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(option);
return acc;
},
{}
);
// Group categorias by their group property
const groups = categoriaOptions.reduce<Record<string, SelectOption[]>>(
(acc, option) => {
const key = option.group ?? "Outros";
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(option);
return acc;
},
{},
);
// Define preferred order (Despesa first, then Receita, then others)
const preferredOrder = ["Despesa", "Receita"];
const orderedKeys = [
...preferredOrder.filter((key) => groups[key]?.length),
...Object.keys(groups).filter((key) => !preferredOrder.includes(key)),
];
// Define preferred order (Despesa first, then Receita, then others)
const preferredOrder = ["Despesa", "Receita"];
const orderedKeys = [
...preferredOrder.filter((key) => groups[key]?.length),
...Object.keys(groups).filter((key) => !preferredOrder.includes(key)),
];
// Map to final structure with normalized labels and sorted options
return orderedKeys.map((key) => ({
label: normalizeCategoryGroupLabel(key),
options: groups[key]
.slice()
.sort((a, b) =>
a.label.localeCompare(b.label, "pt-BR", { sensitivity: "base" })
),
}));
// Map to final structure with normalized labels and sorted options
return orderedKeys.map((key) => ({
label: normalizeCategoryGroupLabel(key),
options: groups[key]
.slice()
.sort((a, b) =>
a.label.localeCompare(b.label, "pt-BR", { sensitivity: "base" }),
),
}));
}
/**
* Filters secondary pagador options to exclude the primary pagador
*/
export function filterSecondaryPagadorOptions(
allOptions: SelectOption[],
primaryPagadorId?: string
allOptions: SelectOption[],
primaryPagadorId?: string,
): SelectOption[] {
return allOptions.filter((option) => option.value !== primaryPagadorId);
return allOptions.filter((option) => option.value !== primaryPagadorId);
}