Paciente-inicio

This commit is contained in:
Caio Miguel Lima Nunes 2025-11-13 09:30:03 -03:00
parent 981c4bac6e
commit bff5c42a4e
6 changed files with 1099 additions and 14 deletions

View File

@ -1,10 +1,14 @@
[ [
{
"name": "Início",
"icon": "house-fill",
"url": "/paciente"
},
{ {
"name": "Minhas consulta", "name": "Minhas consulta",
"icon": "calendar-plus-fill", "icon": "calendar-plus-fill",
"url": "/paciente/agendamento" "url": "/paciente/agendamento"
}, },
{ {
"name": "Meus laudos", "name": "Meus laudos",
"icon": "table", "icon": "table",

View File

@ -1,6 +1,8 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { FaUser, FaUserPlus, FaCalendarAlt, FaCalendarCheck } from 'react-icons/fa'; import { FaUser, FaUserPlus, FaCalendarAlt, FaCalendarCheck } from 'react-icons/fa';
import { useAuth } from '../components/utils/AuthProvider';
import API_KEY from '../components/utils/apiKeys';
import './style/Inicio.css'; import './style/Inicio.css';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
@ -8,19 +10,142 @@ import { Link } from 'react-router-dom';
function Inicio() { function Inicio() {
const navigate = useNavigate(); const navigate = useNavigate();
const { getAuthorizationHeader, isAuthenticated } = useAuth();
const [pacientes, setPacientes] = useState([]); const [pacientes, setPacientes] = useState([]);
const [medicos, setMedicos] = useState([]);
const [agendamentos, setAgendamentos] = useState([]); const [agendamentos, setAgendamentos] = useState([]);
const [agendamentosComPacientes, setAgendamentosComPacientes] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchPacientes = async () => {
try {
const authHeader = getAuthorizationHeader();
const myHeaders = new Headers();
myHeaders.append("apikey", API_KEY);
myHeaders.append("Authorization", authHeader);
const requestOptions = {
method: 'GET',
headers: myHeaders,
redirect: 'follow'
};
const response = await fetch("https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/patients", requestOptions);
if (response.ok) {
const data = await response.json();
setPacientes(data);
console.log('Pacientes carregados:', data.length);
} else {
console.error(' Erro ao buscar pacientes:', response.status);
}
} catch (error) {
console.error(' Erro ao buscar pacientes:', error);
}
};
const fetchMedicos = async () => {
try {
const authHeader = getAuthorizationHeader();
const myHeaders = new Headers();
myHeaders.append("apikey", API_KEY);
myHeaders.append("Authorization", authHeader);
const requestOptions = {
method: 'GET',
headers: myHeaders,
redirect: 'follow'
};
const response = await fetch("https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/doctors", requestOptions);
if (response.ok) {
const data = await response.json();
setMedicos(data);
console.log(' Médicos carregados:', data.length);
} else {
console.error('Erro ao buscar médicos:', response.status);
}
} catch (error) {
console.error(' Erro ao buscar médicos:', error);
}
};
const fetchAgendamentos = async () => {
try {
const authHeader = getAuthorizationHeader();
const myHeaders = new Headers();
myHeaders.append("apikey", API_KEY);
myHeaders.append("Authorization", authHeader);
const requestOptions = {
method: 'GET',
headers: myHeaders,
redirect: 'follow'
};
const response = await fetch("https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/appointments", requestOptions);
if (response.ok) {
const data = await response.json();
setAgendamentos(data);
console.log(' Agendamentos carregados:', data.length);
} else {
console.error(' Erro ao buscar agendamentos:', response.status);
}
} catch (error) {
console.error(' Erro ao buscar agendamentos:', error);
} finally {
setLoading(false);
}
};
if (isAuthenticated) {
fetchPacientes();
fetchMedicos();
fetchAgendamentos();
}
}, [isAuthenticated, getAuthorizationHeader]);
useEffect(() => {
if (agendamentos.length > 0 && pacientes.length > 0 && medicos.length > 0) {
const agendamentosComNomes = agendamentos.map(agendamento => {
const paciente = pacientes.find(p => p.id === agendamento.patient_id);
const medico = medicos.find(m => m.id === agendamento.doctor_id);
return {
...agendamento,
nomePaciente: paciente?.full_name || 'Paciente não encontrado',
nomeMedico: medico?.full_name || 'Médico não encontrado',
especialidadeMedico: medico?.specialty || ''
};
});
setAgendamentosComPacientes(agendamentosComNomes);
}
}, [agendamentos, pacientes, medicos]);
const totalPacientes = pacientes.length; const totalPacientes = pacientes.length;
const novosEsseMes = pacientes.filter(p => p.createdAt && new Date(p.createdAt).getMonth() === new Date().getMonth()).length; const novosEsseMes = pacientes.filter(p => p.created_at && new Date(p.created_at).getMonth() === new Date().getMonth()).length;
const hoje = new Date(); const hoje = new Date();
const agendamentosDoDia = agendamentos.filter( hoje.setHours(0, 0, 0, 0);
a => a.data && new Date(a.data).getDate() === hoje.getDate()
); const agendamentosDoDia = agendamentosComPacientes.filter(a => {
if (!a.scheduled_at) return false;
const dataAgendamento = new Date(a.scheduled_at);
dataAgendamento.setHours(0, 0, 0, 0);
return dataAgendamento.getTime() === hoje.getTime();
});
const agendamentosHoje = agendamentosDoDia.length; const agendamentosHoje = agendamentosDoDia.length;
const pendencias = agendamentos.filter(a => a.status === 'pending' || a.status === 'scheduled').length;
return ( return (
<div className="dashboard-container"> <div className="dashboard-container">
<div className="dashboard-header"> <div className="dashboard-header">
@ -57,7 +182,7 @@ function Inicio() {
<div className="stat-card"> <div className="stat-card">
<div className="stat-info"> <div className="stat-info">
<span className="stat-label">PENDÊNCIAS</span> <span className="stat-label">PENDÊNCIAS</span>
<span className="stat-value">0</span> <span className="stat-value">{loading ? '...' : pendencias}</span>
</div> </div>
<div className="stat-icon-wrapper orange"><FaCalendarAlt className="stat-icon" /></div> <div className="stat-icon-wrapper orange"><FaCalendarAlt className="stat-icon" /></div>
</div> </div>
@ -92,14 +217,54 @@ function Inicio() {
<div className="appointments-section"> <div className="appointments-section">
<h2>Próximos Agendamentos</h2> <h2>Próximos Agendamentos</h2>
{agendamentosHoje > 0 ? ( {loading ? (
<div> <div className="no-appointments-content">
{agendamentosDoDia.map(agendamento => ( <p>Carregando agendamentos...</p>
</div>
) : agendamentosHoje > 0 ? (
<div className="agendamentos-list">
{agendamentosDoDia.slice(0, 5).map(agendamento => (
<div key={agendamento.id} className="agendamento-item"> <div key={agendamento.id} className="agendamento-item">
<p>{agendamento.nomePaciente}</p> <div className="agendamento-info">
<p>{new Date(agendamento.data).toLocaleTimeString()}</p> <div className="agendamento-time-date">
<p className="agendamento-hora">
{new Date(agendamento.scheduled_at).toLocaleTimeString('pt-BR', {
hour: '2-digit',
minute: '2-digit'
})}
</p>
<p className="agendamento-data">
{new Date(agendamento.scheduled_at).toLocaleDateString('pt-BR', {
day: '2-digit',
month: '2-digit',
year: 'numeric'
})}
</p>
</div>
<div className="agendamento-detalhes">
<p className="agendamento-paciente">
<strong>Paciente:</strong> {agendamento.nomePaciente}
</p>
<p className="agendamento-medico">
<strong>Dr(a):</strong> {agendamento.nomeMedico}
{agendamento.especialidadeMedico && ` - ${agendamento.especialidadeMedico}`}
</p>
</div>
<span className={`agendamento-status status-${agendamento.status}`}>
{agendamento.status === 'scheduled' ? 'Agendado' :
agendamento.status === 'completed' ? 'Concluído' :
agendamento.status === 'pending' ? 'Pendente' :
agendamento.status === 'cancelled' ? 'Cancelado' :
agendamento.status === 'requested' ? '' : agendamento.status}
</span>
</div>
</div> </div>
))} ))}
{agendamentosHoje > 5 && (
<button className="view-all-button" onClick={() => navigate('/secretaria/agendamento')}>
Ver todos os {agendamentosHoje} agendamentos
</button>
)}
</div> </div>
) : ( ) : (
<div className="no-appointments-content"> <div className="no-appointments-content">

View File

@ -0,0 +1,273 @@
import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { FaCalendarAlt, FaCalendarCheck, FaFileAlt, FaUserMd, FaClock } from 'react-icons/fa';
import { useAuth } from '../components/utils/AuthProvider';
import API_KEY from '../components/utils/apiKeys';
import './style/inicioPaciente.css';
function InicioPaciente() {
const navigate = useNavigate();
const { getAuthorizationHeader, isAuthenticated } = useAuth();
const [agendamentos, setAgendamentos] = useState([]);
const [medicos, setMedicos] = useState([]);
const [agendamentosComMedicos, setAgendamentosComMedicos] = useState([]);
const [loading, setLoading] = useState(true);
const [pacienteId, setPacienteId] = useState(null);
useEffect(() => {
const userId = localStorage.getItem('user_id') || localStorage.getItem('patient_id');
setPacienteId(userId);
}, []);
useEffect(() => {
const fetchMedicos = async () => {
try {
const authHeader = getAuthorizationHeader();
const myHeaders = new Headers();
myHeaders.append("apikey", API_KEY);
myHeaders.append("Authorization", authHeader);
const requestOptions = {
method: 'GET',
headers: myHeaders,
redirect: 'follow'
};
const response = await fetch("https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/doctors", requestOptions);
if (response.ok) {
const data = await response.json();
setMedicos(data);
console.log(' Médicos carregados:', data.length);
} else {
console.error(' Erro ao buscar médicos:', response.status);
}
} catch (error) {
console.error(' Erro ao buscar médicos:', error);
}
};
const fetchAgendamentos = async () => {
try {
const authHeader = getAuthorizationHeader();
const myHeaders = new Headers();
myHeaders.append("apikey", API_KEY);
myHeaders.append("Authorization", authHeader);
const requestOptions = {
method: 'GET',
headers: myHeaders,
redirect: 'follow'
};
// Buscar todos os agendamentos (depois filtraremos pelo paciente)
const response = await fetch("https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/appointments", requestOptions);
if (response.ok) {
const data = await response.json();
setAgendamentos(data);
console.log(' Agendamentos carregados:', data.length);
} else {
console.error(' Erro ao buscar agendamentos:', response.status);
}
} catch (error) {
console.error(' Erro ao buscar agendamentos:', error);
} finally {
setLoading(false);
}
};
if (isAuthenticated) {
fetchMedicos();
fetchAgendamentos();
}
}, [isAuthenticated, getAuthorizationHeader]);
useEffect(() => {
if (agendamentos.length > 0 && medicos.length > 0) {
const agendamentosComNomes = agendamentos.map(agendamento => {
const medico = medicos.find(m => m.id === agendamento.doctor_id);
return {
...agendamento,
nomeMedico: medico?.full_name || 'Médico não encontrado',
especialidadeMedico: medico?.specialty || ''
};
});
setAgendamentosComMedicos(agendamentosComNomes);
}
}, [agendamentos, medicos]);
const meusAgendamentos = agendamentosComMedicos.filter(a =>
pacienteId ? a.patient_id === pacienteId : true
);
const hoje = new Date();
hoje.setHours(0, 0, 0, 0);
const agendamentosFuturos = meusAgendamentos.filter(a => {
if (!a.scheduled_at) return false;
const dataAgendamento = new Date(a.scheduled_at);
return dataAgendamento >= hoje && a.status !== 'cancelled' && a.status !== 'completed';
}).sort((a, b) => new Date(a.scheduled_at) - new Date(b.scheduled_at));
const proximasConsultas = agendamentosFuturos.length;
const consultasHoje = agendamentosFuturos.filter(a => {
const dataAgendamento = new Date(a.scheduled_at);
dataAgendamento.setHours(0, 0, 0, 0);
return dataAgendamento.getTime() === hoje.getTime();
}).length;
const consultasPendentes = meusAgendamentos.filter(a =>
a.status === 'pending' || a.status === 'requested'
).length;
const historicoConsultas = meusAgendamentos.filter(a =>
a.status === 'completed'
).length;
return (
<div className="dashboard-paciente-container">
<div className="dashboard-paciente-header">
<h1>Bem-vindo ao MediConnect</h1>
<p>Gerencie suas consultas e acompanhe seu histórico médico</p>
</div>
<div className="stats-paciente-grid">
<div className="stat-paciente-card">
<div className="stat-paciente-info">
<span className="stat-paciente-label">Próximas Consultas</span>
<span className="stat-paciente-value">{proximasConsultas}</span>
</div>
<div className="stat-paciente-icon-wrapper blue">
<FaCalendarAlt className="stat-paciente-icon" />
</div>
</div>
<div className="stat-paciente-card">
<div className="stat-paciente-info">
<span className="stat-paciente-label">Consultas Hoje</span>
<span className="stat-paciente-value">{consultasHoje}</span>
</div>
<div className="stat-paciente-icon-wrapper green">
<FaCalendarCheck className="stat-paciente-icon" />
</div>
</div>
<div className="stat-paciente-card">
<div className="stat-paciente-info">
<span className="stat-paciente-label">Aguardando</span>
<span className="stat-paciente-value">{loading ? '...' : consultasPendentes}</span>
</div>
<div className="stat-paciente-icon-wrapper purple">
<FaClock className="stat-paciente-icon" />
</div>
</div>
<div className="stat-paciente-card">
<div className="stat-paciente-info">
<span className="stat-paciente-label">Realizadas</span>
<span className="stat-paciente-value">{historicoConsultas}</span>
</div>
<div className="stat-paciente-icon-wrapper orange">
<FaFileAlt className="stat-paciente-icon" />
</div>
</div>
</div>
<div className="quick-actions-paciente">
<h2>Acesso Rápido</h2>
<div className="actions-paciente-grid">
<div className="action-paciente-button" onClick={() => navigate('/paciente/agendamento')}>
<FaCalendarCheck className="action-paciente-icon" />
<div className="action-paciente-info">
<span className="action-paciente-title">Minhas Consultas</span>
<span className="action-paciente-desc">Ver todos os agendamentos</span>
</div>
</div>
<div className="action-paciente-button" onClick={() => navigate('/paciente/laudo')}>
<FaFileAlt className="action-paciente-icon" />
<div className="action-paciente-info">
<span className="action-paciente-title">Meus Laudos</span>
<span className="action-paciente-desc">Acessar documentos médicos</span>
</div>
</div>
<div className="action-paciente-button" onClick={() => navigate('/paciente/agendamento')}>
<FaUserMd className="action-paciente-icon" />
<div className="action-paciente-info">
<span className="action-paciente-title">Meus Médicos</span>
<span className="action-paciente-desc">Ver histórico de atendimentos</span>
</div>
</div>
</div>
</div>
<div className="proximas-consultas-section">
<h2>Próximas Consultas</h2>
{loading ? (
<div className="no-consultas-content">
<p>Carregando suas consultas...</p>
</div>
) : agendamentosFuturos.length > 0 ? (
<div className="consultas-paciente-list">
{agendamentosFuturos.slice(0, 3).map(agendamento => (
<div key={agendamento.id} className="consulta-paciente-item">
<div className="consulta-paciente-info">
<div className="consulta-paciente-time-date">
<p className="consulta-paciente-hora">
{new Date(agendamento.scheduled_at).toLocaleTimeString('pt-BR', {
hour: '2-digit',
minute: '2-digit'
})}
</p>
<p className="consulta-paciente-data">
{new Date(agendamento.scheduled_at).toLocaleDateString('pt-BR', {
day: '2-digit',
month: 'short',
year: 'numeric'
})}
</p>
</div>
<div className="consulta-paciente-detalhes">
<p className="consulta-paciente-medico">
<FaUserMd className="consulta-icon" />
<strong>Dr(a):</strong> {agendamento.nomeMedico}
</p>
{agendamento.especialidadeMedico && (
<p className="consulta-paciente-especialidade">
{agendamento.especialidadeMedico}
</p>
)}
</div>
<span className={`consulta-paciente-status status-${agendamento.status}`}>
{agendamento.status === 'scheduled' ? 'Confirmado' :
agendamento.status === 'pending' ? 'Aguardando' :
agendamento.status === 'requested' ? 'Solicitado' : agendamento.status}
</span>
</div>
</div>
))}
{agendamentosFuturos.length > 3 && (
<button className="view-all-paciente-button" onClick={() => navigate('/paciente/agendamento')}>
Ver todas as consultas
</button>
)}
</div>
) : (
<div className="no-consultas-content">
<FaCalendarCheck className="no-consultas-icon" />
<p>Você não tem consultas agendadas</p>
<button className="agendar-paciente-button" onClick={() => navigate('/paciente/agendamento/criar')}>
Agendar Consulta
</button>
</div>
)}
</div>
</div>
);
}
export default InicioPaciente;

View File

@ -229,3 +229,191 @@ html[data-bs-theme="dark"] .manage-button {
html[data-bs-theme="dark"] .manage-button:hover { html[data-bs-theme="dark"] .manage-button:hover {
background-color: #2323b0; background-color: #2323b0;
} }
/* Lista de Agendamentos */
.agendamentos-list {
display: flex;
flex-direction: column;
gap: 1rem;
}
.agendamento-item {
background-color: #f9fafb;
border-left: 4px solid #5d5dff;
border-radius: 8px;
padding: 1rem 1.25rem;
transition: all 0.2s ease;
}
.agendamento-item:hover {
background-color: #f0f2f5;
transform: translateX(5px);
}
.agendamento-info {
display: flex;
align-items: center;
gap: 1.5rem;
flex-wrap: wrap;
}
.agendamento-time-date {
display: flex;
flex-direction: column;
align-items: center;
min-width: 90px;
}
.agendamento-hora {
font-size: 1.3rem;
font-weight: 700;
color: #5d5dff;
margin: 0;
line-height: 1.2;
}
.agendamento-data {
font-size: 0.75rem;
font-weight: 500;
color: #888;
margin: 0;
margin-top: 0.25rem;
}
.agendamento-detalhes {
display: flex;
flex-direction: column;
gap: 0.5rem;
flex: 1;
min-width: 300px;
}
.agendamento-paciente,
.agendamento-medico {
font-size: 0.95rem;
color: #444;
margin: 0;
line-height: 1.4;
}
.agendamento-paciente strong,
.agendamento-medico strong {
font-weight: 600;
color: #333;
}
.agendamento-status {
font-size: 0.75rem;
font-weight: 600;
padding: 0.4rem 0.8rem;
border-radius: 20px;
text-transform: uppercase;
}
.agendamento-status.status-scheduled {
background-color: #e3f2fd;
color: #1976d2;
}
.agendamento-status.status-completed {
background-color: #e8f5e9;
color: #388e3c;
}
.agendamento-status.status-pending {
background-color: #fff3e0;
color: #f57c00;
}
.agendamento-status.status-cancelled {
background-color: #ffebee;
color: #d32f2f;
}
.agendamento-status.status-requested {
background-color: #f3e5f5;
color: #7b1fa2;
}
.view-all-button {
width: 100%;
margin-top: 1rem;
background-color: #f0f2f5;
color: #5d5dff;
border: 2px solid #5d5dff;
border-radius: 8px;
padding: 0.75rem 1.5rem;
font-size: 0.9rem;
font-weight: 600;
cursor: pointer;
transition: all 0.2s ease;
}
.view-all-button:hover {
background-color: #5d5dff;
color: #fff;
}
/* Dark Mode - Agendamentos */
html[data-bs-theme="dark"] .agendamento-item {
background-color: #2a2a2a;
border-left-color: #6c6cff;
}
html[data-bs-theme="dark"] .agendamento-item:hover {
background-color: #333;
}
html[data-bs-theme="dark"] .agendamento-hora {
color: #8888ff;
}
html[data-bs-theme="dark"] .agendamento-data {
color: #999;
}
html[data-bs-theme="dark"] .agendamento-paciente,
html[data-bs-theme="dark"] .agendamento-medico {
color: #d0d0d0;
}
html[data-bs-theme="dark"] .agendamento-paciente strong,
html[data-bs-theme="dark"] .agendamento-medico strong {
color: #e0e0e0;
}
html[data-bs-theme="dark"] .agendamento-status.status-scheduled {
background-color: #1a3a52;
color: #64b5f6;
}
html[data-bs-theme="dark"] .agendamento-status.status-completed {
background-color: #1b3a1f;
color: #81c784;
}
html[data-bs-theme="dark"] .agendamento-status.status-pending {
background-color: #3d2817;
color: #ffb74d;
}
html[data-bs-theme="dark"] .agendamento-status.status-cancelled {
background-color: #3d1f1f;
color: #e57373;
}
html[data-bs-theme="dark"] .agendamento-status.status-requested {
background-color: #2d1f3d;
color: #ba68c8;
}
html[data-bs-theme="dark"] .view-all-button {
background-color: #2a2a2a;
color: #8888ff;
border-color: #6c6cff;
}
html[data-bs-theme="dark"] .view-all-button:hover {
background-color: #6c6cff;
color: #fff;
}

View File

@ -0,0 +1,454 @@
.dashboard-paciente-container {
padding: 2rem;
background-color: #f7f9fc;
flex-grow: 1;
min-height: 100vh;
}
/* Header - Paciente */
.dashboard-paciente-header {
margin-bottom: 2rem;
}
.dashboard-paciente-header h1 {
font-size: 2rem;
font-weight: 600;
color: #333;
margin-bottom: 0.5rem;
}
.dashboard-paciente-header p {
font-size: 1rem;
color: #666;
}
/* Estatísticas - Paciente */
.stats-paciente-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 1.5rem;
margin-bottom: 2.5rem;
}
.stat-paciente-card {
background-color: #fff;
border-radius: 12px;
padding: 1.5rem;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.05);
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.stat-paciente-card:hover {
transform: translateY(-3px);
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.1);
}
.stat-paciente-info {
display: flex;
flex-direction: column;
}
.stat-paciente-label {
font-size: 0.75rem;
font-weight: 600;
color: #888;
margin-bottom: 0.5rem;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.stat-paciente-value {
font-size: 2.2rem;
font-weight: 700;
color: #444;
}
.stat-paciente-icon-wrapper {
width: 55px;
height: 55px;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
}
.stat-paciente-icon {
font-size: 1.4rem;
color: #fff;
}
/* Cores dos ícones - Paciente */
.stat-paciente-icon-wrapper.blue { background-color: #5d5dff; }
.stat-paciente-icon-wrapper.green { background-color: #30d158; }
.stat-paciente-icon-wrapper.purple { background-color: #a272ff; }
.stat-paciente-icon-wrapper.orange { background-color: #f1952e; }
/* Ações Rápidas - Paciente */
.quick-actions-paciente h2 {
font-size: 1.3rem;
font-weight: 600;
color: #333;
margin-bottom: 1.5rem;
}
.actions-paciente-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1.5rem;
margin-bottom: 2.5rem;
}
.action-paciente-button {
background-color: #fff;
border-radius: 12px;
padding: 1.5rem;
display: flex;
align-items: center;
cursor: pointer;
transition: all 0.2s ease-in-out;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.05);
}
.action-paciente-button:hover {
transform: translateY(-5px);
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.12);
}
.action-paciente-icon {
font-size: 2.5rem;
margin-right: 1.2rem;
color: #5d5dff;
}
.action-paciente-info {
display: flex;
flex-direction: column;
}
.action-paciente-title {
font-size: 1.05rem;
font-weight: 600;
color: #444;
margin-bottom: 0.25rem;
}
.action-paciente-desc {
font-size: 0.85rem;
color: #888;
}
/* Próximas Consultas - Paciente */
.proximas-consultas-section {
background-color: #fff;
border-radius: 12px;
padding: 2rem;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.05);
}
.proximas-consultas-section h2 {
font-size: 1.3rem;
font-weight: 600;
color: #333;
margin-bottom: 1.5rem;
}
/* Lista de Consultas - Paciente */
.consultas-paciente-list {
display: flex;
flex-direction: column;
gap: 1.2rem;
}
.consulta-paciente-item {
background: linear-gradient(135deg, #f9fafb 0%, #ffffff 100%);
border-left: 5px solid #5d5dff;
border-radius: 10px;
padding: 1.25rem 1.5rem;
transition: all 0.3s ease;
}
.consulta-paciente-item:hover {
background: linear-gradient(135deg, #f0f2f5 0%, #fafbfc 100%);
transform: translateX(8px);
box-shadow: 0 4px 12px rgba(93, 93, 255, 0.15);
}
.consulta-paciente-info {
display: flex;
align-items: center;
gap: 2rem;
flex-wrap: wrap;
}
.consulta-paciente-time-date {
display: flex;
flex-direction: column;
align-items: center;
min-width: 90px;
padding: 0.5rem;
background-color: #f0f2ff;
border-radius: 8px;
}
.consulta-paciente-hora {
font-size: 1.5rem;
font-weight: 700;
color: #5d5dff;
margin: 0;
line-height: 1.2;
}
.consulta-paciente-data {
font-size: 0.8rem;
font-weight: 500;
color: #7777aa;
margin: 0;
margin-top: 0.25rem;
text-transform: capitalize;
}
.consulta-paciente-detalhes {
display: flex;
flex-direction: column;
gap: 0.5rem;
flex: 1;
min-width: 250px;
}
.consulta-paciente-medico {
font-size: 1rem;
color: #444;
margin: 0;
display: flex;
align-items: center;
gap: 0.5rem;
}
.consulta-icon {
color: #5d5dff;
font-size: 1.1rem;
}
.consulta-paciente-medico strong {
font-weight: 600;
color: #333;
}
.consulta-paciente-especialidade {
font-size: 0.85rem;
color: #666;
margin: 0;
margin-left: 1.6rem;
font-style: italic;
}
.consulta-paciente-status {
font-size: 0.75rem;
font-weight: 600;
padding: 0.5rem 1rem;
border-radius: 20px;
text-transform: uppercase;
white-space: nowrap;
}
.consulta-paciente-status.status-scheduled {
background-color: #e3f2fd;
color: #1976d2;
}
.consulta-paciente-status.status-pending {
background-color: #fff3e0;
color: #f57c00;
}
.consulta-paciente-status.status-requested {
background-color: #f3e5f5;
color: #7b1fa2;
}
/* Sem Consultas */
.no-consultas-content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
padding: 3rem 1rem;
}
.no-consultas-icon {
font-size: 4rem;
color: #bbb;
margin-bottom: 1.5rem;
}
.no-consultas-content p {
font-size: 1.1rem;
color: #666;
margin-bottom: 2rem;
}
.agendar-paciente-button,
.view-all-paciente-button {
background-color: #5d5dff;
color: #fff;
border: none;
border-radius: 8px;
padding: 0.875rem 2rem;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.2s ease;
}
.agendar-paciente-button:hover,
.view-all-paciente-button:hover {
background-color: #4444ff;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(93, 93, 255, 0.3);
}
.view-all-paciente-button {
width: 100%;
margin-top: 1rem;
background-color: #f0f2f5;
color: #5d5dff;
border: 2px solid #5d5dff;
}
.view-all-paciente-button:hover {
background-color: #5d5dff;
color: #fff;
}
/* Dark Mode - Paciente */
html[data-bs-theme="dark"] .dashboard-paciente-container {
background-color: #121212;
color: #e0e0e0;
}
html[data-bs-theme="dark"] .dashboard-paciente-header h1,
html[data-bs-theme="dark"] .dashboard-paciente-header p,
html[data-bs-theme="dark"] .quick-actions-paciente h2,
html[data-bs-theme="dark"] .proximas-consultas-section h2,
html[data-bs-theme="dark"] .action-paciente-title,
html[data-bs-theme="dark"] .stat-paciente-value {
color: #e0e0e0;
}
html[data-bs-theme="dark"] .stat-paciente-card,
html[data-bs-theme="dark"] .action-paciente-button,
html[data-bs-theme="dark"] .proximas-consultas-section {
background-color: #1e1e1e;
box-shadow: 0 4px 10px rgba(0,0,0,0.3);
}
html[data-bs-theme="dark"] .stat-paciente-label,
html[data-bs-theme="dark"] .action-paciente-desc,
html[data-bs-theme="dark"] .no-consultas-content p {
color: #b0b0b0;
}
html[data-bs-theme="dark"] .consulta-paciente-item {
background: linear-gradient(135deg, #2a2a2a 0%, #1e1e1e 100%);
border-left-color: #6c6cff;
}
html[data-bs-theme="dark"] .consulta-paciente-item:hover {
background: linear-gradient(135deg, #333 0%, #252525 100%);
box-shadow: 0 4px 12px rgba(108, 108, 255, 0.2);
}
html[data-bs-theme="dark"] .consulta-paciente-time-date {
background-color: #2a2a3a;
}
html[data-bs-theme="dark"] .consulta-paciente-hora {
color: #8888ff;
}
html[data-bs-theme="dark"] .consulta-paciente-data {
color: #9999cc;
}
html[data-bs-theme="dark"] .consulta-paciente-medico,
html[data-bs-theme="dark"] .consulta-paciente-especialidade {
color: #d0d0d0;
}
html[data-bs-theme="dark"] .consulta-paciente-medico strong {
color: #e0e0e0;
}
html[data-bs-theme="dark"] .consulta-icon,
html[data-bs-theme="dark"] .action-paciente-icon {
color: #8888ff;
}
html[data-bs-theme="dark"] .consulta-paciente-status.status-scheduled {
background-color: #1a3a52;
color: #64b5f6;
}
html[data-bs-theme="dark"] .consulta-paciente-status.status-pending {
background-color: #3d2817;
color: #ffb74d;
}
html[data-bs-theme="dark"] .consulta-paciente-status.status-requested {
background-color: #2d1f3d;
color: #ba68c8;
}
html[data-bs-theme="dark"] .no-consultas-icon {
color: #666;
}
html[data-bs-theme="dark"] .agendar-paciente-button {
background-color: #6c6cff;
}
html[data-bs-theme="dark"] .agendar-paciente-button:hover {
background-color: #5555dd;
}
html[data-bs-theme="dark"] .view-all-paciente-button {
background-color: #2a2a2a;
color: #8888ff;
border-color: #6c6cff;
}
html[data-bs-theme="dark"] .view-all-paciente-button:hover {
background-color: #6c6cff;
color: #fff;
}
/* Responsivo */
@media (max-width: 768px) {
.dashboard-paciente-container {
padding: 1rem;
}
.stats-paciente-grid {
grid-template-columns: 1fr;
}
.actions-paciente-grid {
grid-template-columns: 1fr;
}
.consulta-paciente-info {
flex-direction: column;
align-items: flex-start;
gap: 1rem;
}
.consulta-paciente-time-date {
width: 100%;
flex-direction: row;
justify-content: space-around;
}
}

View File

@ -2,6 +2,7 @@ import { Routes, Route } from "react-router-dom";
import Sidebar from "../../components/Sidebar"; import Sidebar from "../../components/Sidebar";
import PacienteItems from "../../data/sidebar-items-paciente.json"; import PacienteItems from "../../data/sidebar-items-paciente.json";
import { useState } from "react"; import { useState } from "react";
import InicioPaciente from "../../pages/inicioPaciente";
import LaudoManager from "../../pages/LaudoManager"; import LaudoManager from "../../pages/LaudoManager";
import ConsultaCadastroManager from "../../PagesPaciente/ConsultaCadastroManager"; import ConsultaCadastroManager from "../../PagesPaciente/ConsultaCadastroManager";
import ConsultasPaciente from "../../PagesPaciente/ConsultasPaciente"; import ConsultasPaciente from "../../PagesPaciente/ConsultasPaciente";
@ -16,7 +17,7 @@ const [dadosConsulta, setConsulta] = useState({})
<div id="main"> <div id="main">
<Routes> <Routes>
<Route path="/" element={<LaudoManager />} /> <Route path="/" element={<InicioPaciente />} />
<Route path="agendamento" element={<ConsultasPaciente setConsulta={setConsulta}/>} /> <Route path="agendamento" element={<ConsultasPaciente setConsulta={setConsulta}/>} />
<Route path="agendamento/criar" element={<ConsultaCadastroManager />} /> <Route path="agendamento/criar" element={<ConsultaCadastroManager />} />
<Route path="agendamento/edit" element={<ConsultaEditPage dadosConsulta={dadosConsulta} />} /> <Route path="agendamento/edit" element={<ConsultaEditPage dadosConsulta={dadosConsulta} />} />