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:
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
}: {
|
}: {
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -394,7 +394,7 @@ export function AnticipateInstallmentsDialog({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<DialogFooter className="gap-3">
|
<DialogFooter>
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -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[];
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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";
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user