refactor(ui): renomear "Pagador/Pagadores" para "Pessoa/Pessoas" na interface

Todas as strings visíveis ao usuário (labels, títulos, toasts, mensagens
de erro, cabeçalhos de tabela, exportações) foram atualizadas. Acordos
de gênero em português corrigidos. Código, rotas (/payers) e schema do
banco (pagadores) permanecem inalterados — divergência intencional
documentada em CLAUDE.md e CHANGELOG.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Felipe Coutinho
2026-04-20 18:29:55 +00:00
parent 2f68bcf039
commit 0bc3f06b77
42 changed files with 101 additions and 99 deletions

View File

@@ -2,7 +2,7 @@ import { RiGroupLine } from "@remixicon/react";
import PageDescription from "@/shared/components/page-description";
export const metadata = {
title: "Pagadores",
title: "Pessoas",
};
export default function RootLayout({
@@ -14,7 +14,7 @@ export default function RootLayout({
<section className="space-y-6">
<PageDescription
icon={<RiGroupLine />}
title="Pagadores"
title="Pessoas"
subtitle="Gerencie as pessoas ou entidades responsáveis pelos pagamentos."
/>
{children}

View File

@@ -1,7 +1,7 @@
import { Skeleton } from "@/shared/components/ui/skeleton";
/**
* Loading state para a página de pagadores
* Loading state para a página de pessoas
* Layout: Header + Input de compartilhamento + Grid de cards
*/
export default function PagadoresLoading() {
@@ -17,7 +17,7 @@ export default function PagadoresLoading() {
</div>
</div>
{/* Grid de cards de pagadores */}
{/* Grid de cards de pessoas */}
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
{Array.from({ length: 6 }).map((_, i) => (
<div key={i} className="rounded-md border p-6 space-y-4">

View File

@@ -99,7 +99,7 @@ export async function createAccountAction(
if (hasInitialBalance && !adminPayerId) {
throw new Error(
"Pagador com papel administrador não encontrado. Crie um pagador admin antes de definir um saldo inicial.",
"Pessoa com papel administrador não encontrado. Crie um pessoa admin antes de definir um saldo inicial.",
);
}
@@ -299,7 +299,7 @@ export async function transferBetweenAccountsAction(
if (!adminPayerId) {
throw new Error(
"Pagador administrador não encontrado. Por favor, crie um pagador admin.",
"Pessoa administrador não encontrado. Por favor, crie um pessoa admin.",
);
}

View File

@@ -123,7 +123,7 @@ export function AccountStatementCard({
<MetaItem
label="Saídas"
tooltip="Total de despesas pagas neste mês (considerando divisão entre pagadores)."
tooltip="Total de despesas pagas neste mês (considerando divisão entre pessoas)."
>
<span className="text-sm font-medium text-destructive">
{formatCurrency(totalExpenses)}

View File

@@ -38,7 +38,7 @@ const CARDS = [
helpTitle: "Como calculamos receitas",
helpLines: [
"Somamos os lançamentos do tipo Receita no período selecionado.",
"Consideramos lançamentos efetivados e não efetivados do pagador principal (admin).",
"Consideramos lançamentos efetivados e não efetivados da pessoa principal (admin).",
"Movimentações de contas marcadas como não consideradas no saldo total ficam fora deste card.",
"Não entram transferências internas nem lançamentos automáticos de fatura.",
"Saldo inicial também fica fora quando a conta está marcada para desconsiderá-lo das receitas.",
@@ -54,7 +54,7 @@ const CARDS = [
helpTitle: "Como calculamos despesas",
helpLines: [
"Somamos os lançamentos do tipo Despesa no período selecionado.",
"Consideramos lançamentos efetivados e não efetivados do pagador principal (admin).",
"Consideramos lançamentos efetivados e não efetivados da pessoa principal (admin).",
"Movimentações de contas marcadas como não consideradas no saldo total ficam fora deste card.",
"Não entram transferências internas nem lançamentos automáticos de fatura.",
"O valor mostrado é a saída efetiva do período, sempre em número positivo no card.",

View File

@@ -86,7 +86,7 @@ export function InvoiceListItem({ invoice, onPay }: InvoiceListItemProps) {
<HoverCardTrigger asChild>{linkNode}</HoverCardTrigger>
<HoverCardContent align="start" className="w-80 space-y-3">
<p className="text-xs text-muted-foreground">
Distribuição por pagador
Distribuição por pessoa
</p>
<ul className="space-y-2">
{breakdown.map((share, index) => (

View File

@@ -28,8 +28,8 @@ export function PayersWidget({ payers }: PayersWidgetProps) {
{payers.length === 0 ? (
<WidgetEmptyState
icon={<RiGroupLine className="size-6 text-muted-foreground" />}
title="Nenhum pagador para o período"
description="Quando houver despesas associadas a pagadores, eles aparecerão aqui."
title="Nenhuma pessoa para o período"
description="Quando houver despesas associadas a pessoas, elas aparecerão aqui."
/>
) : (
<div className="flex flex-col">

View File

@@ -71,7 +71,7 @@ export async function fetchInstallmentAnalysis(
return { installmentGroups: [], totalPendingInstallments: 0 };
}
// 1. Buscar todos os lançamentos parcelados não antecipados do pagador admin
// 1. Buscar todos os lançamentos parcelados não antecipados da pessoa admin
const installmentRows = await db
.select({
id: transactions.id,

View File

@@ -244,7 +244,7 @@ export async function fetchDashboardInvoices(
}
const payerId = row.payerId ?? null;
const pagadorName = row.pagadorName?.trim() || "Sem pagador";
const pagadorName = row.pagadorName?.trim() || "Sem pessoa";
const pagadorAvatar = row.pagadorAvatar ?? null;
const payerKey = payerId ?? "__without-payer__";
const key = `${row.cardId}:${payerKey}`;

View File

@@ -251,8 +251,8 @@ export const widgetsConfig: WidgetConfig[] = [
},
{
id: "pagadores",
title: "Pagadores",
subtitle: "Despesas por pagador no período",
title: "Pessoas",
subtitle: "Despesas por pessoa no período",
icon: <RiGroupLine className="size-4" />,
component: ({ data }) => (
<PayersWidget payers={data.pagadoresSnapshot.payers} />

View File

@@ -34,9 +34,9 @@ const statusEnum = z
const baseSchema = z.object({
name: z
.string({ message: "Informe o nome do pagador." })
.string({ message: "Informe o nome da pessoa." })
.trim()
.min(1, "Informe o nome do pagador."),
.min(1, "Informe o nome da pessoa."),
email: z
.string()
.trim()
@@ -110,7 +110,7 @@ export async function createPayerAction(
revalidate(user.id);
return { success: true, message: "Payer criado com sucesso." };
return { success: true, message: "Pessoa criada com sucesso." };
} catch (error) {
return handleActionError(error);
}
@@ -130,7 +130,7 @@ export async function updatePayerAction(
if (!existing) {
return {
success: false,
error: "Pagador não encontrado.",
error: "Pessoa não encontrada.",
};
}
@@ -160,7 +160,7 @@ export async function updatePayerAction(
revalidate(currentUser.id);
return { success: true, message: "Payer atualizado com sucesso." };
return { success: true, message: "Pessoa atualizada com sucesso." };
} catch (error) {
return handleActionError(error);
}
@@ -180,14 +180,14 @@ export async function deletePayerAction(
if (!existing) {
return {
success: false,
error: "Pagador não encontrado.",
error: "Pessoa não encontrada.",
};
}
if (existing.role === PAYER_ROLE_ADMIN) {
return {
success: false,
error: "Pagadores administradores não podem ser removidos.",
error: "Pessoas administradoras não podem ser removidas.",
};
}
@@ -197,7 +197,7 @@ export async function deletePayerAction(
revalidate(user.id);
return { success: true, message: "Payer removido com sucesso." };
return { success: true, message: "Pessoa removida com sucesso." };
} catch (error) {
return handleActionError(error);
}
@@ -221,7 +221,7 @@ export async function joinPayerByShareCodeAction(
if (pagadorRow.userId === user.id) {
return {
success: false,
error: "Você já é o proprietário deste pagador.",
error: "Você já é o proprietário desta entidade pagadora.",
};
}
@@ -235,7 +235,7 @@ export async function joinPayerByShareCodeAction(
if (existingShare) {
return {
success: false,
error: "Você já possui acesso a este pagador.",
error: "Você já possui acesso a esta pessoa.",
};
}
@@ -248,7 +248,7 @@ export async function joinPayerByShareCodeAction(
revalidate(user.id);
return { success: true, message: "Payer adicionado à sua lista." };
return { success: true, message: "Pessoa adicionada à sua lista." };
} catch (error) {
return handleActionError(error);
}
@@ -313,7 +313,7 @@ export async function regeneratePayerShareCodeAction(
});
if (!existing) {
return { success: false, error: "Payer não encontrado." };
return { success: false, error: "Pessoa não encontrada." };
}
let attempts = 0;

View File

@@ -66,7 +66,7 @@ export function PayerHeaderCard({
const openConfirmDialog = () => {
if (!payer.email) {
toast.error("Cadastre um e-mail para este pagador antes de enviar.");
toast.error("Cadastre um e-mail para esta pessoa antes de enviar.");
return;
}
setConfirmOpen(true);
@@ -74,7 +74,7 @@ export function PayerHeaderCard({
const handleSendSummary = () => {
if (!payer.email) {
toast.error("Cadastre um e-mail para este pagador antes de enviar.");
toast.error("Cadastre um e-mail para esta pessoa antes de enviar.");
return;
}

View File

@@ -67,7 +67,7 @@ export function PayerHistoryCard({ data }: PagadorHistoryCardProps) {
Evolução (últimos 6 meses)
</CardTitle>
<p className="text-xs text-muted-foreground">
Despesas registradas para este pagador ao longo do tempo.
Despesas registradas para esta pessoa ao longo do tempo.
</p>
</CardHeader>

View File

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

View File

@@ -89,7 +89,7 @@ export function PayerSharingCard({
</CardTitle>
<p className="text-sm text-muted-foreground">
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 pessoas usando a opção Adicionar por código para ter
acesso somente leitura.
</p>
</CardHeader>

View File

@@ -182,7 +182,7 @@ export function PayerDialog({
const payerId = payer?.id;
if (mode === "update" && !payerId) {
const message = "Pagador inválido.";
const message = "Pessoa inválida.";
setErrorMessage(message);
toast.error(message);
return;
@@ -216,13 +216,12 @@ export function PayerDialog({
});
};
const title = mode === "create" ? "Novo pagador" : "Editar pagador";
const title = mode === "create" ? "Nova pessoa" : "Editar pessoa";
const description =
mode === "create"
? "Selecione um avatar e informe os detalhes para criar um novo pagador."
: "Atualize os detalhes do pagador selecionado.";
const submitLabel =
mode === "create" ? "Salvar pagador" : "Atualizar pagador";
? "Selecione um avatar e informe os detalhes para criar uma nova pessoa."
: "Atualize os detalhes da pessoa selecionada.";
const submitLabel = mode === "create" ? "Salvar pessoa" : "Atualizar pessoa";
const isUploadSelected =
uploadedAvatar !== null && formState.avatarUrl === uploadedAvatar;
@@ -388,7 +387,7 @@ export function PayerDialog({
id="payer-note"
value={formState.note}
onChange={(event) => updateField("note", event.target.value)}
placeholder="Observações sobre este pagador"
placeholder="Observações sobre esta pessoa"
/>
</div>
</div>

View File

@@ -60,7 +60,7 @@ export function PayersPage({ payers, avatarOptions }: PayersPageProps) {
const handleRemoveRequest = (payer: Payer) => {
if (payer.role === PAYER_ROLE_ADMIN) {
toast.error("Pagadores administradores não podem ser removidos.");
toast.error("Pessoas administradoras não podem ser removidas.");
return;
}
setPayerToRemove(payer);
@@ -91,8 +91,8 @@ export function PayersPage({ payers, avatarOptions }: PayersPageProps) {
};
const removeTitle = payerToRemove
? `Remover pagador "${payerToRemove.name}"?`
: "Remover pagador?";
? `Remover pessoa "${payerToRemove.name}"?`
: "Remover pessoa?";
const handleJoinByCode = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
@@ -127,7 +127,7 @@ export function PayersPage({ payers, avatarOptions }: PayersPageProps) {
trigger={
<Button className="w-full sm:w-auto">
<RiAddFill className="size-4" />
Novo pagador
Nova pessoa
</Button>
}
/>
@@ -151,7 +151,7 @@ export function PayersPage({ payers, avatarOptions }: PayersPageProps) {
{orderedPayers.length === 0 ? (
<div className="flex min-h-[320px] items-center justify-center rounded-lg border border-dashed bg-muted/30">
<div className="max-w-sm text-center text-sm text-muted-foreground">
Cadastre seu primeiro pagador para organizar cobranças e
Cadastre seu primeira pessoa para organizar cobranças e
pagamentos recorrentes.
</div>
</div>
@@ -185,8 +185,8 @@ export function PayersPage({ payers, avatarOptions }: PayersPageProps) {
open={removeOpen && !!payerToRemove}
onOpenChange={handleRemoveOpenChange}
title={removeTitle}
description="Ao remover este pagador, os registros relacionados a ele deixarão de ser associados automaticamente."
confirmLabel="Remover pagador"
description="Ao remover esta pessoa, os registros relacionados a ele deixarão de ser associados automaticamente."
confirmLabel="Remover pessoa"
pendingLabel="Removendo..."
confirmVariant="destructive"
onConfirm={handleRemoveConfirm}

View File

@@ -19,7 +19,7 @@ import { formatDateTime } from "@/shared/utils/date";
import { displayPeriod } from "@/shared/utils/period";
const inputSchema = z.object({
payerId: z.string().uuid("Payer inválido."),
payerId: z.string().uuid("Pessoa inválida."),
period: z
.string()
.regex(/^\d{4}-\d{2}$/, "Período inválido. Informe no formato AAAA-MM."),
@@ -404,7 +404,7 @@ export async function sendPayerSummaryAction(
});
if (!pagadorRow) {
return { success: false, error: "Pagador não encontrado." };
return { success: false, error: "Pessoa não encontrada." };
}
if (!pagadorRow.email) {

View File

@@ -81,7 +81,7 @@ async function resetUserAppData(
const payerName =
(user.name && user.name.trim().length > 0
? user.name.trim()
: normalizeNameFromEmail(user.email)) || "Payer principal";
: normalizeNameFromEmail(user.email)) || "Pessoa principal";
const avatarUrl = user.image ?? DEFAULT_PAYER_AVATAR;
const defaultPayerStatus = PAYER_STATUS_OPTIONS[0];
@@ -176,7 +176,7 @@ export async function updateNameAction(
.set({ name: fullName })
.where(eq(schema.user.id, session.user.id));
// Sincronizar nome com o pagador admin
// Sincronizar nome com o pessoa admin
if (adminPayerId) {
await db
.update(payers)

View File

@@ -94,12 +94,12 @@ export function DeleteAccountForm() {
<ul className="list-disc list-inside text-sm text-muted-foreground space-y-1">
<li>Lançamentos, faturas, antecipações e pré-lançamentos</li>
<li>Contas, cartões, orçamentos e anotações</li>
<li>Pagadores próprios e compartilhamentos recebidos</li>
<li>Pessoas próprios e compartilhamentos recebidos</li>
<li>
Preferências do app, insights salvos e tokens do Companion
</li>
<li className="font-medium text-foreground">
Categorias padrão e pagador admin serão recriados
Categorias padrão e pessoa admin serão recriadas
automaticamente
</li>
</ul>
@@ -130,7 +130,7 @@ export function DeleteAccountForm() {
<ul className="list-disc list-inside text-sm text-destructive space-y-1">
<li>Lançamentos, orçamentos e anotações</li>
<li>Contas, cartões e categorias</li>
<li>Pagadores, credenciais e configurações</li>
<li>Pessoas, credenciais e configurações</li>
<li className="font-medium">
Resumindo, sua conta irá de arrasta pra cima!
</li>

View File

@@ -602,7 +602,7 @@ export async function createMassTransactionsAction(
if (transaction.payerId && invalidPayers.has(transaction.payerId)) {
return {
success: false,
error: `Payer não encontrado na transação ${i + 1}.`,
error: `Pessoa não encontrado na transação ${i + 1}.`,
};
}
if (
@@ -611,7 +611,7 @@ export async function createMassTransactionsAction(
) {
return {
success: false,
error: `Category não encontrada na transação ${i + 1}.`,
error: `Categoria não encontrada na transação ${i + 1}.`,
};
}
}

View File

@@ -189,8 +189,8 @@ export async function validateAllOwnership(
];
const errors = [
"Pagador não encontrado ou sem permissão.",
"Pagador secundário não encontrado ou sem permissão.",
"Pessoa não encontrada ou sem permissão.",
"Pessoa secundário não encontrado ou sem permissão.",
"Categoria não encontrada.",
"Conta não encontrada.",
"Cartão não encontrado.",
@@ -359,7 +359,7 @@ const refineLancamento = (
ctx.addIssue({
code: z.ZodIssueCode.custom,
path: ["payerId"],
message: "Selecione o pagador principal para dividir o lançamento.",
message: "Selecione a pessoa principal para dividir o lançamento.",
});
}
@@ -367,13 +367,13 @@ const refineLancamento = (
ctx.addIssue({
code: z.ZodIssueCode.custom,
path: ["secondaryPayerId"],
message: "Selecione o pagador secundário para dividir o lançamento.",
message: "Selecione a pessoa secundário para dividir o lançamento.",
});
} else if (data.payerId && data.secondaryPayerId === data.payerId) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
path: ["secondaryPayerId"],
message: "Escolha um pagador diferente para dividir o lançamento.",
message: "Escolha uma pessoa diferente para dividir o lançamento.",
});
}

View File

@@ -84,7 +84,7 @@ export async function importTransactionsAction(
validateCartaoOwnership(userId, cardId),
]);
if (!payerOk) return { success: false, error: "Pagador não encontrado." };
if (!payerOk) return { success: false, error: "Pessoa não encontrada." };
if (!accountOk) return { success: false, error: "Conta não encontrada." };
if (!cardOk) return { success: false, error: "Cartão não encontrado." };

View File

@@ -159,7 +159,7 @@ export async function createInstallmentAnticipationAction(
if (data.payerId && payer.length === 0) {
return {
success: false,
error: "Pagador inválido para esta conta.",
error: "Pessoa inválida para esta conta.",
};
}

View File

@@ -21,7 +21,7 @@ export const LANCAMENTOS_COLUMN_LABELS: Record<string, string> = {
condition: "Condição",
paymentMethod: "Forma de Pagamento",
categoriaName: "Categoria",
pagadorName: "Pagador",
pagadorName: "Pessoa",
note: "Anotação",
contaCartao: "Conta/Cartão",
};

View File

@@ -269,7 +269,7 @@ export function AnticipateInstallmentsDialog({
</Field>
<Field className="gap-1">
<FieldLabel htmlFor="anticipation-pagador">Pagador</FieldLabel>
<FieldLabel htmlFor="anticipation-pagador">Pessoa</FieldLabel>
<FieldContent>
<Select
value={formState.payerId}

View File

@@ -116,7 +116,7 @@ export function BulkActionDialog({
htmlFor="period"
className="text-sm cursor-pointer font-medium"
>
Todos os pagadores deste período
Todas as pessoas deste período
</Label>
<p className="text-xs text-muted-foreground">
Aplica a todos os lançamentos deste mesmo mês na série
@@ -125,7 +125,7 @@ export function BulkActionDialog({
<div className="mt-1.5 flex items-start gap-1.5 rounded-md bg-amber-50 px-2 py-1.5 text-amber-800 dark:bg-amber-950/40 dark:text-amber-300">
<RiErrorWarningLine className="mt-0.5 size-3.5 shrink-0" />
<p className="text-xs">
Atenção: os valores individuais de cada pagador serão
Atenção: os valores individuais de cada pessoa serão
substituídos pelos valores deste lançamento.
</p>
</div>

View File

@@ -90,7 +90,7 @@ export function BulkImportDialog({
event.preventDefault();
if (!payerId) {
toast.error("Selecione o pagador.");
toast.error("Selecione a pessoa.");
return;
}
@@ -197,16 +197,16 @@ export function BulkImportDialog({
<DialogDescription>
Importando {itemCount}{" "}
{itemCount === 1 ? "lançamento" : "lançamentos"}. Selecione o
pagador, categoria e forma de pagamento para aplicar a todos.
pessoa, categoria e forma de pagamento para aplicar a todos.
</DialogDescription>
</DialogHeader>
<form className="space-y-4" onSubmit={handleSubmit}>
<div className="space-y-2">
<Label htmlFor="pagador">Pagador *</Label>
<Label htmlFor="pagador">Pessoa *</Label>
<Select value={payerId} onValueChange={setPagadorId}>
<SelectTrigger id="pagador" className="w-full">
<SelectValue placeholder="Selecione o pagador">
<SelectValue placeholder="Selecione a pessoa">
{payerId &&
(() => {
const selectedOption = payerOptions.find(

View File

@@ -525,7 +525,7 @@ export function MassAddDialog({
htmlFor={`pagador-${transaction.id}`}
className="sr-only"
>
Pagador {index + 1}
Pessoa {index + 1}
</Label>
<Select
value={transaction.payerId}
@@ -537,7 +537,7 @@ export function MassAddDialog({
id={`pagador-${transaction.id}`}
className="w-32 truncate"
>
<SelectValue placeholder="Pagador">
<SelectValue placeholder="Pessoa">
{transaction.payerId &&
(() => {
const selectedOption = payerOptions.find(

View File

@@ -50,7 +50,7 @@ export function PayerSection({
<div>
<p className="text-sm text-foreground">Dividir lançamento</p>
<p className="text-xs text-muted-foreground">
Atribuir parte do valor a outro pagador.
Atribuir parte do valor a outra pessoa.
</p>
</div>
</div>
@@ -75,7 +75,7 @@ export function PayerSection({
<div className="flex w-full flex-col gap-2 md:flex-row">
<div className="w-full space-y-1">
<Label htmlFor="payer">Pagador</Label>
<Label htmlFor="payer">Pessoa</Label>
<div className="flex gap-2">
<Select
value={formState.payerId ?? ""}

View File

@@ -230,7 +230,7 @@ export function TransactionDialog({
if (formState.isSplit && !formState.payerId) {
const message =
"Selecione o pagador principal para dividir o lançamento.";
"Selecione a pessoa principal para dividir o lançamento.";
setErrorMessage(message);
toast.error(message);
return;
@@ -238,7 +238,7 @@ export function TransactionDialog({
if (formState.isSplit && !formState.secondaryPayerId) {
const message =
"Selecione o pagador secundário para dividir o lançamento.";
"Selecione a pessoa secundário para dividir o lançamento.";
setErrorMessage(message);
toast.error(message);
return;
@@ -464,7 +464,7 @@ export function TransactionDialog({
const description =
mode === "create"
? isImportMode
? "Importando lançamento de outro usuário. Ajuste a categoria, pagador e cartão/conta antes de salvar."
? "Importando lançamento de outro usuário. Ajuste a categoria, pessoa e cartão/conta antes de salvar."
: isCopyMode
? "Os dados do lançamento foram copiados. Revise e ajuste conforme necessário antes de salvar."
: isNewWithType
@@ -519,7 +519,7 @@ export function TransactionDialog({
<div className="border-t border-border/40 my-3" />
{/* Pagador */}
{/* Pessoa */}
<PayerSection
formState={formState}
onFieldChange={handleFieldChange}

View File

@@ -123,13 +123,13 @@ export function GlobalFields({
</div>
<div className="flex min-w-44 flex-col gap-1.5">
<Label>Pagador</Label>
<Label>Pessoa</Label>
<Select
value={payerId ?? ""}
onValueChange={(v) => onPayerChange(v || null)}
>
<SelectTrigger>
<SelectValue placeholder="Selecionar pagador…" />
<SelectValue placeholder="Selecionar pessoa…" />
</SelectTrigger>
<SelectContent>
{payerOptions.map((opt) => (

View File

@@ -134,7 +134,7 @@ export function AnticipationCard({
{anticipation.payer && (
<div>
<dt className="text-muted-foreground">Pagador</dt>
<dt className="text-muted-foreground">Pessoa</dt>
<dd className="mt-1 font-medium">{anticipation.payer.name}</dd>
</div>
)}

View File

@@ -229,12 +229,12 @@ function buildColumns({
aria-hidden
/>
<span className="sr-only">
Dividido entre pagadores
Dividido entre pessoas
</span>
</span>
</TooltipTrigger>
<TooltipContent side="top">
Dividido entre pagadores
Dividido entre pessoas
</TooltipContent>
</Tooltip>
)}
@@ -408,10 +408,10 @@ function buildColumns({
},
{
accessorKey: "pagadorName",
header: "Pagador",
header: "Pessoa",
cell: ({ row }) => {
const { payerId, pagadorName, pagadorAvatar } = row.original;
const label = pagadorName?.trim() || "Sem pagador";
const label = pagadorName?.trim() || "Sem pessoa";
const displayName = label.split(/\s+/)[0] ?? label;
const avatarSrc = getAvatarSrc(pagadorAvatar);
const initial = displayName.charAt(0).toUpperCase() || "?";

View File

@@ -386,7 +386,7 @@ export function TransactionsFilters({
</div>
<div className="space-y-2">
<label className="text-sm font-medium">Pagador</label>
<label className="text-sm font-medium">Pessoa</label>
<Select
value={getParamValue("payer")}
onValueChange={(value) =>

View File

@@ -109,7 +109,7 @@ export function TransactionsExport({
"Valor",
"Category",
"Conta/Cartão",
"Payer",
"Pessoa",
];
const rows: string[][] = [];
@@ -169,7 +169,7 @@ export function TransactionsExport({
"Valor",
"Category",
"Conta/Cartão",
"Payer",
"Pessoa",
];
const rows: (string | number)[][] = [];
@@ -277,7 +277,7 @@ export function TransactionsExport({
"Valor",
"Categoria",
"Conta/Cartão",
"Payer",
"Pessoa",
],
];
@@ -317,7 +317,7 @@ export function TransactionsExport({
5: { cellWidth: 24 }, // Valor
6: { cellWidth: 30 }, // Categoria
7: { cellWidth: 30 }, // Conta/Cartão
8: { cellWidth: 31 }, // Payer
8: { cellWidth: 31 }, // Pessoa
},
didParseCell: (cellData) => {
if (cellData.section === "body" && cellData.column.index === 5) {

View File

@@ -92,7 +92,7 @@ export const NAV_SECTIONS: NavSection[] = [
items: [
{
href: "/payers",
label: "Pagadores",
label: "Pessoas",
description: "Gerencie quem divide as despesas",
icon: <RiGroupLine className="size-4" />,
iconClass: "text-primary",

View File

@@ -24,7 +24,7 @@ export function TransactionsTableSkeleton() {
<TableHead className="w-[120px]">Valor</TableHead>
<TableHead className="w-[120px]">Condição</TableHead>
<TableHead className="w-[120px]">Pagamento</TableHead>
<TableHead className="w-[140px]">Pagador</TableHead>
<TableHead className="w-[140px]">Pessoa</TableHead>
<TableHead className="w-[140px]">Categoria</TableHead>
<TableHead className="w-[140px]">Conta/Cartão</TableHead>
<TableHead className="w-[80px]">Ações</TableHead>

View File

@@ -36,7 +36,7 @@ export async function ensureDefaultPagadorForUser(user: SeedUserLike) {
const name =
(user.name && user.name.trim().length > 0
? user.name.trim()
: normalizeNameFromEmail(user.email)) || "Payer principal";
: normalizeNameFromEmail(user.email)) || "Pessoa principal";
// Usa a imagem do Google se disponível, senão usa o avatar padrão
const avatarUrl = user.image ?? DEFAULT_PAYER_AVATAR;

View File

@@ -53,11 +53,11 @@ export const normalizeNameFromEmail = (
email: string | null | undefined,
): string => {
if (!email) {
return "Novo pagador";
return "Nova pessoa";
}
const [local] = email.split("@");
if (!local) {
return "Novo pagador";
return "Nova pessoa";
}
return local
.split(".")