Perfil Financeiro
This commit is contained in:
parent
cf11b2aaf5
commit
d1a8eab04c
67
src/App.js
67
src/App.js
@ -1,26 +1,34 @@
|
|||||||
// src/App.js
|
// src/App.js
|
||||||
//import PerfilSecretaria from "./perfis/perfil_secretaria/PerfilSecretaria";
|
//import PerfilSecretaria from "./perfis/perfil_secretaria/PerfilSecretaria";
|
||||||
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
|
import { BrowserRouter as Router, Routes, Route, Navigate } from "react-router-dom";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
import Login from "./pages/Login";
|
import Login from "./pages/Login";
|
||||||
import Register from "./pages/Register";
|
import Register from "./pages/Register";
|
||||||
import Forgot from "./pages/ForgotPassword";
|
import Forgot from "./pages/ForgotPassword";
|
||||||
import PerfilSecretaria from "./perfis/perfil_secretaria/PerfilSecretaria";
|
import PerfilSecretaria from "./perfis/perfil_secretaria/PerfilSecretaria";
|
||||||
|
import PerfilFinanceiro from "./perfis/perfil_financeiro/PerfilFinanceiro";
|
||||||
import LandingPage from './pages/LandingPage';
|
import LandingPage from './pages/LandingPage';
|
||||||
// Mantenha todas as importações de CSS globais aqui se houver!
|
// Mantenha todas as importações de CSS globais aqui se houver!
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
// O estado controla qual view mostrar: false = Landing Page, true = Dashboard
|
const [userProfile, setUserProfile] = useState(
|
||||||
const [isInternalView, setIsInternalView] = useState(false);
|
localStorage.getItem('userProfile') || null
|
||||||
// const [isSecretaria, setIsSecretaria] = useState(false);
|
);
|
||||||
|
|
||||||
const handleEnterSystem = () => {
|
const handleEnterSystem = (profile, keepConnected) => {
|
||||||
setIsInternalView(true);
|
setUserProfile(profile);
|
||||||
|
|
||||||
|
if (keepConnected) {
|
||||||
|
localStorage.setItem('userProfile', profile);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
localStorage.removeItem('userProfile');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleExitSystem = () => {
|
const handleExitSystem = () => {
|
||||||
setIsInternalView(false);
|
setUserProfile(null);
|
||||||
|
localStorage.removeItem('userProfile');
|
||||||
};
|
};
|
||||||
|
|
||||||
// if (isSecretaria) {
|
// if (isSecretaria) {
|
||||||
@ -28,25 +36,44 @@ function App() {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// Se não estiver na visualização interna, retorna a LandingPage.
|
// Se não estiver na visualização interna, retorna a LandingPage.
|
||||||
if (!isInternalView) {
|
|
||||||
return (
|
return (
|
||||||
<Router>
|
<Router>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<LandingPage onEnterSystem={handleEnterSystem}/>} />
|
<Route path="/" element={<LandingPage/>} />
|
||||||
<Route path="/login" element={<Login />} />
|
<Route path="/login" element={<Login onEnterSystem={handleEnterSystem} />} />
|
||||||
<Route path="/register" element={<Register/>} />
|
<Route path="/register" element={<Register/>} />
|
||||||
<Route path="/forgotPassword" element={<Forgot />} />
|
<Route path="/forgotPassword" element={<Forgot />} />
|
||||||
<Route path="/secretaria/*" element={<PerfilSecretaria />} />
|
<Route
|
||||||
<Route path="*" element={<h2>Página não encontrada</h2>} />
|
path="/secretaria/*"
|
||||||
</Routes>
|
element={
|
||||||
</Router>
|
userProfile === 'secretaria' ? (
|
||||||
|
<PerfilSecretaria onLogout={handleExitSystem} />
|
||||||
|
) : (
|
||||||
|
<Navigate to="/login" replace />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
/>
|
||||||
// Se estiver na visualização interna, retorna o PerfilSecretaria
|
<Route
|
||||||
return (
|
path="/financeiro/*"
|
||||||
// Passamos a função de saída (logout)
|
element={
|
||||||
<PerfilSecretaria onLogout={handleExitSystem} />
|
userProfile === 'financeiro' ? (
|
||||||
|
<PerfilFinanceiro onLogout={handleExitSystem} />
|
||||||
|
) : (
|
||||||
|
<Navigate to="/login" replace />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="*"
|
||||||
|
element={
|
||||||
|
userProfile ?
|
||||||
|
<Navigate to={`/${userProfile}/`} replace /> :
|
||||||
|
<Navigate to="/" replace /> // Se não logado, volta para a Landing Page
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Routes>
|
||||||
|
</Router>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import menuItems from "../data/sidebar-items.json";
|
|
||||||
|
|
||||||
function Sidebar() {
|
// 1. Recebe 'menuItems' e 'onLogout' como props
|
||||||
|
function Sidebar({ menuItems, onLogout }) {
|
||||||
const [isActive, setIsActive] = useState(true);
|
const [isActive, setIsActive] = useState(true);
|
||||||
const [openSubmenu, setOpenSubmenu] = useState(null);
|
const [openSubmenu, setOpenSubmenu] = useState(null);
|
||||||
|
|
||||||
@ -43,6 +43,7 @@ function Sidebar() {
|
|||||||
<div id="sidebar" className={isActive ? "active" : ""}>
|
<div id="sidebar" className={isActive ? "active" : ""}>
|
||||||
<div className="sidebar-wrapper active">
|
<div className="sidebar-wrapper active">
|
||||||
<div className="sidebar-header">
|
<div className="sidebar-header">
|
||||||
|
{/* ... Header... */}
|
||||||
<div className="d-flex justify-content-between">
|
<div className="d-flex justify-content-between">
|
||||||
<div className="logo">
|
<div className="logo">
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
@ -63,7 +64,7 @@ function Sidebar() {
|
|||||||
|
|
||||||
<div className="sidebar-menu">
|
<div className="sidebar-menu">
|
||||||
<ul className="menu">
|
<ul className="menu">
|
||||||
{menuItems.map((item, index) => {
|
{menuItems && menuItems.map((item, index) => {
|
||||||
if (item.isTitle) {
|
if (item.isTitle) {
|
||||||
return (
|
return (
|
||||||
<li key={index} className="sidebar-title">
|
<li key={index} className="sidebar-title">
|
||||||
@ -80,6 +81,7 @@ function Sidebar() {
|
|||||||
openSubmenu === item.key ? "active" : ""
|
openSubmenu === item.key ? "active" : ""
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
|
{/* ... Lógica de Submenu ... */}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="sidebar-link btn"
|
className="sidebar-link btn"
|
||||||
@ -109,6 +111,14 @@ function Sidebar() {
|
|||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
{/* 3. Adiciona o botão de logout no final do menu */}
|
||||||
|
<li className="sidebar-item" onClick={onLogout}>
|
||||||
|
<button type="button" className="sidebar-link btn">
|
||||||
|
<i className="bi bi-box-arrow-right"></i>
|
||||||
|
<span>Sair (Logout)</span>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
31
src/data/sidebar-items-financeiro.json
Normal file
31
src/data/sidebar-items-financeiro.json
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "Menu-Financeiro",
|
||||||
|
"isTitle": true
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name":"Início",
|
||||||
|
"url": "/financeiro/inicio",
|
||||||
|
"icon": "house"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "Lista de Pacientes",
|
||||||
|
"icon": "clipboard-heart-fill",
|
||||||
|
"url": "/financeiro/pacientes"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "Lista de Médico",
|
||||||
|
"icon": "hospital-fill",
|
||||||
|
"url": "/financeiro/medicos"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "Controle Financeiro",
|
||||||
|
"icon": "cash-coin",
|
||||||
|
"url": "/financeiro/controlefinanceiro"
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
@ -43,6 +43,12 @@
|
|||||||
"name": "Laudo do Paciente",
|
"name": "Laudo do Paciente",
|
||||||
"icon": "table",
|
"icon": "table",
|
||||||
"url": "/secretaria/laudo"
|
"url": "/secretaria/laudo"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "Controle Financeiro",
|
||||||
|
"icon": "cash-coin",
|
||||||
|
"url": "/secretaria/controlefinanceiro"
|
||||||
}
|
}
|
||||||
|
|
||||||
]
|
]
|
||||||
435
src/pages/FinanceiroDashboard.jsx
Normal file
435
src/pages/FinanceiroDashboard.jsx
Normal file
@ -0,0 +1,435 @@
|
|||||||
|
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 (
|
||||||
|
<div className="form-group">
|
||||||
|
<label htmlFor={id}>{label}</label>
|
||||||
|
<input
|
||||||
|
id={id}
|
||||||
|
className="input-field currency-input"
|
||||||
|
type="text"
|
||||||
|
value={formattedValue}
|
||||||
|
onChange={() => {}}
|
||||||
|
onKeyDown={handleKeyDown}
|
||||||
|
placeholder="R$ 0,00"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<div className="financeiro-wrap">
|
||||||
|
<h2>Controle Financeiro</h2>
|
||||||
|
|
||||||
|
<div className="summary-card-container">
|
||||||
|
<div className="summary-card green">
|
||||||
|
<h3>Total Recebido (Filtrado)</h3>
|
||||||
|
<p className="value">{formatCurrency(summary.totalRecebido)}</p>
|
||||||
|
</div>
|
||||||
|
<div className="summary-card red">
|
||||||
|
<h3>Total a Receber (Filtrado)</h3>
|
||||||
|
<p className="value">{formatCurrency(summary.totalAReceber)}</p>
|
||||||
|
</div>
|
||||||
|
<div className="summary-card blue">
|
||||||
|
<h3>Descontos Aplicados</h3>
|
||||||
|
<p className="value">{formatCurrency(summary.totalDescontos)}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="list-page-card">
|
||||||
|
<div style={{ display:"flex", gap:12, marginBottom:20 }}>
|
||||||
|
<input
|
||||||
|
className="input-field"
|
||||||
|
placeholder="Buscar paciente"
|
||||||
|
value={query}
|
||||||
|
onChange={e => setQuery(e.target.value)}
|
||||||
|
style={{ flexGrow: 1 }}
|
||||||
|
/>
|
||||||
|
<select className="select-field" value={filtroStatus} onChange={e => setFiltroStatus(e.target.value)}>
|
||||||
|
<option value="Todos">Todos</option>
|
||||||
|
<option value="pago">Pago</option>
|
||||||
|
<option value="pendente">Pendente</option>
|
||||||
|
<option value="vencido">Vencido</option>
|
||||||
|
</select>
|
||||||
|
<button
|
||||||
|
className="action-btn"
|
||||||
|
style={{ background: "#3b82f6", color: "#fff", borderColor: "#3b82f6" }}
|
||||||
|
onClick={() => {
|
||||||
|
setModalPagamento({
|
||||||
|
paciente: { nome:"", convenio: CONVENIOS_LIST[0] },
|
||||||
|
valor:0,
|
||||||
|
forma_pagamento:"Dinheiro",
|
||||||
|
data_vencimento: new Date().toISOString().split('T')[0],
|
||||||
|
status:"pendente",
|
||||||
|
desconto:0,
|
||||||
|
observacoes:""
|
||||||
|
});
|
||||||
|
setNovoPagamento(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
+ Adicionar Pagamento
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{filteredPagamentos.length === 0 ? (
|
||||||
|
<div className="empty">Nenhum pagamento encontrado.</div>
|
||||||
|
) : (
|
||||||
|
<div className="table-container">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Paciente</th>
|
||||||
|
<th>Convênio</th>
|
||||||
|
<th>Valor Total (R$)</th>
|
||||||
|
<th>Desconto (R$)</th>
|
||||||
|
<th>Valor Líquido (R$)</th>
|
||||||
|
<th>Forma</th>
|
||||||
|
<th>Vencimento</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th>Ações</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{filteredPagamentos.map(p => (
|
||||||
|
<tr key={p.id}>
|
||||||
|
<td>{p.paciente.nome}</td>
|
||||||
|
<td>{p.paciente.convenio}</td>
|
||||||
|
<td>{formatCurrency(p.valor)}</td>
|
||||||
|
<td>{formatCurrency(p.desconto)}</td>
|
||||||
|
<td style={{ fontWeight: 600 }}>{formatCurrency(getValorLiquido(p.valor, p.desconto))}</td>
|
||||||
|
<td>{p.forma_pagamento}</td>
|
||||||
|
<td>{p.data_vencimento.split('-').reverse().join('/')}</td>
|
||||||
|
<td><span className={`badge ${p.status}`}>{p.status.toUpperCase()}</span></td>
|
||||||
|
<td>
|
||||||
|
<div className="action-group">
|
||||||
|
<button
|
||||||
|
className="action-btn"
|
||||||
|
onClick={() => { setModalPagamento({...p}); setNovoPagamento(false); }}
|
||||||
|
>
|
||||||
|
Ver / Editar
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="action-btn delete"
|
||||||
|
onClick={() => handleDelete(p.id)}
|
||||||
|
>
|
||||||
|
Excluir
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{modalPagamento && (
|
||||||
|
<div className="modal" onClick={(e) => e.target.classList.contains('modal') && closeModal()}>
|
||||||
|
<div className="modal-card">
|
||||||
|
<div className="modal-header">
|
||||||
|
<h2>{novoPagamento ? "Adicionar Pagamento" : `Editar Pagamento - ${modalPagamento.paciente.nome}`}</h2>
|
||||||
|
<button className="close-btn" onClick={closeModal}>×</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="modal-body">
|
||||||
|
<div className="form-group">
|
||||||
|
<label htmlFor="paciente_nome">Paciente</label>
|
||||||
|
<input
|
||||||
|
id="paciente_nome"
|
||||||
|
className="input-field"
|
||||||
|
value={modalPagamento.paciente.nome}
|
||||||
|
onChange={e => setModalPagamento({...modalPagamento, paciente:{...modalPagamento.paciente, nome:e.target.value}})}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="form-group">
|
||||||
|
<label htmlFor="convenio">Convênio</label>
|
||||||
|
<select
|
||||||
|
id="convenio"
|
||||||
|
className="select-field"
|
||||||
|
value={modalPagamento.paciente.convenio}
|
||||||
|
onChange={e => setModalPagamento({...modalPagamento, paciente:{...modalPagamento.paciente, convenio:e.target.value}})}
|
||||||
|
>
|
||||||
|
<option value="">Selecione</option>
|
||||||
|
{CONVENIOS_LIST.map(conv => (
|
||||||
|
<option key={conv} value={conv}>{conv}</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<CurrencyInput
|
||||||
|
id="valor"
|
||||||
|
label="Valor da consulta (R$)"
|
||||||
|
value={modalPagamento.valor}
|
||||||
|
onChange={newValue => setModalPagamento({...modalPagamento, valor: newValue})}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<CurrencyInput
|
||||||
|
id="desconto"
|
||||||
|
label="Desconto aplicado (R$)"
|
||||||
|
value={modalPagamento.desconto}
|
||||||
|
onChange={newValue => setModalPagamento({...modalPagamento, desconto: newValue})}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="form-group">
|
||||||
|
<label htmlFor="forma">Forma de pagamento</label>
|
||||||
|
<select
|
||||||
|
id="forma"
|
||||||
|
className="select-field"
|
||||||
|
value={modalPagamento.forma_pagamento}
|
||||||
|
onChange={e => setModalPagamento({...modalPagamento, forma_pagamento:e.target.value})}
|
||||||
|
>
|
||||||
|
<option>Dinheiro</option>
|
||||||
|
<option>Cartão</option>
|
||||||
|
<option>Pix</option>
|
||||||
|
<option>Transferência</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="form-group">
|
||||||
|
<label htmlFor="vencimento">Data de vencimento</label>
|
||||||
|
<input
|
||||||
|
id="vencimento"
|
||||||
|
className="input-field"
|
||||||
|
type="date"
|
||||||
|
value={modalPagamento.data_vencimento}
|
||||||
|
onChange={e => setModalPagamento({...modalPagamento, data_vencimento:e.target.value})}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="form-group">
|
||||||
|
<label htmlFor="status">Status do pagamento</label>
|
||||||
|
<select
|
||||||
|
id="status"
|
||||||
|
className="select-field"
|
||||||
|
value={modalPagamento.status}
|
||||||
|
onChange={e => setModalPagamento({...modalPagamento, status:e.target.value})}
|
||||||
|
>
|
||||||
|
<option value="pago">Pago</option>
|
||||||
|
<option value="pendente">Pendente</option>
|
||||||
|
<option value="vencido">Vencido</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="form-group">
|
||||||
|
<label htmlFor="observacoes">Observações financeiras</label>
|
||||||
|
<textarea
|
||||||
|
id="observacoes"
|
||||||
|
className="input-field"
|
||||||
|
rows={3}
|
||||||
|
value={modalPagamento.observacoes}
|
||||||
|
onChange={e => setModalPagamento({...modalPagamento, observacoes:e.target.value})}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="modal-footer">
|
||||||
|
<button className="action-btn" onClick={() => handleSave(modalPagamento)}>
|
||||||
|
Salvar
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="action-btn"
|
||||||
|
onClick={closeModal}
|
||||||
|
style={{ borderColor: '#d1d5db', color: '#4b5563' }}
|
||||||
|
>
|
||||||
|
Cancelar
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -110,28 +110,6 @@ function Inicio({ setCurrentPage }) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="appointments-section">
|
|
||||||
<h2>Próximos Agendamentos</h2>
|
|
||||||
{agendamentosHoje > 0 ? (
|
|
||||||
<div>
|
|
||||||
{agendamentosDoDia.map(agendamento => (
|
|
||||||
<div key={agendamento.id} className="agendamento-item">
|
|
||||||
<p>{agendamento.nomePaciente}</p>
|
|
||||||
<p>{new Date(agendamento.data).toLocaleTimeString()}</p>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="no-appointments-content">
|
|
||||||
<FaCalendarCheck className="no-appointments-icon" />
|
|
||||||
<p>Nenhum agendamento para hoje</p>
|
|
||||||
<button className="manage-button" onClick={() => setCurrentPage('agendamento')}>
|
|
||||||
Gerenciar Agendamentos
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,26 @@
|
|||||||
import React from 'react';
|
|
||||||
import { Link, useNavigate } from "react-router-dom";
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
function Login() {
|
function Login({ onEnterSystem }) {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const [username, setUsername] = useState('');
|
||||||
|
const [password, setPassword] = useState('');
|
||||||
|
const [keepConnected, setKeepConnected] = useState(false);
|
||||||
const handleLogin = (e) => {
|
const handleLogin = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
// ...login logic...
|
|
||||||
navigate('/secretaria/inicio');
|
let profile = null;
|
||||||
|
if (username.toLowerCase() === 'secretaria') {
|
||||||
|
profile = 'secretaria';
|
||||||
|
} else if (username.toLowerCase() === 'financeiro') {
|
||||||
|
profile = 'financeiro';
|
||||||
|
}
|
||||||
|
if (!profile) {
|
||||||
|
alert("Usuário não reconhecido. Use 'secretaria' ou 'financeiro' para testar.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
onEnterSystem(profile, keepConnected);
|
||||||
|
navigate(`/${profile}/`);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -24,12 +38,15 @@ function Login() {
|
|||||||
<p className="auth-subtitle mb-5">
|
<p className="auth-subtitle mb-5">
|
||||||
Entre com os dados que você inseriu durante o registro.
|
Entre com os dados que você inseriu durante o registro.
|
||||||
</p>
|
</p>
|
||||||
<form action="index.html">
|
<form onSubmit={handleLogin}>
|
||||||
<div className="form-group position-relative has-icon-left mb-4">
|
<div className="form-group position-relative has-icon-left mb-4">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
className="form-control form-control-xl"
|
className="form-control form-control-xl"
|
||||||
placeholder="Username"
|
placeholder="Username"
|
||||||
|
value={username}
|
||||||
|
onChange={(e) => setUsername(e.target.value)}
|
||||||
|
required
|
||||||
/>
|
/>
|
||||||
<div className="form-control-icon">
|
<div className="form-control-icon">
|
||||||
<i className="bi bi-person" />
|
<i className="bi bi-person" />
|
||||||
@ -40,6 +57,9 @@ function Login() {
|
|||||||
type="password"
|
type="password"
|
||||||
className="form-control form-control-xl"
|
className="form-control form-control-xl"
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
|
value={password} // Adicione o estado real da senha aqui
|
||||||
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
|
required
|
||||||
/>
|
/>
|
||||||
<div className="form-control-icon">
|
<div className="form-control-icon">
|
||||||
<i className="bi bi-shield-lock" />
|
<i className="bi bi-shield-lock" />
|
||||||
@ -49,7 +69,8 @@ function Login() {
|
|||||||
<input
|
<input
|
||||||
className="form-check-input me-2"
|
className="form-check-input me-2"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
defaultValue=""
|
checked={keepConnected}
|
||||||
|
onChange={(e) => setKeepConnected(e.target.checked)}
|
||||||
id="flexCheckDefault"
|
id="flexCheckDefault"
|
||||||
/>
|
/>
|
||||||
<label
|
<label
|
||||||
@ -59,8 +80,7 @@ function Login() {
|
|||||||
Manter-me conectado
|
Manter-me conectado
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<button className="btn btn-primary btn-block btn-lg shadow-lg mt-5"
|
<button type="submit" className="btn btn-primary btn-block btn-lg shadow-lg mt-5">
|
||||||
onClick={handleLogin}>
|
|
||||||
Entrar
|
Entrar
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
278
src/pages/style/FinanceiroDashboard.css
Normal file
278
src/pages/style/FinanceiroDashboard.css
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
/* GERAL */
|
||||||
|
.financeiro-wrap {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 18px;
|
||||||
|
font-family: Inter, Roboto, Arial, sans-serif;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.financeiro-wrap h2 {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Container Cards de Resumo (Fluxo de Caixa) */
|
||||||
|
.summary-card-container {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 20px;
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-card {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 200px;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
|
||||||
|
transition: transform 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-card:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-card h3 {
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-card .value {
|
||||||
|
font-size: 26px;
|
||||||
|
font-weight: 700;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cores dos Cards de Resumo */
|
||||||
|
.summary-card.green {
|
||||||
|
background: linear-gradient(45deg, #10b981, #059669); /* Recebido */
|
||||||
|
}
|
||||||
|
.summary-card.red {
|
||||||
|
background: linear-gradient(45deg, #f97316, #ea580c); /* A Receber */
|
||||||
|
}
|
||||||
|
.summary-card.blue {
|
||||||
|
background: linear-gradient(45deg, #3b82f6, #2563eb); /* Descontos */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsiidade básica para o resumo */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.summary-card-container {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
.summary-card {
|
||||||
|
min-width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* CARD PRINCIPAL (LISTA) */
|
||||||
|
.list-page-card {
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 24px;
|
||||||
|
margin-top: 16px;
|
||||||
|
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tabela */
|
||||||
|
.table-container {
|
||||||
|
overflow-x: auto;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container th,
|
||||||
|
.table-container td {
|
||||||
|
padding: 14px 12px;
|
||||||
|
text-align: left;
|
||||||
|
border-bottom: 1px solid #eef3f8;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container th {
|
||||||
|
background: #f1f5f9;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #475569;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Botões de ação */
|
||||||
|
.action-group {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 6px 12px;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 1px solid #d7e6fb;
|
||||||
|
background: #fff;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn:hover {
|
||||||
|
background: #f6f9fc;
|
||||||
|
border-color: #93c5fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn.delete {
|
||||||
|
border-color: #fca5a5;
|
||||||
|
color: #b91c1c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn.delete:hover {
|
||||||
|
background: #fee2e2;
|
||||||
|
border-color: #ef4444;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Badges de status */
|
||||||
|
.badge {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 4px 10px;
|
||||||
|
border-radius: 9999px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge.pago {
|
||||||
|
background: #d1fae5;
|
||||||
|
color: #065f46;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge.pendente {
|
||||||
|
background: #fef3c7;
|
||||||
|
color: #a16207;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge.vencido {
|
||||||
|
background: #fee2e2;
|
||||||
|
color: #991b1b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Modal */
|
||||||
|
.modal {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 24px 12px;
|
||||||
|
background: rgba(0, 0, 0, 0.55);
|
||||||
|
z-index: 12000;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-card {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 24px;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 550px;
|
||||||
|
max-height: 90vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
box-sizing: border-box;
|
||||||
|
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header h2 {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #1f2937;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group label {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #4b5563;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #6c757d;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: color 0.2s;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn:hover {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 10px;
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Inputs e selects */
|
||||||
|
.input-field,
|
||||||
|
.select-field,
|
||||||
|
textarea {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px 12px;
|
||||||
|
border: 1px solid #d1d5db;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-size: 14px;
|
||||||
|
transition: border-color 0.2s, box-shadow 0.2s;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-field:focus,
|
||||||
|
.select-field:focus,
|
||||||
|
textarea:focus {
|
||||||
|
border-color: #3b82f6;
|
||||||
|
outline: none;
|
||||||
|
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
resize: vertical;
|
||||||
|
min-height: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mensagem quando não há pagamentos */
|
||||||
|
.empty {
|
||||||
|
text-align: center;
|
||||||
|
padding: 40px;
|
||||||
|
color: #7d97b4;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
31
src/perfis/perfil_financeiro/PerfilFinanceiro.jsx
Normal file
31
src/perfis/perfil_financeiro/PerfilFinanceiro.jsx
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { Routes, Route } from "react-router-dom";
|
||||||
|
import Sidebar from "../../components/Sidebar";
|
||||||
|
import FinanceiroItems from "../../data/sidebar-items-financeiro.json";
|
||||||
|
import Inicio from "../../pages/Inicio";
|
||||||
|
import TablePaciente from "../../pages/TablePaciente";
|
||||||
|
import FinanceiroDashboard from "../../pages/FinanceiroDashboard";
|
||||||
|
import DoctorTable from "../../pages/DoctorTable";
|
||||||
|
import Details from "../../pages/Details";
|
||||||
|
import DoctorDetails from "../../pages/DoctorDetails";
|
||||||
|
|
||||||
|
function PerfilFinanceiro({ onLogout }) {
|
||||||
|
return (
|
||||||
|
<div id="app" className="active">
|
||||||
|
<Sidebar onLogout={onLogout} menuItems={FinanceiroItems} />
|
||||||
|
<div id="main">
|
||||||
|
<Routes>
|
||||||
|
<Route path="/" element={<FinanceiroDashboard/>}/>
|
||||||
|
<Route path="inicio" element={<Inicio />} />
|
||||||
|
<Route path="controlefinanceiro" element={<FinanceiroDashboard/>}/>
|
||||||
|
<Route path="pacientes" element={<TablePaciente />} />
|
||||||
|
<Route path="medicos" element={<DoctorTable />} />
|
||||||
|
<Route path="pacientes/:id" element={<Details />} />
|
||||||
|
<Route path="medicos/:id" element={<DoctorDetails />} />
|
||||||
|
<Route path="*" element={<h2>Página não encontrada</h2>} />
|
||||||
|
</Routes>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PerfilFinanceiro;
|
||||||
@ -2,6 +2,8 @@
|
|||||||
import { Routes, Route } from "react-router-dom";
|
import { Routes, Route } from "react-router-dom";
|
||||||
|
|
||||||
import Sidebar from "../../components/Sidebar";
|
import Sidebar from "../../components/Sidebar";
|
||||||
|
import FinanceiroDashboard from "../../pages/FinanceiroDashboard";
|
||||||
|
import SecretariaItems from "../../data/sidebar-items.json";
|
||||||
import Inicio from "../../pages/Inicio";
|
import Inicio from "../../pages/Inicio";
|
||||||
import TablePaciente from "../../pages/TablePaciente";
|
import TablePaciente from "../../pages/TablePaciente";
|
||||||
import PatientCadastroManager from "../../pages/PatientCadastroManager";
|
import PatientCadastroManager from "../../pages/PatientCadastroManager";
|
||||||
@ -14,24 +16,26 @@ import EditPage from "../../pages/EditPage";
|
|||||||
import DoctorDetails from "../../pages/DoctorDetails";
|
import DoctorDetails from "../../pages/DoctorDetails";
|
||||||
import DoctorEditPage from "../../pages/DoctorEditPage";
|
import DoctorEditPage from "../../pages/DoctorEditPage";
|
||||||
|
|
||||||
function PerfilSecretaria() {
|
function PerfilSecretaria({ onLogout }) {
|
||||||
return (
|
return (
|
||||||
// <Router>
|
// <Router>
|
||||||
<div id="app" className="active">
|
<div id="app" className="active">
|
||||||
<Sidebar />
|
<Sidebar onLogout={onLogout} menuItems={SecretariaItems} />
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/inicio" element={<Inicio />} />
|
<Route path="/" element={<Inicio/>}/>
|
||||||
<Route path="/pacientes/cadastro" element={<PatientCadastroManager />} />
|
<Route path="inicio" element={<Inicio />} />
|
||||||
<Route path="/medicos/cadastro" element={<DoctorCadastroManager />} />
|
<Route path="pacientes/cadastro" element={<PatientCadastroManager />} />
|
||||||
<Route path="/pacientes" element={<TablePaciente />} />
|
<Route path="medicos/cadastro" element={<DoctorCadastroManager />} />
|
||||||
<Route path="/medicos" element={<DoctorTable />} />
|
<Route path="pacientes" element={<TablePaciente />} />
|
||||||
<Route path="/pacientes/:id" element={<Details />} />
|
<Route path="medicos" element={<DoctorTable />} />
|
||||||
<Route path="/pacientes/:id/edit" element={<EditPage />} />
|
<Route path="pacientes/:id" element={<Details />} />
|
||||||
<Route path="/medicos/:id" element={<DoctorDetails />} />
|
<Route path="pacientes/:id/edit" element={<EditPage />} />
|
||||||
<Route path="/medicos/:id/edit" element={<DoctorEditPage />} />
|
<Route path="medicos/:id" element={<DoctorDetails />} />
|
||||||
<Route path="/agendamento" element={<Agendamento />} />
|
<Route path="medicos/:id/edit" element={<DoctorEditPage />} />
|
||||||
<Route path="/laudo" element={<LaudoManager />} />
|
<Route path="agendamento" element={<Agendamento />} />
|
||||||
|
<Route path="laudo" element={<LaudoManager />} />
|
||||||
|
<Route path="controlefinanceiro" element={<FinanceiroDashboard/>}/>
|
||||||
<Route path="*" element={<h2>Página não encontrada</h2>} />
|
<Route path="*" element={<h2>Página não encontrada</h2>} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user