style(ui): padronizar tipografia — font-medium para font-semibold

Padronização de peso tipográfico em títulos, rótulos de seção,
nomes de entidades e valores monetários em toda a interface.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Felipe Coutinho
2026-04-11 17:51:34 +00:00
parent 3bd8117b65
commit e8cc673e52
111 changed files with 361 additions and 272 deletions

View File

@@ -11,7 +11,7 @@ export default function RootLayout({
children: React.ReactNode; children: React.ReactNode;
}) { }) {
return ( return (
<section className="space-y-6 pt-4"> <section className="space-y-6">
<PageDescription <PageDescription
icon={<RiBankLine />} icon={<RiBankLine />}
title="Contas" title="Contas"

View File

@@ -11,7 +11,7 @@ export default function RootLayout({
children: React.ReactNode; children: React.ReactNode;
}) { }) {
return ( return (
<section className="space-y-6 pt-4"> <section className="space-y-6">
<PageDescription <PageDescription
icon={<RiBarChart2Line />} icon={<RiBarChart2Line />}
title="Orçamentos" title="Orçamentos"

View File

@@ -11,7 +11,7 @@ export default function RootLayout({
children: React.ReactNode; children: React.ReactNode;
}) { }) {
return ( return (
<section className="space-y-6 pt-4"> <section className="space-y-6">
<PageDescription <PageDescription
icon={<RiCalendarEventLine />} icon={<RiCalendarEventLine />}
title="Calendário" title="Calendário"

View File

@@ -11,7 +11,7 @@ export default function RootLayout({
children: React.ReactNode; children: React.ReactNode;
}) { }) {
return ( return (
<section className="space-y-6 pt-4"> <section className="space-y-6">
<PageDescription <PageDescription
icon={<RiBankCard2Line />} icon={<RiBankCard2Line />}
title="Cartões" title="Cartões"

View File

@@ -11,7 +11,7 @@ export default function RootLayout({
children: React.ReactNode; children: React.ReactNode;
}) { }) {
return ( return (
<section className="space-y-6 pt-4"> <section className="space-y-6">
<PageDescription <PageDescription
icon={<RiPriceTag3Line />} icon={<RiPriceTag3Line />}
title="Categorias" title="Categorias"

View File

@@ -11,7 +11,7 @@ export default function RootLayout({
children: React.ReactNode; children: React.ReactNode;
}) { }) {
return ( return (
<section className="space-y-6 pt-4"> <section className="space-y-6">
<PageDescription <PageDescription
icon={<RiHistoryLine />} icon={<RiHistoryLine />}
title="Changelog" title="Changelog"

View File

@@ -11,7 +11,7 @@ export default function RootLayout({
children: React.ReactNode; children: React.ReactNode;
}) { }) {
return ( return (
<section className="space-y-6 pt-4"> <section className="space-y-6">
<PageDescription <PageDescription
icon={<RiAtLine />} icon={<RiAtLine />}
title="Pré-Lançamentos" title="Pré-Lançamentos"

View File

@@ -11,7 +11,7 @@ export default function RootLayout({
children: React.ReactNode; children: React.ReactNode;
}) { }) {
return ( return (
<section className="space-y-6 pt-4"> <section className="space-y-6">
<PageDescription <PageDescription
icon={<RiSparklingLine />} icon={<RiSparklingLine />}
title="Insights" title="Insights"

View File

@@ -11,7 +11,7 @@ export default function RootLayout({
children: React.ReactNode; children: React.ReactNode;
}) { }) {
return ( return (
<section className="space-y-6 pt-4"> <section className="space-y-6">
<PageDescription <PageDescription
icon={<RiTodoLine />} icon={<RiTodoLine />}
title="Anotações" title="Anotações"

View File

@@ -11,7 +11,7 @@ export default function RootLayout({
children: React.ReactNode; children: React.ReactNode;
}) { }) {
return ( return (
<section className="space-y-6 pt-4"> <section className="space-y-6">
<PageDescription <PageDescription
icon={<RiGroupLine />} icon={<RiGroupLine />}
title="Pagadores" title="Pagadores"

View File

@@ -11,7 +11,7 @@ export default function RootLayout({
children: React.ReactNode; children: React.ReactNode;
}) { }) {
return ( return (
<section className="space-y-6 pt-4"> <section className="space-y-6">
<PageDescription <PageDescription
icon={<RiBankCard2Line />} icon={<RiBankCard2Line />}
title="Uso de Cartões" title="Uso de Cartões"

View File

@@ -71,7 +71,7 @@ export default async function RelatorioCartoesPage({
<div className="flex size-14 items-center justify-center rounded-full bg-muted mb-4"> <div className="flex size-14 items-center justify-center rounded-full bg-muted mb-4">
<RiBankCard2Line className="size-7 text-muted-foreground" /> <RiBankCard2Line className="size-7 text-muted-foreground" />
</div> </div>
<p className="text-base font-medium">Nenhum cartão selecionado</p> <p className="text-base font-semibold">Nenhum cartão selecionado</p>
<p className="text-sm text-muted-foreground mt-1"> <p className="text-sm text-muted-foreground mt-1">
Selecione um cartão para ver os detalhes de uso. Selecione um cartão para ver os detalhes de uso.
</p> </p>

View File

@@ -11,7 +11,7 @@ export default function RootLayout({
children: React.ReactNode; children: React.ReactNode;
}) { }) {
return ( return (
<section className="space-y-6 pt-4"> <section className="space-y-6">
<PageDescription <PageDescription
icon={<RiFileChartLine />} icon={<RiFileChartLine />}
title="Tendências" title="Tendências"

View File

@@ -11,7 +11,7 @@ export default function RootLayout({
children: React.ReactNode; children: React.ReactNode;
}) { }) {
return ( return (
<section className="space-y-6 pt-4"> <section className="space-y-6">
<PageDescription <PageDescription
icon={<RiStore2Line />} icon={<RiStore2Line />}
title="Top Estabelecimentos" title="Top Estabelecimentos"

View File

@@ -11,7 +11,7 @@ export default function RootLayout({
children: React.ReactNode; children: React.ReactNode;
}) { }) {
return ( return (
<section className="space-y-6 pt-4"> <section className="space-y-6">
<PageDescription <PageDescription
icon={<RiSecurePaymentLine />} icon={<RiSecurePaymentLine />}
title="Análise de Parcelas" title="Análise de Parcelas"

View File

@@ -11,7 +11,7 @@ export default function RootLayout({
children: React.ReactNode; children: React.ReactNode;
}) { }) {
return ( return (
<section className="space-y-6 pt-4"> <section className="space-y-6">
<PageDescription <PageDescription
icon={<RiSettings2Line />} icon={<RiSettings2Line />}
title="Ajustes" title="Ajustes"

View File

@@ -67,7 +67,7 @@ export default async function Page() {
<Card className="p-6"> <Card className="p-6">
<div className="space-y-4"> <div className="space-y-4">
<div> <div>
<h2 className="text-xl font-medium mb-1">Preferências</h2> <h2 className="text-xl font-semibold mb-1">Preferências</h2>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Personalize sua experiência no OpenMonetis ajustando as Personalize sua experiência no OpenMonetis ajustando as
configurações de acordo com suas necessidades. configurações de acordo com suas necessidades.
@@ -92,7 +92,9 @@ export default async function Page() {
<div className="space-y-4"> <div className="space-y-4">
<div> <div>
<div className="flex items-center gap-2 mb-1"> <div className="flex items-center gap-2 mb-1">
<h2 className="text-xl font-medium">OpenMonetis Companion</h2> <h2 className="text-xl font-semibold">
OpenMonetis Companion
</h2>
<span className="inline-flex items-center gap-1 rounded-full bg-success/10 px-2 py-0.5 text-xs font-medium text-success dark:bg-success/10"> <span className="inline-flex items-center gap-1 rounded-full bg-success/10 px-2 py-0.5 text-xs font-medium text-success dark:bg-success/10">
<RiAndroidLine className="h-3 w-3" /> <RiAndroidLine className="h-3 w-3" />
Android Android
@@ -114,7 +116,7 @@ export default async function Page() {
<Card className="p-6"> <Card className="p-6">
<div className="space-y-4"> <div className="space-y-4">
<div> <div>
<h2 className="text-xl font-medium mb-1">Alterar nome</h2> <h2 className="text-xl font-semibold mb-1">Alterar nome</h2>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Atualize como seu nome aparece no OpenMonetis. Esse nome pode Atualize como seu nome aparece no OpenMonetis. Esse nome pode
ser exibido em diferentes seções do app e em comunicações. ser exibido em diferentes seções do app e em comunicações.
@@ -130,7 +132,7 @@ export default async function Page() {
<Card className="p-6"> <Card className="p-6">
<div className="space-y-4"> <div className="space-y-4">
<div> <div>
<h2 className="text-xl font-medium mb-1">Alterar senha</h2> <h2 className="text-xl font-semibold mb-1">Alterar senha</h2>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Defina uma nova senha para sua conta. Guarde-a em local Defina uma nova senha para sua conta. Guarde-a em local
seguro. seguro.
@@ -146,7 +148,7 @@ export default async function Page() {
<Card className="p-6"> <Card className="p-6">
<div className="space-y-4"> <div className="space-y-4">
<div> <div>
<h2 className="text-xl font-medium mb-1">Passkeys</h2> <h2 className="text-xl font-semibold mb-1">Passkeys</h2>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Passkeys permitem login sem senha, usando biometria (Face ID, Passkeys permitem login sem senha, usando biometria (Face ID,
Touch ID, Windows Hello) ou chaves de segurança. Touch ID, Windows Hello) ou chaves de segurança.
@@ -162,7 +164,7 @@ export default async function Page() {
<Card className="p-6"> <Card className="p-6">
<div className="space-y-4"> <div className="space-y-4">
<div> <div>
<h2 className="text-xl font-medium mb-1">Alterar e-mail</h2> <h2 className="text-xl font-semibold mb-1">Alterar e-mail</h2>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Atualize o e-mail associado à sua conta. Você precisará Atualize o e-mail associado à sua conta. Você precisará
confirmar os links enviados para o novo e também para o e-mail confirmar os links enviados para o novo e também para o e-mail
@@ -182,7 +184,7 @@ export default async function Page() {
<Card className="p-6"> <Card className="p-6">
<div className="space-y-4"> <div className="space-y-4">
<div> <div>
<h2 className="text-xl font-medium mb-1 text-destructive"> <h2 className="text-xl font-semibold mb-1 text-destructive">
Ações perigosas Ações perigosas
</h2> </h2>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">

View File

@@ -11,7 +11,7 @@ export default function RootLayout({
children: React.ReactNode; children: React.ReactNode;
}) { }) {
return ( return (
<section className="space-y-6 pt-4"> <section className="space-y-6">
<PageDescription <PageDescription
icon={<RiArrowLeftRightLine />} icon={<RiArrowLeftRightLine />}
title="Lançamentos" title="Lançamentos"

View File

@@ -120,13 +120,13 @@ export default async function Page() {
</div> </div>
<div className="max-w-8xl mx-auto px-4 relative"> <div className="max-w-8xl mx-auto px-4 relative">
<div className="mx-auto flex max-w-3xl flex-col items-center text-center gap-5 md:gap-6 pb-10 md:pb-14"> <div className="mx-auto flex max-w-4xl flex-col items-center text-center gap-5 md:gap-6 pb-10 md:pb-14">
<Badge variant="outline"> <Badge variant="outline">
<RiGithubFill className="size-4 mr-1" /> <RiGithubFill className="size-4 mr-1" />
Projeto Open Source Projeto Open Source
</Badge> </Badge>
<h1 className="text-3xl sm:text-4xl md:text-5xl lg:text-6xl font-medium tracking-tight"> <h1 className="text-3xl sm:text-4xl md:text-5xl lg:text-6xl font-semibold">
Suas finanças, Suas finanças,
<span className="text-primary"> do seu jeito</span> <span className="text-primary"> do seu jeito</span>
</h1> </h1>
@@ -207,9 +207,7 @@ export default async function Page() {
className="flex flex-col items-center text-center gap-1.5" className="flex flex-col items-center text-center gap-1.5"
> >
<Icon className="size-5" style={{ color: colorVar }} /> <Icon className="size-5" style={{ color: colorVar }} />
<span className="text-2xl md:text-3xl font-medium"> <span className="text-2xl md:text-3xl ">{value}</span>
{value}
</span>
<span className="text-xs md:text-sm text-muted-foreground"> <span className="text-xs md:text-sm text-muted-foreground">
{label} {label}
</span> </span>
@@ -229,7 +227,7 @@ export default async function Page() {
<Badge variant="outline" className="mb-4"> <Badge variant="outline" className="mb-4">
Conheça as telas Conheça as telas
</Badge> </Badge>
<h2 className="text-2xl sm:text-3xl md:text-4xl font-medium tracking-tight mb-3 md:mb-4"> <h2 className="text-2xl sm:text-3xl md:text-4xl mb-3 md:mb-4">
Veja o que você pode fazer Veja o que você pode fazer
</h2> </h2>
<p className="text-base md:text-lg text-muted-foreground max-w-2xl mx-auto px-4 sm:px-0"> <p className="text-base md:text-lg text-muted-foreground max-w-2xl mx-auto px-4 sm:px-0">
@@ -254,7 +252,7 @@ export default async function Page() {
<Badge variant="outline" className="mb-4"> <Badge variant="outline" className="mb-4">
O que tem aqui O que tem aqui
</Badge> </Badge>
<h2 className="text-2xl sm:text-3xl md:text-4xl font-medium tracking-tight mb-3 md:mb-4"> <h2 className="text-2xl sm:text-3xl md:text-4xl mb-3 md:mb-4">
Funcionalidades que importam Funcionalidades que importam
</h2> </h2>
<p className="text-base md:text-lg text-muted-foreground max-w-2xl mx-auto px-4 sm:px-0"> <p className="text-base md:text-lg text-muted-foreground max-w-2xl mx-auto px-4 sm:px-0">
@@ -282,7 +280,7 @@ export default async function Page() {
/> />
</div> </div>
<div> <div>
<h3 className="font-medium text-base md:text-lg mb-1.5 md:mb-2"> <h3 className="font-semibold text-base md:text-lg mb-1.5 md:mb-2">
{feature.title} {feature.title}
</h3> </h3>
<p className="text-sm text-muted-foreground leading-relaxed"> <p className="text-sm text-muted-foreground leading-relaxed">
@@ -298,7 +296,7 @@ export default async function Page() {
<AnimateOnScroll> <AnimateOnScroll>
<div className="mt-8 md:mt-12"> <div className="mt-8 md:mt-12">
<h3 className="text-sm font-medium text-center mb-4 md:mb-6 text-muted-foreground"> <h3 className="text-sm font-semibold text-center mb-4 md:mb-6 text-muted-foreground">
Também inclui Também inclui
</h3> </h3>
<div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3"> <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
@@ -319,7 +317,7 @@ export default async function Page() {
/> />
</div> </div>
<div className="min-w-0"> <div className="min-w-0">
<h4 className="font-medium text-sm mb-0.5"> <h4 className="font-semibold text-sm mb-0.5">
{feature.title} {feature.title}
</h4> </h4>
<p className="text-xs text-muted-foreground leading-relaxed"> <p className="text-xs text-muted-foreground leading-relaxed">
@@ -346,7 +344,7 @@ export default async function Page() {
<RiSmartphoneLine className="size-3.5 mr-1" /> <RiSmartphoneLine className="size-3.5 mr-1" />
Mobile Mobile
</Badge> </Badge>
<h2 className="text-2xl sm:text-3xl md:text-4xl font-medium tracking-tight mb-3 md:mb-4"> <h2 className="text-2xl sm:text-3xl md:text-4xl mb-3 md:mb-4">
Use o OpenMonetis no celular sem perder o fluxo Use o OpenMonetis no celular sem perder o fluxo
</h2> </h2>
<p className="text-base md:text-lg text-muted-foreground max-w-2xl mx-auto px-4 sm:px-0"> <p className="text-base md:text-lg text-muted-foreground max-w-2xl mx-auto px-4 sm:px-0">
@@ -384,7 +382,7 @@ export default async function Page() {
<RiSmartphoneLine className="size-3.5 mr-1" /> <RiSmartphoneLine className="size-3.5 mr-1" />
PWA instalável PWA instalável
</Badge> </Badge>
<h3 className="text-2xl md:text-3xl font-medium tracking-tight mb-3"> <h3 className="text-2xl md:text-3xl font-semibold tracking-tight mb-3">
Leve o OpenMonetis para a tela inicial Leve o OpenMonetis para a tela inicial
</h3> </h3>
<p className="text-muted-foreground mb-6 leading-relaxed"> <p className="text-muted-foreground mb-6 leading-relaxed">
@@ -430,7 +428,7 @@ export default async function Page() {
Companion Android Companion Android
</Badge> </Badge>
</div> </div>
<h3 className="text-2xl md:text-3xl font-medium tracking-tight mb-3"> <h3 className="text-2xl md:text-3xl font-semibold tracking-tight mb-3">
Capture, envie e revise no mesmo fluxo Capture, envie e revise no mesmo fluxo
</h3> </h3>
<p className="text-muted-foreground mb-6 leading-relaxed"> <p className="text-muted-foreground mb-6 leading-relaxed">
@@ -529,7 +527,7 @@ export default async function Page() {
<Badge variant="outline" className="mb-4"> <Badge variant="outline" className="mb-4">
Stack técnica Stack técnica
</Badge> </Badge>
<h2 className="text-2xl sm:text-3xl md:text-4xl font-medium tracking-tight mb-3 md:mb-4"> <h2 className="text-2xl sm:text-3xl md:text-4xl mb-3 md:mb-4">
O que roda por baixo O que roda por baixo
</h2> </h2>
<p className="text-base md:text-lg text-muted-foreground max-w-2xl mx-auto px-4 sm:px-0"> <p className="text-base md:text-lg text-muted-foreground max-w-2xl mx-auto px-4 sm:px-0">
@@ -556,7 +554,7 @@ export default async function Page() {
/> />
</div> </div>
<div> <div>
<h3 className="font-medium text-base md:text-lg mb-1.5 md:mb-2"> <h3 className="font-semibold text-base md:text-lg mb-1.5 md:mb-2">
{item.title} {item.title}
</h3> </h3>
<p className="text-sm text-muted-foreground mb-2 md:mb-3"> <p className="text-sm text-muted-foreground mb-2 md:mb-3">
@@ -582,7 +580,7 @@ export default async function Page() {
<Badge variant="outline" className="mb-4"> <Badge variant="outline" className="mb-4">
Como usar Como usar
</Badge> </Badge>
<h2 className="text-2xl sm:text-3xl md:text-4xl font-medium tracking-tight mb-3 md:mb-4"> <h2 className="text-2xl sm:text-3xl md:text-4xl mb-3 md:mb-4">
Rode no seu computador Rode no seu computador
</h2> </h2>
<p className="text-base md:text-lg text-muted-foreground px-4 sm:px-0"> <p className="text-base md:text-lg text-muted-foreground px-4 sm:px-0">
@@ -617,7 +615,7 @@ export default async function Page() {
<Badge variant="outline" className="mb-4"> <Badge variant="outline" className="mb-4">
Para quem é? Para quem é?
</Badge> </Badge>
<h2 className="text-2xl sm:text-3xl md:text-4xl font-medium tracking-tight mb-3 md:mb-4"> <h2 className="text-2xl sm:text-3xl md:text-4xl mb-3 md:mb-4">
Feito para quem gosta de controle Feito para quem gosta de controle
</h2> </h2>
<p className="text-base md:text-lg text-muted-foreground px-4 sm:px-0"> <p className="text-base md:text-lg text-muted-foreground px-4 sm:px-0">
@@ -644,7 +642,7 @@ export default async function Page() {
/> />
</div> </div>
<div> <div>
<h3 className="font-medium mb-1">{item.title}</h3> <h3 className="font-semibold mb-1">{item.title}</h3>
<p className="text-xs sm:text-sm text-muted-foreground"> <p className="text-xs sm:text-sm text-muted-foreground">
{item.description} {item.description}
</p> </p>
@@ -664,7 +662,7 @@ export default async function Page() {
<div className="max-w-8xl mx-auto px-4"> <div className="max-w-8xl mx-auto px-4">
<AnimateOnScroll> <AnimateOnScroll>
<div className="mx-auto max-w-4xl rounded-2xl border bg-card px-8 py-12 md:py-16 text-center"> <div className="mx-auto max-w-4xl rounded-2xl border bg-card px-8 py-12 md:py-16 text-center">
<h2 className="text-2xl sm:text-3xl md:text-4xl font-medium tracking-tight mb-3 md:mb-4"> <h2 className="text-2xl sm:text-3xl md:text-4xl mb-3 md:mb-4">
Pronto para testar? Pronto para testar?
</h2> </h2>
<p className="text-base md:text-lg text-muted-foreground mb-6 md:mb-8"> <p className="text-base md:text-lg text-muted-foreground mb-6 md:mb-8">
@@ -715,7 +713,7 @@ export default async function Page() {
</div> </div>
<div> <div>
<h3 className="font-medium mb-3 md:mb-4">Projeto</h3> <h3 className="font-semibold mb-3 md:mb-4">Projeto</h3>
<ul className="space-y-2.5 md:space-y-3 text-sm text-muted-foreground"> <ul className="space-y-2.5 md:space-y-3 text-sm text-muted-foreground">
<li> <li>
<Link <Link
@@ -749,7 +747,7 @@ export default async function Page() {
</div> </div>
<div> <div>
<h3 className="font-medium mb-3 md:mb-4">Companion</h3> <h3 className="font-semibold mb-3 md:mb-4">Companion</h3>
<ul className="space-y-2.5 md:space-y-3 text-sm text-muted-foreground"> <ul className="space-y-2.5 md:space-y-3 text-sm text-muted-foreground">
<li> <li>
<Link <Link

View File

@@ -88,7 +88,9 @@ export function AccountCard({
{icon} {icon}
</div> </div>
) : null} ) : null}
<h2 className="text-lg font-medium text-foreground">{accountName}</h2> <h2 className="text-lg font-semibold text-foreground">
{accountName}
</h2>
{(excludeFromBalance || excludeInitialBalanceFromIncome) && ( {(excludeFromBalance || excludeInitialBalanceFromIncome) && (
<Tooltip> <Tooltip>

View File

@@ -68,7 +68,7 @@ export function AccountStatementCard({
</div> </div>
) : null} ) : null}
<div className="min-w-0"> <div className="min-w-0">
<h2 className="truncate text-sm font-medium text-foreground"> <h2 className="truncate text-sm font-semibold text-foreground">
{accountName} {accountName}
</h2> </h2>
<p className="text-xs text-muted-foreground"> <p className="text-xs text-muted-foreground">
@@ -81,12 +81,12 @@ export function AccountStatementCard({
{/* Linha 2 — saldo final (hero) */} {/* Linha 2 — saldo final (hero) */}
<div className="space-y-4"> <div className="space-y-4">
<p className="text-sm font-medium text-muted-foreground "> <p className="text-sm text-muted-foreground ">
Saldo ao final do período Saldo ao final do período
</p> </p>
<MoneyValues <MoneyValues
amount={currentBalance} amount={currentBalance}
className="text-3xl leading-none font-medium tracking-tight sm:text-[2rem]" className="text-3xl leading-none tracking-tighter sm:text-[2rem]"
/> />
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Badge <Badge

View File

@@ -69,9 +69,7 @@ function PdfCanvas({ url }: PdfCanvasProps) {
return ( return (
<div className="flex h-full w-full flex-col items-center justify-center gap-2 bg-muted/50"> <div className="flex h-full w-full flex-col items-center justify-center gap-2 bg-muted/50">
<RiFilePdf2Line className="size-12 text-muted-foreground/40" /> <RiFilePdf2Line className="size-12 text-muted-foreground/40" />
<span className="text-xs font-medium text-muted-foreground/60"> <span className="text-xs text-muted-foreground/60">PDF Protegido</span>
PDF Protegido
</span>
</div> </div>
); );
} }
@@ -153,7 +151,7 @@ export function AttachmentGridItem({
<Tooltip> <Tooltip>
<TooltipTrigger asChild> <TooltipTrigger asChild>
<p className="truncate text-sm font-medium leading-tight text-foreground"> <p className="truncate text-sm font-semibold leading-tight text-foreground">
{attachment.fileName} {attachment.fileName}
</p> </p>
</TooltipTrigger> </TooltipTrigger>
@@ -180,25 +178,21 @@ export function AttachmentGridItem({
{attachment.transactionName} {attachment.transactionName}
</TooltipContent> </TooltipContent>
</Tooltip> </Tooltip>
<span <span className={cn("shrink-0 text-sm font-medium tracking-tighter")}>
className={cn(
"shrink-0 text-sm font-medium tracking-tighter tabular-nums",
)}
>
{formatCurrency(amount)} {formatCurrency(amount)}
</span> </span>
</div> </div>
{/* Footer: Tamanho + Botão Detalhes */} {/* Footer: Tamanho + Botão Detalhes */}
<div className="mt-auto flex items-center justify-between border-t pt-3"> <div className="mt-auto flex items-center justify-between border-t pt-3">
<span className="text-xs font-medium text-muted-foreground/70"> <span className="text-xs text-muted-foreground/70">
{formatBytes(attachment.fileSize)} {formatBytes(attachment.fileSize)}
</span> </span>
<button <button
type="button" type="button"
onClick={onDetails} onClick={onDetails}
disabled={isLoadingDetails} disabled={isLoadingDetails}
className="text-xs font-medium text-muted-foreground/70 underline-offset-2 hover:underline focus-visible:outline-none disabled:opacity-50" className="text-xs text-muted-foreground/70 underline-offset-2 hover:underline focus-visible:outline-none disabled:opacity-50"
> >
{isLoadingDetails ? "Carregando..." : "Detalhes"} {isLoadingDetails ? "Carregando..." : "Detalhes"}
</button> </button>

View File

@@ -105,7 +105,7 @@ export function AttachmentPreview({
> >
<RiArrowLeftSLine className="size-4" /> <RiArrowLeftSLine className="size-4" />
</Button> </Button>
<span className="select-none text-xs text-muted-foreground tabular-nums"> <span className="select-none text-xs text-muted-foreground">
{currentIndex + 1} / {attachments.length} {currentIndex + 1} / {attachments.length}
</span> </span>
<Button <Button

View File

@@ -19,8 +19,6 @@ import { TransactionDetailsDialog } from "@/features/transactions/components/dia
import { TransactionDialog } from "@/features/transactions/components/dialogs/transaction-dialog/transaction-dialog"; import { TransactionDialog } from "@/features/transactions/components/dialogs/transaction-dialog/transaction-dialog";
import type { TransactionItem } from "@/features/transactions/components/types"; import type { TransactionItem } from "@/features/transactions/components/types";
import { EmptyState } from "@/shared/components/empty-state"; import { EmptyState } from "@/shared/components/empty-state";
import MonthNavigation from "@/shared/components/month-picker/month-navigation";
import PageDescription from "@/shared/components/page-description";
import { Card, CardContent } from "@/shared/components/ui/card"; import { Card, CardContent } from "@/shared/components/ui/card";
import { cn } from "@/shared/utils/ui"; import { cn } from "@/shared/utils/ui";
@@ -143,14 +141,6 @@ export function AttachmentsPage({ attachments }: AttachmentsPageProps) {
return ( return (
<div className="w-full space-y-6"> <div className="w-full space-y-6">
<PageDescription
icon={<RiAttachmentLine className="size-5" />}
title="Anexos"
subtitle="Comprovantes e documentos dos seus lançamentos no mês."
/>
<MonthNavigation />
<Card> <Card>
<CardContent> <CardContent>
{attachments.length === 0 ? ( {attachments.length === 0 ? (

View File

@@ -8,7 +8,7 @@ interface AuthHeaderProps {
export function AuthHeader({ title, description }: AuthHeaderProps) { export function AuthHeader({ title, description }: AuthHeaderProps) {
return ( return (
<div className={cn("flex flex-col gap-2.5")}> <div className={cn("flex flex-col gap-2.5")}>
<h1 className="text-2xl font-medium tracking-tight text-card-foreground"> <h1 className="text-2xl font-semibold tracking-tight text-card-foreground">
{title} {title}
</h1> </h1>
{description ? ( {description ? (

View File

@@ -52,7 +52,7 @@ export function BudgetCard({
size="lg" size="lg"
/> />
<div className="space-y-1"> <div className="space-y-1">
<h3 className="text-base font-medium leading-tight"> <h3 className="text-base font-semibold leading-tight">
{formatCategoryName(budget)} {formatCategoryName(budget)}
</h3> </h3>
<p className="text-xs text-muted-foreground"> <p className="text-xs text-muted-foreground">

View File

@@ -19,9 +19,9 @@ export function CalendarGrid({
}: CalendarGridProps) { }: CalendarGridProps) {
return ( return (
<div className="overflow-hidden rounded-lg bg-card drop-shadow-xs border-none"> <div className="overflow-hidden rounded-lg bg-card drop-shadow-xs border-none">
<div className="grid grid-cols-7 text-sm font-medium uppercase tracking-wide text-muted-foreground"> <div className="grid grid-cols-7 text-sm font-semibold uppercase tracking-wide text-muted-foreground">
{WEEK_DAYS_SHORT.map((dayName) => ( {WEEK_DAYS_SHORT.map((dayName) => (
<span key={dayName} className="px-3 py-2 text-center text-primary"> <span key={dayName} className="px-3 py-2 text-center">
{dayName} {dayName}
</span> </span>
))} ))}

View File

@@ -130,7 +130,7 @@ const renderCard = (event: Extract<CalendarEvent, { type: "card" }>) => (
<div className="flex flex-col gap-1"> <div className="flex flex-col gap-1">
<div className="flex gap-1 items-center"> <div className="flex gap-1 items-center">
<span className="text-sm font-medium leading-tight"> <span className="text-sm font-medium leading-tight">
Vencimento Invoice - {event.card.name} Vencimento Fatura - {event.card.name}
</span> </span>
</div> </div>

View File

@@ -136,7 +136,7 @@ export function CardItem({
<div className="min-w-0"> <div className="min-w-0">
<div className="flex items-center gap-1.5"> <div className="flex items-center gap-1.5">
<h3 className="truncate text-sm font-medium text-foreground sm:text-base"> <h3 className="truncate text-sm font-semibold text-foreground sm:text-base">
{name} {name}
</h3> </h3>
{note ? ( {note ? (
@@ -206,29 +206,29 @@ export function CardItem({
<> <>
<div className="grid grid-cols-3 gap-4"> <div className="grid grid-cols-3 gap-4">
<div className="flex flex-col items-start gap-1"> <div className="flex flex-col items-start gap-1">
<p className="text-sm font-medium text-foreground"> <p className="text-sm font-semibold text-foreground">
<MoneyValues amount={metrics[0].value} /> <MoneyValues amount={metrics[0].value} />
</p> </p>
<span className="text-xs font-medium text-muted-foreground"> <span className="text-xs text-muted-foreground">
{metrics[0].label} {metrics[0].label}
</span> </span>
</div> </div>
<div className="flex flex-col items-center gap-1"> <div className="flex flex-col items-center gap-1">
<p className="flex items-center gap-1.5 text-sm font-medium text-foreground"> <p className="flex items-center gap-1.5 text-sm font-semibold text-foreground">
<span className="size-2 rounded-full bg-primary" /> <span className="size-2 rounded-full bg-primary" />
<MoneyValues amount={metrics[1].value} /> <MoneyValues amount={metrics[1].value} />
</p> </p>
<span className="text-xs font-medium text-muted-foreground"> <span className="text-xs text-muted-foreground">
{metrics[1].label} {metrics[1].label}
</span> </span>
</div> </div>
<div className="flex flex-col items-end gap-1"> <div className="flex flex-col items-end gap-1">
<p className="text-sm font-medium text-foreground"> <p className="text-sm font-semibold text-foreground">
<MoneyValues amount={metrics[2].value} /> <MoneyValues amount={metrics[2].value} />
</p> </p>
<span className="text-xs font-medium text-muted-foreground"> <span className="text-xs text-muted-foreground">
{metrics[2].label} {metrics[2].label}
</span> </span>
</div> </div>

View File

@@ -183,7 +183,7 @@ export function CategoriesPage({ categories }: CategoriesPageProps) {
<TableCell className="font-medium"> <TableCell className="font-medium">
<Link <Link
href={`/categories/${category.id}`} href={`/categories/${category.id}`}
className="inline-flex items-center gap-1 underline-offset-2 hover:text-primary hover:underline" className="inline-flex items-center gap-1 underline-offset-2 hover:text-primary hover:underline font-semibold"
> >
{category.name} {category.name}
<RiExternalLinkLine <RiExternalLinkLine

View File

@@ -80,7 +80,7 @@ export function CategoryDetailHeader({
size="lg" size="lg"
/> />
<div className="space-y-2"> <div className="space-y-2">
<h1 className="text-xl font-medium leading-tight"> <h1 className="text-xl font-semibold leading-tight">
{category.name} {category.name}
</h1> </h1>
<div className="flex flex-wrap items-center gap-2 text-sm text-muted-foreground"> <div className="flex flex-wrap items-center gap-2 text-sm text-muted-foreground">
@@ -99,7 +99,7 @@ export function CategoryDetailHeader({
<p className="text-xs font-medium uppercase tracking-wide text-muted-foreground"> <p className="text-xs font-medium uppercase tracking-wide text-muted-foreground">
Total em {currentPeriodLabel} Total em {currentPeriodLabel}
</p> </p>
<p className="mt-1 text-2xl font-medium"> <p className="mt-1 text-2xl font-semibold">
{currencyFormatter.format(currentTotal)} {currencyFormatter.format(currentTotal)}
</p> </p>
</div> </div>
@@ -107,7 +107,7 @@ export function CategoryDetailHeader({
<p className="text-xs font-medium uppercase tracking-wide text-muted-foreground"> <p className="text-xs font-medium uppercase tracking-wide text-muted-foreground">
Total em {previousPeriodLabel} Total em {previousPeriodLabel}
</p> </p>
<p className="mt-1 text-lg font-medium text-muted-foreground"> <p className="mt-1 text-lg font-semibold text-muted-foreground">
{currencyFormatter.format(previousTotal)} {currencyFormatter.format(previousTotal)}
</p> </p>
</div> </div>
@@ -117,7 +117,7 @@ export function CategoryDetailHeader({
</p> </p>
<div <div
className={cn( className={cn(
"mt-1 flex items-center gap-1 text-xl font-medium", "mt-1 flex items-center gap-1 text-lg font-semibold",
variationColor, variationColor,
)} )}
> >

View File

@@ -80,7 +80,7 @@ export function CategoryPickerDialog({
<div className="flex max-h-96 flex-col gap-4 overflow-y-auto pr-1"> <div className="flex max-h-96 flex-col gap-4 overflow-y-auto pr-1">
{filteredGroups.map((group) => ( {filteredGroups.map((group) => (
<div key={group.label}> <div key={group.label}>
<p className="mb-2 text-xs font-medium text-muted-foreground"> <p className="mb-2 text-xs text-muted-foreground">
{group.label} {group.label}
</p> </p>
<div className="grid grid-cols-8 gap-1.5"> <div className="grid grid-cols-8 gap-1.5">

View File

@@ -5,7 +5,10 @@ import {
ACCOUNT_AUTO_INVOICE_NOTE_PREFIX, ACCOUNT_AUTO_INVOICE_NOTE_PREFIX,
INITIAL_BALANCE_NOTE, INITIAL_BALANCE_NOTE,
} from "@/shared/lib/accounts/constants"; } from "@/shared/lib/accounts/constants";
import type { CategoryType } from "@/shared/lib/categories/constants"; import {
type CategoryType,
INVOICE_PAYMENT_CATEGORY_NAME,
} from "@/shared/lib/categories/constants";
import { db } from "@/shared/lib/db"; import { db } from "@/shared/lib/db";
import { getAdminPayerId } from "@/shared/lib/payers/get-admin-id"; import { getAdminPayerId } from "@/shared/lib/payers/get-admin-id";
import { calculatePercentageChange } from "@/shared/utils/math"; import { calculatePercentageChange } from "@/shared/utils/math";
@@ -45,6 +48,7 @@ export async function fetchCategoryDetails(
const previousPeriod = getPreviousPeriod(period); const previousPeriod = getPreviousPeriod(period);
const transactionType = category.type === "receita" ? "Receita" : "Despesa"; const transactionType = category.type === "receita" ? "Receita" : "Despesa";
const adminPayerId = await getAdminPayerId(userId); const adminPayerId = await getAdminPayerId(userId);
const isInvoiceCategory = category.name === INVOICE_PAYMENT_CATEGORY_NAME;
const sanitizedNote = or( const sanitizedNote = or(
isNull(transactions.note), isNull(transactions.note),
@@ -59,7 +63,7 @@ export async function fetchCategoryDetails(
eq(transactions.transactionType, transactionType), eq(transactions.transactionType, transactionType),
eq(transactions.period, period), eq(transactions.period, period),
eq(transactions.payerId, adminPayerId), eq(transactions.payerId, adminPayerId),
sanitizedNote, ...(isInvoiceCategory ? [] : [sanitizedNote]),
), ),
with: { with: {
payer: true, payer: true,
@@ -108,7 +112,7 @@ export async function fetchCategoryDetails(
eq(transactions.categoryId, categoryId), eq(transactions.categoryId, categoryId),
eq(transactions.transactionType, transactionType), eq(transactions.transactionType, transactionType),
eq(transactions.payerId, adminPayerId), eq(transactions.payerId, adminPayerId),
sanitizedNote, ...(isInvoiceCategory ? [] : [sanitizedNote]),
eq(transactions.period, previousPeriod), eq(transactions.period, previousPeriod),
or( or(
isNull(transactions.note), isNull(transactions.note),

View File

@@ -46,7 +46,7 @@ export function BillListItem({ bill, onPay }: BillListItemProps) {
<span <span
className={cn( className={cn(
"cursor-help rounded-full py-0.5", "cursor-help rounded-full py-0.5",
bill.isSettled && "text-success", bill.isSettled && "text-success font-semibold",
)} )}
> >
{statusLabel} {statusLabel}
@@ -60,7 +60,7 @@ export function BillListItem({ bill, onPay }: BillListItemProps) {
<span <span
className={cn( className={cn(
"rounded-full py-0.5", "rounded-full py-0.5",
bill.isSettled && "text-success", bill.isSettled && "text-success font-semibold",
)} )}
> >
{statusLabel} {statusLabel}
@@ -72,7 +72,7 @@ export function BillListItem({ bill, onPay }: BillListItemProps) {
</div> </div>
<div className="flex shrink-0 flex-col items-end"> <div className="flex shrink-0 flex-col items-end">
<MoneyValues amount={bill.amount} /> <MoneyValues className="font-medium" amount={bill.amount} />
<Button <Button
type="button" type="button"
size="sm" size="sm"

View File

@@ -97,7 +97,7 @@ export function BillPaymentDialog({
<p className="mb-1 text-xs font-medium text-muted-foreground uppercase tracking-wide"> <p className="mb-1 text-xs font-medium text-muted-foreground uppercase tracking-wide">
Boleto Boleto
</p> </p>
<p className="text-base font-medium text-foreground"> <p className="text-base font-semibold text-foreground">
{bill.name} {bill.name}
</p> </p>
</div> </div>
@@ -113,7 +113,7 @@ export function BillPaymentDialog({
</div> </div>
<MoneyValues <MoneyValues
amount={bill.amount} amount={bill.amount}
className="text-lg font-medium" className="text-lg font-semibold"
/> />
</div> </div>

View File

@@ -281,12 +281,12 @@ export function CategoryBreakdownWidgetView({
<div className="flex shrink-0 flex-col items-end gap-0.5"> <div className="flex shrink-0 flex-col items-end gap-0.5">
<MoneyValues <MoneyValues
className="text-foreground" className="text-foreground font-medium"
amount={category.currentAmount} amount={category.currentAmount}
/> />
{category.percentageChange !== null ? ( {category.percentageChange !== null ? (
<span <span
className={`flex items-center gap-0.5 text-xs ${changeClassName}`} className={`flex items-center gap-0.5 text-xs font-medium ${changeClassName}`}
> >
{hasIncrease ? ( {hasIncrease ? (
<RiArrowUpSFill className="size-3" /> <RiArrowUpSFill className="size-3" />

View File

@@ -197,7 +197,9 @@ export function CategoryHistoryWidget({ data }: CategoryHistoryWidgetProps) {
style={{ backgroundColor: color }} style={{ backgroundColor: color }}
/> />
)} )}
<span className="text-foreground">{category.name}</span> <span className="text-sm font-medium text-foreground">
{category.name}
</span>
<Button <Button
variant="ghost" variant="ghost"
size="sm" size="sm"
@@ -398,7 +400,7 @@ export function CategoryHistoryWidget({ data }: CategoryHistoryWidgetProps) {
{config?.label} {config?.label}
</span> </span>
</div> </div>
<span className="text-xs font-medium tabular-nums"> <span className="text-xs font-medium">
{formatCurrency(value)} {formatCurrency(value)}
</span> </span>
</div> </div>

View File

@@ -116,13 +116,14 @@ const getPercentChange = (current: number, previous: number): string => {
} }
const change = ((current - previous) / Math.abs(previous)) * 100; const change = ((current - previous) / Math.abs(previous)) * 100;
return Number.isFinite(change) && Math.abs(change) < 1000000 if (!Number.isFinite(change)) return "—";
? formatPercentage(change, { if (change > 999) return "+999%";
maximumFractionDigits: 1, if (change < -999) return "-999%";
minimumFractionDigits: 1, return formatPercentage(change, {
signDisplay: "always", maximumFractionDigits: 2,
}) minimumFractionDigits: 2,
: "—"; signDisplay: "always",
});
}; };
const getTrendBadgeClass = (trend: Trend, invertTrend: boolean): string => { const getTrendBadgeClass = (trend: Trend, invertTrend: boolean): string => {
@@ -159,7 +160,7 @@ export function DashboardMetricsCards({ metrics }: DashboardMetricsCardsProps) {
<CardHeader> <CardHeader>
<div className="flex items-start justify-between"> <div className="flex items-start justify-between">
<div> <div>
<CardTitle className="flex items-center gap-1.5 tracking-tight"> <CardTitle className="flex items-center gap-1.5 ">
<Icon className={cn("size-4", iconClass)} aria-hidden /> <Icon className={cn("size-4", iconClass)} aria-hidden />
{label} {label}
<MetricsCardInfoButton <MetricsCardInfoButton
@@ -179,12 +180,12 @@ export function DashboardMetricsCards({ metrics }: DashboardMetricsCardsProps) {
<CardContent className="flex flex-col gap-3"> <CardContent className="flex flex-col gap-3">
<div className="flex flex-wrap items-center justify-between gap-2 mt-1"> <div className="flex flex-wrap items-center justify-between gap-2 mt-1">
<MoneyValues <MoneyValues
className="text-2xl leading-none" className="text-2xl leading-none font-medium"
amount={metric.current} amount={metric.current}
/> />
<div <div
className={cn( className={cn(
"inline-flex items-center gap-1 text-xs ", "inline-flex items-center gap-1 text-xs font-medium",
trendBadgeClass, trendBadgeClass,
)} )}
> >
@@ -195,7 +196,7 @@ export function DashboardMetricsCards({ metrics }: DashboardMetricsCardsProps) {
<div className="text-xs text-muted-foreground"> <div className="text-xs text-muted-foreground">
<MoneyValues <MoneyValues
className="inline text-xs text-muted-foreground" className="inline text-xs font-medium text-muted-foreground"
amount={metric.previous} amount={metric.previous}
/> />
<span className="ml-1">no mês anterior</span> <span className="ml-1">no mês anterior</span>

View File

@@ -1,17 +1,21 @@
import { formatCurrentDate, getGreeting } from "./welcome-widget"; import { formatCurrentDate, getGreeting } from "./welcome-widget";
export function DashboardWelcome({ name }: { name?: string | null }) { type DashboardWelcomeProps = {
name?: string | null;
};
export function DashboardWelcome({ name }: DashboardWelcomeProps) {
const displayName = name && name.trim().length > 0 ? name : "Administrador"; const displayName = name && name.trim().length > 0 ? name : "Administrador";
const formattedDate = formatCurrentDate(); const formattedDate = formatCurrentDate();
const greeting = getGreeting(); const greeting = getGreeting();
return ( return (
<section className="py-4"> <section className="py-4">
<div className="tracking-tight"> <div>
<h1 className="text-xl font-medium"> <h1 className="text-xl tracking-tight">
{greeting}, {displayName} {greeting}, {displayName}
</h1> </h1>
<h2 className="text-sm mt-1 text-muted-foreground">{formattedDate}</h2> <h2 className="mt-1 text-sm text-muted-foreground">{formattedDate}</h2>
</div> </div>
</section> </section>
); );

View File

@@ -44,8 +44,9 @@ export function GoalProgressItem({
{item.categoryName} {item.categoryName}
</p> </p>
<p className="mt-0.5 text-xs text-muted-foreground"> <p className="mt-0.5 text-xs text-muted-foreground">
<MoneyValues amount={item.spentAmount} /> de{" "} <MoneyValues className="font-medium" amount={item.spentAmount} />{" "}
<MoneyValues amount={item.budgetAmount} /> de{" "}
<MoneyValues className="font-medium" amount={item.budgetAmount} />
<span className={`ml-1.5 font-medium ${deltaColor}`}> <span className={`ml-1.5 font-medium ${deltaColor}`}>
{formatGoalProgressPercentage(percentageDelta, true)} {formatGoalProgressPercentage(percentageDelta, true)}
</span> </span>

View File

@@ -132,12 +132,12 @@ export function InstallmentAnalysisPage({
{/* Card de resumo principal */} {/* Card de resumo principal */}
<Card className="border-none bg-primary/15"> <Card className="border-none bg-primary/15">
<CardContent className="flex flex-col items-start justify-center gap-2 py-2"> <CardContent className="flex flex-col items-start justify-center gap-2 py-2">
<p className="text-sm font-medium text-muted-foreground"> <p className="text-sm text-muted-foreground">
Se você pagar tudo que está selecionado: Se você pagar tudo que está selecionado:
</p> </p>
<MoneyValues <MoneyValues
amount={grandTotal} amount={grandTotal}
className="text-3xl font-medium text-primary" className="text-3xl font-semibold text-primary"
/> />
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
{selectedCount} {selectedCount === 1 ? "parcela" : "parcelas"}{" "} {selectedCount} {selectedCount === 1 ? "parcela" : "parcelas"}{" "}
@@ -167,7 +167,7 @@ export function InstallmentAnalysisPage({
{/* Seção de Lançamentos Parcelados */} {/* Seção de Lançamentos Parcelados */}
{data.installmentGroups.length > 0 && ( {data.installmentGroups.length > 0 && (
<div className="flex flex-col gap-3"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
{data.installmentGroups.map((group) => ( {data.installmentGroups.map((group) => (
<InstallmentGroupCard <InstallmentGroupCard
key={group.seriesId} key={group.seriesId}

View File

@@ -59,7 +59,10 @@ export function InstallmentExpenseListItem({
</span> </span>
) : null} ) : null}
</div> </div>
<MoneyValues amount={expense.amount} className="shrink-0" /> <MoneyValues
amount={expense.amount}
className="shrink-0 font-medium"
/>
</div> </div>
<p className="text-xs text-muted-foreground"> <p className="text-xs text-muted-foreground">
@@ -67,7 +70,7 @@ export function InstallmentExpenseListItem({
{" · Restante "} {" · Restante "}
<MoneyValues <MoneyValues
amount={remainingAmount} amount={remainingAmount}
className="inline-block font-medium" className="inline-block font-semibold"
/>{" "} />{" "}
({remainingInstallments}) ({remainingInstallments})
</p> </p>

View File

@@ -116,7 +116,10 @@ export function InvoiceListItem({ invoice, onPay }: InvoiceListItemProps) {
</p> </p>
</div> </div>
<div className="text-sm font-medium text-foreground"> <div className="text-sm font-medium text-foreground">
<MoneyValues amount={share.amount} /> <MoneyValues
className="font-medium"
amount={share.amount}
/>
</div> </div>
</li> </li>
))} ))}
@@ -144,7 +147,7 @@ export function InvoiceListItem({ invoice, onPay }: InvoiceListItemProps) {
paymentTooltipLabel ? ( paymentTooltipLabel ? (
<Tooltip> <Tooltip>
<TooltipTrigger asChild> <TooltipTrigger asChild>
<span className="cursor-help text-success"> <span className="cursor-help text-success font-semibold">
{paymentInfo.label} {paymentInfo.label}
</span> </span>
</TooltipTrigger> </TooltipTrigger>
@@ -153,7 +156,9 @@ export function InvoiceListItem({ invoice, onPay }: InvoiceListItemProps) {
</TooltipContent> </TooltipContent>
</Tooltip> </Tooltip>
) : ( ) : (
<span className="text-success">{paymentInfo.label}</span> <span className="text-success font-semibold">
{paymentInfo.label}
</span>
) )
) : null} ) : null}
</div> </div>
@@ -161,7 +166,10 @@ export function InvoiceListItem({ invoice, onPay }: InvoiceListItemProps) {
</div> </div>
<div className="flex shrink-0 flex-col items-end"> <div className="flex shrink-0 flex-col items-end">
<MoneyValues amount={Math.abs(invoice.totalAmount)} /> <MoneyValues
className="font-medium"
amount={Math.abs(invoice.totalAmount)}
/>
<Button <Button
type="button" type="button"
size="sm" size="sm"

View File

@@ -113,7 +113,7 @@ export function InvoicePaymentDialog({
<p className="text-xs font-medium text-muted-foreground uppercase tracking-wide"> <p className="text-xs font-medium text-muted-foreground uppercase tracking-wide">
Cartão Cartão
</p> </p>
<p className="truncate text-base font-medium text-foreground"> <p className="truncate text-base font-semibold text-foreground">
{invoice.cardName} {invoice.cardName}
</p> </p>
</div> </div>
@@ -130,7 +130,7 @@ export function InvoicePaymentDialog({
</div> </div>
<MoneyValues <MoneyValues
amount={Math.abs(invoice.totalAmount)} amount={Math.abs(invoice.totalAmount)}
className="text-lg font-medium" className="text-lg font-semibold"
/> />
</div> </div>

View File

@@ -78,7 +78,7 @@ export function MyAccountsWidget({
<div className="flex items-start justify-between gap-3 py-1"> <div className="flex items-start justify-between gap-3 py-1">
<div className="space-y-1"> <div className="space-y-1">
<p className="text-sm text-muted-foreground">Saldo Total</p> <p className="text-sm text-muted-foreground">Saldo Total</p>
<MoneyValues className="text-2xl" amount={totalBalance} /> <MoneyValues className="text-2xl font-medium" amount={totalBalance} />
</div> </div>
{excludedAccountsCount > 0 ? ( {excludedAccountsCount > 0 ? (
@@ -137,7 +137,7 @@ export function MyAccountsWidget({
</div> </div>
) : ( ) : (
<ul className="flex flex-col"> <ul className="flex flex-col">
{displayedAccounts.map((account) => { {displayedAccounts.map((account, index) => {
const logoSrc = resolveLogoSrc(account.logo); const logoSrc = resolveLogoSrc(account.logo);
return ( return (
@@ -154,6 +154,7 @@ export function MyAccountsWidget({
fill fill
sizes="38px" sizes="38px"
className="object-contain rounded-full" className="object-contain rounded-full"
priority={index === 0}
/> />
) : null} ) : null}
</div> </div>
@@ -199,7 +200,10 @@ export function MyAccountsWidget({
</div> </div>
<div className="flex flex-col items-end gap-0.5 text-right"> <div className="flex flex-col items-end gap-0.5 text-right">
<MoneyValues amount={account.balance} /> <MoneyValues
className="font-medium"
amount={account.balance}
/>
</div> </div>
</div> </div>
); );

View File

@@ -83,10 +83,13 @@ export function PayersWidget({ payers }: PayersWidgetProps) {
</div> </div>
<div className="flex shrink-0 flex-col items-end"> <div className="flex shrink-0 flex-col items-end">
<MoneyValues amount={payer.totalExpenses} /> <MoneyValues
className="font-medium"
amount={payer.totalExpenses}
/>
{percentageChange !== null && ( {percentageChange !== null && (
<span <span
className={`flex items-center gap-0.5 text-xs ${ className={`flex items-center gap-0.5 text-xs font-medium ${
percentageChange > 0 percentageChange > 0
? "text-destructive" ? "text-destructive"
: percentageChange < 0 : percentageChange < 0

View File

@@ -8,11 +8,15 @@ import { PaymentOverviewWidgetView } from "./payment-overview/payment-overview-w
type PaymentOverviewWidgetProps = { type PaymentOverviewWidgetProps = {
paymentConditionsData: PaymentConditionsData; paymentConditionsData: PaymentConditionsData;
paymentMethodsData: PaymentMethodsData; paymentMethodsData: PaymentMethodsData;
period: string;
adminPayerSlug: string | null;
}; };
export function PaymentOverviewWidget({ export function PaymentOverviewWidget({
paymentConditionsData, paymentConditionsData,
paymentMethodsData, paymentMethodsData,
period,
adminPayerSlug,
}: PaymentOverviewWidgetProps) { }: PaymentOverviewWidgetProps) {
const { activeTab, handleTabChange } = usePaymentOverviewWidgetController(); const { activeTab, handleTabChange } = usePaymentOverviewWidgetController();
@@ -22,6 +26,8 @@ export function PaymentOverviewWidget({
paymentConditionsData={paymentConditionsData} paymentConditionsData={paymentConditionsData}
paymentMethodsData={paymentMethodsData} paymentMethodsData={paymentMethodsData}
onTabChange={handleTabChange} onTabChange={handleTabChange}
period={period}
adminPayerSlug={adminPayerSlug}
/> />
); );
} }

View File

@@ -1,3 +1,5 @@
import { RiExternalLinkLine } from "@remixicon/react";
import Link from "next/link";
import type { ReactNode } from "react"; import type { ReactNode } from "react";
import { import {
formatPaymentBreakdownPercentage, formatPaymentBreakdownPercentage,
@@ -17,6 +19,7 @@ export type PaymentBreakdownListItemData = {
amount: number; amount: number;
transactions: number; transactions: number;
percentage: number; percentage: number;
href?: string;
}; };
type PaymentBreakdownListItemProps = { type PaymentBreakdownListItemProps = {
@@ -40,8 +43,21 @@ export function PaymentBreakdownListItem({
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<p className="text-sm font-medium text-foreground">{item.title}</p> {item.href ? (
<MoneyValues amount={item.amount} /> <Link
href={item.href}
className="inline-flex items-center gap-1 text-sm font-medium text-foreground underline-offset-2 hover:text-primary hover:underline"
>
<span className="truncate">{item.title}</span>
<RiExternalLinkLine
className="size-3 shrink-0 text-muted-foreground"
aria-hidden
/>
</Link>
) : (
<p className="text-sm font-medium text-foreground">{item.title}</p>
)}
<MoneyValues className="font-medium" amount={item.amount} />
</div> </div>
<div className="flex items-center justify-between text-xs text-muted-foreground"> <div className="flex items-center justify-between text-xs text-muted-foreground">

View File

@@ -1,6 +1,8 @@
import { RiCheckLine, RiSlideshowLine } from "@remixicon/react"; import { RiCheckLine, RiSlideshowLine } from "@remixicon/react";
import type { PaymentConditionsData } from "@/features/dashboard/payments/payment-conditions-queries"; import type { PaymentConditionsData } from "@/features/dashboard/payments/payment-conditions-queries";
import { getConditionIcon } from "@/shared/utils/icons"; import { getConditionIcon } from "@/shared/utils/icons";
import { formatPeriodForUrl } from "@/shared/utils/period";
import { slugify } from "@/shared/utils/string";
import { import {
PaymentBreakdownList, PaymentBreakdownList,
type PaymentBreakdownListItemData, type PaymentBreakdownListItemData,
@@ -8,6 +10,8 @@ import {
type PaymentConditionsWidgetProps = { type PaymentConditionsWidgetProps = {
data: PaymentConditionsData; data: PaymentConditionsData;
period: string;
adminPayerSlug: string | null;
}; };
const resolveConditionIcon = (condition: string) => const resolveConditionIcon = (condition: string) =>
@@ -15,16 +19,27 @@ const resolveConditionIcon = (condition: string) =>
export function PaymentConditionsWidget({ export function PaymentConditionsWidget({
data, data,
period,
adminPayerSlug,
}: PaymentConditionsWidgetProps) { }: PaymentConditionsWidgetProps) {
const items: PaymentBreakdownListItemData[] = data.conditions.map( const items: PaymentBreakdownListItemData[] = data.conditions.map(
(condition) => ({ (condition) => {
id: condition.condition, const params = new URLSearchParams({
title: condition.condition, type: slugify("Despesa"),
icon: resolveConditionIcon(condition.condition), condition: slugify(condition.condition),
amount: condition.amount, periodo: formatPeriodForUrl(period),
transactions: condition.transactions, });
percentage: condition.percentage, if (adminPayerSlug) params.set("payer", adminPayerSlug);
}), return {
id: condition.condition,
title: condition.condition,
icon: resolveConditionIcon(condition.condition),
amount: condition.amount,
transactions: condition.transactions,
percentage: condition.percentage,
href: `/transactions?${params.toString()}`,
};
},
); );
return ( return (

View File

@@ -1,6 +1,8 @@
import { RiBankCard2Line, RiMoneyDollarCircleLine } from "@remixicon/react"; import { RiBankCard2Line, RiMoneyDollarCircleLine } from "@remixicon/react";
import type { PaymentMethodsData } from "@/features/dashboard/payments/payment-methods-queries"; import type { PaymentMethodsData } from "@/features/dashboard/payments/payment-methods-queries";
import { getPaymentMethodIcon } from "@/shared/utils/icons"; import { getPaymentMethodIcon } from "@/shared/utils/icons";
import { formatPeriodForUrl } from "@/shared/utils/period";
import { slugify } from "@/shared/utils/string";
import { import {
PaymentBreakdownList, PaymentBreakdownList,
type PaymentBreakdownListItemData, type PaymentBreakdownListItemData,
@@ -8,6 +10,8 @@ import {
type PaymentMethodsWidgetProps = { type PaymentMethodsWidgetProps = {
data: PaymentMethodsData; data: PaymentMethodsData;
period: string;
adminPayerSlug: string | null;
}; };
const resolvePaymentMethodIcon = (paymentMethod: string) => const resolvePaymentMethodIcon = (paymentMethod: string) =>
@@ -15,15 +19,28 @@ const resolvePaymentMethodIcon = (paymentMethod: string) =>
<RiBankCard2Line className="size-5" aria-hidden /> <RiBankCard2Line className="size-5" aria-hidden />
); );
export function PaymentMethodsWidget({ data }: PaymentMethodsWidgetProps) { export function PaymentMethodsWidget({
const items: PaymentBreakdownListItemData[] = data.methods.map((method) => ({ data,
id: method.paymentMethod, period,
title: method.paymentMethod, adminPayerSlug,
icon: resolvePaymentMethodIcon(method.paymentMethod), }: PaymentMethodsWidgetProps) {
amount: method.amount, const items: PaymentBreakdownListItemData[] = data.methods.map((method) => {
transactions: method.transactions, const params = new URLSearchParams({
percentage: method.percentage, type: slugify("Despesa"),
})); payment: slugify(method.paymentMethod),
periodo: formatPeriodForUrl(period),
});
if (adminPayerSlug) params.set("payer", adminPayerSlug);
return {
id: method.paymentMethod,
title: method.paymentMethod,
icon: resolvePaymentMethodIcon(method.paymentMethod),
amount: method.amount,
transactions: method.transactions,
percentage: method.percentage,
href: `/transactions?${params.toString()}`,
};
});
return ( return (
<PaymentBreakdownList <PaymentBreakdownList

View File

@@ -16,6 +16,8 @@ type PaymentOverviewWidgetViewProps = {
paymentConditionsData: PaymentConditionsData; paymentConditionsData: PaymentConditionsData;
paymentMethodsData: PaymentMethodsData; paymentMethodsData: PaymentMethodsData;
onTabChange: (value: string) => void; onTabChange: (value: string) => void;
period: string;
adminPayerSlug: string | null;
}; };
export function PaymentOverviewWidgetView({ export function PaymentOverviewWidgetView({
@@ -23,6 +25,8 @@ export function PaymentOverviewWidgetView({
paymentConditionsData, paymentConditionsData,
paymentMethodsData, paymentMethodsData,
onTabChange, onTabChange,
period,
adminPayerSlug,
}: PaymentOverviewWidgetViewProps) { }: PaymentOverviewWidgetViewProps) {
return ( return (
<Tabs value={activeTab} onValueChange={onTabChange} className="w-full"> <Tabs value={activeTab} onValueChange={onTabChange} className="w-full">
@@ -38,11 +42,19 @@ export function PaymentOverviewWidgetView({
</TabsList> </TabsList>
<TabsContent value="conditions" className="mt-2"> <TabsContent value="conditions" className="mt-2">
<PaymentConditionsWidget data={paymentConditionsData} /> <PaymentConditionsWidget
data={paymentConditionsData}
period={period}
adminPayerSlug={adminPayerSlug}
/>
</TabsContent> </TabsContent>
<TabsContent value="methods" className="mt-2"> <TabsContent value="methods" className="mt-2">
<PaymentMethodsWidget data={paymentMethodsData} /> <PaymentMethodsWidget
data={paymentMethodsData}
period={period}
adminPayerSlug={adminPayerSlug}
/>
</TabsContent> </TabsContent>
</Tabs> </Tabs>
); );

View File

@@ -24,10 +24,7 @@ export function PaymentStatusCategorySection({
<div className="mt-4 space-y-3"> <div className="mt-4 space-y-3">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<span className="text-sm font-medium text-foreground">{title}</span> <span className="text-sm font-medium text-foreground">{title}</span>
<MoneyValues <MoneyValues amount={total} className="font-medium" />
amount={total}
className="text-sm font-medium tabular-nums"
/>
</div> </div>
<Progress value={confirmedPercentage} className="h-2" /> <Progress value={confirmedPercentage} className="h-2" />
@@ -35,13 +32,13 @@ export function PaymentStatusCategorySection({
<div className="flex flex-col gap-1 text-sm sm:flex-row sm:items-center sm:justify-between sm:gap-4"> <div className="flex flex-col gap-1 text-sm sm:flex-row sm:items-center sm:justify-between sm:gap-4">
<div className="flex items-center gap-1.5"> <div className="flex items-center gap-1.5">
<StatusDot color="bg-primary" /> <StatusDot color="bg-primary" />
<MoneyValues amount={confirmed} className="tabular-nums" /> <MoneyValues amount={confirmed} className="font-medium" />
<span className="text-xs text-muted-foreground">confirmados</span> <span className="text-xs text-muted-foreground">confirmados</span>
</div> </div>
<div className="flex items-center gap-1.5"> <div className="flex items-center gap-1.5">
<StatusDot color="bg-warning/40" /> <StatusDot color="bg-warning/40" />
<MoneyValues amount={pending} className="tabular-nums" /> <MoneyValues amount={pending} className="font-medium" />
<span className="text-xs text-muted-foreground">pendentes</span> <span className="text-xs text-muted-foreground">pendentes</span>
</div> </div>
</div> </div>

View File

@@ -178,7 +178,10 @@ export function PurchasesByCategoryWidget({
</div> </div>
<div className="shrink-0 text-foreground"> <div className="shrink-0 text-foreground">
<MoneyValues amount={transaction.amount} /> <MoneyValues
className="font-medium"
amount={transaction.amount}
/>
</div> </div>
</div> </div>
); );

View File

@@ -45,7 +45,7 @@ export function RecurringExpensesWidget({
{expense.name} {expense.name}
</p> </p>
<MoneyValues amount={expense.amount} /> <MoneyValues className="font-medium" amount={expense.amount} />
</div> </div>
<div className="flex items-center justify-between text-xs text-muted-foreground"> <div className="flex items-center justify-between text-xs text-muted-foreground">

View File

@@ -48,7 +48,10 @@ export function TopEstablishmentsWidget({
</div> </div>
<div className="shrink-0 text-foreground"> <div className="shrink-0 text-foreground">
<MoneyValues amount={establishment.amount} /> <MoneyValues
className="font-medium"
amount={establishment.amount}
/>
</div> </div>
</div> </div>
); );

View File

@@ -113,7 +113,10 @@ export function TopExpensesWidget({
</div> </div>
<div className="shrink-0 text-foreground"> <div className="shrink-0 text-foreground">
<MoneyValues amount={expense.amount} /> <MoneyValues
className="font-medium"
amount={expense.amount}
/>
</div> </div>
</div> </div>
); );

View File

@@ -67,7 +67,7 @@ export function InboxDetailsDialog({
<Separator /> <Separator />
<div> <div>
<h4 className="mb-1 text-sm font-medium text-muted-foreground"> <h4 className="mb-1 text-sm font-semibold text-muted-foreground">
Notificação Original Notificação Original
</h4> </h4>
{item.originalTitle && ( {item.originalTitle && (

View File

@@ -82,7 +82,7 @@ export function InsightsGrid({ insights }: InsightsGridProps) {
<CardHeader> <CardHeader>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Icon className={cn("size-5", colors.chatAiIcon)} /> <Icon className={cn("size-5", colors.chatAiIcon)} />
<CardTitle className={cn("font-medium", colors.titleText)}> <CardTitle className={cn("font-semibold", colors.titleText)}>
{categoryConfig.title} {categoryConfig.title}
</CardTitle> </CardTitle>
</div> </div>

View File

@@ -301,7 +301,7 @@ function ErrorState({
return ( return (
<div className="flex flex-col items-center justify-center gap-4 py-12 px-4 text-center"> <div className="flex flex-col items-center justify-center gap-4 py-12 px-4 text-center">
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<h3 className="text-lg font-medium text-destructive">{title}</h3> <h3 className="text-lg font-semibold text-destructive">{title}</h3>
<p className="text-sm text-muted-foreground max-w-md">{error}</p> <p className="text-sm text-muted-foreground max-w-md">{error}</p>
</div> </div>
<Button onClick={onRetry} variant="outline"> <Button onClick={onRetry} variant="outline">

View File

@@ -133,7 +133,7 @@ export function ModelSelector({
<Card className="grid grid-cols-1 lg:grid-cols-[1fr,auto] gap-6 items-start p-6"> <Card className="grid grid-cols-1 lg:grid-cols-[1fr,auto] gap-6 items-start p-6">
{/* Descrição */} {/* Descrição */}
<div className="space-y-2"> <div className="space-y-2">
<h3 className="text-lg font-medium">Definir modelo de análise</h3> <h3 className="text-lg font-semibold">Definir modelo de análise</h3>
<p className="text-sm text-muted-foreground leading-relaxed"> <p className="text-sm text-muted-foreground leading-relaxed">
Escolha o provedor de IA e o modelo específico que será utilizado para Escolha o provedor de IA e o modelo específico que será utilizado para
gerar insights sobre seus dados financeiros. <br /> gerar insights sobre seus dados financeiros. <br />

View File

@@ -176,7 +176,7 @@ export function InvoiceSummaryCard({
</span> </span>
) : null} ) : null}
<div className="min-w-0"> <div className="min-w-0">
<h2 className="truncate text-sm font-medium text-foreground"> <h2 className="truncate text-sm font-semibold text-foreground">
{cardName} {cardName}
</h2> </h2>
<p className="text-xs text-muted-foreground"> <p className="text-xs text-muted-foreground">
@@ -189,13 +189,11 @@ export function InvoiceSummaryCard({
{/* Linha 2 — valor da fatura (hero) */} {/* Linha 2 — valor da fatura (hero) */}
<div className="space-y-4"> <div className="space-y-4">
<p className="text-sm font-medium text-muted-foreground"> <p className="text-sm text-muted-foreground">Valor da fatura</p>
Valor da fatura
</p>
<MoneyValues <MoneyValues
amount={totalAmount} amount={totalAmount}
className={cn( className={cn(
"text-3xl leading-none font-medium tracking-tight sm:text-[2rem]", "text-3xl leading-none tracking-tighter sm:text-[2rem]",
isPaid ? "text-success" : "text-foreground", isPaid ? "text-success" : "text-foreground",
)} )}
/> />

View File

@@ -103,7 +103,7 @@ function StepCard({
{step} {step}
</div> </div>
<div className="min-w-0"> <div className="min-w-0">
<h3 className="font-medium mb-1.5 md:mb-2">{title}</h3> <h3 className="font-semibold mb-1.5 md:mb-2">{title}</h3>
{children} {children}
</div> </div>
</div> </div>

View File

@@ -77,7 +77,7 @@ export function NoteCard({
<CardContent className="flex min-h-0 flex-1 flex-col gap-4"> <CardContent className="flex min-h-0 flex-1 flex-col gap-4">
<div className="flex shrink-0 items-start justify-between gap-3"> <div className="flex shrink-0 items-start justify-between gap-3">
<div className="flex min-w-0 flex-col gap-1"> <div className="flex min-w-0 flex-col gap-1">
<h3 className="text-lg font-medium leading-tight text-foreground wrap-break-word"> <h3 className="text-lg font-semibold text-foreground wrap-break-word">
{displayTitle} {displayTitle}
</h3> </h3>
{createdAtLabel && ( {createdAtLabel && (

View File

@@ -118,7 +118,7 @@ export function PayerHeaderCard({
<div className="flex flex-1 flex-col gap-2"> <div className="flex flex-1 flex-col gap-2">
<div className="flex flex-wrap items-center gap-2"> <div className="flex flex-wrap items-center gap-2">
<CardTitle className="text-xl font-medium text-foreground"> <CardTitle className="text-xl font-semibold text-foreground">
{payer.name} {payer.name}
</CardTitle> </CardTitle>
{isAdmin ? ( {isAdmin ? (
@@ -215,10 +215,10 @@ export function PayerHeaderCard({
<RiExchangeDollarLine className="size-5 text-primary" /> <RiExchangeDollarLine className="size-5 text-primary" />
</div> </div>
<div> <div>
<p className="text-sm font-medium text-muted-foreground"> <p className="text-sm text-muted-foreground">
Total de Despesas Total de Despesas
</p> </p>
<p className="text-2xl font-medium text-foreground"> <p className="text-2xl font-semibold text-foreground">
{formatCurrency(summary.totalExpenses)} {formatCurrency(summary.totalExpenses)}
</p> </p>
</div> </div>
@@ -239,7 +239,7 @@ export function PayerHeaderCard({
Cartões Cartões
</span> </span>
</div> </div>
<p className="text-lg font-medium text-foreground"> <p className="text-lg font-semibold text-foreground">
{formatCurrency(summary.paymentSplits.card)} {formatCurrency(summary.paymentSplits.card)}
</p> </p>
</div> </div>
@@ -251,7 +251,7 @@ export function PayerHeaderCard({
Boletos Boletos
</span> </span>
</div> </div>
<p className="text-lg font-medium text-foreground"> <p className="text-lg font-semibold text-foreground">
{formatCurrency(summary.paymentSplits.boleto)} {formatCurrency(summary.paymentSplits.boleto)}
</p> </p>
</div> </div>
@@ -263,7 +263,7 @@ export function PayerHeaderCard({
Pix/Débito Pix/Débito
</span> </span>
</div> </div>
<p className="text-lg font-medium text-foreground"> <p className="text-lg font-semibold text-foreground">
{formatCurrency(summary.paymentSplits.instant)} {formatCurrency(summary.paymentSplits.instant)}
</p> </p>
</div> </div>

View File

@@ -63,7 +63,7 @@ export function PayerHistoryCard({ data }: PagadorHistoryCardProps) {
return ( return (
<Card className="border"> <Card className="border">
<CardHeader className="gap-1.5 pb-3"> <CardHeader className="gap-1.5 pb-3">
<CardTitle className="text-lg font-medium"> <CardTitle className="text-lg font-semibold">
Evolução (últimos 6 meses) Evolução (últimos 6 meses)
</CardTitle> </CardTitle>
<p className="text-xs text-muted-foreground"> <p className="text-xs text-muted-foreground">

View File

@@ -31,7 +31,7 @@ export function PagadorInfoCard({ payer }: PayerInfoCardProps) {
return ( return (
<Card className="border gap-4"> <Card className="border gap-4">
<CardHeader className="gap-1.5"> <CardHeader className="gap-1.5">
<CardTitle className="text-lg font-medium"> <CardTitle className="text-lg font-semibold">
Detalhes do pagador Detalhes do pagador
</CardTitle> </CardTitle>
<CardDescription> <CardDescription>
@@ -106,7 +106,7 @@ export function PagadorInfoCard({ payer }: PayerInfoCardProps) {
const resolveRoleLabel = (role: string | null) => { const resolveRoleLabel = (role: string | null) => {
if (role === PAYER_ROLE_ADMIN) return "Administrador"; if (role === PAYER_ROLE_ADMIN) return "Administrador";
return "Payer"; return "Pagador";
}; };
type InfoItemProps = { type InfoItemProps = {

View File

@@ -53,7 +53,7 @@ export function PayerLeaveShareCard({
return ( return (
<Card className="border"> <Card className="border">
<CardHeader> <CardHeader>
<CardTitle className="text-base font-medium"> <CardTitle className="text-base font-semibold">
Acesso Compartilhado Acesso Compartilhado
</CardTitle> </CardTitle>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">

View File

@@ -51,7 +51,7 @@ export function PayerMonthlySummaryCard({
return ( return (
<Card> <Card>
<CardHeader className="flex flex-col gap-1.5"> <CardHeader className="flex flex-col gap-1.5">
<CardTitle className="text-lg font-medium">Totais do mês</CardTitle> <CardTitle className="text-lg font-semibold">Totais do mês</CardTitle>
<p className="text-xs text-muted-foreground"> <p className="text-xs text-muted-foreground">
{periodLabel} - Despesas por forma de pagamento {periodLabel} - Despesas por forma de pagamento
</p> </p>
@@ -65,7 +65,7 @@ export function PayerMonthlySummaryCard({
</span> </span>
<MoneyValues <MoneyValues
amount={breakdown.totalExpenses} amount={breakdown.totalExpenses}
className="block text-2xl font-medium text-foreground" className="block text-2xl font-semibold text-foreground"
/> />
</div> </div>
@@ -100,7 +100,7 @@ export function PayerMonthlySummaryCard({
totalBase > 0 ? Math.round((entry.value / totalBase) * 100) : 0; totalBase > 0 ? Math.round((entry.value / totalBase) * 100) : 0;
return ( return (
<div key={entry.key} className="space-y-1 rounded-lg border p-3"> <div key={entry.key} className="space-y-1 rounded-lg border p-3">
<span className="flex items-center gap-2 text-xs font-medium uppercase tracking-wide text-muted-foreground/70"> <span className="flex items-center gap-2 text-xs uppercase tracking-wide text-muted-foreground/70">
<span <span
className={cn("size-2 rounded-full", entry.color)} className={cn("size-2 rounded-full", entry.color)}
aria-hidden aria-hidden
@@ -109,7 +109,7 @@ export function PayerMonthlySummaryCard({
</span> </span>
<MoneyValues <MoneyValues
amount={entry.value} amount={entry.value}
className="block text-lg font-medium text-foreground" className="block text-lg font-semibold text-foreground"
/> />
<span className="text-xs text-muted-foreground"> <span className="text-xs text-muted-foreground">
{percent}% das despesas {percent}% das despesas

View File

@@ -84,7 +84,9 @@ export function PayerSharingCard({
return ( return (
<Card className="border"> <Card className="border">
<CardHeader> <CardHeader>
<CardTitle className="text-lg font-medium">Compartilhamentos</CardTitle> <CardTitle className="text-lg font-semibold">
Compartilhamentos
</CardTitle>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Compartilhe o código abaixo com outra pessoa. Ela poderá adicioná-lo Compartilhe o código abaixo com outra pessoa. Ela poderá adicioná-lo
na página de pagadores usando a opção Adicionar por código para ter na página de pagadores usando a opção Adicionar por código para ter

View File

@@ -42,9 +42,7 @@ export function PayerCard({ payer, onEdit, onRemove }: PayerCardProps) {
{/* Nome e badges */} {/* Nome e badges */}
<div className="flex items-center gap-1.5"> <div className="flex items-center gap-1.5">
<h3 className="text-base font-medium text-foreground"> <h3 className="font-semibold text-foreground">{payer.name}</h3>
{payer.name}
</h3>
{isAdmin ? ( {isAdmin ? (
<RiVerifiedBadgeFill className="size-4 text-blue-500" aria-hidden /> <RiVerifiedBadgeFill className="size-4 text-blue-500" aria-hidden />
) : null} ) : null}

View File

@@ -119,7 +119,7 @@ export function PayerDialog({
const payerId = payer?.id; const payerId = payer?.id;
if (mode === "update" && !payerId) { if (mode === "update" && !payerId) {
const message = "Payer inválido."; const message = "Pagador inválido.";
setErrorMessage(message); setErrorMessage(message);
toast.error(message); toast.error(message);
return; return;

View File

@@ -142,7 +142,7 @@ export function CardUsageChart({ data, limit, card }: CardUsageChartProps) {
<span className="text-xs text-muted-foreground"> <span className="text-xs text-muted-foreground">
Uso Uso
</span> </span>
<span className="text-xs font-medium tabular-nums"> <span className="text-xs font-medium">
{formatCurrency(value, { {formatCurrency(value, {
maximumFractionDigits: 0, maximumFractionDigits: 0,
minimumFractionDigits: 0, minimumFractionDigits: 0,
@@ -154,7 +154,7 @@ export function CardUsageChart({ data, limit, card }: CardUsageChartProps) {
<span className="text-xs text-muted-foreground"> <span className="text-xs text-muted-foreground">
% do Limite % do Limite
</span> </span>
<span className="text-xs font-medium tabular-nums"> <span className="text-xs font-medium">
{formatPercentage(usagePercent, { {formatPercentage(usagePercent, {
maximumFractionDigits: 0, maximumFractionDigits: 0,
minimumFractionDigits: 0, minimumFractionDigits: 0,

View File

@@ -67,11 +67,11 @@ export function CardsOverview({ data }: CardsOverviewProps) {
<p className="text-xs text-muted-foreground">{card.title}</p> <p className="text-xs text-muted-foreground">{card.title}</p>
{card.isMoney ? ( {card.isMoney ? (
<MoneyValues <MoneyValues
className="text-2xl font-medium" className="text-2xl font-semibold"
amount={card.value} amount={card.value}
/> />
) : ( ) : (
<p className="text-2xl font-medium"> <p className="text-2xl font-semibold">
{formatPercentage(card.value, { {formatPercentage(card.value, {
maximumFractionDigits: 0, maximumFractionDigits: 0,
minimumFractionDigits: 0, minimumFractionDigits: 0,
@@ -83,7 +83,7 @@ export function CardsOverview({ data }: CardsOverviewProps) {
))} ))}
</div> </div>
<p className="text-base font-medium ml-2 py-2">Meus cartões</p> <p className="text-base font-semibold ml-2 py-2">Meus cartões</p>
{/* Cards list */} {/* Cards list */}
<div className="grid gap-2 grid-cols-2 lg:grid-cols-4 xl:grid-cols-4"> <div className="grid gap-2 grid-cols-2 lg:grid-cols-4 xl:grid-cols-4">
@@ -116,7 +116,7 @@ export function CardsOverview({ data }: CardsOverviewProps) {
</div> </div>
<div className="min-w-0 flex-1 space-y-1"> <div className="min-w-0 flex-1 space-y-1">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span className="text-base font-medium truncate"> <span className="text-base font-semibold truncate">
{card.name} {card.name}
</span> </span>
{brandAsset && ( {brandAsset && (
@@ -129,7 +129,7 @@ export function CardsOverview({ data }: CardsOverviewProps) {
/> />
)} )}
</div> </div>
<p className="text-xs text-muted-foreground tabular-nums"> <p className="text-xs text-muted-foreground">
{formatCurrency(card.currentUsage)} /{" "} {formatCurrency(card.currentUsage)} /{" "}
{formatCurrency(card.limit)} {formatCurrency(card.limit)}
</p> </p>
@@ -141,7 +141,7 @@ export function CardsOverview({ data }: CardsOverviewProps) {
`[&>div]:${getUsageColor(card.usagePercent)}`, `[&>div]:${getUsageColor(card.usagePercent)}`,
)} )}
/> />
<span className="text-xs font-medium tabular-nums"> <span className="text-xs font-medium">
{formatPercentage(card.usagePercent, { {formatPercentage(card.usagePercent, {
maximumFractionDigits: 0, maximumFractionDigits: 0,
minimumFractionDigits: 0, minimumFractionDigits: 0,

View File

@@ -53,7 +53,9 @@ export function CategoryCell({
> >
{isIncrease && <RiArrowUpSFill className="h-3 w-3" />} {isIncrease && <RiArrowUpSFill className="h-3 w-3" />}
{isDecrease && <RiArrowDownSFill className="h-3 w-3" />} {isDecrease && <RiArrowDownSFill className="h-3 w-3" />}
<span>{formatPercentageChange(percentageChange)}</span> <span className="font-medium">
{formatPercentageChange(percentageChange)}
</span>
</div> </div>
)} )}
</div> </div>

View File

@@ -73,7 +73,7 @@ function AreaTooltip({
{entry.name} {entry.name}
</span> </span>
</div> </div>
<span className="shrink-0 text-xs font-medium tabular-nums text-foreground"> <span className="shrink-0 text-xs font-medium text-foreground">
{currencyFormatter.format(Number(entry.value))} {currencyFormatter.format(Number(entry.value))}
</span> </span>
</div> </div>

View File

@@ -78,12 +78,12 @@ export function CategoryTable({
{periods.map((period) => ( {periods.map((period) => (
<TableHead <TableHead
key={period} key={period}
className="text-right min-w-[120px] font-medium" className="text-right min-w-[120px] font-semibold"
> >
{formatPeriodLabel(period)} {formatPeriodLabel(period)}
</TableHead> </TableHead>
))} ))}
<TableHead className="text-right min-w-[140px] font-medium"> <TableHead className="text-right min-w-[140px] font-semibold">
<div className="flex items-center justify-end gap-1"> <div className="flex items-center justify-end gap-1">
Média Média
<Tooltip> <Tooltip>
@@ -100,7 +100,7 @@ export function CategoryTable({
</Tooltip> </Tooltip>
</div> </div>
</TableHead> </TableHead>
<TableHead className="text-right min-w-[120px] font-medium"> <TableHead className="text-right min-w-[120px] font-semibold">
Total Total
</TableHead> </TableHead>
</TableRow> </TableRow>
@@ -128,7 +128,7 @@ export function CategoryTable({
/> />
<Link <Link
href={`/categories/${category.categoryId}?periodo=${periodParam}`} href={`/categories/${category.categoryId}?periodo=${periodParam}`}
className="flex items-center gap-1.5 truncate hover:underline underline-offset-2" className="flex items-center gap-1.5 truncate hover:underline underline-offset-2 font-semibold"
> >
{category.name} {category.name}
</Link> </Link>
@@ -149,7 +149,7 @@ export function CategoryTable({
</TableCell> </TableCell>
); );
})} })}
<TableCell className="text-right font-medium text-info"> <TableCell className="text-right font-semibold text-info">
{(() => { {(() => {
const nonZeroCount = periods.filter( const nonZeroCount = periods.filter(
(p) => (category.monthlyData.get(p)?.amount ?? 0) > 0, (p) => (category.monthlyData.get(p)?.amount ?? 0) > 0,
@@ -178,10 +178,10 @@ export function CategoryTable({
</TableCell> </TableCell>
); );
})} })}
<TableCell className="text-right font-medium text-info"> <TableCell className="text-right font-semibold text-info">
{formatCurrency(sectionTotals.averageMonthlyTotal)} {formatCurrency(sectionTotals.averageMonthlyTotal)}
</TableCell> </TableCell>
<TableCell className="text-right font-medium"> <TableCell className="text-right font-semibold">
{formatCurrency(sectionTotals.grandTotal)} {formatCurrency(sectionTotals.grandTotal)}
</TableCell> </TableCell>
</TableRow> </TableRow>

View File

@@ -19,7 +19,7 @@ export function HighlightsCards({ summary }: HighlightsCardsProps) {
</div> </div>
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<p className="text-xs font-medium">Mais Frequente</p> <p className="text-xs font-medium">Mais Frequente</p>
<p className="font-medium text-2xl truncate"> <p className="font-semibold text-2xl truncate">
{summary.mostFrequent || "—"} {summary.mostFrequent || "—"}
</p> </p>
</div> </div>
@@ -35,7 +35,7 @@ export function HighlightsCards({ summary }: HighlightsCardsProps) {
</div> </div>
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<p className="text-xs font-medium">Maior Gasto Total</p> <p className="text-xs font-medium">Maior Gasto Total</p>
<p className="font-medium text-2xl truncate"> <p className="font-semibold text-2xl truncate">
{summary.highestSpending || "—"} {summary.highestSpending || "—"}
</p> </p>
</div> </div>

View File

@@ -53,16 +53,14 @@ export function SummaryCards({ summary }: SummaryCardsProps) {
<CardContent className="px-4 py-2"> <CardContent className="px-4 py-2">
<div className="flex items-start justify-between gap-3"> <div className="flex items-start justify-between gap-3">
<div className="space-y-1"> <div className="space-y-1">
<p className="text-xs font-medium text-muted-foreground"> <p className="text-xs text-muted-foreground">{card.title}</p>
{card.title}
</p>
{card.isMoney ? ( {card.isMoney ? (
<MoneyValues <MoneyValues
className="text-2xl font-medium" className="text-2xl font-semibold"
amount={card.value} amount={card.value}
/> />
) : ( ) : (
<p className="text-2xl font-medium">{card.value}</p> <p className="text-2xl font-semibold">{card.value}</p>
)} )}
<p className="text-xs text-muted-foreground"> <p className="text-xs text-muted-foreground">
{card.description} {card.description}

View File

@@ -139,7 +139,7 @@ export function ApiTokensForm({ tokens }: ApiTokensFormProps) {
<div className="space-y-4"> <div className="space-y-4">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div> <div>
<h3 className="font-medium">Dispositivos conectados</h3> <h3 className="font-semibold">Dispositivos conectados</h3>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Gerencie os dispositivos que podem enviar notificações para o Gerencie os dispositivos que podem enviar notificações para o
OpenMonetis. OpenMonetis.

View File

@@ -32,7 +32,7 @@ export function ChangelogTab({ versions }: { versions: ChangelogVersion[] }) {
{versions.map((version) => ( {versions.map((version) => (
<Card key={version.version} className="p-6"> <Card key={version.version} className="p-6">
<div className="flex items-baseline gap-3"> <div className="flex items-baseline gap-3">
<h3 className="text-lg font-medium">v{version.version}</h3> <h3 className="text-lg font-semibold">v{version.version}</h3>
<span className="text-sm text-muted-foreground"> <span className="text-sm text-muted-foreground">
{version.date} {version.date}
</span> </span>

View File

@@ -84,7 +84,7 @@ export function DeleteAccountForm() {
<div className="rounded-lg border p-4"> <div className="rounded-lg border p-4">
<div className="space-y-4"> <div className="space-y-4">
<div> <div>
<h3 className="font-medium">Zerar conta</h3> <h3 className="font-semibold">Zerar conta</h3>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Apaga todos os dados do OpenMonetis e deixa sua conta no estado Apaga todos os dados do OpenMonetis e deixa sua conta no estado
inicial, mantendo seu login e credenciais de acesso. inicial, mantendo seu login e credenciais de acesso.
@@ -120,7 +120,7 @@ export function DeleteAccountForm() {
<div className="rounded-lg border border-destructive/30 bg-destructive/5 p-4"> <div className="rounded-lg border border-destructive/30 bg-destructive/5 p-4">
<div className="space-y-4"> <div className="space-y-4">
<div> <div>
<h3 className="font-medium text-destructive">Deletar conta</h3> <h3 className="font-semibold text-destructive">Deletar conta</h3>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Remove seu usuário e todos os dados associados de forma Remove seu usuário e todos os dados associados de forma
permanente. permanente.

View File

@@ -197,7 +197,7 @@ export function PasskeysForm() {
<div className="space-y-4"> <div className="space-y-4">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div> <div>
<h3 className="font-medium">Suas passkeys</h3> <h3 className="font-semibold">Suas passkeys</h3>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Gerencie suas passkeys para login sem senha. Gerencie suas passkeys para login sem senha.
</p> </p>

View File

@@ -145,7 +145,7 @@ export function PreferencesForm({
{/* Seção: Lançamentos */} {/* Seção: Lançamentos */}
<section className="space-y-4"> <section className="space-y-4">
<div> <div>
<h3 className="text-base font-medium">Lançamentos</h3> <h3 className="text-base font-semibold">Lançamentos</h3>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Configurações de exibição da tabela de movimentações. Configurações de exibição da tabela de movimentações.
</p> </p>

View File

@@ -131,7 +131,7 @@ export function UpdatePasswordForm({ authProvider }: UpdatePasswordFormProps) {
<div className="flex gap-3"> <div className="flex gap-3">
<RiAlertLine className="h-5 w-5 text-warning shrink-0 mt-0.5" /> <RiAlertLine className="h-5 w-5 text-warning shrink-0 mt-0.5" />
<div> <div>
<h3 className="font-medium text-warning"> <h3 className="font-semibold text-warning">
Alteração de senha não disponível Alteração de senha não disponível
</h3> </h3>
<p className="mt-1 text-sm text-warning"> <p className="mt-1 text-sm text-warning">

View File

@@ -54,6 +54,7 @@ function AttachmentPreview({
<Dialog open={open} onOpenChange={onOpenChange}> <Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent <DialogContent
showCloseButton={false} showCloseButton={false}
aria-describedby={undefined}
className="flex h-[92vh] w-[min(96vw,1400px)] max-w-none flex-col gap-0 overflow-hidden p-0 sm:p-0" className="flex h-[92vh] w-[min(96vw,1400px)] max-w-none flex-col gap-0 overflow-hidden p-0 sm:p-0"
> >
<DialogHeader className="flex-row items-center justify-between gap-3 border-b px-4 py-3 sm:px-5"> <DialogHeader className="flex-row items-center justify-between gap-3 border-b px-4 py-3 sm:px-5">

View File

@@ -44,8 +44,10 @@ export function AttachmentSection({
} = useTransactionAttachments(transactionId); } = useTransactionAttachments(transactionId);
useEffect(() => { useEffect(() => {
onLoaded?.(items.length); if (!isLoading) {
}, [items.length, onLoaded]); onLoaded?.(items.length);
}
}, [items.length, isLoading, onLoaded]);
const invalidateAttachments = () => { const invalidateAttachments = () => {
void queryClient.invalidateQueries({ void queryClient.invalidateQueries({

View File

@@ -342,21 +342,21 @@ export function AnticipateInstallmentsDialog({
{/* Seção 3: Resumo */} {/* Seção 3: Resumo */}
{selectedIds.length > 0 && ( {selectedIds.length > 0 && (
<div className="rounded-lg border bg-muted/20 p-3"> <div className="rounded-lg border bg-muted/20 p-3">
<h4 className="text-sm font-medium mb-2">Resumo</h4> <h4 className="text-sm font-semibold mb-2">Resumo</h4>
<dl className="space-y-1.5 text-sm"> <dl className="space-y-1.5 text-sm">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<dt className="text-muted-foreground"> <dt className="text-muted-foreground">
{selectedIds.length} parcela {selectedIds.length} parcela
{selectedIds.length > 1 ? "s" : ""} {selectedIds.length > 1 ? "s" : ""}
</dt> </dt>
<dd className="font-medium tabular-nums"> <dd className="font-medium">
<MoneyValues amount={totalAmount} className="text-sm" /> <MoneyValues amount={totalAmount} className="text-sm" />
</dd> </dd>
</div> </div>
{Number(formState.discount) > 0 && ( {Number(formState.discount) > 0 && (
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<dt className="text-muted-foreground">Desconto</dt> <dt className="text-muted-foreground">Desconto</dt>
<dd className="font-medium tabular-nums text-success"> <dd className="font-medium text-success">
-{" "} -{" "}
<MoneyValues <MoneyValues
amount={Number(formState.discount)} amount={Number(formState.discount)}
@@ -367,7 +367,7 @@ export function AnticipateInstallmentsDialog({
)} )}
<div className="flex items-center justify-between border-t pt-1.5"> <div className="flex items-center justify-between border-t pt-1.5">
<dt className="font-medium">Total</dt> <dt className="font-medium">Total</dt>
<dd className="text-base font-medium tabular-nums text-primary"> <dd className="text-base font-semibold text-primary">
<MoneyValues amount={finalAmount} className="text-sm" /> <MoneyValues amount={finalAmount} className="text-sm" />
</dd> </dd>
</div> </div>

View File

@@ -116,7 +116,7 @@ export function InstallmentSelectionTable({
<TableCell className="text-muted-foreground"> <TableCell className="text-muted-foreground">
{formatDate(inst.dueDate)} {formatDate(inst.dueDate)}
</TableCell> </TableCell>
<TableCell className="text-right font-medium tabular-nums"> <TableCell className="text-right font-medium">
<MoneyValues amount={Number(inst.amount)} /> <MoneyValues amount={Number(inst.amount)} />
</TableCell> </TableCell>
</TableRow> </TableRow>

View File

@@ -279,7 +279,7 @@ export function MassAddDialog({
<div className="space-y-4"> <div className="space-y-4">
{/* Fixed Fields Section */} {/* Fixed Fields Section */}
<div className="space-y-4"> <div className="space-y-4">
<h3 className="text-sm font-medium">Valores Padrão</h3> <h3 className="text-sm font-semibold">Valores Padrão</h3>
<div className="grid gap-3 grid-cols-1 sm:grid-cols-3"> <div className="grid gap-3 grid-cols-1 sm:grid-cols-3">
{/* Transaction Type */} {/* Transaction Type */}
<div className="space-y-2"> <div className="space-y-2">
@@ -452,7 +452,7 @@ export function MassAddDialog({
{/* Transactions Section */} {/* Transactions Section */}
<div className="space-y-4"> <div className="space-y-4">
<h3 className="text-sm font-medium">Lançamentos</h3> <h3 className="text-sm font-semibold">Lançamentos</h3>
<div className="space-y-3"> <div className="space-y-3">
{transactions.map((transaction, index) => ( {transactions.map((transaction, index) => (

View File

@@ -88,7 +88,7 @@ export function TransactionDetailsDialog({
<p className="text-xs uppercase tracking-wide text-muted-foreground"> <p className="text-xs uppercase tracking-wide text-muted-foreground">
Resumo Resumo
</p> </p>
<p className="mt-1 text-2xl font-medium"> <p className="mt-1 text-2xl font-semibold">
{currencyFormatter.format(valorTotal)} {currencyFormatter.format(valorTotal)}
</p> </p>
</div> </div>
@@ -116,7 +116,7 @@ export function TransactionDetailsDialog({
</section> </section>
<section className="space-y-2"> <section className="space-y-2">
<h3 className="text-xs font-medium uppercase tracking-wide text-muted-foreground"> <h3 className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
Detalhes Detalhes
</h3> </h3>
<ul className="min-w-0 grid gap-2 rounded-lg border p-3"> <ul className="min-w-0 grid gap-2 rounded-lg border p-3">
@@ -167,7 +167,7 @@ export function TransactionDetailsDialog({
</section> </section>
<section className="space-y-2"> <section className="space-y-2">
<h3 className="text-xs font-medium uppercase tracking-wide text-muted-foreground"> <h3 className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
Valores Valores
</h3> </h3>
<ul className="min-w-0 grid gap-2 rounded-lg border p-3"> <ul className="min-w-0 grid gap-2 rounded-lg border p-3">
@@ -207,7 +207,7 @@ export function TransactionDetailsDialog({
{transaction.note ? ( {transaction.note ? (
<section className="space-y-2"> <section className="space-y-2">
<h3 className="text-xs font-medium uppercase tracking-wide text-muted-foreground"> <h3 className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
Notas Notas
</h3> </h3>
<div className="rounded-lg border p-3 text-foreground"> <div className="rounded-lg border p-3 text-foreground">
@@ -218,7 +218,7 @@ export function TransactionDetailsDialog({
{attachmentCount !== 0 && ( {attachmentCount !== 0 && (
<section className="space-y-2"> <section className="space-y-2">
<h3 className="text-xs font-medium uppercase tracking-wide text-muted-foreground"> <h3 className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
Anexos Anexos
</h3> </h3>
<div className="min-w-0"> <div className="min-w-0">

View File

@@ -131,7 +131,7 @@ export function ReviewTable({
aria-label={`Selecionar ${row.description}`} aria-label={`Selecionar ${row.description}`}
/> />
</TableCell> </TableCell>
<TableCell className="text-muted-foreground text-sm tabular-nums"> <TableCell className="text-muted-foreground text-sm">
{formatDate(row.date)} {formatDate(row.date)}
</TableCell> </TableCell>
<TableCell className="max-w-[200px] text-sm"> <TableCell className="max-w-[200px] text-sm">
@@ -204,7 +204,7 @@ export function ReviewTable({
} }
/> />
</TableCell> </TableCell>
<TableCell className="text-right tabular-nums text-sm"> <TableCell className="text-right text-sm">
<MoneyValues <MoneyValues
amount={ amount={
row.transactionType === "expense" row.transactionType === "expense"

View File

@@ -84,7 +84,7 @@ export function AnticipationCard({
<dl className="grid grid-cols-2 gap-3 text-sm"> <dl className="grid grid-cols-2 gap-3 text-sm">
<div> <div>
<dt className="text-muted-foreground">Valor Original</dt> <dt className="text-muted-foreground">Valor Original</dt>
<dd className="mt-1 font-medium tabular-nums"> <dd className="mt-1 font-medium">
<MoneyValues amount={Number(anticipation.totalAmount)} /> <MoneyValues amount={Number(anticipation.totalAmount)} />
</dd> </dd>
</div> </div>
@@ -92,7 +92,7 @@ export function AnticipationCard({
{Number(anticipation.discount) > 0 && ( {Number(anticipation.discount) > 0 && (
<div> <div>
<dt className="text-muted-foreground">Desconto</dt> <dt className="text-muted-foreground">Desconto</dt>
<dd className="mt-1 font-medium tabular-nums text-success"> <dd className="mt-1 font-medium text-success">
- <MoneyValues amount={Number(anticipation.discount)} /> - <MoneyValues amount={Number(anticipation.discount)} />
</dd> </dd>
</div> </div>
@@ -110,7 +110,7 @@ export function AnticipationCard({
? "Valor Final" ? "Valor Final"
: "Valor Total"} : "Valor Total"}
</dt> </dt>
<dd className="mt-1 text-lg font-medium tabular-nums text-primary"> <dd className="mt-1 text-lg font-semibold text-primary">
<MoneyValues <MoneyValues
amount={ amount={
Number(anticipation.totalAmount) < 0 Number(anticipation.totalAmount) < 0

View File

@@ -34,7 +34,7 @@ export function CalculatorDisplay({
<div className="mt-auto flex items-end justify-end gap-2"> <div className="mt-auto flex items-end justify-end gap-2">
<div <div
className={cn( className={cn(
"truncate text-right font-medium tracking-tight tabular-nums leading-none transition-all", "truncate text-right font-medium tracking-tight leading-none transition-all",
isResultView ? "text-2xl" : "text-3xl", isResultView ? "text-2xl" : "text-3xl",
)} )}
> >

View File

@@ -20,9 +20,9 @@ function MoneyValues({ amount, className, showPositiveSign = false }: Props) {
return ( return (
<span <span
className={cn( className={cn(
"inline-flex items-baseline transition-all duration-200 tracking-tighter", "inline-flex items-baseline tabular-nums transition-all duration-200 tracking-tighter",
privacyMode && privacyMode &&
"blur-[6px] select-none hover:blur-none focus-within:blur-none", "blur-sm select-none hover:blur-none focus-within:blur-none",
className, className,
)} )}
aria-label={privacyMode ? "Valor oculto" : displayValue} aria-label={privacyMode ? "Valor oculto" : displayValue}

View File

@@ -37,7 +37,7 @@ export default function MonthNavigation() {
}; };
return ( return (
<Card className="sticky top-16 z-10 flex w-full flex-row p-4 backdrop-blur-xs supports-backdrop-filter:bg-card/80"> <Card className="sticky top-16 z-10 flex w-full flex-row p-4 backdrop-blur-xs supports-backdrop-filter:bg-card/80 ">
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<NavigationButton <NavigationButton
direction="left" direction="left"

View File

@@ -96,7 +96,7 @@ export function FeedbackDialogBody({ onClose }: { onClose?: () => void }) {
<Icon className={cn("h-5 w-5", item.color)} /> <Icon className={cn("h-5 w-5", item.color)} />
</div> </div>
<div className="flex-1 text-left space-y-1"> <div className="flex-1 text-left space-y-1">
<h3 className="font-medium text-sm flex items-center gap-2"> <h3 className="font-semibold text-sm flex items-center gap-2">
{item.title} {item.title}
<RiExternalLinkLine className="h-3.5 w-3.5 text-muted-foreground" /> <RiExternalLinkLine className="h-3.5 w-3.5 text-muted-foreground" />
</h3> </h3>

View File

@@ -42,7 +42,7 @@ export function NavDropdown({ items }: NavDropdownProps) {
{item.icon} {item.icon}
</span> </span>
<span className="flex flex-col min-w-0"> <span className="flex flex-col min-w-0">
<span className="font-medium">{item.label}</span> <span className="font-semibold">{item.label}</span>
{item.description && ( {item.description && (
<span className="text-xs text-muted-foreground truncate lowercase"> <span className="text-xs text-muted-foreground truncate lowercase">
{item.description} {item.description}

View File

@@ -42,7 +42,7 @@ export function NavMenu() {
return ( return (
<> <>
{/* Desktop */} {/* Desktop */}
<nav className="hidden md:flex items-center justify-center flex-1 "> <nav className="hidden md:flex items-center justify-center flex-1">
<NavigationMenu viewport={false}> <NavigationMenu viewport={false}>
<NavigationMenuList className="gap-0"> <NavigationMenuList className="gap-0">
<NavigationMenuItem> <NavigationMenuItem>

View File

@@ -22,7 +22,7 @@ export function NavToolsDropdown({ onOpenCalculator }: NavToolsDropdownProps) {
<RiCalculatorLine className="size-4" /> <RiCalculatorLine className="size-4" />
</span> </span>
<span className="flex flex-col flex-1 text-left"> <span className="flex flex-col flex-1 text-left">
<span className="font-medium">calculadora</span> <span className="font-semibold">calculadora</span>
<span className="text-xs text-muted-foreground lowercase"> <span className="text-xs text-muted-foreground lowercase">
Faça cálculos rápidos Faça cálculos rápidos
</span> </span>
@@ -39,7 +39,7 @@ export function NavToolsDropdown({ onOpenCalculator }: NavToolsDropdownProps) {
)} )}
</span> </span>
<span className="flex flex-col flex-1 text-left"> <span className="flex flex-col flex-1 text-left">
<span className="font-medium">privacidade</span> <span className="font-semibold">privacidade</span>
<span className="text-xs text-muted-foreground lowercase"> <span className="text-xs text-muted-foreground lowercase">
Oculta valores na tela Oculta valores na tela
</span> </span>

View File

@@ -126,7 +126,9 @@ export function NavbarUser({
> >
<RiHistoryLine className="size-4 text-muted-foreground shrink-0" /> <RiHistoryLine className="size-4 text-muted-foreground shrink-0" />
<span className="flex-1">Changelog</span> <span className="flex-1">Changelog</span>
<Badge variant="outline">v{version}</Badge> <Badge variant="outline" className="text-xs font-semibold">
v{version}
</Badge>
</Link> </Link>
<DialogTrigger asChild> <DialogTrigger asChild>
@@ -147,7 +149,7 @@ export function NavbarUser({
className={cn(itemClass, "text-success")} className={cn(itemClass, "text-success")}
> >
<RiMegaphoneLine className="size-4 text-success shrink-0" /> <RiMegaphoneLine className="size-4 text-success shrink-0" />
<span className="flex-1 tracking-wide text-xs font-medium"> <span className="flex-1 tracking-wide text-xs font-bold">
Atualização {updateCheck.latestVersion} disponível Atualização {updateCheck.latestVersion} disponível
</span> </span>
</Link> </Link>

Some files were not shown because too many files have changed in this diff Show More