style: padronizar dialogs e aplicar formatação Biome

DialogContent: padding p-6→p-10, max-w-lg→max-w-xl.
DialogFooter/AlertDialogFooter: botões com flex-1 (largura igual).
Remove gap-3/w-full redundantes de 12+ dialogs.

Reformatação Biome: line wrapping, import ordering.
Error component renomeado para evitar shadowing do global Error.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Felipe Coutinho
2026-02-26 17:22:59 +00:00
parent 803e273538
commit 96118d85e4
24 changed files with 70 additions and 56 deletions

View File

@@ -5,9 +5,9 @@ import { revalidatePath } from "next/cache";
import { Resend } from "resend";
import { z } from "zod";
import { lancamentos, pagadores } from "@/db/schema";
import { getResendFromEmail } from "@/lib/email/resend";
import { getUser } from "@/lib/auth/server";
import { db } from "@/lib/db";
import { getResendFromEmail } from "@/lib/email/resend";
import {
fetchPagadorBoletoStats,
fetchPagadorCardUsage,

View File

@@ -14,7 +14,7 @@ import {
EmptyTitle,
} from "@/components/ui/empty";
export default function Error({
export default function ErrorComponent({
error,
reset,
}: {

View File

@@ -59,9 +59,10 @@ export function ChangelogTab({ versions }: { versions: ChangelogVersion[] }) {
{version.contributor && (
<div className="border-t pt-4 mt-4">
<span className="text-sm text-muted-foreground">
Contribuições:{" "}
{(() => {
const { label, url } = parseContributorLine(version.contributor);
Contribuições: {(() => {
const { label, url } = parseContributorLine(
version.contributor,
);
if (url) {
return (
<Link
@@ -74,7 +75,11 @@ export function ChangelogTab({ versions }: { versions: ChangelogVersion[] }) {
</Link>
);
}
return <span className="font-medium text-foreground">{label}</span>;
return (
<span className="font-medium text-foreground">
{label}
</span>
);
})()}
</span>
</div>

View File

@@ -111,7 +111,7 @@ export function DeleteAccountForm() {
</div>
</div>
<DialogFooter className="sm:justify-end">
<DialogFooter>
<Button
type="button"
variant="outline"

View File

@@ -1,15 +1,20 @@
"use client";
import {
DndContext,
closestCenter,
DndContext,
type DragEndEvent,
KeyboardSensor,
PointerSensor,
useSensor,
useSensors,
} from "@dnd-kit/core";
import { arrayMove, SortableContext, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable";
import {
arrayMove,
SortableContext,
useSortable,
verticalListSortingStrategy,
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { RiDragMove2Line } from "@remixicon/react";
import { useRouter } from "next/navigation";
@@ -69,7 +74,10 @@ function SortableColumnItem({ id }: { id: string }) {
{...attributes}
{...listeners}
>
<RiDragMove2Line className="size-4 shrink-0 text-muted-foreground" aria-hidden />
<RiDragMove2Line
className="size-4 shrink-0 text-muted-foreground"
aria-hidden
/>
<span>{label}</span>
</div>
);
@@ -86,8 +94,9 @@ export function PreferencesForm({
const [isPending, startTransition] = useTransition();
const [magnetlinesDisabled, setMagnetlinesDisabled] =
useState(disableMagnetlines);
const [extratoNoteAsColumn, setExtratoNoteAsColumn] =
useState(initialExtratoNoteAsColumn);
const [extratoNoteAsColumn, setExtratoNoteAsColumn] = useState(
initialExtratoNoteAsColumn,
);
const [columnOrder, setColumnOrder] = useState<string[]>(
initialColumnOrder && initialColumnOrder.length > 0
? initialColumnOrder
@@ -232,7 +241,8 @@ export function PreferencesForm({
<div>
<h3 className="text-base font-semibold">Extrato e lançamentos</h3>
<p className="text-sm text-muted-foreground">
Como exibir anotações e a ordem das colunas na tabela de movimentações.
Como exibir anotações e a ordem das colunas na tabela de
movimentações.
</p>
</div>
@@ -242,7 +252,9 @@ export function PreferencesForm({
Anotações em coluna
</Label>
<p className="text-sm text-muted-foreground">
Quando ativo, as anotações aparecem em uma coluna na tabela. Quando desativado, aparecem em um balão ao passar o mouse no ícone.
Quando ativo, as anotações aparecem em uma coluna na tabela.
Quando desativado, aparecem em um balão ao passar o mouse no
ícone.
</p>
</div>
<Switch
@@ -256,7 +268,8 @@ export function PreferencesForm({
<div className="space-y-2 max-w-md">
<Label className="text-base">Ordem das colunas</Label>
<p className="text-sm text-muted-foreground">
Arraste os itens para definir a ordem em que as colunas aparecem na tabela do extrato e dos lançamentos.
Arraste os itens para definir a ordem em que as colunas aparecem na
tabela do extrato e dos lançamentos.
</p>
<DndContext
sensors={sensors}

View File

@@ -194,7 +194,7 @@ export function EventModal({ open, day, onClose, onCreate }: EventModalProps) {
)}
</div>
<DialogFooter className="flex justify-end gap-2">
<DialogFooter>
<Button variant="outline" onClick={onClose}>
Cancelar
</Button>

View File

@@ -241,7 +241,7 @@ export function CardDialog({
<p className="text-sm text-destructive">{errorMessage}</p>
)}
<DialogFooter className="gap-3">
<DialogFooter>
<Button
type="button"
variant="outline"

View File

@@ -85,7 +85,7 @@ export function CategoryDialog({
setFormState(initialState);
setErrorMessage(null);
}
}, [dialogOpen, setFormState, category, defaultType]);
}, [dialogOpen, setFormState, initialState]);
// Clear error when dialog closes
useEffect(() => {
@@ -156,7 +156,7 @@ export function CategoryDialog({
<p className="text-sm text-destructive">{errorMessage}</p>
)}
<DialogFooter className="gap-3">
<DialogFooter>
<Button
type="button"
variant="outline"

View File

@@ -14,7 +14,6 @@ import {
AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
import { buttonVariants } from "@/components/ui/button";
import { cn } from "@/lib/utils/ui";
interface ConfirmActionDialogProps {
trigger?: React.ReactNode;
@@ -87,19 +86,13 @@ export function ConfirmActionDialog({
) : null}
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel
disabled={isPending || disabled}
className="w-full sm:w-auto"
>
<AlertDialogCancel disabled={isPending || disabled}>
{cancelLabel}
</AlertDialogCancel>
<AlertDialogAction
onClick={handleConfirm}
disabled={isPending || disabled}
className={cn(
buttonVariants({ variant: confirmVariant }),
"w-full sm:w-auto",
)}
className={buttonVariants({ variant: confirmVariant })}
>
{isPending ? resolvedPendingLabel : confirmLabel}
</AlertDialogAction>

View File

@@ -261,7 +261,7 @@ export function AccountDialog({
<p className="text-sm text-destructive">{errorMessage}</p>
)}
<DialogFooter className="gap-3">
<DialogFooter>
<Button
type="button"
variant="outline"

View File

@@ -230,7 +230,7 @@ export function TransferDialog({
<p className="text-sm text-destructive">{errorMessage}</p>
)}
<DialogFooter className="gap-3">
<DialogFooter>
<Button
type="button"
variant="outline"

View File

@@ -394,7 +394,7 @@ export function AnticipateInstallmentsDialog({
</div>
)}
<DialogFooter className="gap-3">
<DialogFooter>
<Button
type="button"
variant="outline"

View File

@@ -140,7 +140,7 @@ export function BulkActionDialog({
</div>
</RadioGroup>
<DialogFooter className="gap-2">
<DialogFooter>
<Button
type="button"
variant="outline"

View File

@@ -185,9 +185,7 @@ export function LancamentoDetailsDialog({
<DialogFooter>
<DialogClose asChild>
<Button className="w-full" type="button">
Entendi
</Button>
<Button type="button">Entendi</Button>
</DialogClose>
</DialogFooter>
</CardContent>

View File

@@ -504,9 +504,13 @@ const buildColumns = ({
header: "Anotação",
cell: ({ row }) => {
const note = row.original.note;
if (!note?.trim()) return <span className="text-muted-foreground"></span>;
if (!note?.trim())
return <span className="text-muted-foreground"></span>;
return (
<span className="max-w-[200px] truncate whitespace-pre-line text-sm" title={note}>
<span
className="max-w-[200px] truncate whitespace-pre-line text-sm"
title={note}
>
{note}
</span>
);

View File

@@ -88,7 +88,7 @@ export function BudgetDialog({
setFormState(initialState);
setErrorMessage(null);
}
}, [dialogOpen, setFormState, budget, defaultPeriod]);
}, [dialogOpen, setFormState, initialState]);
// Clear error when dialog closes
useEffect(() => {
@@ -180,7 +180,7 @@ export function BudgetDialog({
Cadastre pelo menos uma categoria de despesa para criar um
orçamento.
</div>
<DialogFooter className="gap-3">
<DialogFooter>
<Button
type="button"
variant="outline"
@@ -242,7 +242,7 @@ export function BudgetDialog({
</p>
) : null}
<DialogFooter className="gap-3">
<DialogFooter>
<Button
type="button"
variant="outline"

View File

@@ -421,7 +421,7 @@ export function PagadorInfoCard({
</div>
</div>
<DialogFooter className="gap-2">
<DialogFooter>
<Button
type="button"
variant="outline"

View File

@@ -311,7 +311,7 @@ export function PagadorDialog({
<p className="text-sm text-destructive">{errorMessage}</p>
) : null}
<DialogFooter className="gap-3">
<DialogFooter>
<Button
type="button"
variant="outline"

View File

@@ -112,9 +112,7 @@ export function InboxDetailsDialog({
<DialogFooter>
<DialogClose asChild>
<Button className="w-full mt-2" type="button">
Entendi
</Button>
<Button type="button">Entendi</Button>
</DialogClose>
</DialogFooter>
</DialogContent>

View File

@@ -83,7 +83,7 @@ function AlertDialogFooter({
<div
data-slot="alert-dialog-footer"
className={cn(
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
"flex flex-col-reverse gap-2 sm:flex-row [&>button]:flex-1",
className,
)}
{...props}

View File

@@ -36,10 +36,7 @@ function DialogOverlay({
return (
<DialogPrimitive.Overlay
data-slot="dialog-overlay"
className={cn(
"fixed inset-0 z-50 bg-black/50",
className,
)}
className={cn("fixed inset-0 z-50 bg-black/50", className)}
{...props}
/>
);
@@ -59,7 +56,7 @@ function DialogContent({
<DialogPrimitive.Content
data-slot="dialog-content"
className={cn(
"bg-background fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg sm:max-w-lg",
"bg-background fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-10 shadow-lg sm:max-w-xl",
className,
)}
{...props}
@@ -94,7 +91,7 @@ function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
<div
data-slot="dialog-footer"
className={cn(
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
"flex flex-col-reverse gap-2 sm:flex-row [&>button]:flex-1",
className,
)}
{...props}

View File

@@ -107,10 +107,14 @@ export const preferenciasUsuario = pgTable("preferencias_usuario", {
.unique()
.references(() => user.id, { onDelete: "cascade" }),
disableMagnetlines: boolean("disable_magnetlines").notNull().default(false),
extratoNoteAsColumn: boolean("extrato_note_as_column").notNull().default(false),
extratoNoteAsColumn: boolean("extrato_note_as_column")
.notNull()
.default(false),
systemFont: text("system_font").notNull().default("ai-sans"),
moneyFont: text("money_font").notNull().default("ai-sans"),
lancamentosColumnOrder: jsonb("lancamentos_column_order").$type<string[] | null>(),
lancamentosColumnOrder: jsonb("lancamentos_column_order").$type<
string[] | null
>(),
dashboardWidgets: jsonb("dashboard_widgets").$type<{
order: string[];
hidden: string[];

View File

@@ -56,7 +56,9 @@ export function parseChangelog(): ChangelogVersion[] {
}
// **Contribuições:** ou **Autor:** com texto/link opcional
const contributorMatch = line.match(/^\*\*(?:Contribuições|Autor):\*\*\s*(.+)$/);
const contributorMatch = line.match(
/^\*\*(?:Contribuições|Autor):\*\*\s*(.+)$/,
);
if (contributorMatch && currentVersion) {
currentVersion.contributor = contributorMatch[1].trim() || undefined;
}

View File

@@ -1,8 +1,8 @@
import { inArray } from "drizzle-orm";
import { Resend } from "resend";
import { pagadores } from "@/db/schema";
import { getResendFromEmail } from "@/lib/email/resend";
import { db } from "@/lib/db";
import { getResendFromEmail } from "@/lib/email/resend";
type ActionType = "created" | "deleted";