feat: implementar melhorias em importação, compartilhamento e contas inativas

- Corrigir cálculo de valor na importação de lançamentos parcelados
    - Exibir valor total (parcela × quantidade) ao invés do valor da parcela individual
    - Permite recriar parcelamentos importados com valor correto

  - Permitir que usuários compartilhados se descompartilhem de pagadores
    - Adicionar componente PagadorLeaveShareCard na aba Perfil
    - Usuário filho pode sair do compartilhamento sem precisar do usuário pai
    - Manter autorização bidirecionada na action de remoção de share

  - Implementar submenu "Inativos" para contas bancárias
    - Criar página /contas/inativos seguindo padrão de cartões
    - Filtrar contas ativas e inativas em páginas separadas
    - Adicionar ícone e navegação no sidebar
This commit is contained in:
Felipe Coutinho
2026-01-11 22:44:20 +00:00
parent 147857c5bd
commit 6a45a5110d
26 changed files with 812 additions and 405 deletions

View File

@@ -1,7 +1,7 @@
import { cartoes, contas, lancamentos } from "@/db/schema"; import { cartoes, contas, lancamentos } from "@/db/schema";
import { db } from "@/lib/db"; import { db } from "@/lib/db";
import { loadLogoOptions } from "@/lib/logo/options"; import { loadLogoOptions } from "@/lib/logo/options";
import { and, eq, isNull, or, sql } from "drizzle-orm"; import { and, eq, ilike, isNull, not, or, sql } from "drizzle-orm";
export type CardData = { export type CardData = {
id: string; id: string;
@@ -33,7 +33,91 @@ export async function fetchCardsForUser(userId: string): Promise<{
const [cardRows, accountRows, logoOptions, usageRows] = await Promise.all([ const [cardRows, accountRows, logoOptions, usageRows] = await Promise.all([
db.query.cartoes.findMany({ db.query.cartoes.findMany({
orderBy: (card: typeof cartoes.$inferSelect, { desc }: { desc: (field: unknown) => unknown }) => [desc(card.name)], orderBy: (card: typeof cartoes.$inferSelect, { desc }: { desc: (field: unknown) => unknown }) => [desc(card.name)],
where: eq(cartoes.userId, userId), where: and(eq(cartoes.userId, userId), not(ilike(cartoes.status, "inativo"))),
with: {
conta: {
columns: {
id: true,
name: true,
},
},
},
}),
db.query.contas.findMany({
orderBy: (account: typeof contas.$inferSelect, { desc }: { desc: (field: unknown) => unknown }) => [desc(account.name)],
where: eq(contas.userId, userId),
columns: {
id: true,
name: true,
logo: true,
},
}),
loadLogoOptions(),
db
.select({
cartaoId: lancamentos.cartaoId,
total: sql<number>`coalesce(sum(${lancamentos.amount}), 0)`,
})
.from(lancamentos)
.where(
and(
eq(lancamentos.userId, userId),
or(isNull(lancamentos.isSettled), eq(lancamentos.isSettled, false))
)
)
.groupBy(lancamentos.cartaoId),
]);
const usageMap = new Map<string, number>();
usageRows.forEach((row: { cartaoId: string | null; total: number | null }) => {
if (!row.cartaoId) return;
usageMap.set(row.cartaoId, Number(row.total ?? 0));
});
const cards = cardRows.map((card) => ({
id: card.id,
name: card.name,
brand: card.brand,
status: card.status,
closingDay: card.closingDay,
dueDay: card.dueDay,
note: card.note,
logo: card.logo,
limit: card.limit ? Number(card.limit) : null,
limitInUse: (() => {
const total = usageMap.get(card.id) ?? 0;
return total < 0 ? Math.abs(total) : 0;
})(),
limitAvailable: (() => {
if (!card.limit) {
return null;
}
const total = usageMap.get(card.id) ?? 0;
const inUse = total < 0 ? Math.abs(total) : 0;
return Math.max(Number(card.limit) - inUse, 0);
})(),
contaId: card.contaId,
contaName: card.conta?.name ?? "Conta não encontrada",
}));
const accounts = accountRows.map((account) => ({
id: account.id,
name: account.name,
logo: account.logo,
}));
return { cards, accounts, logoOptions };
}
export async function fetchInativosForUser(userId: string): Promise<{
cards: CardData[];
accounts: AccountSimple[];
logoOptions: LogoOption[];
}> {
const [cardRows, accountRows, logoOptions, usageRows] = await Promise.all([
db.query.cartoes.findMany({
orderBy: (card: typeof cartoes.$inferSelect, { desc }: { desc: (field: unknown) => unknown }) => [desc(card.name)],
where: and(eq(cartoes.userId, userId), ilike(cartoes.status, "inativo")),
with: { with: {
conta: { conta: {
columns: { columns: {

View File

@@ -0,0 +1,19 @@
import { CardsPage } from "@/components/cartoes/cards-page";
import { getUserId } from "@/lib/auth/server";
import { fetchInativosForUser } from "../data";
export default async function InativosPage() {
const userId = await getUserId();
const { cards, accounts, logoOptions } = await fetchInativosForUser(userId);
return (
<main className="flex flex-col items-start gap-6">
<CardsPage
cards={cards}
accounts={accounts}
logoOptions={logoOptions}
isInativos={true}
/>
</main>
);
}

View File

@@ -1,5 +1,5 @@
import PageDescription from "@/components/page-description"; import PageDescription from "@/components/page-description";
import { RiBankCardLine } from "@remixicon/react"; import { RiBankCard2Line } from "@remixicon/react";
export const metadata = { export const metadata = {
title: "Cartões | Opensheets", title: "Cartões | Opensheets",
@@ -13,7 +13,7 @@ export default function RootLayout({
return ( return (
<section className="space-y-6 px-6"> <section className="space-y-6 px-6">
<PageDescription <PageDescription
icon={<RiBankCardLine />} icon={<RiBankCard2Line />}
title="Cartões" title="Cartões"
subtitle="Acompanhe todas os cartões do mês selecionado incluindo faturas, limites subtitle="Acompanhe todas os cartões do mês selecionado incluindo faturas, limites
e transações previstas. Use o seletor abaixo para navegar pelos meses e e transações previstas. Use o seletor abaixo para navegar pelos meses e

View File

@@ -3,7 +3,7 @@ import { INITIAL_BALANCE_NOTE } from "@/lib/accounts/constants";
import { db } from "@/lib/db"; import { db } from "@/lib/db";
import { loadLogoOptions } from "@/lib/logo/options"; import { loadLogoOptions } from "@/lib/logo/options";
import { PAGADOR_ROLE_ADMIN } from "@/lib/pagadores/constants"; import { PAGADOR_ROLE_ADMIN } from "@/lib/pagadores/constants";
import { and, eq, sql } from "drizzle-orm"; import { and, eq, ilike, not, sql } from "drizzle-orm";
export type AccountData = { export type AccountData = {
id: string; id: string;
@@ -58,6 +58,83 @@ export async function fetchAccountsForUser(
.where( .where(
and( and(
eq(contas.userId, userId), eq(contas.userId, userId),
not(ilike(contas.status, "inativa")),
sql`(${lancamentos.id} IS NULL OR ${pagadores.role} = ${PAGADOR_ROLE_ADMIN})`
)
)
.groupBy(
contas.id,
contas.name,
contas.accountType,
contas.status,
contas.note,
contas.logo,
contas.initialBalance,
contas.excludeFromBalance,
contas.excludeInitialBalanceFromIncome
),
loadLogoOptions(),
]);
const accounts = accountRows.map((account) => ({
id: account.id,
name: account.name,
accountType: account.accountType,
status: account.status,
note: account.note,
logo: account.logo,
initialBalance: Number(account.initialBalance ?? 0),
balance:
Number(account.initialBalance ?? 0) +
Number(account.balanceMovements ?? 0),
excludeFromBalance: account.excludeFromBalance,
excludeInitialBalanceFromIncome: account.excludeInitialBalanceFromIncome,
}));
return { accounts, logoOptions };
}
export async function fetchInativosForUser(
userId: string
): Promise<{ accounts: AccountData[]; logoOptions: LogoOption[] }> {
const [accountRows, logoOptions] = await Promise.all([
db
.select({
id: contas.id,
name: contas.name,
accountType: contas.accountType,
status: contas.status,
note: contas.note,
logo: contas.logo,
initialBalance: contas.initialBalance,
excludeFromBalance: contas.excludeFromBalance,
excludeInitialBalanceFromIncome: contas.excludeInitialBalanceFromIncome,
balanceMovements: sql<number>`
coalesce(
sum(
case
when ${lancamentos.note} = ${INITIAL_BALANCE_NOTE} then 0
else ${lancamentos.amount}
end
),
0
)
`,
})
.from(contas)
.leftJoin(
lancamentos,
and(
eq(lancamentos.contaId, contas.id),
eq(lancamentos.userId, userId),
eq(lancamentos.isSettled, true)
)
)
.leftJoin(pagadores, eq(lancamentos.pagadorId, pagadores.id))
.where(
and(
eq(contas.userId, userId),
ilike(contas.status, "inativa"),
sql`(${lancamentos.id} IS NULL OR ${pagadores.role} = ${PAGADOR_ROLE_ADMIN})` sql`(${lancamentos.id} IS NULL OR ${pagadores.role} = ${PAGADOR_ROLE_ADMIN})`
) )
) )

View File

@@ -0,0 +1,14 @@
import { AccountsPage } from "@/components/contas/accounts-page";
import { getUserId } from "@/lib/auth/server";
import { fetchInativosForUser } from "../data";
export default async function InativosPage() {
const userId = await getUserId();
const { accounts, logoOptions } = await fetchInativosForUser(userId);
return (
<main className="flex flex-col items-start gap-6">
<AccountsPage accounts={accounts} logoOptions={logoOptions} isInativos={true} />
</main>
);
}

View File

@@ -33,14 +33,24 @@ export const PROVIDERS = {
* Lista de modelos de IA disponíveis para análise de insights * Lista de modelos de IA disponíveis para análise de insights
*/ */
export const AVAILABLE_MODELS = [ export const AVAILABLE_MODELS = [
// OpenAI Models (5) // OpenAI Models - GPT-5.2 Family (Latest)
{ id: "gpt-5.1", name: "GPT-5.1 ", provider: "openai" as const }, { id: "gpt-5.2", name: "GPT-5.2", provider: "openai" as const },
{ id: "gpt-5.1-chat", name: "GPT-5.1 Chat", provider: "openai" as const }, {
{ id: "gpt-5", name: "GPT-5", provider: "openai" as const }, id: "gpt-5.2-instant",
{ id: "gpt-5-mini", name: "GPT-5 Mini", provider: "openai" as const }, name: "GPT-5.2 Instant",
{ id: "gpt-5-nano", name: "GPT-5 Nano", provider: "openai" as const }, provider: "openai" as const,
},
{
id: "gpt-5.2-thinking",
name: "GPT-5.2 Thinking",
provider: "openai" as const,
},
// Anthropic Models (5) // OpenAI Models - GPT-5 Family
{ id: "gpt-5", name: "GPT-5", provider: "openai" as const },
{ id: "gpt-5-instant", name: "GPT-5 Instant", provider: "openai" as const },
// Anthropic Models - Claude 4.5
{ {
id: "claude-4.5-haiku", id: "claude-4.5-haiku",
name: "Claude 4.5 Haiku", name: "Claude 4.5 Haiku",
@@ -57,20 +67,27 @@ export const AVAILABLE_MODELS = [
provider: "anthropic" as const, provider: "anthropic" as const,
}, },
// Google Models (5) // Google Models - Gemini 3 (Latest)
{ {
id: "gemini-2.5-pro", id: "gemini-3-flash-preview",
name: "Gemini 2.5 Pro", name: "Gemini 3 Flash",
provider: "google" as const, provider: "google" as const,
}, },
{ {
id: "gemini-2.5-flash", id: "gemini-3-pro-preview",
name: "Gemini 2.5 Flash", name: "Gemini 3 Pro",
provider: "google" as const,
},
// Google Models - Gemini 2.0
{
id: "gemini-2.0-flash",
name: "Gemini 2.0 Flash",
provider: "google" as const, provider: "google" as const,
}, },
] as const; ] as const;
export const DEFAULT_MODEL = "gpt-5.1"; export const DEFAULT_MODEL = "gpt-5.2";
export const DEFAULT_PROVIDER = "openai"; export const DEFAULT_PROVIDER = "openai";
/** /**

View File

@@ -1,4 +1,4 @@
import { lancamentos, pagadorShares, user as usersTable } from "@/db/schema"; import { lancamentos, pagadorShares, user as usersTable, contas, cartoes, categorias, pagadores } from "@/db/schema";
import { db } from "@/lib/db"; import { db } from "@/lib/db";
import { and, desc, eq, type SQL } from "drizzle-orm"; import { and, desc, eq, type SQL } from "drizzle-orm";
@@ -37,17 +37,54 @@ export async function fetchPagadorShares(
})); }));
} }
export async function fetchPagadorLancamentos(filters: SQL[]) { export async function fetchCurrentUserShare(
const lancamentoRows = await db.query.lancamentos.findMany({ pagadorId: string,
where: and(...filters), userId: string
with: { ): Promise<{ id: string; createdAt: string } | null> {
pagador: true, const shareRow = await db.query.pagadorShares.findFirst({
conta: true, columns: {
cartao: true, id: true,
categoria: true, createdAt: true,
}, },
orderBy: desc(lancamentos.purchaseDate), where: and(
eq(pagadorShares.pagadorId, pagadorId),
eq(pagadorShares.sharedWithUserId, userId)
),
}); });
return lancamentoRows; if (!shareRow) {
return null;
}
return {
id: shareRow.id,
createdAt: shareRow.createdAt?.toISOString() ?? new Date().toISOString(),
};
}
export async function fetchPagadorLancamentos(filters: SQL[]) {
const lancamentoRows = await db
.select({
lancamento: lancamentos,
pagador: pagadores,
conta: contas,
cartao: cartoes,
categoria: categorias,
})
.from(lancamentos)
.leftJoin(pagadores, eq(lancamentos.pagadorId, pagadores.id))
.leftJoin(contas, eq(lancamentos.contaId, contas.id))
.leftJoin(cartoes, eq(lancamentos.cartaoId, cartoes.id))
.leftJoin(categorias, eq(lancamentos.categoriaId, categorias.id))
.where(and(...filters))
.orderBy(desc(lancamentos.purchaseDate), desc(lancamentos.createdAt));
// Transformar resultado para o formato esperado
return lancamentoRows.map((row: any) => ({
...row.lancamento,
pagador: row.pagador,
conta: row.conta,
cartao: row.cartao,
categoria: row.categoria,
}));
} }

View File

@@ -5,6 +5,7 @@ import { PagadorInfoCard } from "@/components/pagadores/details/pagador-info-car
import { PagadorMonthlySummaryCard } from "@/components/pagadores/details/pagador-monthly-summary-card"; import { PagadorMonthlySummaryCard } from "@/components/pagadores/details/pagador-monthly-summary-card";
import { PagadorBoletoCard } from "@/components/pagadores/details/pagador-payment-method-cards"; import { PagadorBoletoCard } from "@/components/pagadores/details/pagador-payment-method-cards";
import { PagadorSharingCard } from "@/components/pagadores/details/pagador-sharing-card"; import { PagadorSharingCard } from "@/components/pagadores/details/pagador-sharing-card";
import { PagadorLeaveShareCard } from "@/components/pagadores/details/pagador-leave-share-card";
import { LancamentosPage as LancamentosSection } from "@/components/lancamentos/page/lancamentos-page"; import { LancamentosPage as LancamentosSection } from "@/components/lancamentos/page/lancamentos-page";
import type { import type {
ContaCartaoFilterOption, ContaCartaoFilterOption,
@@ -39,7 +40,7 @@ import {
fetchPagadorMonthlyBreakdown, fetchPagadorMonthlyBreakdown,
} from "@/lib/pagadores/details"; } from "@/lib/pagadores/details";
import { notFound } from "next/navigation"; import { notFound } from "next/navigation";
import { fetchPagadorLancamentos, fetchPagadorShares } from "./data"; import { fetchPagadorLancamentos, fetchPagadorShares, fetchCurrentUserShare } from "./data";
type PageSearchParams = Promise<ResolvedSearchParams>; type PageSearchParams = Promise<ResolvedSearchParams>;
@@ -92,9 +93,13 @@ export default async function Page({ params, searchParams }: PageProps) {
} = parsePeriodParam(periodoParamRaw); } = parsePeriodParam(periodoParamRaw);
const periodLabel = `${capitalize(monthName)} de ${year}`; const periodLabel = `${capitalize(monthName)} de ${year}`;
const allSearchFilters = extractLancamentoSearchFilters(resolvedSearchParams);
const searchFilters = canEdit const searchFilters = canEdit
? extractLancamentoSearchFilters(resolvedSearchParams) ? allSearchFilters
: EMPTY_FILTERS; : {
...EMPTY_FILTERS,
searchFilter: allSearchFilters.searchFilter, // Permitir busca mesmo em modo read-only
};
let filterSources: Awaited< let filterSources: Awaited<
ReturnType<typeof fetchLancamentoFilterSources> ReturnType<typeof fetchLancamentoFilterSources>
@@ -133,6 +138,10 @@ export default async function Page({ params, searchParams }: PageProps) {
? fetchPagadorShares(pagador.id) ? fetchPagadorShares(pagador.id)
: Promise.resolve([]); : Promise.resolve([]);
const currentUserSharePromise = !canEdit
? fetchCurrentUserShare(pagador.id, userId)
: Promise.resolve(null);
const [ const [
lancamentoRows, lancamentoRows,
monthlyBreakdown, monthlyBreakdown,
@@ -140,6 +149,7 @@ export default async function Page({ params, searchParams }: PageProps) {
cardUsage, cardUsage,
boletoStats, boletoStats,
shareRows, shareRows,
currentUserShare,
estabelecimentos, estabelecimentos,
] = await Promise.all([ ] = await Promise.all([
fetchPagadorLancamentos(filters), fetchPagadorLancamentos(filters),
@@ -164,6 +174,7 @@ export default async function Page({ params, searchParams }: PageProps) {
period: selectedPeriod, period: selectedPeriod,
}), }),
sharesPromise, sharesPromise,
currentUserSharePromise,
getRecentEstablishmentsAction(), getRecentEstablishmentsAction(),
]); ]);
@@ -281,6 +292,13 @@ export default async function Page({ params, searchParams }: PageProps) {
shares={pagadorSharesData} shares={pagadorSharesData}
/> />
) : null} ) : null}
{!canEdit && currentUserShare ? (
<PagadorLeaveShareCard
shareId={currentUserShare.id}
pagadorName={pagadorData.name}
createdAt={currentUserShare.createdAt}
/>
) : null}
</TabsContent> </TabsContent>
<TabsContent value="painel" className="space-y-4"> <TabsContent value="painel" className="space-y-4">

View File

@@ -6,7 +6,7 @@ import { Card, CardContent } from "@/components/ui/card";
import { getOptionalUserSession } from "@/lib/auth/server"; import { getOptionalUserSession } from "@/lib/auth/server";
import { import {
RiArrowRightSLine, RiArrowRightSLine,
RiBankCardLine, RiBankCard2Line,
RiBarChartBoxLine, RiBarChartBoxLine,
RiCalendarLine, RiCalendarLine,
RiCodeSSlashLine, RiCodeSSlashLine,
@@ -15,7 +15,6 @@ import {
RiGithubFill, RiGithubFill,
RiLineChartLine, RiLineChartLine,
RiLockLine, RiLockLine,
RiMoneyDollarCircleLine,
RiPieChartLine, RiPieChartLine,
RiShieldCheckLine, RiShieldCheckLine,
RiTimeLine, RiTimeLine,
@@ -234,9 +233,9 @@ export default async function Page() {
Parcelamentos avançados Parcelamentos avançados
</h3> </h3>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Controle completo de compras parceladas. Antecipe parcelas Controle completo de compras parceladas. Antecipe
com cálculo automático de desconto. Veja análise parcelas com cálculo automático de desconto. Veja
consolidada de todas as parcelas em aberto. análise consolidada de todas as parcelas em aberto.
</p> </p>
</div> </div>
</div> </div>
@@ -254,9 +253,9 @@ export default async function Page() {
Insights com IA Insights com IA
</h3> </h3>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Análises financeiras geradas por IA (Claude, GPT, Gemini). Análises financeiras geradas por IA (Claude, GPT,
Insights personalizados sobre seus padrões de gastos e Gemini). Insights personalizados sobre seus padrões de
recomendações inteligentes. gastos e recomendações inteligentes.
</p> </p>
</div> </div>
</div> </div>
@@ -287,16 +286,16 @@ export default async function Page() {
<CardContent className="pt-6"> <CardContent className="pt-6">
<div className="flex flex-col gap-4"> <div className="flex flex-col gap-4">
<div className="flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10"> <div className="flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10">
<RiBankCardLine size={24} className="text-primary" /> <RiBankCard2Line size={24} className="text-primary" />
</div> </div>
<div> <div>
<h3 className="font-semibold text-lg mb-2"> <h3 className="font-semibold text-lg mb-2">
Faturas de cartão Faturas de cartão
</h3> </h3>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Cadastre seus cartões e acompanhe as faturas por período. Cadastre seus cartões e acompanhe as faturas por
Veja o que ainda não foi fechado. Controle limites, período. Veja o que ainda não foi fechado. Controle
vencimentos e fechamentos. limites, vencimentos e fechamentos.
</p> </p>
</div> </div>
</div> </div>
@@ -315,8 +314,8 @@ export default async function Page() {
</h3> </h3>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Compartilhe pagadores com permissões granulares (admin/ Compartilhe pagadores com permissões granulares (admin/
viewer). Notificações automáticas por e-mail. Colabore em viewer). Notificações automáticas por e-mail. Colabore
lançamentos compartilhados. em lançamentos compartilhados.
</p> </p>
</div> </div>
</div> </div>
@@ -334,9 +333,9 @@ export default async function Page() {
Categorias e orçamentos Categorias e orçamentos
</h3> </h3>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Crie categorias personalizadas. Defina orçamentos mensais Crie categorias personalizadas. Defina orçamentos
e acompanhe o quanto gastou vs. planejado com indicadores mensais e acompanhe o quanto gastou vs. planejado com
visuais. indicadores visuais.
</p> </p>
</div> </div>
</div> </div>
@@ -394,9 +393,9 @@ export default async function Page() {
Importação em massa Importação em massa
</h3> </h3>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Cole múltiplos lançamentos de uma vez. Economize tempo ao Cole múltiplos lançamentos de uma vez. Economize tempo
registrar várias transações. Formatação inteligente para ao registrar várias transações. Formatação inteligente
facilitar a entrada de dados. para facilitar a entrada de dados.
</p> </p>
</div> </div>
</div> </div>
@@ -434,9 +433,9 @@ export default async function Page() {
Performance otimizada Performance otimizada
</h3> </h3>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Dashboard carrega em ~200-500ms com 18+ queries paralelas. Dashboard carrega em ~200-500ms com 18+ queries
Índices otimizados. Type-safe em toda codebase. Isolamento paralelas. Índices otimizados. Type-safe em toda
completo de dados por usuário. codebase. Isolamento completo de dados por usuário.
</p> </p>
</div> </div>
</div> </div>

View File

@@ -5,7 +5,7 @@ import { ConfirmActionDialog } from "@/components/confirm-action-dialog";
import { EmptyState } from "@/components/empty-state"; import { EmptyState } from "@/components/empty-state";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card"; import { Card } from "@/components/ui/card";
import { RiAddCircleLine, RiBankCardLine } from "@remixicon/react"; import { RiAddCircleLine, RiBankCard2Line } from "@remixicon/react";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { useCallback, useMemo, useState } from "react"; import { useCallback, useMemo, useState } from "react";
import { toast } from "sonner"; import { toast } from "sonner";
@@ -21,9 +21,15 @@ interface CardsPageProps {
cards: Card[]; cards: Card[];
accounts: AccountOption[]; accounts: AccountOption[];
logoOptions: string[]; logoOptions: string[];
isInativos?: boolean;
} }
export function CardsPage({ cards, accounts, logoOptions }: CardsPageProps) { export function CardsPage({
cards,
accounts,
logoOptions,
isInativos = false,
}: CardsPageProps) {
const router = useRouter(); const router = useRouter();
const [editOpen, setEditOpen] = useState(false); const [editOpen, setEditOpen] = useState(false);
const [selectedCard, setSelectedCard] = useState<Card | null>(null); const [selectedCard, setSelectedCard] = useState<Card | null>(null);
@@ -102,19 +108,21 @@ export function CardsPage({ cards, accounts, logoOptions }: CardsPageProps) {
return ( return (
<> <>
<div className="flex w-full flex-col gap-6"> <div className="flex w-full flex-col gap-6">
<div className="flex justify-start"> {!isInativos && (
<CardDialog <div className="flex justify-start">
mode="create" <CardDialog
accounts={accounts} mode="create"
logoOptions={logoOptions} accounts={accounts}
trigger={ logoOptions={logoOptions}
<Button> trigger={
<RiAddCircleLine className="size-4" /> <Button>
Novo cartão <RiAddCircleLine className="size-4" />
</Button> Novo cartão
} </Button>
/> }
</div> />
</div>
)}
{hasCards ? ( {hasCards ? (
<div className="flex flex-wrap gap-4"> <div className="flex flex-wrap gap-4">
@@ -141,9 +149,17 @@ export function CardsPage({ cards, accounts, logoOptions }: CardsPageProps) {
) : ( ) : (
<Card className="flex w-full items-center justify-center py-12"> <Card className="flex w-full items-center justify-center py-12">
<EmptyState <EmptyState
media={<RiBankCardLine className="size-6 text-primary" />} media={<RiBankCard2Line className="size-6 text-primary" />}
title="Nenhum cartão cadastrado" title={
description="Adicione seu primeiro cartão para acompanhar limites e faturas com mais controle." isInativos
? "Nenhum cartão inativo"
: "Nenhum cartão cadastrado"
}
description={
isInativos
? "Os cartões inativos aparecerão aqui."
: "Adicione seu primeiro cartão para acompanhar limites e faturas com mais controle."
}
/> />
</Card> </Card>
)} )}

View File

@@ -19,6 +19,7 @@ import type { Account } from "./types";
interface AccountsPageProps { interface AccountsPageProps {
accounts: Account[]; accounts: Account[];
logoOptions: string[]; logoOptions: string[];
isInativos?: boolean;
} }
const resolveLogoSrc = (logo: string | null) => { const resolveLogoSrc = (logo: string | null) => {
@@ -30,7 +31,7 @@ const resolveLogoSrc = (logo: string | null) => {
return `/logos/${fileName}`; return `/logos/${fileName}`;
}; };
export function AccountsPage({ accounts, logoOptions }: AccountsPageProps) { export function AccountsPage({ accounts, logoOptions, isInativos = false }: AccountsPageProps) {
const router = useRouter(); const router = useRouter();
const [editOpen, setEditOpen] = useState(false); const [editOpen, setEditOpen] = useState(false);
const [selectedAccount, setSelectedAccount] = useState<Account | null>(null); const [selectedAccount, setSelectedAccount] = useState<Account | null>(null);
@@ -169,8 +170,8 @@ export function AccountsPage({ accounts, logoOptions }: AccountsPageProps) {
<Card className="flex min-h-[50vh] w-full items-center justify-center py-12"> <Card className="flex min-h-[50vh] w-full items-center justify-center py-12">
<EmptyState <EmptyState
media={<RiBankLine className="size-6 text-primary" />} media={<RiBankLine className="size-6 text-primary" />}
title="Nenhuma conta cadastrada" title={isInativos ? "Nenhuma conta inativa" : "Nenhuma conta cadastrada"}
description="Cadastre sua primeira conta para começar a organizar os lançamentos." description={isInativos ? "Não há contas inativas no momento." : "Cadastre sua primeira conta para começar a organizar os lançamentos."}
/> />
</Card> </Card>
)} )}

View File

@@ -1,7 +1,7 @@
import MoneyValues from "@/components/money-values"; import MoneyValues from "@/components/money-values";
import type { PaymentMethodsData } from "@/lib/dashboard/payments/payment-methods"; import type { PaymentMethodsData } from "@/lib/dashboard/payments/payment-methods";
import { getPaymentMethodIcon } from "@/lib/utils/icons"; import { getPaymentMethodIcon } from "@/lib/utils/icons";
import { RiBankCardLine, RiMoneyDollarCircleLine } from "@remixicon/react"; import { RiBankCard2Line, RiMoneyDollarCircleLine } from "@remixicon/react";
import { Progress } from "../ui/progress"; import { Progress } from "../ui/progress";
import { WidgetEmptyState } from "../widget-empty-state"; import { WidgetEmptyState } from "../widget-empty-state";
@@ -28,7 +28,7 @@ const resolveIcon = (paymentMethod: string | null | undefined) => {
return icon; return icon;
} }
return <RiBankCardLine className="size-5" aria-hidden />; return <RiBankCard2Line className="size-5" aria-hidden />;
}; };
export function PaymentMethodsWidget({ data }: PaymentMethodsWidgetProps) { export function PaymentMethodsWidget({ data }: PaymentMethodsWidgetProps) {

View File

@@ -130,6 +130,7 @@ interface LancamentosFiltersProps {
contaCartaoOptions: ContaCartaoFilterOption[]; contaCartaoOptions: ContaCartaoFilterOption[];
className?: string; className?: string;
exportButton?: ReactNode; exportButton?: ReactNode;
hideAdvancedFilters?: boolean;
} }
export function LancamentosFilters({ export function LancamentosFilters({
@@ -138,6 +139,7 @@ export function LancamentosFilters({
contaCartaoOptions, contaCartaoOptions,
className, className,
exportButton, exportButton,
hideAdvancedFilters = false,
}: LancamentosFiltersProps) { }: LancamentosFiltersProps) {
const router = useRouter(); const router = useRouter();
const pathname = usePathname(); const pathname = usePathname();
@@ -277,22 +279,31 @@ export function LancamentosFilters({
return ( return (
<div className={cn("flex flex-wrap items-center gap-2", className)}> <div className={cn("flex flex-wrap items-center gap-2", className)}>
<Input
value={searchValue}
onChange={(event) => setSearchValue(event.target.value)}
placeholder="Buscar"
aria-label="Buscar lançamentos"
className="w-[250px] text-sm border-dashed"
/>
{exportButton} {exportButton}
<Drawer direction="right" open={drawerOpen} onOpenChange={setDrawerOpen}> {!hideAdvancedFilters && (
<DrawerTrigger asChild> <Drawer direction="right" open={drawerOpen} onOpenChange={setDrawerOpen}>
<Button <DrawerTrigger asChild>
variant="outline" <Button
className="text-sm border-dashed relative" variant="outline"
aria-label="Abrir filtros" className="text-sm border-dashed relative"
> aria-label="Abrir filtros"
<RiFilter3Line className="size-4" /> >
Filtros <RiFilter3Line className="size-4" />
{hasActiveFilters && ( Filtros
<span className="absolute -top-1 -right-1 size-2 rounded-full bg-primary" /> {hasActiveFilters && (
)} <span className="absolute -top-1 -right-1 size-2 rounded-full bg-primary" />
</Button> )}
</DrawerTrigger> </Button>
</DrawerTrigger>
<DrawerContent> <DrawerContent>
<DrawerHeader> <DrawerHeader>
<DrawerTitle>Filtros</DrawerTitle> <DrawerTitle>Filtros</DrawerTitle>
@@ -319,7 +330,9 @@ export function LancamentosFilters({
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<label className="text-sm font-medium">Condição</label> <label className="text-sm font-medium">
Condição de Lançamento
</label>
<FilterSelect <FilterSelect
param="condicao" param="condicao"
placeholder="Todas" placeholder="Todas"
@@ -335,7 +348,7 @@ export function LancamentosFilters({
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<label className="text-sm font-medium">Pagamento</label> <label className="text-sm font-medium">Forma de Pagamento</label>
<FilterSelect <FilterSelect
param="pagamento" param="pagamento"
placeholder="Todos" placeholder="Todos"
@@ -532,15 +545,8 @@ export function LancamentosFilters({
</Button> </Button>
</DrawerFooter> </DrawerFooter>
</DrawerContent> </DrawerContent>
</Drawer> </Drawer>
)}
<Input
value={searchValue}
onChange={(event) => setSearchValue(event.target.value)}
placeholder="Buscar"
aria-label="Buscar lançamentos"
className="w-[250px] text-sm border-dashed"
/>
</div> </div>
); );
} }

View File

@@ -734,9 +734,8 @@ export function LancamentosTable({
0 0
); );
// Check if all data belongs to current user to determine if filters should be shown // Check if there's any data from other users
const isOwnData = data.every((item) => item.userId === currentUserId); const hasOtherUserData = data.some((item) => item.userId !== currentUserId);
const shouldShowFilters = showFilters && isOwnData;
const handleBulkDelete = () => { const handleBulkDelete = () => {
if (onBulkDelete && selectedCount > 0) { if (onBulkDelete && selectedCount > 0) {
@@ -755,7 +754,7 @@ export function LancamentosTable({
}; };
const showTopControls = const showTopControls =
Boolean(onCreate) || Boolean(onMassAdd) || shouldShowFilters; Boolean(onCreate) || Boolean(onMassAdd) || showFilters;
return ( return (
<TooltipProvider> <TooltipProvider>
@@ -791,15 +790,16 @@ export function LancamentosTable({
) : null} ) : null}
</div> </div>
) : ( ) : (
<span className={shouldShowFilters ? "hidden sm:block" : ""} /> <span className={showFilters ? "hidden sm:block" : ""} />
)} )}
{shouldShowFilters ? ( {showFilters ? (
<LancamentosFilters <LancamentosFilters
pagadorOptions={pagadorFilterOptions} pagadorOptions={pagadorFilterOptions}
categoriaOptions={categoriaFilterOptions} categoriaOptions={categoriaFilterOptions}
contaCartaoOptions={contaCartaoFilterOptions} contaCartaoOptions={contaCartaoFilterOptions}
className="w-full lg:flex-1 lg:justify-end" className="w-full lg:flex-1 lg:justify-end"
hideAdvancedFilters={hasOtherUserData}
exportButton={ exportButton={
selectedPeriod ? ( selectedPeriod ? (
<LancamentosExport <LancamentosExport

View File

@@ -2,7 +2,7 @@ import MoneyValues from "@/components/money-values";
import { WidgetEmptyState } from "@/components/widget-empty-state"; import { WidgetEmptyState } from "@/components/widget-empty-state";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import type { PagadorCardUsageItem } from "@/lib/pagadores/details"; import type { PagadorCardUsageItem } from "@/lib/pagadores/details";
import { RiBankCardLine } from "@remixicon/react"; import { RiBankCard2Line } from "@remixicon/react";
import Image from "next/image"; import Image from "next/image";
const resolveLogoPath = (logo?: string | null) => { const resolveLogoPath = (logo?: string | null) => {
@@ -36,7 +36,7 @@ export function PagadorCardUsageCard({ items }: PagadorCardUsageCardProps) {
<CardContent className="space-y-3 pt-2"> <CardContent className="space-y-3 pt-2">
{items.length === 0 ? ( {items.length === 0 ? (
<WidgetEmptyState <WidgetEmptyState
icon={<RiBankCardLine className="size-6 text-muted-foreground" />} icon={<RiBankCard2Line className="size-6 text-muted-foreground" />}
title="Nenhum lançamento com cartão de crédito" title="Nenhum lançamento com cartão de crédito"
description="Quando houver despesas registradas com cartão, elas aparecerão aqui." description="Quando houver despesas registradas com cartão, elas aparecerão aqui."
/> />

View File

@@ -0,0 +1,114 @@
"use client";
import { deletePagadorShareAction } from "@/app/(dashboard)/pagadores/actions";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { RiLogoutBoxLine } from "@remixicon/react";
import { useRouter } from "next/navigation";
import { useState, useTransition } from "react";
import { toast } from "sonner";
interface PagadorLeaveShareCardProps {
shareId: string;
pagadorName: string;
createdAt: string;
}
export function PagadorLeaveShareCard({
shareId,
pagadorName,
createdAt,
}: PagadorLeaveShareCardProps) {
const router = useRouter();
const [isPending, startTransition] = useTransition();
const [showConfirm, setShowConfirm] = useState(false);
const handleLeave = () => {
startTransition(async () => {
const result = await deletePagadorShareAction({ shareId });
if (!result.success) {
toast.error(result.error);
return;
}
toast.success("Você saiu do compartilhamento.");
router.push("/pagadores");
});
};
const formattedDate = new Date(createdAt).toLocaleDateString("pt-BR", {
day: "2-digit",
month: "long",
year: "numeric",
});
return (
<Card className="border">
<CardHeader>
<CardTitle className="text-base font-semibold">
Acesso Compartilhado
</CardTitle>
<p className="text-sm text-muted-foreground">
Você tem acesso somente leitura aos dados de{" "}
<strong>{pagadorName}</strong>.
</p>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex flex-col gap-2 rounded-lg border border-dashed p-4 text-sm">
<span className="text-xs font-semibold uppercase text-muted-foreground/80">
Informações do compartilhamento
</span>
<div className="flex flex-col gap-1">
<p className="text-sm">
<span className="text-muted-foreground">Acesso desde:</span>{" "}
<strong>{formattedDate}</strong>
</p>
<p className="text-sm text-muted-foreground">
Você pode visualizar os lançamentos, mas não pode criar ou editar.
</p>
</div>
</div>
{!showConfirm ? (
<Button
type="button"
variant="outline"
onClick={() => setShowConfirm(true)}
className="w-full"
>
<RiLogoutBoxLine className="size-4" />
Sair do compartilhamento
</Button>
) : (
<div className="space-y-2">
<p className="text-sm font-medium text-destructive">
Tem certeza que deseja sair? Você perderá o acesso aos dados de{" "}
{pagadorName}.
</p>
<div className="flex gap-2">
<Button
type="button"
variant="outline"
onClick={() => setShowConfirm(false)}
disabled={isPending}
className="flex-1"
>
Cancelar
</Button>
<Button
type="button"
variant="destructive"
onClick={handleLeave}
disabled={isPending}
className="flex-1"
>
{isPending ? "Saindo..." : "Confirmar saída"}
</Button>
</div>
</div>
)}
</CardContent>
</Card>
);
}

View File

@@ -1,46 +1,46 @@
"use client"; "use client";
import { formatCurrency, formatPercentageChange } from "@/lib/relatorios/utils"; import { formatCurrency, formatPercentageChange } from "@/lib/relatorios/utils";
import { RiArrowDownLine, RiArrowUpLine } from "@remixicon/react";
import { cn } from "@/lib/utils/ui"; import { cn } from "@/lib/utils/ui";
import { RiArrowDownLine, RiArrowUpLine } from "@remixicon/react";
interface CategoryCellProps { interface CategoryCellProps {
value: number; value: number;
previousValue: number; previousValue: number;
categoryType: "despesa" | "receita"; categoryType: "despesa" | "receita";
isFirstMonth: boolean; isFirstMonth: boolean;
} }
export function CategoryCell({ export function CategoryCell({
value, value,
previousValue, previousValue,
categoryType, categoryType,
isFirstMonth, isFirstMonth,
}: CategoryCellProps) { }: CategoryCellProps) {
const percentageChange = const percentageChange =
!isFirstMonth && previousValue !== 0 !isFirstMonth && previousValue !== 0
? ((value - previousValue) / previousValue) * 100 ? ((value - previousValue) / previousValue) * 100
: null; : null;
const isIncrease = percentageChange !== null && percentageChange > 0; const isIncrease = percentageChange !== null && percentageChange > 0;
const isDecrease = percentageChange !== null && percentageChange < 0; const isDecrease = percentageChange !== null && percentageChange < 0;
return ( return (
<div className="flex flex-col items-end gap-0.5"> <div className="flex flex-col items-end gap-0.5 min-h-9">
<span className="font-medium">{formatCurrency(value)}</span> <span className="font-medium">{formatCurrency(value)}</span>
{!isFirstMonth && percentageChange !== null && ( {!isFirstMonth && percentageChange !== null && (
<div <div
className={cn( className={cn(
"flex items-center gap-0.5 text-xs", "flex items-center gap-0.5 text-xs",
isIncrease && "text-red-600 dark:text-red-400", isIncrease && "text-red-600 dark:text-red-400",
isDecrease && "text-green-600 dark:text-green-400" isDecrease && "text-green-600 dark:text-green-400"
)} )}
> >
{isIncrease && <RiArrowUpLine className="h-3 w-3" />} {isIncrease && <RiArrowUpLine className="h-3 w-3" />}
{isDecrease && <RiArrowDownLine className="h-3 w-3" />} {isDecrease && <RiArrowDownLine className="h-3 w-3" />}
<span>{formatPercentageChange(percentageChange)}</span> <span>{formatPercentageChange(percentageChange)}</span>
</div>
)}
</div> </div>
); )}
</div>
);
} }

View File

@@ -9,13 +9,12 @@ import {
TableHeader, TableHeader,
TableRow, TableRow,
} from "@/components/ui/table"; } from "@/components/ui/table";
import { getIconComponent } from "@/lib/utils/icons";
import { formatPeriodLabel } from "@/lib/relatorios/utils";
import type { CategoryReportData } from "@/lib/relatorios/types"; import type { CategoryReportData } from "@/lib/relatorios/types";
import { CategoryCell } from "./category-cell"; import { formatCurrency, formatPeriodLabel } from "@/lib/relatorios/utils";
import { formatCurrency } from "@/lib/relatorios/utils"; import { getIconComponent } from "@/lib/utils/icons";
import { Card } from "../ui/card";
import DotIcon from "../dot-icon"; import DotIcon from "../dot-icon";
import { Card } from "../ui/card";
import { CategoryCell } from "./category-cell";
interface CategoryReportTableProps { interface CategoryReportTableProps {
data: CategoryReportData; data: CategoryReportData;
@@ -88,16 +87,19 @@ export function CategoryReportTable({ data }: CategoryReportTableProps) {
<TableFooter> <TableFooter>
<TableRow> <TableRow>
<TableCell>Total Geral</TableCell> <TableCell className="min-h-[2.5rem]">Total Geral</TableCell>
{periods.map((period) => { {periods.map((period) => {
const periodTotal = totals.get(period) ?? 0; const periodTotal = totals.get(period) ?? 0;
return ( return (
<TableCell key={period} className="text-right font-semibold"> <TableCell
key={period}
className="text-right font-semibold min-h-8"
>
{formatCurrency(periodTotal)} {formatCurrency(periodTotal)}
</TableCell> </TableCell>
); );
})} })}
<TableCell className="text-right font-semibold"> <TableCell className="text-right font-semibold min-h-8">
{formatCurrency(grandTotal)} {formatCurrency(grandTotal)}
</TableCell> </TableCell>
</TableRow> </TableRow>

View File

@@ -1,17 +1,19 @@
import { import {
RiArchiveLine, RiArchiveLine,
RiArrowLeftRightLine, RiArrowLeftRightLine,
RiBankCardLine, RiBankCard2Line,
RiBankLine, RiBankLine,
RiCalendarEventLine, RiCalendarEventLine,
RiDashboardLine, RiDashboardLine,
RiFileChartLine, RiFileChartLine,
RiFundsLine, RiFundsLine,
RiGroupLine, RiGroupLine,
RiNoCreditCardLine,
RiPriceTag3Line, RiPriceTag3Line,
RiSettingsLine, RiSettingsLine,
RiSparklingLine, RiSparklingLine,
RiTodoLine, RiTodoLine,
RiEyeOffLine,
type RemixiconComponentType, type RemixiconComponentType,
} from "@remixicon/react"; } from "@remixicon/react";
@@ -98,12 +100,28 @@ export function createSidebarNavData(pagadores: PagadorLike[]): SidebarNavData {
{ {
title: "Cartões", title: "Cartões",
url: "/cartoes", url: "/cartoes",
icon: RiBankCardLine, icon: RiBankCard2Line,
items: [
{
title: "Inativos",
url: "/cartoes/inativos",
key: "cartoes-inativos",
icon: RiNoCreditCardLine,
},
],
}, },
{ {
title: "Contas", title: "Contas",
url: "/contas", url: "/contas",
icon: RiBankLine, icon: RiBankLine,
items: [
{
title: "Inativas",
url: "/contas/inativos",
key: "contas-inativos",
icon: RiEyeOffLine,
},
],
}, },
{ {
title: "Orçamentos", title: "Orçamentos",

View File

@@ -21,7 +21,7 @@ import {
import { getAvatarSrc } from "@/lib/pagadores/utils"; import { getAvatarSrc } from "@/lib/pagadores/utils";
import { import {
RiArrowRightSLine, RiArrowRightSLine,
RiStackshareLine, RiUserSharedLine,
type RemixiconComponentType, type RemixiconComponentType,
} from "@remixicon/react"; } from "@remixicon/react";
import Link from "next/link"; import Link from "next/link";
@@ -182,7 +182,7 @@ export function NavMain({ sections }: { sections: NavSection[] }) {
) : null} ) : null}
<span>{subItem.title}</span> <span>{subItem.title}</span>
{subItem.isShared ? ( {subItem.isShared ? (
<RiStackshareLine className="size-3.5 text-muted-foreground" /> <RiUserSharedLine className="size-3.5 text-muted-foreground" />
) : null} ) : null}
</Link> </Link>
</SidebarMenuSubButton> </SidebarMenuSubButton>

View File

@@ -15,7 +15,7 @@ export const CATEGORY_ICON_OPTIONS: CategoryIconOption[] = [
{ label: "Dinheiro", value: "RiMoneyDollarCircleLine" }, { label: "Dinheiro", value: "RiMoneyDollarCircleLine" },
{ label: "Carteira", value: "RiWallet3Line" }, { label: "Carteira", value: "RiWallet3Line" },
{ label: "Carteira 2", value: "RiWalletLine" }, { label: "Carteira 2", value: "RiWalletLine" },
{ label: "Cartão", value: "RiBankCardLine" }, { label: "Cartão", value: "RiBankCard2Line" },
{ label: "Banco", value: "RiBankLine" }, { label: "Banco", value: "RiBankLine" },
{ label: "Moedas", value: "RiHandCoinLine" }, { label: "Moedas", value: "RiHandCoinLine" },
{ label: "Gráfico", value: "RiLineChartLine" }, { label: "Gráfico", value: "RiLineChartLine" },

View File

@@ -78,6 +78,19 @@ export function buildLancamentoInitialState(
? getTodayDateString() ? getTodayDateString()
: ""); : "");
// Calcular o valor correto para importação de parcelados
let amountValue = "";
if (typeof lancamento?.amount === "number") {
let baseAmount = Math.abs(lancamento.amount);
// Se está importando e é parcelado, usar o valor total (parcela * quantidade)
if (isImporting && lancamento.condition === "Parcelado" && lancamento.installmentCount) {
baseAmount = baseAmount * lancamento.installmentCount;
}
amountValue = (Math.round(baseAmount * 100) / 100).toFixed(2);
}
return { return {
purchaseDate, purchaseDate,
period: period:
@@ -87,10 +100,7 @@ export function buildLancamentoInitialState(
name: lancamento?.name ?? "", name: lancamento?.name ?? "",
transactionType: transactionType:
lancamento?.transactionType ?? LANCAMENTO_TRANSACTION_TYPES[0], lancamento?.transactionType ?? LANCAMENTO_TRANSACTION_TYPES[0],
amount: amount: amountValue,
typeof lancamento?.amount === "number"
? (Math.round(Math.abs(lancamento.amount) * 100) / 100).toFixed(2)
: "",
condition: lancamento?.condition ?? LANCAMENTO_CONDITIONS[0], condition: lancamento?.condition ?? LANCAMENTO_CONDITIONS[0],
paymentMethod, paymentMethod,
pagadorId: fallbackPagadorId ?? undefined, pagadorId: fallbackPagadorId ?? undefined,

View File

@@ -15,7 +15,7 @@ import {
} from "@/lib/lancamentos/constants"; } from "@/lib/lancamentos/constants";
import { PAGADOR_ROLE_ADMIN, PAGADOR_ROLE_TERCEIRO } from "@/lib/pagadores/constants"; import { PAGADOR_ROLE_ADMIN, PAGADOR_ROLE_TERCEIRO } from "@/lib/pagadores/constants";
import type { SQL } from "drizzle-orm"; import type { SQL } from "drizzle-orm";
import { eq, ilike, or } from "drizzle-orm"; import { and, eq, ilike, isNotNull, or } from "drizzle-orm";
type PagadorRow = typeof pagadores.$inferSelect; type PagadorRow = typeof pagadores.$inferSelect;
type ContaRow = typeof contas.$inferSelect; type ContaRow = typeof contas.$inferSelect;
@@ -370,8 +370,12 @@ export const buildLancamentoWhere = ({
where.push( where.push(
or( or(
ilike(lancamentos.name, searchPattern), ilike(lancamentos.name, searchPattern),
ilike(lancamentos.note, searchPattern) ilike(lancamentos.note, searchPattern),
) ilike(lancamentos.paymentMethod, searchPattern),
ilike(lancamentos.condition, searchPattern),
and(isNotNull(contas.name), ilike(contas.name, searchPattern)),
and(isNotNull(cartoes.name), ilike(cartoes.name, searchPattern))
)!
); );
} }

View File

@@ -49,14 +49,16 @@ export const getPaymentMethodIcon = (paymentMethod: string): ReactNode => {
<RemixIcons.RiMoneyDollarCircleLine className={ICON_CLASS} aria-hidden /> <RemixIcons.RiMoneyDollarCircleLine className={ICON_CLASS} aria-hidden />
), ),
cartaodecredito: ( cartaodecredito: (
<RemixIcons.RiBankCardLine className={ICON_CLASS} aria-hidden /> <RemixIcons.RiBankCard2Line className={ICON_CLASS} aria-hidden />
), ),
cartaodedebito: ( cartaodedebito: (
<RemixIcons.RiBankCardLine className={ICON_CLASS} aria-hidden /> <RemixIcons.RiBankCard2Line className={ICON_CLASS} aria-hidden />
), ),
debito: <RemixIcons.RiBankCardLine className={ICON_CLASS} aria-hidden />, debito: <RemixIcons.RiBankCard2Line className={ICON_CLASS} aria-hidden />,
prepagovrva: <RemixIcons.RiCouponLine className={ICON_CLASS} aria-hidden />, prepagovrva: <RemixIcons.RiCouponLine className={ICON_CLASS} aria-hidden />,
transferenciabancaria: <RemixIcons.RiExchangeLine className={ICON_CLASS} aria-hidden />, transferenciabancaria: (
<RemixIcons.RiExchangeLine className={ICON_CLASS} aria-hidden />
),
}; };
return registry[key] ?? null; return registry[key] ?? null;

View File

@@ -27,9 +27,9 @@
"docker:rebuild": "docker compose up --build --force-recreate" "docker:rebuild": "docker compose up --build --force-recreate"
}, },
"dependencies": { "dependencies": {
"@ai-sdk/anthropic": "^3.0.2", "@ai-sdk/anthropic": "^3.0.9",
"@ai-sdk/google": "^3.0.2", "@ai-sdk/google": "^3.0.6",
"@ai-sdk/openai": "^3.0.2", "@ai-sdk/openai": "^3.0.7",
"@openrouter/ai-sdk-provider": "^1.5.4", "@openrouter/ai-sdk-provider": "^1.5.4",
"@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-accordion": "^1.2.12",
"@radix-ui/react-alert-dialog": "1.1.15", "@radix-ui/react-alert-dialog": "1.1.15",
@@ -56,7 +56,7 @@
"@tanstack/react-table": "8.21.3", "@tanstack/react-table": "8.21.3",
"@vercel/analytics": "^1.6.1", "@vercel/analytics": "^1.6.1",
"@vercel/speed-insights": "^1.3.1", "@vercel/speed-insights": "^1.3.1",
"ai": "^6.0.7", "ai": "^6.0.27",
"babel-plugin-react-compiler": "^1.0.0", "babel-plugin-react-compiler": "^1.0.0",
"better-auth": "1.4.10", "better-auth": "1.4.10",
"class-variance-authority": "0.7.1", "class-variance-authority": "0.7.1",
@@ -66,7 +66,7 @@
"drizzle-orm": "0.45.1", "drizzle-orm": "0.45.1",
"jspdf": "^4.0.0", "jspdf": "^4.0.0",
"jspdf-autotable": "^5.0.7", "jspdf-autotable": "^5.0.7",
"motion": "^12.23.27", "motion": "^12.25.0",
"next": "16.1.1", "next": "16.1.1",
"next-themes": "0.4.6", "next-themes": "0.4.6",
"pg": "8.16.3", "pg": "8.16.3",
@@ -74,7 +74,7 @@
"react-day-picker": "^9.13.0", "react-day-picker": "^9.13.0",
"react-dom": "19.2.3", "react-dom": "19.2.3",
"recharts": "3.6.0", "recharts": "3.6.0",
"resend": "^6.6.0", "resend": "^6.7.0",
"sonner": "2.0.7", "sonner": "2.0.7",
"tailwind-merge": "3.4.0", "tailwind-merge": "3.4.0",
"vaul": "1.1.2", "vaul": "1.1.2",
@@ -88,7 +88,7 @@
"@types/pg": "^8.16.0", "@types/pg": "^8.16.0",
"@types/react": "19.2.7", "@types/react": "19.2.7",
"@types/react-dom": "19.2.3", "@types/react-dom": "19.2.3",
"baseline-browser-mapping": "^2.9.11", "baseline-browser-mapping": "^2.9.14",
"depcheck": "^1.4.7", "depcheck": "^1.4.7",
"dotenv": "^17.2.3", "dotenv": "^17.2.3",
"drizzle-kit": "0.31.8", "drizzle-kit": "0.31.8",

431
pnpm-lock.yaml generated
View File

@@ -9,17 +9,17 @@ importers:
.: .:
dependencies: dependencies:
'@ai-sdk/anthropic': '@ai-sdk/anthropic':
specifier: ^3.0.2 specifier: ^3.0.9
version: 3.0.2(zod@4.3.5) version: 3.0.9(zod@4.3.5)
'@ai-sdk/google': '@ai-sdk/google':
specifier: ^3.0.2 specifier: ^3.0.6
version: 3.0.2(zod@4.3.5) version: 3.0.6(zod@4.3.5)
'@ai-sdk/openai': '@ai-sdk/openai':
specifier: ^3.0.2 specifier: ^3.0.7
version: 3.0.2(zod@4.3.5) version: 3.0.7(zod@4.3.5)
'@openrouter/ai-sdk-provider': '@openrouter/ai-sdk-provider':
specifier: ^1.5.4 specifier: ^1.5.4
version: 1.5.4(ai@6.0.7(zod@4.3.5))(zod@4.3.5) version: 1.5.4(ai@6.0.27(zod@4.3.5))(zod@4.3.5)
'@radix-ui/react-accordion': '@radix-ui/react-accordion':
specifier: ^1.2.12 specifier: ^1.2.12
version: 1.2.12(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) version: 1.2.12(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
@@ -96,8 +96,8 @@ importers:
specifier: ^1.3.1 specifier: ^1.3.1
version: 1.3.1(next@16.1.1(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3) version: 1.3.1(next@16.1.1(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)
ai: ai:
specifier: ^6.0.7 specifier: ^6.0.27
version: 6.0.7(zod@4.3.5) version: 6.0.27(zod@4.3.5)
babel-plugin-react-compiler: babel-plugin-react-compiler:
specifier: ^1.0.0 specifier: ^1.0.0
version: 1.0.0 version: 1.0.0
@@ -126,8 +126,8 @@ importers:
specifier: ^5.0.7 specifier: ^5.0.7
version: 5.0.7(jspdf@4.0.0) version: 5.0.7(jspdf@4.0.0)
motion: motion:
specifier: ^12.23.27 specifier: ^12.25.0
version: 12.23.27(react-dom@19.2.3(react@19.2.3))(react@19.2.3) version: 12.25.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
next: next:
specifier: 16.1.1 specifier: 16.1.1
version: 16.1.1(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) version: 16.1.1(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
@@ -150,8 +150,8 @@ importers:
specifier: 3.6.0 specifier: 3.6.0
version: 3.6.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react-is@16.13.1)(react@19.2.3)(redux@5.0.1) version: 3.6.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react-is@16.13.1)(react@19.2.3)(redux@5.0.1)
resend: resend:
specifier: ^6.6.0 specifier: ^6.7.0
version: 6.6.0 version: 6.7.0
sonner: sonner:
specifier: 2.0.7 specifier: 2.0.7
version: 2.0.7(react-dom@19.2.3(react@19.2.3))(react@19.2.3) version: 2.0.7(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
@@ -187,8 +187,8 @@ importers:
specifier: 19.2.3 specifier: 19.2.3
version: 19.2.3(@types/react@19.2.7) version: 19.2.3(@types/react@19.2.7)
baseline-browser-mapping: baseline-browser-mapping:
specifier: ^2.9.11 specifier: ^2.9.14
version: 2.9.11 version: 2.9.14
depcheck: depcheck:
specifier: ^1.4.7 specifier: ^1.4.7
version: 1.4.7 version: 1.4.7
@@ -203,7 +203,7 @@ importers:
version: 9.39.2(jiti@2.6.1) version: 9.39.2(jiti@2.6.1)
eslint-config-next: eslint-config-next:
specifier: 16.1.1 specifier: 16.1.1
version: 16.1.1(@typescript-eslint/parser@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) version: 16.1.1(@typescript-eslint/parser@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
tailwindcss: tailwindcss:
specifier: 4.1.18 specifier: 4.1.18
version: 4.1.18 version: 4.1.18
@@ -216,38 +216,38 @@ importers:
packages: packages:
'@ai-sdk/anthropic@3.0.2': '@ai-sdk/anthropic@3.0.9':
resolution: {integrity: sha512-D6iSsrOYryBSPsFtOiEDv54jnjVCU/flIuXdjuRY7LdikB0KGjpazN8Dt4ONXzL+ux69ds2nzFNKke/w/fgLAA==} resolution: {integrity: sha512-QBD4qDnwIHd+N5PpjxXOaWJig1aRB43J0PM5ZUe6Yyl9Qq2bUmraQjvNznkuFKy+hMFDgj0AvgGogTiO5TC+qA==}
engines: {node: '>=18'} engines: {node: '>=18'}
peerDependencies: peerDependencies:
zod: ^3.25.76 || ^4.1.8 zod: ^3.25.76 || ^4.1.8
'@ai-sdk/gateway@3.0.6': '@ai-sdk/gateway@3.0.11':
resolution: {integrity: sha512-oEpwjM0PIaSUErtZI8Ag+gQ+ZelysRWA96N5ahvOc5e9d7QkKJWF0POWx0nI1qBxvmUSw7ca0sLTVw+J5yn7Tg==} resolution: {integrity: sha512-gLrgNXA95wdo/zAlA0miX/SJEYKSYCHg+e0Y/uQeABLScZAMjPw3jWaeANta/Db1T4xfi8cBvY3nnV8Pa27z+w==}
engines: {node: '>=18'} engines: {node: '>=18'}
peerDependencies: peerDependencies:
zod: ^3.25.76 || ^4.1.8 zod: ^3.25.76 || ^4.1.8
'@ai-sdk/google@3.0.2': '@ai-sdk/google@3.0.6':
resolution: {integrity: sha512-KyV4AR8fBKVCABfav3zGn/PY7cMDMt9m7yYhH+FJ7jLfBrEVdjT4sM0ojPFRHYUelXHl42oOAgpy3GWkeG6vtw==} resolution: {integrity: sha512-Nr7E+ouWd/bKO9SFlgLnJJ1+fiGHC07KAeFr08faT+lvkECWlxVox3aL0dec8uCgBDUghYbq7f4S5teUrCc+QQ==}
engines: {node: '>=18'} engines: {node: '>=18'}
peerDependencies: peerDependencies:
zod: ^3.25.76 || ^4.1.8 zod: ^3.25.76 || ^4.1.8
'@ai-sdk/openai@3.0.2': '@ai-sdk/openai@3.0.7':
resolution: {integrity: sha512-GONwavgSWtcWO+t9+GpGK8l7nIYh+zNtCL/NYDSeHxHiw6ksQS9XMRWrZyE5NpJ0EXNxSAWCHIDmb1WvTqhq9Q==} resolution: {integrity: sha512-CBoYn1U59Lop8yBL9KuVjHCKc/B06q9Qo0SasRwHoyMEq+X4I8LQZu3a8Ck1jwwcZTTxfyiExB70LtIRSynBDA==}
engines: {node: '>=18'} engines: {node: '>=18'}
peerDependencies: peerDependencies:
zod: ^3.25.76 || ^4.1.8 zod: ^3.25.76 || ^4.1.8
'@ai-sdk/provider-utils@4.0.2': '@ai-sdk/provider-utils@4.0.4':
resolution: {integrity: sha512-KaykkuRBdF/ffpI5bwpL4aSCmO/99p8/ci+VeHwJO8tmvXtiVAb99QeyvvvXmL61e9Zrvv4GBGoajW19xdjkVQ==} resolution: {integrity: sha512-VxhX0B/dWGbpNHxrKCWUAJKXIXV015J4e7qYjdIU9lLWeptk0KMLGcqkB4wFxff5Njqur8dt8wRi1MN9lZtDqg==}
engines: {node: '>=18'} engines: {node: '>=18'}
peerDependencies: peerDependencies:
zod: ^3.25.76 || ^4.1.8 zod: ^3.25.76 || ^4.1.8
'@ai-sdk/provider@3.0.1': '@ai-sdk/provider@3.0.2':
resolution: {integrity: sha512-2lR4w7mr9XrydzxBSjir4N6YMGdXD+Np1Sh0RXABh7tWdNFFwIeRI1Q+SaYZMbfL8Pg8RRLcrxQm51yxTLhokg==} resolution: {integrity: sha512-HrEmNt/BH/hkQ7zpi2o6N3k1ZR1QTb7z85WYhYygiTxOQuaml4CMtHCWRbric5WPU+RNsYI7r1EpyVQMKO1pYw==}
engines: {node: '>=18'} engines: {node: '>=18'}
'@alloc/quick-lru@5.2.0': '@alloc/quick-lru@5.2.0':
@@ -352,11 +352,11 @@ packages:
'@drizzle-team/brocli@0.10.2': '@drizzle-team/brocli@0.10.2':
resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==} resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==}
'@emnapi/core@1.7.1': '@emnapi/core@1.8.1':
resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==} resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==}
'@emnapi/runtime@1.7.1': '@emnapi/runtime@1.8.1':
resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==} resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==}
'@emnapi/wasi-threads@1.1.0': '@emnapi/wasi-threads@1.1.0':
resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==}
@@ -813,8 +813,8 @@ packages:
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@eslint-community/eslint-utils@4.9.0': '@eslint-community/eslint-utils@4.9.1':
resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies: peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
@@ -1880,9 +1880,6 @@ packages:
'@types/minimatch@3.0.5': '@types/minimatch@3.0.5':
resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==}
'@types/node@22.19.3':
resolution: {integrity: sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==}
'@types/node@25.0.3': '@types/node@25.0.3':
resolution: {integrity: sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==} resolution: {integrity: sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==}
@@ -1912,63 +1909,63 @@ packages:
'@types/use-sync-external-store@0.0.6': '@types/use-sync-external-store@0.0.6':
resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==} resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==}
'@typescript-eslint/eslint-plugin@8.50.1': '@typescript-eslint/eslint-plugin@8.52.0':
resolution: {integrity: sha512-PKhLGDq3JAg0Jk/aK890knnqduuI/Qj+udH7wCf0217IGi4gt+acgCyPVe79qoT+qKUvHMDQkwJeKW9fwl8Cyw==} resolution: {integrity: sha512-okqtOgqu2qmZJ5iN4TWlgfF171dZmx2FzdOv2K/ixL2LZWDStL8+JgQerI2sa8eAEfoydG9+0V96m7V+P8yE1Q==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
'@typescript-eslint/parser': ^8.50.1 '@typescript-eslint/parser': ^8.52.0
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0' typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/parser@8.50.1': '@typescript-eslint/parser@8.52.0':
resolution: {integrity: sha512-hM5faZwg7aVNa819m/5r7D0h0c9yC4DUlWAOvHAtISdFTc8xB86VmX5Xqabrama3wIPJ/q9RbGS1worb6JfnMg==} resolution: {integrity: sha512-iIACsx8pxRnguSYhHiMn2PvhvfpopO9FXHyn1mG5txZIsAaB6F0KwbFnUQN3KCiG3Jcuad/Cao2FAs1Wp7vAyg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0' typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/project-service@8.50.1': '@typescript-eslint/project-service@8.52.0':
resolution: {integrity: sha512-E1ur1MCVf+YiP89+o4Les/oBAVzmSbeRB0MQLfSlYtbWU17HPxZ6Bhs5iYmKZRALvEuBoXIZMOIRRc/P++Ortg==} resolution: {integrity: sha512-xD0MfdSdEmeFa3OmVqonHi+Cciab96ls1UhIF/qX/O/gPu5KXD0bY9lu33jj04fjzrXHcuvjBcBC+D3SNSadaw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
typescript: '>=4.8.4 <6.0.0' typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/scope-manager@8.50.1': '@typescript-eslint/scope-manager@8.52.0':
resolution: {integrity: sha512-mfRx06Myt3T4vuoHaKi8ZWNTPdzKPNBhiblze5N50//TSHOAQQevl/aolqA/BcqqbJ88GUnLqjjcBc8EWdBcVw==} resolution: {integrity: sha512-ixxqmmCcc1Nf8S0mS0TkJ/3LKcC8mruYJPOU6Ia2F/zUUR4pApW7LzrpU3JmtePbRUTes9bEqRc1Gg4iyRnDzA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/tsconfig-utils@8.50.1': '@typescript-eslint/tsconfig-utils@8.52.0':
resolution: {integrity: sha512-ooHmotT/lCWLXi55G4mvaUF60aJa012QzvLK0Y+Mp4WdSt17QhMhWOaBWeGTFVkb2gDgBe19Cxy1elPXylslDw==} resolution: {integrity: sha512-jl+8fzr/SdzdxWJznq5nvoI7qn2tNYV/ZBAEcaFMVXf+K6jmXvAFrgo/+5rxgnL152f//pDEAYAhhBAZGrVfwg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
typescript: '>=4.8.4 <6.0.0' typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/type-utils@8.50.1': '@typescript-eslint/type-utils@8.52.0':
resolution: {integrity: sha512-7J3bf022QZE42tYMO6SL+6lTPKFk/WphhRPe9Tw/el+cEwzLz1Jjz2PX3GtGQVxooLDKeMVmMt7fWpYRdG5Etg==} resolution: {integrity: sha512-JD3wKBRWglYRQkAtsyGz1AewDu3mTc7NtRjR/ceTyGoPqmdS5oCdx/oZMWD5Zuqmo6/MpsYs0wp6axNt88/2EQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0' typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/types@8.50.1': '@typescript-eslint/types@8.52.0':
resolution: {integrity: sha512-v5lFIS2feTkNyMhd7AucE/9j/4V9v5iIbpVRncjk/K0sQ6Sb+Np9fgYS/63n6nwqahHQvbmujeBL7mp07Q9mlA==} resolution: {integrity: sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/typescript-estree@8.50.1': '@typescript-eslint/typescript-estree@8.52.0':
resolution: {integrity: sha512-woHPdW+0gj53aM+cxchymJCrh0cyS7BTIdcDxWUNsclr9VDkOSbqC13juHzxOmQ22dDkMZEpZB+3X1WpUvzgVQ==} resolution: {integrity: sha512-XP3LClsCc0FsTK5/frGjolyADTh3QmsLp6nKd476xNI9CsSsLnmn4f0jrzNoAulmxlmNIpeXuHYeEQv61Q6qeQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
typescript: '>=4.8.4 <6.0.0' typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/utils@8.50.1': '@typescript-eslint/utils@8.52.0':
resolution: {integrity: sha512-lCLp8H1T9T7gPbEuJSnHwnSuO9mDf8mfK/Nion5mZmiEaQD9sWf9W4dfeFqRyqRjF06/kBuTmAqcs9sewM2NbQ==} resolution: {integrity: sha512-wYndVMWkweqHpEpwPhwqE2lnD2DxC6WVLupU/DOt/0/v+/+iQbbzO3jOHjmBMnhu0DgLULvOaU4h4pwHYi2oRQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0' typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/visitor-keys@8.50.1': '@typescript-eslint/visitor-keys@8.52.0':
resolution: {integrity: sha512-IrDKrw7pCRUR94zeuCSUWQ+w8JEf5ZX5jl/e6AHGSLi1/zIr0lgutfn/7JpfCey+urpgQEdrZVYzCaVVKiTwhQ==} resolution: {integrity: sha512-ink3/Zofus34nmBsPjow63FP5M7IGff0RKAgqR6+CFpdk22M7aLwC9gOcLGYqr7MczLPzZVERW9hRog3O4n1sQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@unrs/resolver-binding-android-arm-eabi@1.11.1': '@unrs/resolver-binding-android-arm-eabi@1.11.1':
@@ -2092,8 +2089,8 @@ packages:
vue-router: vue-router:
optional: true optional: true
'@vercel/oidc@3.0.5': '@vercel/oidc@3.1.0':
resolution: {integrity: sha512-fnYhv671l+eTTp48gB4zEsTW/YtRgRPnkI2nT7x6qw5rkI1Lq2hTmQIpHPgyThI0znLK+vX2n9XxKdXZ7BUbbw==} resolution: {integrity: sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w==}
engines: {node: '>= 20'} engines: {node: '>= 20'}
'@vercel/speed-insights@1.3.1': '@vercel/speed-insights@1.3.1':
@@ -2148,8 +2145,8 @@ packages:
resolution: {integrity: sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==} resolution: {integrity: sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==}
engines: {node: '>=0.8'} engines: {node: '>=0.8'}
ai@6.0.7: ai@6.0.27:
resolution: {integrity: sha512-kLzSXHdW6cAcb2mFSIfkbfzxYqqjrUnyhrB1sg855qlC+6XkLI8hmwFE8f/4SnjmtcTDOnkIaVjWoO5i5Ir0bw==} resolution: {integrity: sha512-a4ToMt5+4xOzHuYdoTy2GQXuNa2/Tpuhxfs5QESHtEV/Vf2HAzSwmTwikrIs8CDKPuMWV1I9YqAvaN5xexMCiQ==}
engines: {node: '>=18'} engines: {node: '>=18'}
peerDependencies: peerDependencies:
zod: ^3.25.76 || ^4.1.8 zod: ^3.25.76 || ^4.1.8
@@ -2234,8 +2231,8 @@ packages:
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
axe-core@4.11.0: axe-core@4.11.1:
resolution: {integrity: sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ==} resolution: {integrity: sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A==}
engines: {node: '>=4'} engines: {node: '>=4'}
axobject-query@4.1.0: axobject-query@4.1.0:
@@ -2252,8 +2249,8 @@ packages:
resolution: {integrity: sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==} resolution: {integrity: sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==}
engines: {node: '>= 0.6.0'} engines: {node: '>= 0.6.0'}
baseline-browser-mapping@2.9.11: baseline-browser-mapping@2.9.14:
resolution: {integrity: sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==} resolution: {integrity: sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg==}
hasBin: true hasBin: true
better-auth@1.4.10: better-auth@1.4.10:
@@ -2364,8 +2361,8 @@ packages:
resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
engines: {node: '>=10'} engines: {node: '>=10'}
caniuse-lite@1.0.30001761: caniuse-lite@1.0.30001763:
resolution: {integrity: sha512-JF9ptu1vP2coz98+5051jZ4PwQgd2ni8A+gYSN7EA7dPKIMf0pDlSUxhdmVOaV3/fYK5uWBkgSXJaRLr4+3A6g==} resolution: {integrity: sha512-mh/dGtq56uN98LlNX9qdbKnzINhX0QzhiWBFEkFfsFO4QyCvL8YegrJAazCwXIeqkIob8BlZPGM3xdnY+sgmvQ==}
canvg@3.0.11: canvg@3.0.11:
resolution: {integrity: sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==} resolution: {integrity: sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==}
@@ -2721,9 +2718,6 @@ packages:
es-toolkit@1.43.0: es-toolkit@1.43.0:
resolution: {integrity: sha512-SKCT8AsWvYzBBuUqMk4NPwFlSdqLpJwmy6AP322ERn8W2YLIB6JBXnwMI2Qsh2gfphT3q7EKAxKb23cvFHFwKA==} resolution: {integrity: sha512-SKCT8AsWvYzBBuUqMk4NPwFlSdqLpJwmy6AP322ERn8W2YLIB6JBXnwMI2Qsh2gfphT3q7EKAxKb23cvFHFwKA==}
es6-promise@4.2.8:
resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==}
esbuild-register@3.6.0: esbuild-register@3.6.0:
resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==} resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==}
peerDependencies: peerDependencies:
@@ -2857,8 +2851,8 @@ packages:
engines: {node: '>=4'} engines: {node: '>=4'}
hasBin: true hasBin: true
esquery@1.6.0: esquery@1.7.0:
resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==}
engines: {node: '>=0.10'} engines: {node: '>=0.10'}
esrecurse@4.3.0: esrecurse@4.3.0:
@@ -2952,8 +2946,8 @@ packages:
resolution: {integrity: sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==} resolution: {integrity: sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==}
engines: {node: '>=0.8'} engines: {node: '>=0.8'}
framer-motion@12.23.27: framer-motion@12.25.0:
resolution: {integrity: sha512-EAcX8FS8jzZ4tSKpj+1GhwbVY+r1gfamPFwXZAsioPqu/ffRwU2otkKg6GEDCR41FVJv3RoBN7Aqep6drL9Itg==} resolution: {integrity: sha512-mlWqd0rApIjeyhTCSNCqPYsUAEhkcUukZxH3ke6KbstBRPcxhEpuIjmiUQvB+1E9xkEm5SpNHBgHCapH/QHTWg==}
peerDependencies: peerDependencies:
'@emotion/is-prop-valid': '*' '@emotion/is-prop-valid': '*'
react: ^18.0.0 || ^19.0.0 react: ^18.0.0 || ^19.0.0
@@ -3099,8 +3093,8 @@ packages:
immer@10.2.0: immer@10.2.0:
resolution: {integrity: sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==} resolution: {integrity: sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==}
immer@11.1.0: immer@11.1.3:
resolution: {integrity: sha512-dlzb07f5LDY+tzs+iLCSXV2yuhaYfezqyZQc+n6baLECWkOMEWxkECAOnXL0ba7lsA25fM9b2jtzpu/uxo1a7g==} resolution: {integrity: sha512-6jQTc5z0KJFtr1UgFpIL3N9XSC3saRaI9PwWtzM2pSqkNGtiNkYY2OSwkOGDK2XcTRcLb1pi/aNkKZz0nxVH4Q==}
import-fresh@3.3.1: import-fresh@3.3.1:
resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
@@ -3444,14 +3438,14 @@ packages:
minimist@1.2.8: minimist@1.2.8:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
motion-dom@12.23.23: motion-dom@12.24.11:
resolution: {integrity: sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA==} resolution: {integrity: sha512-DlWOmsXMJrV8lzZyd+LKjG2CXULUs++bkq8GZ2Sr0R0RRhs30K2wtY+LKiTjhmJU3W61HK+rB0GLz6XmPvTA1A==}
motion-utils@12.23.6: motion-utils@12.24.10:
resolution: {integrity: sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==} resolution: {integrity: sha512-x5TFgkCIP4pPsRLpKoI86jv/q8t8FQOiM/0E8QKBzfMozWHfkKap2gA1hOki+B5g3IsBNpxbUnfOum1+dgvYww==}
motion@12.23.27: motion@12.25.0:
resolution: {integrity: sha512-EDb0hAE6jNX8BHpmQK1GBf9Eizx9bg/Tz2KEAJBOGEnIJp8W77QweRpVb05U8R0L0/LXndHmS1Xv3fwXJh/kcQ==} resolution: {integrity: sha512-jBFohEYklpZ+TL64zv03sHdqr1Tsc8/yDy7u68hVzi7hTJYtv53AduchqCiY3aWi4vY1hweS8DWtgCuckusYdQ==}
peerDependencies: peerDependencies:
'@emotion/is-prop-valid': '*' '@emotion/is-prop-valid': '*'
react: ^18.0.0 || ^19.0.0 react: ^18.0.0 || ^19.0.0
@@ -3686,9 +3680,6 @@ packages:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'} engines: {node: '>=6'}
querystringify@2.2.0:
resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==}
queue-microtask@1.2.3: queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
@@ -3793,14 +3784,11 @@ packages:
require-package-name@2.0.1: require-package-name@2.0.1:
resolution: {integrity: sha512-uuoJ1hU/k6M0779t3VMVIYpb2VMJk05cehCaABFhXaibcbvfgR8wKiozLjVFSzJPmQMRqIcO0HMyTFqfV09V6Q==} resolution: {integrity: sha512-uuoJ1hU/k6M0779t3VMVIYpb2VMJk05cehCaABFhXaibcbvfgR8wKiozLjVFSzJPmQMRqIcO0HMyTFqfV09V6Q==}
requires-port@1.0.0:
resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==}
reselect@5.1.1: reselect@5.1.1:
resolution: {integrity: sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==} resolution: {integrity: sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==}
resend@6.6.0: resend@6.7.0:
resolution: {integrity: sha512-d1WoOqSxj5x76JtQMrieNAG1kZkh4NU4f+Je1yq4++JsDpLddhEwnJlNfvkCzvUuZy9ZquWmMMAm2mENd2JvRw==} resolution: {integrity: sha512-2ZV0NDZsh4Gh+Nd1hvluZIitmGJ59O4+OxMufymG6Y8uz1Jgt2uS1seSENnkIUlmwg7/dwmfIJC9rAufByz7wA==}
engines: {node: '>=20'} engines: {node: '>=20'}
peerDependencies: peerDependencies:
'@react-email/render': '*' '@react-email/render': '*'
@@ -3951,6 +3939,9 @@ packages:
resolution: {integrity: sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==} resolution: {integrity: sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==}
engines: {node: '>=0.1.14'} engines: {node: '>=0.1.14'}
standardwebhooks@1.0.0:
resolution: {integrity: sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg==}
stop-iteration-iterator@1.1.0: stop-iteration-iterator@1.1.0:
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@@ -4019,8 +4010,8 @@ packages:
resolution: {integrity: sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==} resolution: {integrity: sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==}
engines: {node: '>=12.0.0'} engines: {node: '>=12.0.0'}
svix@1.76.1: svix@1.84.1:
resolution: {integrity: sha512-CRuDWBTgYfDnBLRaZdKp9VuoPcNUq9An14c/k+4YJ15Qc5Grvf66vp0jvTltd4t7OIRj+8lM1DAgvSgvf7hdLw==} resolution: {integrity: sha512-K8DPPSZaW/XqXiz1kEyzSHYgmGLnhB43nQCMeKjWGCUpLIpAMMM8kx3rVVOSm6Bo6EHyK1RQLPT4R06skM/MlQ==}
tailwind-merge@3.4.0: tailwind-merge@3.4.0:
resolution: {integrity: sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==} resolution: {integrity: sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==}
@@ -4046,8 +4037,8 @@ packages:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'} engines: {node: '>=8.0'}
ts-api-utils@2.1.0: ts-api-utils@2.4.0:
resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==}
engines: {node: '>=18.12'} engines: {node: '>=18.12'}
peerDependencies: peerDependencies:
typescript: '>=4.8.4' typescript: '>=4.8.4'
@@ -4083,8 +4074,8 @@ packages:
resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
typescript-eslint@8.50.1: typescript-eslint@8.52.0:
resolution: {integrity: sha512-ytTHO+SoYSbhAH9CrYnMhiLx8To6PSSvqnvXyPUgPETCvB6eBKmTI9w6XMPS3HsBRGkwTVBX+urA8dYQx6bHfQ==} resolution: {integrity: sha512-atlQQJ2YkO4pfTVQmQ+wvYQwexPDOIgo+RaVcD7gHgzy/IQA+XTyuxNM9M9TVXvttkF7koBHmcwisKdOAf2EcA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
@@ -4099,9 +4090,6 @@ packages:
resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
undici-types@7.16.0: undici-types@7.16.0:
resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
@@ -4117,9 +4105,6 @@ packages:
uri-js@4.4.1: uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
url-parse@1.5.10:
resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==}
use-callback-ref@1.3.3: use-callback-ref@1.3.3:
resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==}
engines: {node: '>=10'} engines: {node: '>=10'}
@@ -4245,39 +4230,39 @@ packages:
snapshots: snapshots:
'@ai-sdk/anthropic@3.0.2(zod@4.3.5)': '@ai-sdk/anthropic@3.0.9(zod@4.3.5)':
dependencies: dependencies:
'@ai-sdk/provider': 3.0.1 '@ai-sdk/provider': 3.0.2
'@ai-sdk/provider-utils': 4.0.2(zod@4.3.5) '@ai-sdk/provider-utils': 4.0.4(zod@4.3.5)
zod: 4.3.5 zod: 4.3.5
'@ai-sdk/gateway@3.0.6(zod@4.3.5)': '@ai-sdk/gateway@3.0.11(zod@4.3.5)':
dependencies: dependencies:
'@ai-sdk/provider': 3.0.1 '@ai-sdk/provider': 3.0.2
'@ai-sdk/provider-utils': 4.0.2(zod@4.3.5) '@ai-sdk/provider-utils': 4.0.4(zod@4.3.5)
'@vercel/oidc': 3.0.5 '@vercel/oidc': 3.1.0
zod: 4.3.5 zod: 4.3.5
'@ai-sdk/google@3.0.2(zod@4.3.5)': '@ai-sdk/google@3.0.6(zod@4.3.5)':
dependencies: dependencies:
'@ai-sdk/provider': 3.0.1 '@ai-sdk/provider': 3.0.2
'@ai-sdk/provider-utils': 4.0.2(zod@4.3.5) '@ai-sdk/provider-utils': 4.0.4(zod@4.3.5)
zod: 4.3.5 zod: 4.3.5
'@ai-sdk/openai@3.0.2(zod@4.3.5)': '@ai-sdk/openai@3.0.7(zod@4.3.5)':
dependencies: dependencies:
'@ai-sdk/provider': 3.0.1 '@ai-sdk/provider': 3.0.2
'@ai-sdk/provider-utils': 4.0.2(zod@4.3.5) '@ai-sdk/provider-utils': 4.0.4(zod@4.3.5)
zod: 4.3.5 zod: 4.3.5
'@ai-sdk/provider-utils@4.0.2(zod@4.3.5)': '@ai-sdk/provider-utils@4.0.4(zod@4.3.5)':
dependencies: dependencies:
'@ai-sdk/provider': 3.0.1 '@ai-sdk/provider': 3.0.2
'@standard-schema/spec': 1.1.0 '@standard-schema/spec': 1.1.0
eventsource-parser: 3.0.6 eventsource-parser: 3.0.6
zod: 4.3.5 zod: 4.3.5
'@ai-sdk/provider@3.0.1': '@ai-sdk/provider@3.0.2':
dependencies: dependencies:
json-schema: 0.4.0 json-schema: 0.4.0
@@ -4410,13 +4395,13 @@ snapshots:
'@drizzle-team/brocli@0.10.2': {} '@drizzle-team/brocli@0.10.2': {}
'@emnapi/core@1.7.1': '@emnapi/core@1.8.1':
dependencies: dependencies:
'@emnapi/wasi-threads': 1.1.0 '@emnapi/wasi-threads': 1.1.0
tslib: 2.8.1 tslib: 2.8.1
optional: true optional: true
'@emnapi/runtime@1.7.1': '@emnapi/runtime@1.8.1':
dependencies: dependencies:
tslib: 2.8.1 tslib: 2.8.1
optional: true optional: true
@@ -4658,7 +4643,7 @@ snapshots:
'@esbuild/win32-x64@0.27.2': '@esbuild/win32-x64@0.27.2':
optional: true optional: true
'@eslint-community/eslint-utils@4.9.0(eslint@9.39.2(jiti@2.6.1))': '@eslint-community/eslint-utils@4.9.1(eslint@9.39.2(jiti@2.6.1))':
dependencies: dependencies:
eslint: 9.39.2(jiti@2.6.1) eslint: 9.39.2(jiti@2.6.1)
eslint-visitor-keys: 3.4.3 eslint-visitor-keys: 3.4.3
@@ -4817,7 +4802,7 @@ snapshots:
'@img/sharp-wasm32@0.34.5': '@img/sharp-wasm32@0.34.5':
dependencies: dependencies:
'@emnapi/runtime': 1.7.1 '@emnapi/runtime': 1.8.1
optional: true optional: true
'@img/sharp-win32-arm64@0.34.5': '@img/sharp-win32-arm64@0.34.5':
@@ -4850,8 +4835,8 @@ snapshots:
'@napi-rs/wasm-runtime@0.2.12': '@napi-rs/wasm-runtime@0.2.12':
dependencies: dependencies:
'@emnapi/core': 1.7.1 '@emnapi/core': 1.8.1
'@emnapi/runtime': 1.7.1 '@emnapi/runtime': 1.8.1
'@tybys/wasm-util': 0.10.1 '@tybys/wasm-util': 0.10.1
optional: true optional: true
@@ -4903,10 +4888,10 @@ snapshots:
'@nolyfill/is-core-module@1.0.39': {} '@nolyfill/is-core-module@1.0.39': {}
'@openrouter/ai-sdk-provider@1.5.4(ai@6.0.7(zod@4.3.5))(zod@4.3.5)': '@openrouter/ai-sdk-provider@1.5.4(ai@6.0.27(zod@4.3.5))(zod@4.3.5)':
dependencies: dependencies:
'@openrouter/sdk': 0.1.27 '@openrouter/sdk': 0.1.27
ai: 6.0.7(zod@4.3.5) ai: 6.0.27(zod@4.3.5)
zod: 4.3.5 zod: 4.3.5
'@openrouter/sdk@0.1.27': '@openrouter/sdk@0.1.27':
@@ -5512,7 +5497,7 @@ snapshots:
dependencies: dependencies:
'@standard-schema/spec': 1.1.0 '@standard-schema/spec': 1.1.0
'@standard-schema/utils': 0.3.0 '@standard-schema/utils': 0.3.0
immer: 11.1.0 immer: 11.1.3
redux: 5.0.1 redux: 5.0.1
redux-thunk: 3.1.0(redux@5.0.1) redux-thunk: 3.1.0(redux@5.0.1)
reselect: 5.1.1 reselect: 5.1.1
@@ -5650,10 +5635,6 @@ snapshots:
'@types/minimatch@3.0.5': {} '@types/minimatch@3.0.5': {}
'@types/node@22.19.3':
dependencies:
undici-types: 6.21.0
'@types/node@25.0.3': '@types/node@25.0.3':
dependencies: dependencies:
undici-types: 7.16.0 undici-types: 7.16.0
@@ -5684,95 +5665,95 @@ snapshots:
'@types/use-sync-external-store@0.0.6': {} '@types/use-sync-external-store@0.0.6': {}
'@typescript-eslint/eslint-plugin@8.50.1(@typescript-eslint/parser@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': '@typescript-eslint/eslint-plugin@8.52.0(@typescript-eslint/parser@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
dependencies: dependencies:
'@eslint-community/regexpp': 4.12.2 '@eslint-community/regexpp': 4.12.2
'@typescript-eslint/parser': 8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/parser': 8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/scope-manager': 8.50.1 '@typescript-eslint/scope-manager': 8.52.0
'@typescript-eslint/type-utils': 8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/type-utils': 8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/utils': 8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/utils': 8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.50.1 '@typescript-eslint/visitor-keys': 8.52.0
eslint: 9.39.2(jiti@2.6.1) eslint: 9.39.2(jiti@2.6.1)
ignore: 7.0.5 ignore: 7.0.5
natural-compare: 1.4.0 natural-compare: 1.4.0
ts-api-utils: 2.1.0(typescript@5.9.3) ts-api-utils: 2.4.0(typescript@5.9.3)
typescript: 5.9.3 typescript: 5.9.3
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/parser@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': '@typescript-eslint/parser@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
dependencies: dependencies:
'@typescript-eslint/scope-manager': 8.50.1 '@typescript-eslint/scope-manager': 8.52.0
'@typescript-eslint/types': 8.50.1 '@typescript-eslint/types': 8.52.0
'@typescript-eslint/typescript-estree': 8.50.1(typescript@5.9.3) '@typescript-eslint/typescript-estree': 8.52.0(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.50.1 '@typescript-eslint/visitor-keys': 8.52.0
debug: 4.4.3 debug: 4.4.3
eslint: 9.39.2(jiti@2.6.1) eslint: 9.39.2(jiti@2.6.1)
typescript: 5.9.3 typescript: 5.9.3
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/project-service@8.50.1(typescript@5.9.3)': '@typescript-eslint/project-service@8.52.0(typescript@5.9.3)':
dependencies: dependencies:
'@typescript-eslint/tsconfig-utils': 8.50.1(typescript@5.9.3) '@typescript-eslint/tsconfig-utils': 8.52.0(typescript@5.9.3)
'@typescript-eslint/types': 8.50.1 '@typescript-eslint/types': 8.52.0
debug: 4.4.3 debug: 4.4.3
typescript: 5.9.3 typescript: 5.9.3
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/scope-manager@8.50.1': '@typescript-eslint/scope-manager@8.52.0':
dependencies: dependencies:
'@typescript-eslint/types': 8.50.1 '@typescript-eslint/types': 8.52.0
'@typescript-eslint/visitor-keys': 8.50.1 '@typescript-eslint/visitor-keys': 8.52.0
'@typescript-eslint/tsconfig-utils@8.50.1(typescript@5.9.3)': '@typescript-eslint/tsconfig-utils@8.52.0(typescript@5.9.3)':
dependencies: dependencies:
typescript: 5.9.3 typescript: 5.9.3
'@typescript-eslint/type-utils@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': '@typescript-eslint/type-utils@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
dependencies: dependencies:
'@typescript-eslint/types': 8.50.1 '@typescript-eslint/types': 8.52.0
'@typescript-eslint/typescript-estree': 8.50.1(typescript@5.9.3) '@typescript-eslint/typescript-estree': 8.52.0(typescript@5.9.3)
'@typescript-eslint/utils': 8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/utils': 8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
debug: 4.4.3 debug: 4.4.3
eslint: 9.39.2(jiti@2.6.1) eslint: 9.39.2(jiti@2.6.1)
ts-api-utils: 2.1.0(typescript@5.9.3) ts-api-utils: 2.4.0(typescript@5.9.3)
typescript: 5.9.3 typescript: 5.9.3
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/types@8.50.1': {} '@typescript-eslint/types@8.52.0': {}
'@typescript-eslint/typescript-estree@8.50.1(typescript@5.9.3)': '@typescript-eslint/typescript-estree@8.52.0(typescript@5.9.3)':
dependencies: dependencies:
'@typescript-eslint/project-service': 8.50.1(typescript@5.9.3) '@typescript-eslint/project-service': 8.52.0(typescript@5.9.3)
'@typescript-eslint/tsconfig-utils': 8.50.1(typescript@5.9.3) '@typescript-eslint/tsconfig-utils': 8.52.0(typescript@5.9.3)
'@typescript-eslint/types': 8.50.1 '@typescript-eslint/types': 8.52.0
'@typescript-eslint/visitor-keys': 8.50.1 '@typescript-eslint/visitor-keys': 8.52.0
debug: 4.4.3 debug: 4.4.3
minimatch: 9.0.5 minimatch: 9.0.5
semver: 7.7.3 semver: 7.7.3
tinyglobby: 0.2.15 tinyglobby: 0.2.15
ts-api-utils: 2.1.0(typescript@5.9.3) ts-api-utils: 2.4.0(typescript@5.9.3)
typescript: 5.9.3 typescript: 5.9.3
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/utils@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': '@typescript-eslint/utils@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
dependencies: dependencies:
'@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2(jiti@2.6.1)) '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1))
'@typescript-eslint/scope-manager': 8.50.1 '@typescript-eslint/scope-manager': 8.52.0
'@typescript-eslint/types': 8.50.1 '@typescript-eslint/types': 8.52.0
'@typescript-eslint/typescript-estree': 8.50.1(typescript@5.9.3) '@typescript-eslint/typescript-estree': 8.52.0(typescript@5.9.3)
eslint: 9.39.2(jiti@2.6.1) eslint: 9.39.2(jiti@2.6.1)
typescript: 5.9.3 typescript: 5.9.3
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/visitor-keys@8.50.1': '@typescript-eslint/visitor-keys@8.52.0':
dependencies: dependencies:
'@typescript-eslint/types': 8.50.1 '@typescript-eslint/types': 8.52.0
eslint-visitor-keys: 4.2.1 eslint-visitor-keys: 4.2.1
'@unrs/resolver-binding-android-arm-eabi@1.11.1': '@unrs/resolver-binding-android-arm-eabi@1.11.1':
@@ -5839,7 +5820,7 @@ snapshots:
next: 16.1.1(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) next: 16.1.1(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
react: 19.2.3 react: 19.2.3
'@vercel/oidc@3.0.5': {} '@vercel/oidc@3.1.0': {}
'@vercel/speed-insights@1.3.1(next@16.1.1(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)': '@vercel/speed-insights@1.3.1(next@16.1.1(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)':
optionalDependencies: optionalDependencies:
@@ -5886,11 +5867,11 @@ snapshots:
adler-32@1.3.1: {} adler-32@1.3.1: {}
ai@6.0.7(zod@4.3.5): ai@6.0.27(zod@4.3.5):
dependencies: dependencies:
'@ai-sdk/gateway': 3.0.6(zod@4.3.5) '@ai-sdk/gateway': 3.0.11(zod@4.3.5)
'@ai-sdk/provider': 3.0.1 '@ai-sdk/provider': 3.0.2
'@ai-sdk/provider-utils': 4.0.2(zod@4.3.5) '@ai-sdk/provider-utils': 4.0.4(zod@4.3.5)
'@opentelemetry/api': 1.9.0 '@opentelemetry/api': 1.9.0
zod: 4.3.5 zod: 4.3.5
@@ -6000,7 +5981,7 @@ snapshots:
dependencies: dependencies:
possible-typed-array-names: 1.1.0 possible-typed-array-names: 1.1.0
axe-core@4.11.0: {} axe-core@4.11.1: {}
axobject-query@4.1.0: {} axobject-query@4.1.0: {}
@@ -6013,7 +5994,7 @@ snapshots:
base64-arraybuffer@1.0.2: base64-arraybuffer@1.0.2:
optional: true optional: true
baseline-browser-mapping@2.9.11: {} baseline-browser-mapping@2.9.14: {}
better-auth@1.4.10(drizzle-kit@0.31.8)(drizzle-orm@0.45.1(@opentelemetry/api@1.9.0)(@types/pg@8.16.0)(kysely@0.28.9)(pg@8.16.3))(next@16.1.1(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(pg@8.16.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3): better-auth@1.4.10(drizzle-kit@0.31.8)(drizzle-orm@0.45.1(@opentelemetry/api@1.9.0)(@types/pg@8.16.0)(kysely@0.28.9)(pg@8.16.3))(next@16.1.1(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(pg@8.16.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
dependencies: dependencies:
@@ -6061,8 +6042,8 @@ snapshots:
browserslist@4.28.1: browserslist@4.28.1:
dependencies: dependencies:
baseline-browser-mapping: 2.9.11 baseline-browser-mapping: 2.9.14
caniuse-lite: 1.0.30001761 caniuse-lite: 1.0.30001763
electron-to-chromium: 1.5.267 electron-to-chromium: 1.5.267
node-releases: 2.0.27 node-releases: 2.0.27
update-browserslist-db: 1.2.3(browserslist@4.28.1) update-browserslist-db: 1.2.3(browserslist@4.28.1)
@@ -6092,7 +6073,7 @@ snapshots:
camelcase@6.3.0: {} camelcase@6.3.0: {}
caniuse-lite@1.0.30001761: {} caniuse-lite@1.0.30001763: {}
canvg@3.0.11: canvg@3.0.11:
dependencies: dependencies:
@@ -6457,8 +6438,6 @@ snapshots:
es-toolkit@1.43.0: {} es-toolkit@1.43.0: {}
es6-promise@4.2.8: {}
esbuild-register@3.6.0(esbuild@0.25.12): esbuild-register@3.6.0(esbuild@0.25.12):
dependencies: dependencies:
debug: 4.4.3 debug: 4.4.3
@@ -6553,18 +6532,18 @@ snapshots:
escape-string-regexp@4.0.0: {} escape-string-regexp@4.0.0: {}
eslint-config-next@16.1.1(@typescript-eslint/parser@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3): eslint-config-next@16.1.1(@typescript-eslint/parser@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3):
dependencies: dependencies:
'@next/eslint-plugin-next': 16.1.1 '@next/eslint-plugin-next': 16.1.1
eslint: 9.39.2(jiti@2.6.1) eslint: 9.39.2(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9 eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@2.6.1)) eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.2(jiti@2.6.1)) eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-react: 7.37.5(eslint@9.39.2(jiti@2.6.1)) eslint-plugin-react: 7.37.5(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-react-hooks: 7.0.1(eslint@9.39.2(jiti@2.6.1)) eslint-plugin-react-hooks: 7.0.1(eslint@9.39.2(jiti@2.6.1))
globals: 16.4.0 globals: 16.4.0
typescript-eslint: 8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) typescript-eslint: 8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
optionalDependencies: optionalDependencies:
typescript: 5.9.3 typescript: 5.9.3
transitivePeerDependencies: transitivePeerDependencies:
@@ -6592,22 +6571,22 @@ snapshots:
tinyglobby: 0.2.15 tinyglobby: 0.2.15
unrs-resolver: 1.11.1 unrs-resolver: 1.11.1
optionalDependencies: optionalDependencies:
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1))
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
eslint-module-utils@2.12.1(@typescript-eslint/parser@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)): eslint-module-utils@2.12.1(@typescript-eslint/parser@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)):
dependencies: dependencies:
debug: 3.2.7 debug: 3.2.7
optionalDependencies: optionalDependencies:
'@typescript-eslint/parser': 8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/parser': 8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
eslint: 9.39.2(jiti@2.6.1) eslint: 9.39.2(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9 eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@2.6.1)) eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@2.6.1))
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)): eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)):
dependencies: dependencies:
'@rtsao/scc': 1.1.0 '@rtsao/scc': 1.1.0
array-includes: 3.1.9 array-includes: 3.1.9
@@ -6618,7 +6597,7 @@ snapshots:
doctrine: 2.1.0 doctrine: 2.1.0
eslint: 9.39.2(jiti@2.6.1) eslint: 9.39.2(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9 eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)) eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1))
hasown: 2.0.2 hasown: 2.0.2
is-core-module: 2.16.1 is-core-module: 2.16.1
is-glob: 4.0.3 is-glob: 4.0.3
@@ -6630,7 +6609,7 @@ snapshots:
string.prototype.trimend: 1.0.9 string.prototype.trimend: 1.0.9
tsconfig-paths: 3.15.0 tsconfig-paths: 3.15.0
optionalDependencies: optionalDependencies:
'@typescript-eslint/parser': 8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/parser': 8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
transitivePeerDependencies: transitivePeerDependencies:
- eslint-import-resolver-typescript - eslint-import-resolver-typescript
- eslint-import-resolver-webpack - eslint-import-resolver-webpack
@@ -6642,7 +6621,7 @@ snapshots:
array-includes: 3.1.9 array-includes: 3.1.9
array.prototype.flatmap: 1.3.3 array.prototype.flatmap: 1.3.3
ast-types-flow: 0.0.8 ast-types-flow: 0.0.8
axe-core: 4.11.0 axe-core: 4.11.1
axobject-query: 4.1.0 axobject-query: 4.1.0
damerau-levenshtein: 1.0.8 damerau-levenshtein: 1.0.8
emoji-regex: 9.2.2 emoji-regex: 9.2.2
@@ -6699,7 +6678,7 @@ snapshots:
eslint@9.39.2(jiti@2.6.1): eslint@9.39.2(jiti@2.6.1):
dependencies: dependencies:
'@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2(jiti@2.6.1)) '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1))
'@eslint-community/regexpp': 4.12.2 '@eslint-community/regexpp': 4.12.2
'@eslint/config-array': 0.21.1 '@eslint/config-array': 0.21.1
'@eslint/config-helpers': 0.4.2 '@eslint/config-helpers': 0.4.2
@@ -6719,7 +6698,7 @@ snapshots:
eslint-scope: 8.4.0 eslint-scope: 8.4.0
eslint-visitor-keys: 4.2.1 eslint-visitor-keys: 4.2.1
espree: 10.4.0 espree: 10.4.0
esquery: 1.6.0 esquery: 1.7.0
esutils: 2.0.3 esutils: 2.0.3
fast-deep-equal: 3.1.3 fast-deep-equal: 3.1.3
file-entry-cache: 8.0.0 file-entry-cache: 8.0.0
@@ -6746,7 +6725,7 @@ snapshots:
esprima@4.0.1: {} esprima@4.0.1: {}
esquery@1.6.0: esquery@1.7.0:
dependencies: dependencies:
estraverse: 5.3.0 estraverse: 5.3.0
@@ -6833,10 +6812,10 @@ snapshots:
frac@1.1.2: {} frac@1.1.2: {}
framer-motion@12.23.27(react-dom@19.2.3(react@19.2.3))(react@19.2.3): framer-motion@12.25.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
dependencies: dependencies:
motion-dom: 12.23.23 motion-dom: 12.24.11
motion-utils: 12.23.6 motion-utils: 12.24.10
tslib: 2.8.1 tslib: 2.8.1
optionalDependencies: optionalDependencies:
react: 19.2.3 react: 19.2.3
@@ -6973,7 +6952,7 @@ snapshots:
immer@10.2.0: {} immer@10.2.0: {}
immer@11.1.0: {} immer@11.1.3: {}
import-fresh@3.3.1: import-fresh@3.3.1:
dependencies: dependencies:
@@ -7291,15 +7270,15 @@ snapshots:
minimist@1.2.8: {} minimist@1.2.8: {}
motion-dom@12.23.23: motion-dom@12.24.11:
dependencies: dependencies:
motion-utils: 12.23.6 motion-utils: 12.24.10
motion-utils@12.23.6: {} motion-utils@12.24.10: {}
motion@12.23.27(react-dom@19.2.3(react@19.2.3))(react@19.2.3): motion@12.25.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
dependencies: dependencies:
framer-motion: 12.23.27(react-dom@19.2.3(react@19.2.3))(react@19.2.3) framer-motion: 12.25.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
tslib: 2.8.1 tslib: 2.8.1
optionalDependencies: optionalDependencies:
react: 19.2.3 react: 19.2.3
@@ -7332,8 +7311,8 @@ snapshots:
dependencies: dependencies:
'@next/env': 16.1.1 '@next/env': 16.1.1
'@swc/helpers': 0.5.15 '@swc/helpers': 0.5.15
baseline-browser-mapping: 2.9.11 baseline-browser-mapping: 2.9.14
caniuse-lite: 1.0.30001761 caniuse-lite: 1.0.30001763
postcss: 8.4.31 postcss: 8.4.31
react: 19.2.3 react: 19.2.3
react-dom: 19.2.3(react@19.2.3) react-dom: 19.2.3(react@19.2.3)
@@ -7526,8 +7505,6 @@ snapshots:
punycode@2.3.1: {} punycode@2.3.1: {}
querystringify@2.2.0: {}
queue-microtask@1.2.3: {} queue-microtask@1.2.3: {}
raf@3.4.1: raf@3.4.1:
@@ -7644,13 +7621,11 @@ snapshots:
require-package-name@2.0.1: {} require-package-name@2.0.1: {}
requires-port@1.0.0: {}
reselect@5.1.1: {} reselect@5.1.1: {}
resend@6.6.0: resend@6.7.0:
dependencies: dependencies:
svix: 1.76.1 svix: 1.84.1
resolve-dir@1.0.1: resolve-dir@1.0.1:
dependencies: dependencies:
@@ -7830,6 +7805,11 @@ snapshots:
stackblur-canvas@2.7.0: stackblur-canvas@2.7.0:
optional: true optional: true
standardwebhooks@1.0.0:
dependencies:
'@stablelib/base64': 1.0.1
fast-sha256: 1.3.0
stop-iteration-iterator@1.1.0: stop-iteration-iterator@1.1.0:
dependencies: dependencies:
es-errors: 1.3.0 es-errors: 1.3.0
@@ -7915,13 +7895,9 @@ snapshots:
svg-pathdata@6.0.3: svg-pathdata@6.0.3:
optional: true optional: true
svix@1.76.1: svix@1.84.1:
dependencies: dependencies:
'@stablelib/base64': 1.0.1 standardwebhooks: 1.0.0
'@types/node': 22.19.3
es6-promise: 4.2.8
fast-sha256: 1.3.0
url-parse: 1.5.10
uuid: 10.0.0 uuid: 10.0.0
tailwind-merge@3.4.0: {} tailwind-merge@3.4.0: {}
@@ -7946,7 +7922,7 @@ snapshots:
dependencies: dependencies:
is-number: 7.0.0 is-number: 7.0.0
ts-api-utils@2.1.0(typescript@5.9.3): ts-api-utils@2.4.0(typescript@5.9.3):
dependencies: dependencies:
typescript: 5.9.3 typescript: 5.9.3
@@ -8003,12 +7979,12 @@ snapshots:
possible-typed-array-names: 1.1.0 possible-typed-array-names: 1.1.0
reflect.getprototypeof: 1.0.10 reflect.getprototypeof: 1.0.10
typescript-eslint@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3): typescript-eslint@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3):
dependencies: dependencies:
'@typescript-eslint/eslint-plugin': 8.50.1(@typescript-eslint/parser@8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/eslint-plugin': 8.52.0(@typescript-eslint/parser@8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/parser': 8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/parser': 8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@typescript-eslint/typescript-estree': 8.50.1(typescript@5.9.3) '@typescript-eslint/typescript-estree': 8.52.0(typescript@5.9.3)
'@typescript-eslint/utils': 8.50.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/utils': 8.52.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
eslint: 9.39.2(jiti@2.6.1) eslint: 9.39.2(jiti@2.6.1)
typescript: 5.9.3 typescript: 5.9.3
transitivePeerDependencies: transitivePeerDependencies:
@@ -8023,8 +7999,6 @@ snapshots:
has-symbols: 1.1.0 has-symbols: 1.1.0
which-boxed-primitive: 1.1.1 which-boxed-primitive: 1.1.1
undici-types@6.21.0: {}
undici-types@7.16.0: {} undici-types@7.16.0: {}
unrs-resolver@1.11.1: unrs-resolver@1.11.1:
@@ -8061,11 +8035,6 @@ snapshots:
dependencies: dependencies:
punycode: 2.3.1 punycode: 2.3.1
url-parse@1.5.10:
dependencies:
querystringify: 2.2.0
requires-port: 1.0.0
use-callback-ref@1.3.3(@types/react@19.2.7)(react@19.2.3): use-callback-ref@1.3.3(@types/react@19.2.7)(react@19.2.3):
dependencies: dependencies:
react: 19.2.3 react: 19.2.3