mirror of
https://github.com/felipegcoutinho/openmonetis.git
synced 2026-05-09 11:01:45 +00:00
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:
@@ -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}
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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.",
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)}
|
||||
|
||||
@@ -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.",
|
||||
|
||||
@@ -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) => (
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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}`;
|
||||
|
||||
@@ -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} />
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}.`,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.",
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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." };
|
||||
|
||||
|
||||
@@ -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.",
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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",
|
||||
};
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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 ?? ""}
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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) => (
|
||||
|
||||
@@ -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>
|
||||
)}
|
||||
|
||||
@@ -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() || "?";
|
||||
|
||||
@@ -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) =>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(".")
|
||||
|
||||
Reference in New Issue
Block a user