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 { Resend } from "resend";
import { z } from "zod"; import { z } from "zod";
import { lancamentos, pagadores } from "@/db/schema"; import { lancamentos, pagadores } from "@/db/schema";
import { getResendFromEmail } from "@/lib/email/resend";
import { getUser } from "@/lib/auth/server"; import { getUser } from "@/lib/auth/server";
import { db } from "@/lib/db"; import { db } from "@/lib/db";
import { getResendFromEmail } from "@/lib/email/resend";
import { import {
fetchPagadorBoletoStats, fetchPagadorBoletoStats,
fetchPagadorCardUsage, fetchPagadorCardUsage,

View File

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

View File

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

View File

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

View File

@@ -1,15 +1,20 @@
"use client"; "use client";
import { import {
DndContext,
closestCenter, closestCenter,
DndContext,
type DragEndEvent, type DragEndEvent,
KeyboardSensor, KeyboardSensor,
PointerSensor, PointerSensor,
useSensor, useSensor,
useSensors, useSensors,
} from "@dnd-kit/core"; } 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 { CSS } from "@dnd-kit/utilities";
import { RiDragMove2Line } from "@remixicon/react"; import { RiDragMove2Line } from "@remixicon/react";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
@@ -69,7 +74,10 @@ function SortableColumnItem({ id }: { id: string }) {
{...attributes} {...attributes}
{...listeners} {...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> <span>{label}</span>
</div> </div>
); );
@@ -86,8 +94,9 @@ export function PreferencesForm({
const [isPending, startTransition] = useTransition(); const [isPending, startTransition] = useTransition();
const [magnetlinesDisabled, setMagnetlinesDisabled] = const [magnetlinesDisabled, setMagnetlinesDisabled] =
useState(disableMagnetlines); useState(disableMagnetlines);
const [extratoNoteAsColumn, setExtratoNoteAsColumn] = const [extratoNoteAsColumn, setExtratoNoteAsColumn] = useState(
useState(initialExtratoNoteAsColumn); initialExtratoNoteAsColumn,
);
const [columnOrder, setColumnOrder] = useState<string[]>( const [columnOrder, setColumnOrder] = useState<string[]>(
initialColumnOrder && initialColumnOrder.length > 0 initialColumnOrder && initialColumnOrder.length > 0
? initialColumnOrder ? initialColumnOrder
@@ -232,7 +241,8 @@ export function PreferencesForm({
<div> <div>
<h3 className="text-base font-semibold">Extrato e lançamentos</h3> <h3 className="text-base font-semibold">Extrato e lançamentos</h3>
<p className="text-sm text-muted-foreground"> <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> </p>
</div> </div>
@@ -242,7 +252,9 @@ export function PreferencesForm({
Anotações em coluna Anotações em coluna
</Label> </Label>
<p className="text-sm text-muted-foreground"> <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> </p>
</div> </div>
<Switch <Switch
@@ -256,7 +268,8 @@ export function PreferencesForm({
<div className="space-y-2 max-w-md"> <div className="space-y-2 max-w-md">
<Label className="text-base">Ordem das colunas</Label> <Label className="text-base">Ordem das colunas</Label>
<p className="text-sm text-muted-foreground"> <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> </p>
<DndContext <DndContext
sensors={sensors} sensors={sensors}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -504,9 +504,13 @@ const buildColumns = ({
header: "Anotação", header: "Anotação",
cell: ({ row }) => { cell: ({ row }) => {
const note = row.original.note; 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 ( 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} {note}
</span> </span>
); );

View File

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

View File

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

View File

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

View File

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

View File

@@ -83,7 +83,7 @@ function AlertDialogFooter({
<div <div
data-slot="alert-dialog-footer" data-slot="alert-dialog-footer"
className={cn( 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, className,
)} )}
{...props} {...props}

View File

@@ -36,10 +36,7 @@ function DialogOverlay({
return ( return (
<DialogPrimitive.Overlay <DialogPrimitive.Overlay
data-slot="dialog-overlay" data-slot="dialog-overlay"
className={cn( className={cn("fixed inset-0 z-50 bg-black/50", className)}
"fixed inset-0 z-50 bg-black/50",
className,
)}
{...props} {...props}
/> />
); );
@@ -59,7 +56,7 @@ function DialogContent({
<DialogPrimitive.Content <DialogPrimitive.Content
data-slot="dialog-content" data-slot="dialog-content"
className={cn( 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, className,
)} )}
{...props} {...props}
@@ -94,7 +91,7 @@ function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
<div <div
data-slot="dialog-footer" data-slot="dialog-footer"
className={cn( 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, className,
)} )}
{...props} {...props}

View File

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

View File

@@ -56,7 +56,9 @@ export function parseChangelog(): ChangelogVersion[] {
} }
// **Contribuições:** ou **Autor:** com texto/link opcional // **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) { if (contributorMatch && currentVersion) {
currentVersion.contributor = contributorMatch[1].trim() || undefined; currentVersion.contributor = contributorMatch[1].trim() || undefined;
} }

View File

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