import React, { useState, useEffect, useMemo, useCallback } from "react";
import './style/FinanceiroDashboard.css';
const CONVENIOS_LIST = [
"Particular",
"Amil",
"Bradesco Saúde",
"SulAmérica",
"Unimed",
"Cassio",
"Outro"
];
function CurrencyInput({ value, onChange, label, id }) {
const formattedValue = useMemo(() => {
let numericValue = Number(value) || 0;
let stringValue = String(numericValue);
while (stringValue.length < 3) {
stringValue = '0' + stringValue;
}
const integerPart = stringValue.slice(0, -2);
const decimalPart = stringValue.slice(-2);
const formattedInteger = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, '.');
return `R$ ${formattedInteger},${decimalPart}`;
}, [value]);
const handleKeyDown = useCallback((e) => {
const key = e.key;
if (['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Tab'].includes(key)) {
if (key === 'Backspace' || key === 'Delete') {
e.preventDefault();
const numericValue = value || 0;
let newValueString = String(numericValue);
if (newValueString.length <= 1) {
onChange(0);
} else {
const newNumericValue = parseInt(newValueString.slice(0, -1)) || 0;
onChange(newNumericValue);
}
}
return;
}
if (!/^\d$/.test(key)) {
e.preventDefault();
return;
}
e.preventDefault();
const digit = key;
const numericValue = value || 0;
let newValueString = String(numericValue) + digit;
if (newValueString.length > 10) return;
const newNumericValue = parseInt(newValueString);
onChange(newNumericValue);
}, [value, onChange]);
return (
{}}
onKeyDown={handleKeyDown}
placeholder="R$ 0,00"
/>
);
}
function mockFetchPagamentos() {
return [
{
id: "PAY-001",
paciente: { nome: "Sarah Oliveira", convenio: "Unimed" },
valor: 20000,
forma_pagamento: "Cartão",
data_vencimento: "2025-09-30",
status: "pendente",
desconto: 0,
observacoes: "Pagamento parcelado em 2x"
},
{
id: "PAY-002",
paciente: { nome: "Laissa Marquetti", convenio: "Bradesco Saúde" },
valor: 15000,
forma_pagamento: "Dinheiro",
data_vencimento: "2025-09-15",
status: "pago",
desconto: 1000,
observacoes: ""
},
{
id: "PAY-003",
paciente: { nome: "Vera Santos", convenio: "Particular" },
valor: 30000,
forma_pagamento: "Pix",
data_vencimento: "2025-09-20",
status: "vencido",
desconto: 0,
observacoes: "Não respondeu ao contato"
},
{
id: "PAY-004",
paciente: { nome: "Carlos Almeida", convenio: "Particular" },
valor: 10000,
forma_pagamento: "Transferência",
data_vencimento: "2025-09-29",
status: "pago",
desconto: 500,
observacoes: "Desconto por pagamento adiantado"
}
];
}
export default function FinanceiroDashboard() {
const [pagamentos, setPagamentos] = useState([]);
const [modalPagamento, setModalPagamento] = useState(null);
const [query, setQuery] = useState("");
const [filtroStatus, setFiltroStatus] = useState("Todos");
const [novoPagamento, setNovoPagamento] = useState(false);
const [summary, setSummary] = useState({ totalRecebido: 0, totalAReceber: 0, totalDescontos: 0 });
useEffect(() => {
const data = mockFetchPagamentos();
setPagamentos(data);
}, []);
function formatCurrency(centavos) {
const valorEmReais = centavos / 100;
return "R$ " + valorEmReais.toFixed(2).replace(".", ",").replace(/\B(?=(\d{3})+(?!\d))/g, '.');
}
function getValorLiquido(valor, desconto) {
return valor - desconto;
}
const filteredPagamentos = useMemo(() => {
return pagamentos.filter(p => {
const q = query.toLowerCase();
const statusOk = filtroStatus === "Todos" || p.status === filtroStatus;
const buscaOk = p.paciente.nome.toLowerCase().includes(q) ||
p.id.toLowerCase().includes(q);
return statusOk && buscaOk;
});
}, [pagamentos, query, filtroStatus]);
useEffect(() => {
let recebido = 0;
let aReceber = 0;
let descontos = 0;
filteredPagamentos.forEach(p => {
const valorLiquido = getValorLiquido(p.valor, p.desconto);
if (p.status === 'pago') {
recebido += valorLiquido;
descontos += p.desconto;
} else {
aReceber += p.valor;
}
});
setSummary({
totalRecebido: recebido,
totalAReceber: aReceber,
totalDescontos: descontos
});
}, [filteredPagamentos]);
function handleDelete(id) {
if (window.confirm("Tem certeza que deseja excluir este pagamento?")) {
setPagamentos(prev => prev.filter(p => p.id !== id));
setModalPagamento(null);
}
}
function handleSave(pagamento) {
if (!pagamento.paciente.nome || !pagamento.valor || !pagamento.data_vencimento || !pagamento.paciente.convenio) {
alert("Preencha Paciente, Convênio, Valor e Data de Vencimento.");
return;
}
if (novoPagamento) {
const newId = "PAY-" + (pagamentos.length + 1).toString().padStart(3, "0");
pagamento.id = newId;
setPagamentos(prev => [...prev, pagamento]);
} else {
setPagamentos(prev => prev.map(p => p.id === pagamento.id ? pagamento : p));
}
setModalPagamento(null);
setNovoPagamento(false);
}
const closeModal = () => {
setModalPagamento(null);
setNovoPagamento(false);
};
return (
Controle Financeiro
Total Recebido (Filtrado)
{formatCurrency(summary.totalRecebido)}
Total a Receber (Filtrado)
{formatCurrency(summary.totalAReceber)}
Descontos Aplicados
{formatCurrency(summary.totalDescontos)}
setQuery(e.target.value)}
style={{ flexGrow: 1 }}
/>
{filteredPagamentos.length === 0 ? (
Nenhum pagamento encontrado.
) : (
| Paciente |
Convênio |
Valor Total (R$) |
Desconto (R$) |
Valor Líquido (R$) |
Forma |
Vencimento |
Status |
Ações |
{filteredPagamentos.map(p => (
| {p.paciente.nome} |
{p.paciente.convenio} |
{formatCurrency(p.valor)} |
{formatCurrency(p.desconto)} |
{formatCurrency(getValorLiquido(p.valor, p.desconto))} |
{p.forma_pagamento} |
{p.data_vencimento.split('-').reverse().join('/')} |
{p.status.toUpperCase()} |
|
))}
)}
{modalPagamento && (
e.target.classList.contains('modal') && closeModal()}>
{novoPagamento ? "Adicionar Pagamento" : `Editar Pagamento - ${modalPagamento.paciente.nome}`}
setModalPagamento({...modalPagamento, paciente:{...modalPagamento.paciente, nome:e.target.value}})}
/>
setModalPagamento({...modalPagamento, valor: newValue})}
/>
setModalPagamento({...modalPagamento, desconto: newValue})}
/>
setModalPagamento({...modalPagamento, data_vencimento:e.target.value})}
/>
)}
);
}