riseup-squad18/MEDICONNECTv3/src/pages/PainelSecretaria.tsx
2025-09-10 16:51:11 -03:00

1030 lines
43 KiB
TypeScript

import React, { useState, useEffect } from 'react'
import {Users, Calendar, FileText, Activity, Plus, Search, Filter, X, UserPlus} from 'lucide-react'
import toast from 'react-hot-toast'
import { useNavigate } from 'react-router-dom'
interface Paciente {
_id: string
nome: string
email: string
telefone: string
dataNascimento: string
altura?: number
peso?: number
endereco?: {
rua?: string
numero?: string
bairro?: string
cidade?: string
cep?: string
}
cpf?: string
convenio?: string
numeroCarteirinha?: string
observacoes?: string
}
interface Medico {
_id: string
nome: string
especialidade: string
crm: string
telefone: string
email: string
senha?: string
}
interface Consulta {
_id: string
paciente_id: string
medico_id: string
dataHora: string
tipo: string
status: string
observacoes?: string
pacienteNome?: string
medicoNome?: string
}
const PainelSecretaria: React.FC = () => {
const [activeTab, setActiveTab] = useState('dashboard')
const [pacientes, setPacientes] = useState<Paciente[]>([])
const [medicos, setMedicos] = useState<Medico[]>([])
const [consultas, setConsultas] = useState<Consulta[]>([])
const [loading, setLoading] = useState(true)
const [searchTerm, setSearchTerm] = useState('')
const [showNovoPacienteForm, setShowNovoPacienteForm] = useState(false)
const [showNovoMedicoForm, setShowNovoMedicoForm] = useState(false)
const navigate = useNavigate()
// Estado do formulário de novo paciente
const [formDataPaciente, setFormDataPaciente] = useState({
nome: '',
cpf: '',
telefone: '',
email: '',
dataNascimento: '',
altura: '',
peso: '',
endereco: {
rua: '',
numero: '',
bairro: '',
cidade: '',
cep: ''
},
convenio: '',
numeroCarteirinha: '',
observacoes: ''
})
// Estado do formulário de novo médico
const [formDataMedico, setFormDataMedico] = useState({
nome: '',
especialidade: '',
crm: '',
telefone: '',
email: '',
senha: ''
})
// Verificar se secretária está logada
useEffect(() => {
const secretariaLogada = localStorage.getItem('secretariaLogada')
if (!secretariaLogada) {
navigate('/secretaria')
return
}
carregarDados()
}, [navigate])
const carregarDados = async () => {
try {
setLoading(true)
// Carregar pacientes da API
const response = await fetch('https://mock.apidog.com/m1/1053378-0-default/pacientes')
const data = await response.json()
// A API retorna { success: true, data: [...] }
setPacientes(Array.isArray(data.data) ? data.data : [])
} catch (error) {
console.error('Erro ao carregar dados:', error)
toast.error('Erro ao carregar dados do sistema')
} finally {
setLoading(false)
}
}
const handleLogout = () => {
localStorage.removeItem('secretariaLogada')
toast.success('Logout realizado com sucesso!')
navigate('/secretaria') // Navegar para login da secretária/gestão
}
const handleNovoPaciente = () => {
setShowNovoPacienteForm(true)
setActiveTab('pacientes') // Mudar para aba pacientes
}
const handleNovoMedico = () => {
setShowNovoMedicoForm(true)
setActiveTab('medicos') // Mudar para aba médicos
}
const resetFormPaciente = () => {
setFormDataPaciente({
nome: '',
cpf: '',
telefone: '',
email: '',
dataNascimento: '',
altura: '',
peso: '',
endereco: {
rua: '',
numero: '',
bairro: '',
cidade: '',
cep: ''
},
convenio: '',
numeroCarteirinha: '',
observacoes: ''
})
setShowNovoPacienteForm(false)
}
const resetFormMedico = () => {
setFormDataMedico({
nome: '',
especialidade: '',
crm: '',
telefone: '',
email: '',
senha: ''
})
setShowNovoMedicoForm(false)
}
const handleSubmitNovoPaciente = async (e: React.FormEvent) => {
e.preventDefault()
try {
setLoading(true)
// Montar o body conforme a API espera
const pacienteData = {
nome: formDataPaciente.nome,
cpf: formDataPaciente.cpf,
data_nascimento: formDataPaciente.dataNascimento,
telefone: formDataPaciente.telefone,
email: formDataPaciente.email,
// Adicione outros campos se a API aceitar
}
const response = await fetch('https://mock.apidog.com/m1/1053378-0-default/pacientes', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(pacienteData)
})
if (!response.ok) throw new Error('Erro ao cadastrar paciente na API')
const novoPaciente = await response.json()
setPacientes(prev => [...prev, novoPaciente])
resetFormPaciente()
toast.success('Paciente cadastrado com sucesso!')
// Opcional: carregarDados() // Se quiser garantir atualização da lista da API
} catch (error) {
console.error('Erro ao cadastrar paciente:', error)
toast.error('Erro ao cadastrar paciente. Tente novamente.')
} finally {
setLoading(false)
}
}
const handleSubmitNovoMedico = async (e: React.FormEvent) => {
e.preventDefault()
try {
setLoading(true)
const medicoData = {
...formDataMedico,
ativo: true,
criadoPor: 'secretaria',
criadoEm: new Date().toISOString()
}
// Aqui você pode fazer um POST para a API se ela aceitar, ou apenas comentar se não houver endpoint
toast.success('Médico cadastrado com sucesso!')
resetFormMedico()
carregarDados() // Recarregar dados
} catch (error) {
console.error('Erro ao cadastrar médico:', error)
toast.error('Erro ao cadastrar médico. Tente novamente.')
} finally {
setLoading(false)
}
}
const formatarData = (data: string) => {
return new Date(data).toLocaleDateString('pt-BR', {
day: '2-digit',
month: '2-digit',
year: 'numeric',
hour: '2-digit',
minute: '2-digit'
})
}
const getStatusColor = (status: string) => {
switch (status) {
case 'agendada': return 'bg-blue-100 text-blue-800'
case 'confirmada': return 'bg-green-100 text-green-800'
case 'cancelada': return 'bg-red-100 text-red-800'
case 'realizada': return 'bg-gray-100 text-gray-800'
default: return 'bg-gray-100 text-gray-800'
}
}
// Filtrar dados baseado no termo de pesquisa
const pacientesFiltrados = pacientes.filter(p =>
(p.nome || '').toLowerCase().includes(searchTerm.toLowerCase()) ||
(p.email || '').toLowerCase().includes(searchTerm.toLowerCase())
)
const medicosFiltrados = medicos.filter(m =>
(m.nome || '').toLowerCase().includes(searchTerm.toLowerCase()) ||
(m.especialidade || '').toLowerCase().includes(searchTerm.toLowerCase())
)
const consultasFiltradas = consultas.filter(c =>
(c.pacienteNome || '').toLowerCase().includes(searchTerm.toLowerCase()) ||
(c.medicoNome || '').toLowerCase().includes(searchTerm.toLowerCase()) ||
(c.tipo || '').toLowerCase().includes(searchTerm.toLowerCase())
)
if (loading && !showNovoPacienteForm && !showNovoMedicoForm) {
return (
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
<div className="text-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-green-600 mx-auto mb-4"></div>
<p className="text-gray-600">Carregando painel da secretária...</p>
</div>
</div>
)
}
return (
<div className="min-h-screen bg-gray-50">
{/* Header */}
<div className="bg-white shadow-sm border-b">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center py-4">
<div>
<h1 className="text-2xl font-bold text-gray-900">Painel da Secretária</h1>
<p className="text-gray-600">Sistema de Gestão Médica</p>
</div>
<div className="flex space-x-3">
<button
onClick={handleNovoPaciente}
className="bg-green-600 text-white px-4 py-2 rounded-lg hover:bg-green-700 transition-colors flex items-center"
>
<Plus className="w-5 h-5 mr-2" />
Novo Paciente
</button>
<button
onClick={handleNovoMedico}
className="bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors flex items-center"
>
<UserPlus className="w-5 h-5 mr-2" />
Novo Médico
</button>
<button
onClick={handleLogout}
className="bg-red-600 text-white px-4 py-2 rounded-lg hover:bg-red-700 transition-colors"
>
Sair
</button>
</div>
</div>
</div>
</div>
{/* Navigation Tabs */}
<div className="bg-white border-b">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<nav className="flex space-x-8">
{[
{ id: 'dashboard', label: 'Dashboard', icon: Activity },
{ id: 'pacientes', label: 'Pacientes', icon: Users },
{ id: 'medicos', label: 'Médicos', icon: Users },
{ id: 'consultas', label: 'Consultas', icon: Calendar },
{ id: 'relatorios', label: 'Relatórios', icon: FileText }
].map(tab => {
const Icon = tab.icon
return (
<button
key={tab.id}
onClick={() => setActiveTab(tab.id)}
className={`flex items-center px-3 py-4 border-b-2 font-medium text-sm ${
activeTab === tab.id
? 'border-green-500 text-green-600'
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'
}`}
>
<Icon className="w-5 h-5 mr-2" />
{tab.label}
</button>
)
})}
</nav>
</div>
</div>
{/* Content */}
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
{/* Dashboard */}
{activeTab === 'dashboard' && (
<div className="space-y-6">
<div className="grid grid-cols-1 md:grid-cols-4 gap-6">
<div className="bg-white p-6 rounded-lg shadow">
<div className="flex items-center">
<Users className="w-8 h-8 text-blue-600" />
<div className="ml-4">
<p className="text-sm font-medium text-gray-600">Total Pacientes</p>
<p className="text-2xl font-bold text-gray-900">{pacientes.length}</p>
</div>
</div>
</div>
<div className="bg-white p-6 rounded-lg shadow">
<div className="flex items-center">
<Users className="w-8 h-8 text-green-600" />
<div className="ml-4">
<p className="text-sm font-medium text-gray-600">Total Médicos</p>
<p className="text-2xl font-bold text-gray-900">{medicos.length}</p>
</div>
</div>
</div>
<div className="bg-white p-6 rounded-lg shadow">
<div className="flex items-center">
<Calendar className="w-8 h-8 text-purple-600" />
<div className="ml-4">
<p className="text-sm font-medium text-gray-600">Consultas Hoje</p>
<p className="text-2xl font-bold text-gray-900">
{consultas.filter(c => {
const hoje = new Date().toDateString()
const dataConsulta = new Date(c.dataHora).toDateString()
return dataConsulta === hoje
}).length}
</p>
</div>
</div>
</div>
<div className="bg-white p-6 rounded-lg shadow">
<div className="flex items-center">
<Activity className="w-8 h-8 text-orange-600" />
<div className="ml-4">
<p className="text-sm font-medium text-gray-600">Consultas Pendentes</p>
<p className="text-2xl font-bold text-gray-900">
{consultas.filter(c => c.status === 'agendada').length}
</p>
</div>
</div>
</div>
</div>
{/* Próximas Consultas */}
<div className="bg-white rounded-lg shadow">
<div className="px-6 py-4 border-b">
<h3 className="text-lg font-medium text-gray-900">Próximas Consultas</h3>
</div>
<div className="p-6">
<div className="space-y-4">
{consultas
.filter(c => new Date(c.dataHora) >= new Date())
.sort((a, b) => new Date(a.dataHora).getTime() - new Date(b.dataHora).getTime())
.slice(0, 5)
.map(consulta => (
<div key={consulta._id} className="flex items-center justify-between p-4 bg-gray-50 rounded-lg">
<div>
<p className="font-medium text-gray-900">{consulta.pacienteNome}</p>
<p className="text-sm text-gray-600">Dr(a). {consulta.medicoNome}</p>
<p className="text-sm text-gray-500">{formatarData(consulta.dataHora)}</p>
</div>
<span className={`px-3 py-1 rounded-full text-xs font-medium ${getStatusColor(consulta.status)}`}>
{consulta.status}
</span>
</div>
))}
</div>
</div>
</div>
</div>
)}
{/* Pacientes */}
{activeTab === 'pacientes' && (
<div className="space-y-6">
<div className="flex justify-between items-center">
<h2 className="text-xl font-bold text-gray-900">Gerenciar Pacientes</h2>
<button
onClick={handleNovoPaciente}
className="bg-green-600 text-white px-4 py-2 rounded-lg hover:bg-green-700 transition-colors flex items-center"
>
<Plus className="w-5 h-5 mr-2" />
Novo Paciente
</button>
</div>
<div className="bg-white rounded-lg shadow">
<div className="p-6 border-b">
<div className="flex items-center space-x-4">
<div className="relative flex-1">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
<input
type="text"
placeholder="Buscar pacientes..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
className="pl-10 pr-4 py-2 w-full border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
/>
</div>
</div>
</div>
<div className="overflow-x-auto">
<table className="min-w-full divide-y divide-gray-200">
<thead className="bg-gray-50">
<tr>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Paciente
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Contato
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Data Nascimento
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Altura/Peso
</th>
</tr>
</thead>
<tbody className="bg-white divide-y divide-gray-200">
{pacientesFiltrados.map(paciente => (
<tr key={paciente._id} className="hover:bg-gray-50">
<td className="px-6 py-4 whitespace-nowrap">
<div>
<div className="text-sm font-medium text-gray-900">{paciente.nome || 'Nome não informado'}</div>
<div className="text-sm text-gray-500">{paciente.endereco?.cidade || 'Cidade não informada'}</div>
</div>
</td>
<td className="px-6 py-4 whitespace-nowrap">
<div className="text-sm text-gray-900">{paciente.email || 'Email não informado'}</div>
<div className="text-sm text-gray-500">{paciente.telefone || 'Telefone não informado'}</div>
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{paciente.dataNascimento ? new Date(paciente.dataNascimento).toLocaleDateString('pt-BR') : 'Não informado'}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{paciente.altura && paciente.peso ? `${paciente.altura}m / ${paciente.peso}kg` : 'Não informado'}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
)}
{/* Médicos */}
{activeTab === 'medicos' && (
<div className="space-y-6">
<div className="flex justify-between items-center">
<h2 className="text-xl font-bold text-gray-900">Gerenciar Médicos</h2>
<button
onClick={handleNovoMedico}
className="bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors flex items-center"
>
<UserPlus className="w-5 h-5 mr-2" />
Novo Médico
</button>
</div>
<div className="bg-white rounded-lg shadow">
<div className="p-6 border-b">
<div className="relative">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
<input
type="text"
placeholder="Buscar médicos..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
className="pl-10 pr-4 py-2 w-full border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
/>
</div>
</div>
<div className="overflow-x-auto">
<table className="min-w-full divide-y divide-gray-200">
<thead className="bg-gray-50">
<tr>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Médico
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Especialidade
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
CRM
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Contato
</th>
</tr>
</thead>
<tbody className="bg-white divide-y divide-gray-200">
{medicosFiltrados.map(medico => (
<tr key={medico._id} className="hover:bg-gray-50">
<td className="px-6 py-4 whitespace-nowrap">
<div className="text-sm font-medium text-gray-900">Dr(a). {medico.nome || 'Nome não informado'}</div>
</td>
<td className="px-6 py-4 whitespace-nowrap">
<div className="text-sm text-gray-900">{medico.especialidade || 'Não informado'}</div>
</td>
<td className="px-6 py-4 whitespace-nowrap">
<div className="text-sm text-gray-900">{medico.crm || 'Não informado'}</div>
</td>
<td className="px-6 py-4 whitespace-nowrap">
<div className="text-sm text-gray-900">{medico.email || 'Email não informado'}</div>
<div className="text-sm text-gray-500">{medico.telefone || 'Telefone não informado'}</div>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
)}
{/* Consultas */}
{activeTab === 'consultas' && (
<div className="space-y-6">
<div className="flex justify-between items-center">
<h2 className="text-xl font-bold text-gray-900">Gerenciar Consultas</h2>
</div>
<div className="bg-white rounded-lg shadow">
<div className="p-6 border-b">
<div className="relative">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
<input
type="text"
placeholder="Buscar consultas..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
className="pl-10 pr-4 py-2 w-full border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
/>
</div>
</div>
<div className="overflow-x-auto">
<table className="min-w-full divide-y divide-gray-200">
<thead className="bg-gray-50">
<tr>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Paciente
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Médico
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Data/Hora
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Tipo
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Status
</th>
</tr>
</thead>
<tbody className="bg-white divide-y divide-gray-200">
{consultasFiltradas.map(consulta => (
<tr key={consulta._id} className="hover:bg-gray-50">
<td className="px-6 py-4 whitespace-nowrap">
<div className="text-sm font-medium text-gray-900">{consulta.pacienteNome}</div>
</td>
<td className="px-6 py-4 whitespace-nowrap">
<div className="text-sm text-gray-900">Dr(a). {consulta.medicoNome}</div>
</td>
<td className="px-6 py-4 whitespace-nowrap">
<div className="text-sm text-gray-900">{formatarData(consulta.dataHora)}</div>
</td>
<td className="px-6 py-4 whitespace-nowrap">
<div className="text-sm text-gray-900">{consulta.tipo || 'Não informado'}</div>
</td>
<td className="px-6 py-4 whitespace-nowrap">
<span className={`px-3 py-1 rounded-full text-xs font-medium ${getStatusColor(consulta.status)}`}>
{consulta.status}
</span>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
)}
{/* Relatórios */}
{activeTab === 'relatorios' && (
<div className="space-y-6">
<h2 className="text-xl font-bold text-gray-900">Relatórios</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="bg-white p-6 rounded-lg shadow">
<h3 className="text-lg font-medium text-gray-900 mb-4">Consultas por Status</h3>
<div className="space-y-3">
{['agendada', 'confirmada', 'realizada', 'cancelada'].map(status => {
const count = consultas.filter(c => c.status === status).length
const percentage = consultas.length > 0 ? (count / consultas.length) * 100 : 0
return (
<div key={status} className="flex items-center justify-between">
<span className="text-sm font-medium text-gray-600 capitalize">{status}</span>
<div className="flex items-center space-x-2">
<div className="w-20 bg-gray-200 rounded-full h-2">
<div
className="bg-green-600 h-2 rounded-full"
style={{ width: `${percentage}%` }}
></div>
</div>
<span className="text-sm font-medium text-gray-900">{count}</span>
</div>
</div>
)
})}
</div>
</div>
<div className="bg-white p-6 rounded-lg shadow">
<h3 className="text-lg font-medium text-gray-900 mb-4">Médicos por Especialidade</h3>
<div className="space-y-3">
{[...new Set(medicos.map(m => m.especialidade).filter(Boolean))].map(especialidade => {
const count = medicos.filter(m => m.especialidade === especialidade).length
return (
<div key={especialidade} className="flex items-center justify-between">
<span className="text-sm font-medium text-gray-600">{especialidade}</span>
<span className="text-sm font-medium text-gray-900">{count}</span>
</div>
)
})}
</div>
</div>
</div>
</div>
)}
</div>
{/* Modal de Novo Paciente */}
{showNovoPacienteForm && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-lg max-w-2xl w-full max-h-[90vh] overflow-y-auto">
<div className="p-6">
<div className="flex justify-between items-center mb-6">
<h3 className="text-lg font-semibold">Cadastrar Novo Paciente</h3>
<button
onClick={resetFormPaciente}
className="text-gray-400 hover:text-gray-600"
>
<X className="w-6 h-6" />
</button>
</div>
<form onSubmit={handleSubmitNovoPaciente} className="space-y-4">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Nome Completo *
</label>
<input
type="text"
value={formDataPaciente.nome}
onChange={(e) => setFormDataPaciente({...formDataPaciente, nome: e.target.value})}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
required
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
CPF *
</label>
<input
type="text"
value={formDataPaciente.cpf}
onChange={(e) => setFormDataPaciente({...formDataPaciente, cpf: e.target.value})}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
required
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Telefone *
</label>
<input
type="tel"
value={formDataPaciente.telefone}
onChange={(e) => setFormDataPaciente({...formDataPaciente, telefone: e.target.value})}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
required
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Email *
</label>
<input
type="email"
value={formDataPaciente.email}
onChange={(e) => setFormDataPaciente({...formDataPaciente, email: e.target.value})}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
required
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Data de Nascimento *
</label>
<input
type="date"
value={formDataPaciente.dataNascimento}
onChange={(e) => setFormDataPaciente({...formDataPaciente, dataNascimento: e.target.value})}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
required
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Altura (cm)
</label>
<input
type="number"
min="50"
max="250"
step="0.1"
value={formDataPaciente.altura}
onChange={(e) => setFormDataPaciente({...formDataPaciente, altura: e.target.value})}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
placeholder="Ex: 170"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Peso (kg)
</label>
<input
type="number"
min="10"
max="300"
step="0.1"
value={formDataPaciente.peso}
onChange={(e) => setFormDataPaciente({...formDataPaciente, peso: e.target.value})}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
placeholder="Ex: 70.5"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
CEP
</label>
<input
type="text"
value={formDataPaciente.endereco.cep}
onChange={(e) => setFormDataPaciente({
...formDataPaciente,
endereco: {...formDataPaciente.endereco, cep: e.target.value}
})}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Cidade
</label>
<input
type="text"
value={formDataPaciente.endereco.cidade}
onChange={(e) => setFormDataPaciente({
...formDataPaciente,
endereco: {...formDataPaciente.endereco, cidade: e.target.value}
})}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Convênio
</label>
<select
value={formDataPaciente.convenio}
onChange={(e) => setFormDataPaciente({...formDataPaciente, convenio: e.target.value})}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
>
<option value="">Selecione</option>
<option value="Particular">Particular</option>
<option value="Unimed">Unimed</option>
<option value="SulAmérica">SulAmérica</option>
<option value="Bradesco Saúde">Bradesco Saúde</option>
<option value="Amil">Amil</option>
<option value="NotreDame">NotreDame</option>
</select>
</div>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Observações
</label>
<textarea
value={formDataPaciente.observacoes}
onChange={(e) => setFormDataPaciente({...formDataPaciente, observacoes: e.target.value})}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
rows={3}
/>
</div>
<div className="flex justify-end space-x-3 pt-4">
<button
type="button"
onClick={resetFormPaciente}
className="px-4 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50 transition-colors"
>
Cancelar
</button>
<button
type="submit"
disabled={loading}
className="px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors disabled:opacity-50"
>
{loading ? 'Cadastrando...' : 'Cadastrar Paciente'}
</button>
</div>
</form>
</div>
</div>
</div>
)}
{/* Modal de Novo Médico */}
{showNovoMedicoForm && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-lg max-w-md w-full max-h-[90vh] overflow-y-auto">
<div className="p-6">
<div className="flex justify-between items-center mb-6">
<h3 className="text-lg font-semibold">Cadastrar Novo Médico</h3>
<button
onClick={resetFormMedico}
className="text-gray-400 hover:text-gray-600"
>
<X className="w-6 h-6" />
</button>
</div>
<form onSubmit={handleSubmitNovoMedico} className="space-y-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Nome Completo *
</label>
<input
type="text"
value={formDataMedico.nome}
onChange={(e) => setFormDataMedico({...formDataMedico, nome: e.target.value})}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
required
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Especialidade *
</label>
<select
value={formDataMedico.especialidade}
onChange={(e) => setFormDataMedico({...formDataMedico, especialidade: e.target.value})}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
required
>
<option value="">Selecione</option>
<option value="Cardiologia">Cardiologia</option>
<option value="Dermatologia">Dermatologia</option>
<option value="Endocrinologia">Endocrinologia</option>
<option value="Gastroenterologia">Gastroenterologia</option>
<option value="Ginecologia">Ginecologia</option>
<option value="Neurologia">Neurologia</option>
<option value="Oftalmologia">Oftalmologia</option>
<option value="Ortopedia">Ortopedia</option>
<option value="Pediatria">Pediatria</option>
<option value="Psiquiatria">Psiquiatria</option>
<option value="Urologia">Urologia</option>
<option value="Clínico Geral">Clínico Geral</option>
</select>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
CRM *
</label>
<input
type="text"
value={formDataMedico.crm}
onChange={(e) => setFormDataMedico({...formDataMedico, crm: e.target.value})}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
placeholder="Ex: CRM/SP 123456"
required
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Telefone *
</label>
<input
type="tel"
value={formDataMedico.telefone}
onChange={(e) => setFormDataMedico({...formDataMedico, telefone: e.target.value})}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
required
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Email *
</label>
<input
type="email"
value={formDataMedico.email}
onChange={(e) => setFormDataMedico({...formDataMedico, email: e.target.value})}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
required
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Senha *
</label>
<input
type="password"
value={formDataMedico.senha}
onChange={(e) => setFormDataMedico({...formDataMedico, senha: e.target.value})}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
required
minLength={6}
/>
</div>
<div className="flex justify-end space-x-3 pt-4">
<button
type="button"
onClick={resetFormMedico}
className="px-4 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50 transition-colors"
>
Cancelar
</button>
<button
type="submit"
disabled={loading}
className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors disabled:opacity-50"
>
{loading ? 'Cadastrando...' : 'Cadastrar Médico'}
</button>
</div>
</form>
</div>
</div>
</div>
)}
</div>
)
}
export default PainelSecretaria