Reorganização das Disponibilidades
This commit is contained in:
parent
4d661dd973
commit
ce3c5b8f22
@ -7,6 +7,7 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
||||||
|
|
||||||
const FormatTelefones = (valor) => {
|
const FormatTelefones = (valor) => {
|
||||||
const digits = String(valor).replace(/\D/g, "").slice(0, 11);
|
const digits = String(valor).replace(/\D/g, "").slice(0, 11);
|
||||||
return digits
|
return digits
|
||||||
@ -28,7 +29,6 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
|
|||||||
const cpfLimpo = cpf.replace(/\D/g, "");
|
const cpfLimpo = cpf.replace(/\D/g, "");
|
||||||
|
|
||||||
if (cpfLimpo.length !== 11) return false;
|
if (cpfLimpo.length !== 11) return false;
|
||||||
|
|
||||||
if (/^(\d)\1+$/.test(cpfLimpo)) return false;
|
if (/^(\d)\1+$/.test(cpfLimpo)) return false;
|
||||||
|
|
||||||
let soma = 0;
|
let soma = 0;
|
||||||
@ -51,6 +51,7 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const [avatarUrl, setAvatarUrl] = useState(null);
|
const [avatarUrl, setAvatarUrl] = useState(null);
|
||||||
const [showRequiredModal, setShowRequiredModal] = useState(false);
|
const [showRequiredModal, setShowRequiredModal] = useState(false);
|
||||||
const [emptyFields, setEmptyFields] = useState([]);
|
const [emptyFields, setEmptyFields] = useState([]);
|
||||||
@ -122,6 +123,10 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleAvailabilityUpdate = (newAvailability) => {
|
||||||
|
setFormData((prev) => ({ ...prev, availability: newAvailability }));
|
||||||
|
};
|
||||||
|
|
||||||
const handleCepBlur = async () => {
|
const handleCepBlur = async () => {
|
||||||
const cep = formData.cep?.replace(/\D/g, "");
|
const cep = formData.cep?.replace(/\D/g, "");
|
||||||
if (cep && cep.length === 8) {
|
if (cep && cep.length === 8) {
|
||||||
@ -250,8 +255,10 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
|
|||||||
setShowRequiredModal(false);
|
setShowRequiredModal(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{/* Modal de Alerta */}
|
||||||
{showRequiredModal && (
|
{showRequiredModal && (
|
||||||
<div className="modal-overlay">
|
<div className="modal-overlay">
|
||||||
<div className="modal-content">
|
<div className="modal-content">
|
||||||
@ -299,6 +306,7 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Formulário Principal */}
|
||||||
<div className="card doctor-form-container shadow-sm">
|
<div className="card doctor-form-container shadow-sm">
|
||||||
<h3 className="doctor-form-title">MediConnect</h3>
|
<h3 className="doctor-form-title">MediConnect</h3>
|
||||||
|
|
||||||
@ -319,6 +327,7 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div className="row mt-3">
|
<div className="row mt-3">
|
||||||
|
{/* Foto / Avatar */}
|
||||||
<div className="col-md-6 mb-3 avatar-container">
|
<div className="col-md-6 mb-3 avatar-container">
|
||||||
<div className="me-3">
|
<div className="me-3">
|
||||||
{avatarUrl ? (
|
{avatarUrl ? (
|
||||||
@ -354,6 +363,7 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Nome Completo */}
|
||||||
<div className="col-md-6 mb-3">
|
<div className="col-md-6 mb-3">
|
||||||
<label className="form-label">Nome: *</label>
|
<label className="form-label">Nome: *</label>
|
||||||
<input
|
<input
|
||||||
@ -365,6 +375,7 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
|
|||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
{/* Data de Nascimento */}
|
||||||
<div className="col-md-6 mb-3">
|
<div className="col-md-6 mb-3">
|
||||||
<label className="form-label">Data de nascimento:</label>
|
<label className="form-label">Data de nascimento:</label>
|
||||||
<input
|
<input
|
||||||
@ -377,6 +388,7 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
|
|||||||
max="2025-09-24"
|
max="2025-09-24"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
{/* CPF */}
|
||||||
<div className="col-md-6 mb-3">
|
<div className="col-md-6 mb-3">
|
||||||
<label className="form-label">CPF: *</label>
|
<label className="form-label">CPF: *</label>
|
||||||
<input
|
<input
|
||||||
@ -399,6 +411,7 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Estado do CRM */}
|
||||||
<div className="col-md-6 mb-3">
|
<div className="col-md-6 mb-3">
|
||||||
<label className="form-label">Estado do CRM: *</label>
|
<label className="form-label">Estado do CRM: *</label>
|
||||||
<select
|
<select
|
||||||
@ -438,6 +451,7 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* CRM */}
|
||||||
<div className="col-md-6 mb-3">
|
<div className="col-md-6 mb-3">
|
||||||
<label className="form-label">CRM: *</label>
|
<label className="form-label">CRM: *</label>
|
||||||
<input
|
<input
|
||||||
@ -450,6 +464,7 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Especialização */}
|
||||||
<div className="col-md-6 mb-3">
|
<div className="col-md-6 mb-3">
|
||||||
<label className="form-label">Especialização:</label>
|
<label className="form-label">Especialização:</label>
|
||||||
<select
|
<select
|
||||||
@ -497,6 +512,7 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
|
|||||||
className={`collapse${collapsedSections.contato ? " show" : ""}`}
|
className={`collapse${collapsedSections.contato ? " show" : ""}`}
|
||||||
>
|
>
|
||||||
<div className="row mt-3">
|
<div className="row mt-3">
|
||||||
|
{/* Email */}
|
||||||
<div className="col-md-6 mb-3">
|
<div className="col-md-6 mb-3">
|
||||||
<label className="form-label">Email: *</label>
|
<label className="form-label">Email: *</label>
|
||||||
<input
|
<input
|
||||||
@ -508,6 +524,7 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
|
|||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
{/* Telefone 1 (Principal) */}
|
||||||
<div className="col-md-6 mb-3">
|
<div className="col-md-6 mb-3">
|
||||||
<label className="form-label">Telefone: *</label>
|
<label className="form-label">Telefone: *</label>
|
||||||
<input
|
<input
|
||||||
@ -519,6 +536,7 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
|
|||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
{/* Telefone 2 (Opcional) */}
|
||||||
<div className="col-md-6 mb-3">
|
<div className="col-md-6 mb-3">
|
||||||
<label className="form-label">Telefone 2:</label>
|
<label className="form-label">Telefone 2:</label>
|
||||||
<input
|
<input
|
||||||
@ -548,6 +566,7 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
|
|||||||
className={`collapse${collapsedSections.endereco ? " show" : ""}`}
|
className={`collapse${collapsedSections.endereco ? " show" : ""}`}
|
||||||
>
|
>
|
||||||
<div className="row mt-3">
|
<div className="row mt-3">
|
||||||
|
{/* CEP */}
|
||||||
<div className="col-md-4 mb-3">
|
<div className="col-md-4 mb-3">
|
||||||
<label className="form-label">CEP:</label>
|
<label className="form-label">CEP:</label>
|
||||||
<input
|
<input
|
||||||
@ -559,6 +578,7 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
|
|||||||
onBlur={handleCepBlur}
|
onBlur={handleCepBlur}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
{/* Rua */}
|
||||||
<div className="col-md-8 mb-3">
|
<div className="col-md-8 mb-3">
|
||||||
<label className="form-label">Rua:</label>
|
<label className="form-label">Rua:</label>
|
||||||
<input
|
<input
|
||||||
@ -569,6 +589,7 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
|
|||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
{/* Bairro */}
|
||||||
<div className="col-md-6 mb-3">
|
<div className="col-md-6 mb-3">
|
||||||
<label className="form-label">Bairro:</label>
|
<label className="form-label">Bairro:</label>
|
||||||
<input
|
<input
|
||||||
@ -579,6 +600,7 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
|
|||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
{/* Cidade */}
|
||||||
<div className="col-md-4 mb-3">
|
<div className="col-md-4 mb-3">
|
||||||
<label className="form-label">Cidade:</label>
|
<label className="form-label">Cidade:</label>
|
||||||
<input
|
<input
|
||||||
@ -589,6 +611,7 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
|
|||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
{/* Estado */}
|
||||||
<div className="col-md-2 mb-3">
|
<div className="col-md-2 mb-3">
|
||||||
<label className="form-label">Estado:</label>
|
<label className="form-label">Estado:</label>
|
||||||
<input
|
<input
|
||||||
@ -599,6 +622,7 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
|
|||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
{/* Número */}
|
||||||
<div className="col-md-4 mb-3">
|
<div className="col-md-4 mb-3">
|
||||||
<label className="form-label">Número:</label>
|
<label className="form-label">Número:</label>
|
||||||
<input
|
<input
|
||||||
@ -609,6 +633,7 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
|
|||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
{/* Complemento */}
|
||||||
<div className="col-md-8 mb-3">
|
<div className="col-md-8 mb-3">
|
||||||
<label className="form-label">Complemento:</label>
|
<label className="form-label">Complemento:</label>
|
||||||
<input
|
<input
|
||||||
@ -624,31 +649,35 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* HORÁRIOS */}
|
{/* HORÁRIOS */}
|
||||||
<div className="form-section">
|
<div className="form-section">
|
||||||
<h4
|
<h4
|
||||||
className="section-header"
|
className="section-header"
|
||||||
onClick={() => handleToggleCollapse("horarios")}
|
onClick={() => handleToggleCollapse("horarios")}
|
||||||
>
|
>
|
||||||
Horários
|
Horários de Atendimento
|
||||||
<span className="section-toggle">
|
<span className="section-toggle">
|
||||||
{collapsedSections.horarios ? "▲" : "▼"}
|
{collapsedSections.horarios ? "▲" : "▼"}
|
||||||
</span>
|
</span>
|
||||||
</h4>
|
</h4>
|
||||||
|
<div
|
||||||
<div className={`collapse${collapsedSections.horarios ? " show" : ""}`}>
|
className={`collapse${collapsedSections.horarios ? " show" : ""}`}
|
||||||
<HorariosDisponibilidade
|
>
|
||||||
onChange={(dados) => {
|
<div className="row mt-3">
|
||||||
console.log("Disponibilidades atualizadas:", dados);
|
<div className="col-12 mb-3">
|
||||||
// Se quiser salvar no formData:
|
<p className="form-label text-muted">
|
||||||
// setFormData(prev => ({ ...prev, disponibilidades: dados }));
|
Defina seus horários de atendimento para cada dia da semana.
|
||||||
}}
|
Marque um dia para começar a adicionar blocos de tempo.
|
||||||
/>
|
</p>
|
||||||
</div>
|
<HorariosDisponibilidade
|
||||||
|
initialAvailability={formData.availability}
|
||||||
|
onUpdate={handleAvailabilityUpdate}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
{/* BOTÕES DE AÇÃO */}
|
||||||
|
|
||||||
{/* BOTÕES DE AÇÃO */}
|
|
||||||
<div className="actions-container">
|
<div className="actions-container">
|
||||||
<button
|
<button
|
||||||
className="btn btn-success btn-submit"
|
className="btn btn-success btn-submit"
|
||||||
@ -662,6 +691,7 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
|
|||||||
<button className="btn btn-light btn-cancel">Cancelar</button>
|
<button className="btn btn-light btn-cancel">Cancelar</button>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,106 +1,401 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState, useEffect, useCallback } from "react";
|
||||||
|
import { Clock } from "lucide-react";
|
||||||
|
|
||||||
const diasDaSemana = [
|
const initialBlockTemplate = {
|
||||||
"segunda",
|
id: null,
|
||||||
"terca",
|
inicio: "09:00",
|
||||||
"quarta",
|
termino: "17:00",
|
||||||
"quinta",
|
isNew: true,
|
||||||
"sexta",
|
};
|
||||||
"sabado",
|
|
||||||
"domingo"
|
const emptyAvailabilityTemplate = [
|
||||||
|
{ dia: "Segunda-feira", isChecked: false, blocos: [] },
|
||||||
|
{ dia: "Terça-feira", isChecked: false, blocos: [] },
|
||||||
|
{ dia: "Quarta-feira", isChecked: false, blocos: [] },
|
||||||
|
{ dia: "Quinta-feira", isChecked: false, blocos: [] },
|
||||||
|
{ dia: "Sexta-feira", isChecked: false, blocos: [] },
|
||||||
|
{ dia: "Sábado", isChecked: false, blocos: [] },
|
||||||
|
{ dia: "Domingo", isChecked: false, blocos: [] },
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function HorariosDisponibilidade({ onChange }) {
|
const HorariosDisponibilidade = ({
|
||||||
const [disponibilidades, setDisponibilidades] = useState(
|
initialAvailability = emptyAvailabilityTemplate,
|
||||||
diasDaSemana.map(dia => ({
|
onUpdate,
|
||||||
weekday: dia,
|
}) => {
|
||||||
slots: [{ start_time: "09:00", end_time: "17:00" }],
|
const [availability, setAvailability] = useState(initialAvailability);
|
||||||
ativo: false,
|
|
||||||
}))
|
|
||||||
);
|
|
||||||
|
|
||||||
function handleToggleDia(index) {
|
useEffect(() => {
|
||||||
const updated = [...disponibilidades];
|
if (initialAvailability !== emptyAvailabilityTemplate) {
|
||||||
updated[index].ativo = !updated[index].ativo;
|
setAvailability(initialAvailability);
|
||||||
setDisponibilidades(updated);
|
}
|
||||||
onChange?.(updated);
|
}, [initialAvailability]);
|
||||||
}
|
|
||||||
|
|
||||||
function handleSlotChange(indexDia, indexSlot, campo, valor) {
|
useEffect(() => {
|
||||||
const updated = [...disponibilidades];
|
if (onUpdate) {
|
||||||
updated[indexDia].slots[indexSlot][campo] = valor;
|
onUpdate(availability);
|
||||||
setDisponibilidades(updated);
|
}
|
||||||
onChange?.(updated);
|
}, [availability, onUpdate]);
|
||||||
}
|
|
||||||
|
|
||||||
function handleAddSlot(indexDia) {
|
const handleDayCheck = useCallback((dayIndex, currentIsChecked) => {
|
||||||
const updated = [...disponibilidades];
|
const isChecked = !currentIsChecked;
|
||||||
updated[indexDia].slots.push({ start_time: "", end_time: "" });
|
|
||||||
setDisponibilidades(updated);
|
|
||||||
onChange?.(updated);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleRemoveSlot(indexDia, indexSlot) {
|
setAvailability((prev) =>
|
||||||
const updated = [...disponibilidades];
|
prev.map((day, i) =>
|
||||||
updated[indexDia].slots.splice(indexSlot, 1);
|
i === dayIndex
|
||||||
setDisponibilidades(updated);
|
? {
|
||||||
onChange?.(updated);
|
...day,
|
||||||
}
|
isChecked,
|
||||||
|
blocos: isChecked
|
||||||
|
? day.blocos.length === 0
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
...initialBlockTemplate,
|
||||||
|
id: Date.now() + Math.random(),
|
||||||
|
isNew: true,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: day.blocos
|
||||||
|
: [],
|
||||||
|
}
|
||||||
|
: day
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
const handleAddBlock = useCallback((dayIndex) => {
|
||||||
<div className="space-y-4">
|
const tempId = Date.now() + Math.random();
|
||||||
{disponibilidades.map((dia, i) => (
|
const newBlock = { ...initialBlockTemplate, id: tempId, isNew: true };
|
||||||
<div key={dia.weekday} className="border p-3 rounded-md bg-gray-50">
|
|
||||||
<div className="flex items-center justify-between">
|
setAvailability((prev) =>
|
||||||
<label className="font-semibold capitalize">
|
prev.map((day, i) =>
|
||||||
{dia.weekday}
|
i === dayIndex
|
||||||
</label>
|
? {
|
||||||
|
...day,
|
||||||
|
blocos: [...day.blocos, newBlock],
|
||||||
|
isChecked: true,
|
||||||
|
}
|
||||||
|
: day
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleRemoveBlock = useCallback((dayIndex, blockId) => {
|
||||||
|
setAvailability((prev) =>
|
||||||
|
prev.map((day, i) => {
|
||||||
|
if (i === dayIndex) {
|
||||||
|
const newBlocos = day.blocos.filter((bloco) => bloco.id !== blockId);
|
||||||
|
return {
|
||||||
|
...day,
|
||||||
|
blocos: newBlocos,
|
||||||
|
isChecked: newBlocos.length > 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return day;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleTimeChange = useCallback((dayIndex, blockId, field, value) => {
|
||||||
|
setAvailability((prev) =>
|
||||||
|
prev.map((day, i) =>
|
||||||
|
i === dayIndex
|
||||||
|
? {
|
||||||
|
...day,
|
||||||
|
blocos: day.blocos.map((bloco) =>
|
||||||
|
bloco.id === blockId ? { ...bloco, [field]: value } : bloco
|
||||||
|
),
|
||||||
|
}
|
||||||
|
: day
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const renderTimeBlock = (dayIndex, bloco) => (
|
||||||
|
<div
|
||||||
|
key={bloco.id}
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: window.innerWidth < 640 ? "column" : "row",
|
||||||
|
alignItems: window.innerWidth < 640 ? "flex-start" : "center",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
padding: "16px",
|
||||||
|
marginBottom: "16px",
|
||||||
|
borderRadius: "12px",
|
||||||
|
boxShadow:
|
||||||
|
"0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)",
|
||||||
|
transition: "all 0.3s",
|
||||||
|
backgroundColor: bloco.isNew ? "#eef2ff" : "#ffffff",
|
||||||
|
border: bloco.isNew ? "2px solid #6366f1" : "1px solid #e5e7eb",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: window.innerWidth < 640 ? "column" : "row",
|
||||||
|
gap: window.innerWidth < 640 ? "0" : "32px",
|
||||||
|
width: window.innerWidth < 640 ? "100%" : "auto",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "8px",
|
||||||
|
marginBottom: window.innerWidth < 640 ? "8px" : "0",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
htmlFor={`inicio-${dayIndex}-${bloco.id}`}
|
||||||
|
style={{ fontWeight: 500, color: "#4b5563", width: "64px" }}
|
||||||
|
>
|
||||||
|
Início:
|
||||||
|
</label>
|
||||||
|
<div style={{ position: "relative" }}>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
id={`inicio-${dayIndex}-${bloco.id}`}
|
||||||
checked={dia.ativo}
|
type="time"
|
||||||
onChange={() => handleToggleDia(i)}
|
value={bloco.inicio}
|
||||||
|
onChange={(e) =>
|
||||||
|
handleTimeChange(dayIndex, bloco.id, "inicio", e.target.value)
|
||||||
|
}
|
||||||
|
style={{
|
||||||
|
padding: "8px",
|
||||||
|
border: "1px solid #d1d5db",
|
||||||
|
borderRadius: "8px",
|
||||||
|
width: "100%",
|
||||||
|
boxSizing: "border-box",
|
||||||
|
outline: "none",
|
||||||
|
}}
|
||||||
|
step="300"
|
||||||
|
/>
|
||||||
|
<Clock
|
||||||
|
size={16}
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
right: "12px",
|
||||||
|
top: "50%",
|
||||||
|
transform: "translateY(-50%)",
|
||||||
|
color: "#9ca3af",
|
||||||
|
pointerEvents: "none",
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{dia.ativo && (
|
|
||||||
<div className="mt-2 space-y-2">
|
|
||||||
{dia.slots.map((slot, j) => (
|
|
||||||
<div key={j} className="flex gap-2 items-center">
|
|
||||||
<input
|
|
||||||
type="time"
|
|
||||||
value={slot.start_time}
|
|
||||||
onChange={e => handleSlotChange(i, j, "start_time", e.target.value)}
|
|
||||||
className="border rounded p-1"
|
|
||||||
/>
|
|
||||||
<span>até</span>
|
|
||||||
<input
|
|
||||||
type="time"
|
|
||||||
value={slot.end_time}
|
|
||||||
onChange={e => handleSlotChange(i, j, "end_time", e.target.value)}
|
|
||||||
className="border rounded p-1"
|
|
||||||
/>
|
|
||||||
{dia.slots.length > 1 && (
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => handleRemoveSlot(i, j)}
|
|
||||||
className="text-red-600 hover:underline"
|
|
||||||
>
|
|
||||||
Remover
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => handleAddSlot(i)}
|
|
||||||
className="text-blue-600 hover:underline mt-2"
|
|
||||||
>
|
|
||||||
+ Adicionar pausa/bloco
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
))}
|
|
||||||
|
<div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
|
||||||
|
<label
|
||||||
|
htmlFor={`termino-${dayIndex}-${bloco.id}`}
|
||||||
|
style={{ fontWeight: 500, color: "#4b5563", width: "64px" }}
|
||||||
|
>
|
||||||
|
Término:
|
||||||
|
</label>
|
||||||
|
<div style={{ position: "relative" }}>
|
||||||
|
<input
|
||||||
|
id={`termino-${dayIndex}-${bloco.id}`}
|
||||||
|
type="time"
|
||||||
|
value={bloco.termino}
|
||||||
|
onChange={(e) =>
|
||||||
|
handleTimeChange(dayIndex, bloco.id, "termino", e.target.value)
|
||||||
|
}
|
||||||
|
style={{
|
||||||
|
padding: "8px",
|
||||||
|
border: "1px solid #d1d5db",
|
||||||
|
borderRadius: "8px",
|
||||||
|
width: "100%",
|
||||||
|
boxSizing: "border-box",
|
||||||
|
outline: "none",
|
||||||
|
}}
|
||||||
|
step="300"
|
||||||
|
/>
|
||||||
|
<Clock
|
||||||
|
size={16}
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
right: "12px",
|
||||||
|
top: "50%",
|
||||||
|
transform: "translateY(-50%)",
|
||||||
|
color: "#9ca3af",
|
||||||
|
pointerEvents: "none",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={() => handleRemoveBlock(dayIndex, bloco.id)}
|
||||||
|
style={{
|
||||||
|
marginTop: window.innerWidth < 640 ? "16px" : "0",
|
||||||
|
padding: "8px 24px",
|
||||||
|
backgroundColor: "#ef4444",
|
||||||
|
color: "white",
|
||||||
|
fontWeight: 600,
|
||||||
|
borderRadius: "12px",
|
||||||
|
boxShadow: "0 4px 6px -1px rgba(0, 0, 0, 0.1)",
|
||||||
|
transition: "all 0.2s",
|
||||||
|
width: window.innerWidth < 640 ? "100%" : "auto",
|
||||||
|
cursor: "pointer",
|
||||||
|
border: "none",
|
||||||
|
opacity: 1,
|
||||||
|
}}
|
||||||
|
onMouseEnter={(e) =>
|
||||||
|
(e.currentTarget.style.backgroundColor = "#dc2626")
|
||||||
|
}
|
||||||
|
onMouseLeave={(e) =>
|
||||||
|
(e.currentTarget.style.backgroundColor = "#ef4444")
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Remover Bloco
|
||||||
|
</button>
|
||||||
|
{bloco.isNew && (
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
fontSize: "12px",
|
||||||
|
color: "#6366f1",
|
||||||
|
marginTop: "8px",
|
||||||
|
marginLeft: window.innerWidth < 640 ? "0" : "16px",
|
||||||
|
fontWeight: 500,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
(Novo)
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
maxWidth: "960px",
|
||||||
|
margin: "0 auto",
|
||||||
|
fontFamily: "Inter, sans-serif",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ display: "flex", flexDirection: "column", gap: "16px" }}>
|
||||||
|
{availability.map((day, dayIndex) => {
|
||||||
|
const isChecked = day.isChecked;
|
||||||
|
|
||||||
|
const dayHeaderStyle = {
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
padding: "12px 0",
|
||||||
|
borderBottom: "1px solid #e5e7eb",
|
||||||
|
marginBottom: "16px",
|
||||||
|
backgroundColor: isChecked ? "#1f2937" : "#f9fafb",
|
||||||
|
borderRadius: "8px",
|
||||||
|
paddingLeft: "16px",
|
||||||
|
paddingRight: "16px",
|
||||||
|
cursor: "pointer",
|
||||||
|
transition: "background-color 0.2s",
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={day.dia}
|
||||||
|
style={{
|
||||||
|
backgroundColor: "#f9fafb",
|
||||||
|
padding: "20px",
|
||||||
|
borderRadius: "12px",
|
||||||
|
border: "1px solid #e5e7eb",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
...dayHeaderStyle,
|
||||||
|
backgroundColor: isChecked ? "#1f2937" : "#f9fafb",
|
||||||
|
borderBottom: isChecked
|
||||||
|
? "1px solid #4b5563"
|
||||||
|
: "1px solid #e5e7eb",
|
||||||
|
}}
|
||||||
|
onClick={() => handleDayCheck(dayIndex, isChecked)}
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
style={{
|
||||||
|
fontSize: "18px",
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: isChecked ? "white" : "#1f2937",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "12px",
|
||||||
|
cursor: "pointer",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span>{day.dia}</span>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={isChecked}
|
||||||
|
onChange={() => {}}
|
||||||
|
style={{
|
||||||
|
width: "20px",
|
||||||
|
height: "20px",
|
||||||
|
accentColor: isChecked ? "#3b82f6" : "#9ca3af",
|
||||||
|
marginLeft: "8px",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{isChecked && (
|
||||||
|
<div style={{ marginTop: "16px" }}>
|
||||||
|
{day.blocos.length === 0 && (
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
color: "#6b7280",
|
||||||
|
fontStyle: "italic",
|
||||||
|
marginBottom: "16px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Nenhum bloco de horário definido.
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
gap: "16px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{day.blocos.map((bloco) =>
|
||||||
|
renderTimeBlock(dayIndex, bloco)
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={() => handleAddBlock(dayIndex)}
|
||||||
|
style={{
|
||||||
|
marginTop: "24px",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
padding: "12px 24px",
|
||||||
|
backgroundColor: "#10b981",
|
||||||
|
color: "white",
|
||||||
|
fontWeight: "bold",
|
||||||
|
borderRadius: "12px",
|
||||||
|
boxShadow: "0 4px 6px -1px rgba(0, 0, 0, 0.1)",
|
||||||
|
transition: "all 0.3s",
|
||||||
|
cursor: "pointer",
|
||||||
|
border: "none",
|
||||||
|
}}
|
||||||
|
onMouseEnter={(e) =>
|
||||||
|
(e.currentTarget.style.backgroundColor = "#059669")
|
||||||
|
}
|
||||||
|
onMouseLeave={(e) =>
|
||||||
|
(e.currentTarget.style.backgroundColor = "#10b981")
|
||||||
|
}
|
||||||
|
>
|
||||||
|
+ Adicionar novo bloco
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default HorariosDisponibilidade;
|
||||||
|
|||||||
@ -1,184 +1,230 @@
|
|||||||
import React, { useState, useMemo, useEffect } from 'react';
|
import React, { useState, useMemo, useEffect } from "react";
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from "react-router-dom";
|
||||||
import API_KEY from '../components/utils/apiKeys.js';
|
import API_KEY from "../components/utils/apiKeys.js";
|
||||||
import AgendamentoCadastroManager from './AgendamentoCadastroManager.jsx';
|
import AgendamentoCadastroManager from "./AgendamentoCadastroManager.jsx";
|
||||||
import TabelaAgendamentoDia from '../components/AgendarConsulta/TabelaAgendamentoDia';
|
import TabelaAgendamentoDia from "../components/AgendarConsulta/TabelaAgendamentoDia";
|
||||||
import TabelaAgendamentoSemana from '../components/AgendarConsulta/TabelaAgendamentoSemana';
|
import TabelaAgendamentoSemana from "../components/AgendarConsulta/TabelaAgendamentoSemana";
|
||||||
import TabelaAgendamentoMes from '../components/AgendarConsulta/TabelaAgendamentoMes';
|
import TabelaAgendamentoMes from "../components/AgendarConsulta/TabelaAgendamentoMes";
|
||||||
import FormNovaConsulta from '../components/AgendarConsulta/FormNovaConsulta';
|
import FormNovaConsulta from "../components/AgendarConsulta/FormNovaConsulta";
|
||||||
|
|
||||||
import { GetAllDoctors } from '../components/utils/Functions-Endpoints/Doctor.js';
|
import { GetAllDoctors } from "../components/utils/Functions-Endpoints/Doctor.js";
|
||||||
|
|
||||||
import { useAuth } from '../components/utils/AuthProvider.js';
|
import { useAuth } from "../components/utils/AuthProvider.js";
|
||||||
// ✨ NOVO: Caminho de importação corrigido com base na sua estrutura de pastas
|
// ✨ NOVO: Caminho de importação corrigido com base na sua estrutura de pastas
|
||||||
import AgendamentosMes from '../components/AgendarConsulta/DadosConsultasMock.js';
|
import AgendamentosMes from "../components/AgendarConsulta/DadosConsultasMock.js";
|
||||||
|
|
||||||
|
import dayjs from "dayjs";
|
||||||
import dayjs from 'dayjs';
|
|
||||||
import "./style/Agendamento.css";
|
import "./style/Agendamento.css";
|
||||||
import './style/FilaEspera.css';
|
import "./style/FilaEspera.css";
|
||||||
import { Search } from 'lucide-react';
|
import { Search } from "lucide-react";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Agendamento = () => {
|
const Agendamento = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const [FiladeEspera, setFiladeEspera] = useState(false);
|
const [FiladeEspera, setFiladeEspera] = useState(false);
|
||||||
const [tabela, setTabela] = useState('diario');
|
const [tabela, setTabela] = useState("diario");
|
||||||
const [PageNovaConsulta, setPageConsulta] = useState(false);
|
const [PageNovaConsulta, setPageConsulta] = useState(false);
|
||||||
const [searchTerm, setSearchTerm] = useState('');
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
const [agendamentos, setAgendamentos] = useState()
|
const [agendamentos, setAgendamentos] = useState();
|
||||||
const {getAuthorizationHeader} = useAuth()
|
const { getAuthorizationHeader } = useAuth();
|
||||||
const [DictAgendamentosOrganizados, setAgendamentosOrganizados ] = useState({})
|
const [DictAgendamentosOrganizados, setAgendamentosOrganizados] = useState(
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
const [showDeleteModal, setShowDeleteModal] = useState(false);
|
||||||
const [AgendamentoFiltrado, setAgendamentoFiltrado] = useState()
|
const [AgendamentoFiltrado, setAgendamentoFiltrado] = useState();
|
||||||
|
|
||||||
const [ListaDeMedicos, setListaDeMedicos] = useState([])
|
|
||||||
const [FiltredTodosMedicos, setFiltredTodosMedicos] = useState([])
|
|
||||||
const [searchTermDoctor, setSearchTermDoctor] = useState('');
|
|
||||||
|
|
||||||
|
const [ListaDeMedicos, setListaDeMedicos] = useState([]);
|
||||||
|
const [FiltredTodosMedicos, setFiltredTodosMedicos] = useState([]);
|
||||||
|
const [searchTermDoctor, setSearchTermDoctor] = useState("");
|
||||||
|
|
||||||
let authHeader = getAuthorizationHeader()
|
let authHeader = getAuthorizationHeader();
|
||||||
|
|
||||||
const FiltrarAgendamentos = (listaTodosAgendamentos) => {
|
const FiltrarAgendamentos = (listaTodosAgendamentos) => {
|
||||||
let DictAgendamentosOrganizados = {};
|
let DictAgendamentosOrganizados = {};
|
||||||
|
|
||||||
for (let i = 0; i < listaTodosAgendamentos.length; i++) {
|
for (let i = 0; i < listaTodosAgendamentos.length; i++) {
|
||||||
const agendamento = listaTodosAgendamentos[i];
|
const agendamento = listaTodosAgendamentos[i];
|
||||||
const DiaAgendamento = agendamento.scheduled_at.split("T")[0];
|
const DiaAgendamento = agendamento.scheduled_at.split("T")[0];
|
||||||
|
|
||||||
//console.log(DictAgendamentosOrganizados)
|
//console.log(DictAgendamentosOrganizados)
|
||||||
|
|
||||||
if (DiaAgendamento in DictAgendamentosOrganizados) {
|
if (DiaAgendamento in DictAgendamentosOrganizados) {
|
||||||
// já existe a data → adiciona na lista
|
// já existe a data → adiciona na lista
|
||||||
DictAgendamentosOrganizados[DiaAgendamento].push(agendamento);
|
DictAgendamentosOrganizados[DiaAgendamento].push(agendamento);
|
||||||
} else {
|
} else {
|
||||||
// não existe → cria nova key com uma lista
|
// não existe → cria nova key com uma lista
|
||||||
DictAgendamentosOrganizados[DiaAgendamento] = [agendamento];
|
DictAgendamentosOrganizados[DiaAgendamento] = [agendamento];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
setAgendamentosOrganizados(DictAgendamentosOrganizados);
|
||||||
setAgendamentosOrganizados(DictAgendamentosOrganizados);
|
};
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Requisição inicial para mostrar os agendamentos do banco de dados
|
// Requisição inicial para mostrar os agendamentos do banco de dados
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
var myHeaders = new Headers();
|
var myHeaders = new Headers();
|
||||||
myHeaders.append("Authorization", authHeader);
|
myHeaders.append("Authorization", authHeader);
|
||||||
myHeaders.append("apikey", API_KEY)
|
myHeaders.append("apikey", API_KEY);
|
||||||
|
|
||||||
var requestOptions = {
|
var requestOptions = {
|
||||||
method: 'GET',
|
method: "GET",
|
||||||
headers: myHeaders,
|
headers: myHeaders,
|
||||||
redirect: 'follow'
|
redirect: "follow",
|
||||||
};
|
};
|
||||||
|
|
||||||
fetch("https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/appointments?select&doctor_id&patient_id&status&scheduled_at&order&limit&offset", requestOptions)
|
fetch(
|
||||||
.then(response => response.json())
|
"https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/appointments?select&doctor_id&patient_id&status&scheduled_at&order&limit&offset",
|
||||||
.then(result => {FiltrarAgendamentos(result);})
|
requestOptions
|
||||||
.catch(error => console.log('error', error));
|
)
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((result) => {
|
||||||
|
FiltrarAgendamentos(result);
|
||||||
|
})
|
||||||
|
.catch((error) => console.log("error", error));
|
||||||
|
|
||||||
const PegarTodosOsMedicos = async () => {
|
const PegarTodosOsMedicos = async () => {
|
||||||
let lista = []
|
let lista = [];
|
||||||
const TodosOsMedicos = await GetAllDoctors(authHeader)
|
const TodosOsMedicos = await GetAllDoctors(authHeader);
|
||||||
|
|
||||||
//console.log(TodosOsMedicos, "tentativa")
|
//console.log(TodosOsMedicos, "tentativa")
|
||||||
for(let d = 0; TodosOsMedicos.length > d; d++){
|
for (let d = 0; TodosOsMedicos.length > d; d++) {
|
||||||
lista.push({nomeMedico: TodosOsMedicos[d].full_name, idMedico: TodosOsMedicos[d].id })}
|
lista.push({
|
||||||
setListaDeMedicos(lista)
|
nomeMedico: TodosOsMedicos[d].full_name,
|
||||||
}
|
idMedico: TodosOsMedicos[d].id,
|
||||||
PegarTodosOsMedicos()
|
});
|
||||||
|
}
|
||||||
}, [])
|
setListaDeMedicos(lista);
|
||||||
|
};
|
||||||
useEffect(() => {
|
PegarTodosOsMedicos();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
console.log("mudou FiltredTodosMedicos:", FiltredTodosMedicos);
|
console.log("mudou FiltredTodosMedicos:", FiltredTodosMedicos);
|
||||||
|
|
||||||
if (FiltredTodosMedicos.length === 1) {
|
if (FiltredTodosMedicos.length === 1) {
|
||||||
|
const unicoMedico = FiltredTodosMedicos[0];
|
||||||
const unicoMedico = FiltredTodosMedicos[0];
|
console.log(unicoMedico);
|
||||||
console.log(unicoMedico)
|
|
||||||
|
const idMedicoFiltrado = unicoMedico.idMedico;
|
||||||
const idMedicoFiltrado = unicoMedico.idMedico;
|
|
||||||
|
console.log(
|
||||||
|
`Médico único encontrado: ${unicoMedico.nomeMedico}. ID: ${idMedicoFiltrado}`
|
||||||
|
);
|
||||||
|
|
||||||
console.log(`Médico único encontrado: ${unicoMedico.nomeMedico}. ID: ${idMedicoFiltrado}`);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const agendamentosDoMedico = filtrarAgendamentosPorMedico(
|
const agendamentosDoMedico = filtrarAgendamentosPorMedico(
|
||||||
DictAgendamentosOrganizados,
|
DictAgendamentosOrganizados,
|
||||||
idMedicoFiltrado
|
idMedicoFiltrado
|
||||||
);
|
);
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
||||||
console.log(`Total de agendamentos filtrados para este médico: ${agendamentosDoMedico.length}`);
|
console.log(
|
||||||
console.log("Lista completa de Agendamentos do Médico:", agendamentosDoMedico);
|
`Total de agendamentos filtrados para este médico: ${agendamentosDoMedico.length}`
|
||||||
FiltrarAgendamentos(agendamentosDoMedico)
|
);
|
||||||
|
console.log(
|
||||||
|
"Lista completa de Agendamentos do Médico:",
|
||||||
|
agendamentosDoMedico
|
||||||
|
);
|
||||||
|
FiltrarAgendamentos(agendamentosDoMedico);
|
||||||
|
|
||||||
// AQUI VOCÊ PODE APLICAR SUA LÓGICA FINAL:
|
// AQUI VOCÊ PODE APLICAR SUA LÓGICA FINAL:
|
||||||
// Ex: setar um novo estado com os agendamentos filtrados, se for necessário:
|
// Ex: setar um novo estado com os agendamentos filtrados, se for necessário:
|
||||||
// setAgendamentosFiltrados(agendamentosDoMedico);
|
// setAgendamentosFiltrados(agendamentosDoMedico);
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Opcional: Limpar a lista filtrada se a busca não for mais única
|
// Opcional: Limpar a lista filtrada se a busca não for mais única
|
||||||
// setAgendamentosFiltrados([]);
|
// setAgendamentosFiltrados([]);
|
||||||
}
|
}
|
||||||
|
}, [FiltredTodosMedicos]);
|
||||||
|
|
||||||
}, [FiltredTodosMedicos]);
|
/**
|
||||||
|
* Filtra todos os agendamentos em um objeto aninhado (data -> [agendamentos])
|
||||||
|
* com base no ID do médico.
|
||||||
|
*
|
||||||
/**
|
* @param {Object} dictAgendamentos - O dicionário de agendamentos.
|
||||||
* Filtra todos os agendamentos em um objeto aninhado (data -> [agendamentos])
|
* @param {string} idMedicoFiltrado - O ID do médico (doctor_id) para ser usado como filtro.
|
||||||
* com base no ID do médico.
|
* @returns {Array} Um array contendo todos os agendamentos que correspondem ao idMedicoFiltrado.
|
||||||
*
|
*/
|
||||||
* @param {Object} dictAgendamentos - O dicionário de agendamentos.
|
const filtrarAgendamentosPorMedico = (dictAgendamentos, idMedicoFiltrado) => {
|
||||||
* @param {string} idMedicoFiltrado - O ID do médico (doctor_id) para ser usado como filtro.
|
|
||||||
* @returns {Array} Um array contendo todos os agendamentos que correspondem ao idMedicoFiltrado.
|
|
||||||
*/
|
|
||||||
const filtrarAgendamentosPorMedico = (dictAgendamentos, idMedicoFiltrado) => {
|
|
||||||
|
|
||||||
// O corpo da função deve usar esses nomes de variáveis:
|
// O corpo da função deve usar esses nomes de variáveis:
|
||||||
const todasAsListasDeAgendamentos = Object.values(dictAgendamentos);
|
const todasAsListasDeAgendamentos = Object.values(dictAgendamentos);
|
||||||
|
|
||||||
const todosOsAgendamentos = todasAsListasDeAgendamentos.flat();
|
const todosOsAgendamentos = todasAsListasDeAgendamentos.flat();
|
||||||
|
|
||||||
const agendamentosFiltrados = todosOsAgendamentos.filter(agendamento =>
|
const agendamentosFiltrados = todosOsAgendamentos.filter(
|
||||||
agendamento.doctor_id === idMedicoFiltrado
|
(agendamento) => agendamento.doctor_id === idMedicoFiltrado
|
||||||
);
|
);
|
||||||
|
|
||||||
return agendamentosFiltrados;
|
return agendamentosFiltrados;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Dados da fila de espera (sem alteração)
|
// Dados da fila de espera (sem alteração)
|
||||||
const filaEsperaData = [
|
const filaEsperaData = [
|
||||||
{ nome: 'Ricardo Pereira', email: 'ricardo.pereira@gmail.com', cpf: '444.777.666-55', telefone: '(79) 99123-4567', entrada: '25/09/2025 às 08:00' },
|
{
|
||||||
{ nome: 'Ana Costa', email: 'ana.costa@gmail.com', cpf: '321.654.987-00', telefone: '(79) 97777-3333', entrada: '25/09/2025 às 08:30' },
|
nome: "Ricardo Pereira",
|
||||||
{ nome: 'Lucas Martins', email: 'lucas.martins@gmail.com', cpf: '777.666.555-33', telefone: '(79) 99654-3210', entrada: '25/09/2025 às 09:00' },
|
email: "ricardo.pereira@gmail.com",
|
||||||
{ nome: 'João Souza', email: 'joao.souza@gmail.com', cpf: '987.654.321-00', telefone: '(79) 98888-2222', entrada: '25/09/2025 às 14:00' },
|
cpf: "444.777.666-55",
|
||||||
{ nome: 'Maria Silva', email: 'maria.silva@gmail.com', cpf: '123.456.789-00', telefone: '(79) 99999-1111', entrada: '25/09/2025 às 14:30' },
|
telefone: "(79) 99123-4567",
|
||||||
{ nome: 'Fernanda Lima', email: 'fernanda.lima@gmail.com', cpf: '888.999.000-22', telefone: '(79) 98877-6655', entrada: '26/09/2025 às 09:30' },
|
entrada: "25/09/2025 às 08:00",
|
||||||
{ nome: 'Carlos Andrade', email: 'carlos.andrade@gmail.com', cpf: '222.555.888-11', telefone: '(79) 99876-5432', entrada: '26/09/2025 às 10:00' },
|
},
|
||||||
{ nome: 'Juliana Oliveira', email: 'juliana.o@gmail.com', cpf: '111.222.333-44', telefone: '(79) 98765-1234', entrada: '26/09/2025 às 11:30' },
|
{
|
||||||
|
nome: "Ana Costa",
|
||||||
|
email: "ana.costa@gmail.com",
|
||||||
|
cpf: "321.654.987-00",
|
||||||
|
telefone: "(79) 97777-3333",
|
||||||
|
entrada: "25/09/2025 às 08:30",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nome: "Lucas Martins",
|
||||||
|
email: "lucas.martins@gmail.com",
|
||||||
|
cpf: "777.666.555-33",
|
||||||
|
telefone: "(79) 99654-3210",
|
||||||
|
entrada: "25/09/2025 às 09:00",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nome: "João Souza",
|
||||||
|
email: "joao.souza@gmail.com",
|
||||||
|
cpf: "987.654.321-00",
|
||||||
|
telefone: "(79) 98888-2222",
|
||||||
|
entrada: "25/09/2025 às 14:00",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nome: "Maria Silva",
|
||||||
|
email: "maria.silva@gmail.com",
|
||||||
|
cpf: "123.456.789-00",
|
||||||
|
telefone: "(79) 99999-1111",
|
||||||
|
entrada: "25/09/2025 às 14:30",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nome: "Fernanda Lima",
|
||||||
|
email: "fernanda.lima@gmail.com",
|
||||||
|
cpf: "888.999.000-22",
|
||||||
|
telefone: "(79) 98877-6655",
|
||||||
|
entrada: "26/09/2025 às 09:30",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nome: "Carlos Andrade",
|
||||||
|
email: "carlos.andrade@gmail.com",
|
||||||
|
cpf: "222.555.888-11",
|
||||||
|
telefone: "(79) 99876-5432",
|
||||||
|
entrada: "26/09/2025 às 10:00",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nome: "Juliana Oliveira",
|
||||||
|
email: "juliana.o@gmail.com",
|
||||||
|
cpf: "111.222.333-44",
|
||||||
|
telefone: "(79) 98765-1234",
|
||||||
|
entrada: "26/09/2025 às 11:30",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
// Filtro da fila de espera (sem alteração)
|
// Filtro da fila de espera (sem alteração)
|
||||||
const filteredFila = filaEsperaData.filter(item =>
|
const filteredFila = filaEsperaData.filter(
|
||||||
item.nome.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
(item) =>
|
||||||
item.email.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
item.nome.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||||
item.cpf.includes(searchTerm) ||
|
item.email.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||||
item.telefone.includes(searchTerm)
|
item.cpf.includes(searchTerm) ||
|
||||||
|
item.telefone.includes(searchTerm)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Lógica para filtrar os dados da AGENDA (AgendamentosMes)
|
// Lógica para filtrar os dados da AGENDA (AgendamentosMes)
|
||||||
@ -192,9 +238,11 @@ const filtrarAgendamentosPorMedico = (dictAgendamentos, idMedicoFiltrado) => {
|
|||||||
for (const semana in AgendamentosMes) {
|
for (const semana in AgendamentosMes) {
|
||||||
filteredData[semana] = {};
|
filteredData[semana] = {};
|
||||||
for (const dia in AgendamentosMes[semana]) {
|
for (const dia in AgendamentosMes[semana]) {
|
||||||
filteredData[semana][dia] = AgendamentosMes[semana][dia].filter(agendamento =>
|
filteredData[semana][dia] = AgendamentosMes[semana][dia].filter(
|
||||||
agendamento.status === 'vazio' ||
|
(agendamento) =>
|
||||||
(agendamento.paciente && agendamento.paciente.toLowerCase().includes(lowerCaseSearchTerm))
|
agendamento.status === "vazio" ||
|
||||||
|
(agendamento.paciente &&
|
||||||
|
agendamento.paciente.toLowerCase().includes(lowerCaseSearchTerm))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -202,206 +250,280 @@ const filtrarAgendamentosPorMedico = (dictAgendamentos, idMedicoFiltrado) => {
|
|||||||
}, [searchTerm]);
|
}, [searchTerm]);
|
||||||
|
|
||||||
const ListarDiasdoMes = (ano, mes) => {
|
const ListarDiasdoMes = (ano, mes) => {
|
||||||
let segundas = []; let tercas = []; let quartas = []; let quintas = []; let sextas = []
|
let segundas = [];
|
||||||
const base = dayjs(`${ano}-${mes}-01`)
|
let tercas = [];
|
||||||
const DiasnoMes = base.daysInMonth()
|
let quartas = [];
|
||||||
|
let quintas = [];
|
||||||
|
let sextas = [];
|
||||||
|
const base = dayjs(`${ano}-${mes}-01`);
|
||||||
|
const DiasnoMes = base.daysInMonth();
|
||||||
for (let d = 1; d <= DiasnoMes; d++) {
|
for (let d = 1; d <= DiasnoMes; d++) {
|
||||||
const data = dayjs(`${ano}-${mes}-${d}`)
|
const data = dayjs(`${ano}-${mes}-${d}`);
|
||||||
const dia = data.format('dddd')
|
const dia = data.format("dddd");
|
||||||
switch (dia) {
|
switch (dia) {
|
||||||
case 'Monday': segundas.push(d); break
|
case "Monday":
|
||||||
case 'Tuesday': tercas.push(d); break
|
segundas.push(d);
|
||||||
case 'Wednesday': quartas.push(d); break
|
break;
|
||||||
case 'Thursday': quintas.push(d); break
|
case "Tuesday":
|
||||||
case 'Friday': sextas.push(d); break
|
tercas.push(d);
|
||||||
default: break
|
break;
|
||||||
|
case "Wednesday":
|
||||||
|
quartas.push(d);
|
||||||
|
break;
|
||||||
|
case "Thursday":
|
||||||
|
quintas.push(d);
|
||||||
|
break;
|
||||||
|
case "Friday":
|
||||||
|
sextas.push(d);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let ListaDiasDatas = {segundas:segundas,tercas:tercas,quartas: quartas,quintas: quintas,sextas: sextas}
|
let ListaDiasDatas = {
|
||||||
return ListaDiasDatas
|
segundas: segundas,
|
||||||
}
|
tercas: tercas,
|
||||||
|
quartas: quartas,
|
||||||
|
quintas: quintas,
|
||||||
|
sextas: sextas,
|
||||||
|
};
|
||||||
|
return ListaDiasDatas;
|
||||||
|
};
|
||||||
|
|
||||||
const handleClickAgendamento = (agendamento) => {
|
const handleClickAgendamento = (agendamento) => {
|
||||||
if (agendamento.status !== 'vazio') return
|
if (agendamento.status !== "vazio") return;
|
||||||
else setPageConsulta(true)
|
else setPageConsulta(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleSearchMedicos = (term) => {
|
||||||
const handleSearchMedicos = (term) => {
|
|
||||||
setSearchTermDoctor(term);
|
setSearchTermDoctor(term);
|
||||||
if (term.trim() === '') {
|
if (term.trim() === "") {
|
||||||
setFiltredTodosMedicos([]);
|
setFiltredTodosMedicos([]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lógica simples de filtragem:
|
// Lógica simples de filtragem:
|
||||||
const filtered = ListaDeMedicos.filter(medico =>
|
const filtered = ListaDeMedicos.filter((medico) =>
|
||||||
medico.nomeMedico.toLowerCase().includes(term.toLowerCase())
|
medico.nomeMedico.toLowerCase().includes(term.toLowerCase())
|
||||||
);
|
);
|
||||||
setFiltredTodosMedicos(filtered);
|
setFiltredTodosMedicos(filtered);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const handleClickCancel = () => setPageConsulta(false)
|
const handleClickCancel = () => setPageConsulta(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h1>Agendar nova consulta</h1>
|
<h1>Agendar nova consulta</h1>
|
||||||
|
|
||||||
<button className='manage-button btn' onClick={() => navigate('/secretaria/excecoes-disponibilidade')}>
|
<div style={{ display: "flex", flexDirection: "column", gap: "10px" }}>
|
||||||
<i className="bi bi-gear-fill me-1"></i>
|
<div>
|
||||||
Mudar Disponibilidade
|
<button
|
||||||
</button>
|
className="manage-button btn"
|
||||||
|
onClick={() => navigate("/secretaria/excecoes-disponibilidade")}
|
||||||
|
>
|
||||||
|
<i className="bi bi-gear-fill me-1"></i>
|
||||||
|
Gerenciar Exceções
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
className="manage-button btn"
|
||||||
|
onClick={() => navigate("/secretaria/disponibilidade")}
|
||||||
|
>
|
||||||
|
<i className="bi bi-gear-fill me-1"></i>
|
||||||
|
Mudar Disponibilidade
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{!PageNovaConsulta ? (
|
{!PageNovaConsulta ? (
|
||||||
<div className='atendimento-eprocura'>
|
<div className="atendimento-eprocura">
|
||||||
|
<div className="busca-atendimento-container">
|
||||||
<div className='busca-atendimento-container'>
|
<div className="input-e-dropdown-wrapper">
|
||||||
|
<div className="busca-atendimento">
|
||||||
<div className='input-e-dropdown-wrapper'>
|
<div>
|
||||||
|
|
||||||
<div className='busca-atendimento'>
|
|
||||||
<div>
|
|
||||||
<i className="fa-solid fa-calendar-day"></i>
|
<i className="fa-solid fa-calendar-day"></i>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Filtrar atendimento por médico..."
|
placeholder="Filtrar atendimento por médico..."
|
||||||
value={searchTermDoctor}
|
value={searchTermDoctor}
|
||||||
onChange={(e) => handleSearchMedicos(e.target.value)} // Chama a nova função de filtro
|
onChange={(e) => handleSearchMedicos(e.target.value)} // Chama a nova função de filtro
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
{/* DROPDOWN (RENDERIZAÇÃO CONDICIONAL) */}
|
||||||
{/* DROPDOWN (RENDERIZAÇÃO CONDICIONAL) */}
|
{searchTermDoctor && FiltredTodosMedicos.length > 0 && (
|
||||||
{searchTermDoctor && FiltredTodosMedicos.length > 0 && (
|
<div className="dropdown-medicos">
|
||||||
<div className='dropdown-medicos'>
|
|
||||||
{FiltredTodosMedicos.map((medico) => (
|
{FiltredTodosMedicos.map((medico) => (
|
||||||
<div
|
<div
|
||||||
key={medico.id}
|
key={medico.id}
|
||||||
className='dropdown-item'
|
className="dropdown-item"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
// Ação ao selecionar o médico
|
// Ação ao selecionar o médico
|
||||||
setSearchTermDoctor(medico.nomeMedico); // Preenche o input
|
setSearchTermDoctor(medico.nomeMedico); // Preenche o input
|
||||||
//setFiltredTodosMedicos([]); // Fecha o dropdown
|
//setFiltredTodosMedicos([]); // Fecha o dropdown
|
||||||
// Lógica adicional, como selecionar o ID do médico...
|
// Lógica adicional, como selecionar o ID do médico...
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<p>{medico.nomeMedico} </p>
|
<p>{medico.nomeMedico} </p>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="unidade-selecionarprofissional">
|
||||||
<div className='unidade-selecionarprofissional'>
|
|
||||||
<select>
|
<select>
|
||||||
<option value="" disabled selected >Unidade</option>
|
<option value="" disabled selected>
|
||||||
|
Unidade
|
||||||
|
</option>
|
||||||
<option value="">Unidade Central</option>
|
<option value="">Unidade Central</option>
|
||||||
<option value="">Unidade Zona Norte</option>
|
<option value="">Unidade Zona Norte</option>
|
||||||
<option value="">Unidade Zona Oeste</option>
|
<option value="">Unidade Zona Oeste</option>
|
||||||
</select>
|
</select>
|
||||||
<input type="text" placeholder='Selecionar profissional' />
|
<input type="text" placeholder="Selecionar profissional" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='container-btns-agenda-fila_esepera'>
|
<div className="container-btns-agenda-fila_esepera">
|
||||||
<button
|
<button
|
||||||
className={`btn-agenda ${FiladeEspera === false ? "opc-agenda-ativo" : ""}`}
|
className={`btn-agenda ${
|
||||||
|
FiladeEspera === false ? "opc-agenda-ativo" : ""
|
||||||
|
}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setFiladeEspera(false);
|
setFiladeEspera(false);
|
||||||
setSearchTerm('');
|
setSearchTerm("");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Agenda
|
Agenda
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className={`btn-fila-espera ${FiladeEspera === true ? "opc-filaespera-ativo" : ""}`}
|
className={`btn-fila-espera ${
|
||||||
|
FiladeEspera === true ? "opc-filaespera-ativo" : ""
|
||||||
|
}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setFiladeEspera(true);
|
setFiladeEspera(true);
|
||||||
setSearchTerm('');
|
setSearchTerm("");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Fila de espera
|
Fila de espera
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<section className='calendario-ou-filaespera'>
|
<section className="calendario-ou-filaespera">
|
||||||
{FiladeEspera === false ?
|
{FiladeEspera === false ? (
|
||||||
(
|
<div className="calendario">
|
||||||
<div className='calendario'>
|
<div>
|
||||||
<div>
|
<section className="btns-e-legenda-container">
|
||||||
<section className='btns-e-legenda-container'>
|
<div>
|
||||||
<div>
|
<button
|
||||||
<button className={`btn-selecionar-tabeladia ${tabela === "diario" ? "ativo" : ""}`} onClick={() => setTabela("diario")}>
|
className={`btn-selecionar-tabeladia ${
|
||||||
<i className="fa-solid fa-calendar-day"></i> Dia
|
tabela === "diario" ? "ativo" : ""
|
||||||
</button>
|
}`}
|
||||||
<button className={`btn-selecionar-tabelasemana ${tabela === 'semanal' ? 'ativo' : ""}`} onClick={() => setTabela("semanal")}>
|
onClick={() => setTabela("diario")}
|
||||||
<i className="fa-solid fa-calendar-day"></i> Semana
|
>
|
||||||
</button>
|
<i className="fa-solid fa-calendar-day"></i> Dia
|
||||||
<button className={`btn-selecionar-tabelames ${tabela === 'mensal' ? 'ativo' : ''}`} onClick={() => setTabela("mensal")}>
|
</button>
|
||||||
<i className="fa-solid fa-calendar-day"></i> Mês
|
<button
|
||||||
</button>
|
className={`btn-selecionar-tabelasemana ${
|
||||||
|
tabela === "semanal" ? "ativo" : ""
|
||||||
|
}`}
|
||||||
|
onClick={() => setTabela("semanal")}
|
||||||
|
>
|
||||||
|
<i className="fa-solid fa-calendar-day"></i> Semana
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className={`btn-selecionar-tabelames ${
|
||||||
|
tabela === "mensal" ? "ativo" : ""
|
||||||
|
}`}
|
||||||
|
onClick={() => setTabela("mensal")}
|
||||||
|
>
|
||||||
|
<i className="fa-solid fa-calendar-day"></i> Mês
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="legenda-tabela">
|
||||||
|
<div className="legenda-item-realizado">
|
||||||
|
<span>Realizado</span>
|
||||||
</div>
|
</div>
|
||||||
<div className='legenda-tabela'>
|
<div className="legenda-item-confirmado">
|
||||||
<div className='legenda-item-realizado'><span>Realizado</span></div>
|
<span>Confirmado</span>
|
||||||
<div className='legenda-item-confirmado'><span>Confirmado</span></div>
|
|
||||||
<div className='legenda-item-agendado'><span>Agendado</span></div>
|
|
||||||
<div className='legenda-item-cancelado'><span>Cancelado</span></div>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
<div className="legenda-item-agendado">
|
||||||
|
<span>Agendado</span>
|
||||||
{tabela === "diario" && <TabelaAgendamentoDia handleClickAgendamento={handleClickAgendamento} agendamentos={DictAgendamentosOrganizados} setShowDeleteModal={setShowDeleteModal} />}
|
</div>
|
||||||
{tabela === 'semanal' && <TabelaAgendamentoSemana agendamentos={DictAgendamentosOrganizados} ListarDiasdoMes={ListarDiasdoMes}/>}
|
<div className="legenda-item-cancelado">
|
||||||
{tabela === 'mensal' && <TabelaAgendamentoMes ListarDiasdoMes={ListarDiasdoMes} aplicarCores={true} agendamentos={DictAgendamentosOrganizados} />}
|
<span>Cancelado</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
</section>
|
||||||
:
|
|
||||||
(
|
{tabela === "diario" && (
|
||||||
<div className="fila-container">
|
<TabelaAgendamentoDia
|
||||||
<div className="fila-header">
|
handleClickAgendamento={handleClickAgendamento}
|
||||||
<input
|
agendamentos={DictAgendamentosOrganizados}
|
||||||
type="text"
|
setShowDeleteModal={setShowDeleteModal}
|
||||||
placeholder="Pesquisar na fila de espera..."
|
|
||||||
className="busca-fila-espera"
|
|
||||||
value={searchTerm}
|
|
||||||
onChange={(e) => setSearchTerm(e.target.value)}
|
|
||||||
/>
|
/>
|
||||||
<h2 className="fila-titulo">Fila de Espera</h2>
|
)}
|
||||||
</div>
|
{tabela === "semanal" && (
|
||||||
<table className="fila-tabela">
|
<TabelaAgendamentoSemana
|
||||||
<thead>
|
agendamentos={DictAgendamentosOrganizados}
|
||||||
<tr>
|
ListarDiasdoMes={ListarDiasdoMes}
|
||||||
<th>Nome</th>
|
/>
|
||||||
<th>Email</th>
|
)}
|
||||||
<th>CPF</th>
|
{tabela === "mensal" && (
|
||||||
<th>Telefone</th>
|
<TabelaAgendamentoMes
|
||||||
<th>Entrou na fila de espera</th>
|
ListarDiasdoMes={ListarDiasdoMes}
|
||||||
</tr>
|
aplicarCores={true}
|
||||||
</thead>
|
agendamentos={DictAgendamentosOrganizados}
|
||||||
<tbody>
|
/>
|
||||||
{filteredFila.map((item, index) => (
|
)}
|
||||||
<tr key={index}>
|
|
||||||
<td>{item.nome}</td>
|
|
||||||
<td>{item.email}</td>
|
|
||||||
<td>{item.cpf}</td>
|
|
||||||
<td>{item.telefone}</td>
|
|
||||||
<td>{item.entrada}</td>
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
</div>
|
||||||
}
|
) : (
|
||||||
|
<div className="fila-container">
|
||||||
|
<div className="fila-header">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Pesquisar na fila de espera..."
|
||||||
|
className="busca-fila-espera"
|
||||||
|
value={searchTerm}
|
||||||
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
|
/>
|
||||||
|
<h2 className="fila-titulo">Fila de Espera</h2>
|
||||||
|
</div>
|
||||||
|
<table className="fila-tabela">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Nome</th>
|
||||||
|
<th>Email</th>
|
||||||
|
<th>CPF</th>
|
||||||
|
<th>Telefone</th>
|
||||||
|
<th>Entrou na fila de espera</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{filteredFila.map((item, index) => (
|
||||||
|
<tr key={index}>
|
||||||
|
<td>{item.nome}</td>
|
||||||
|
<td>{item.email}</td>
|
||||||
|
<td>{item.cpf}</td>
|
||||||
|
<td>{item.telefone}</td>
|
||||||
|
<td>{item.entrada}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<AgendamentoCadastroManager />
|
<AgendamentoCadastroManager />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{showDeleteModal && (
|
{showDeleteModal && (
|
||||||
<div
|
<div
|
||||||
className="modal fade show"
|
className="modal fade show"
|
||||||
style={{
|
style={{
|
||||||
@ -415,7 +537,6 @@ const handleSearchMedicos = (term) => {
|
|||||||
>
|
>
|
||||||
<div className="modal-dialog modal-dialog-centered">
|
<div className="modal-dialog modal-dialog-centered">
|
||||||
<div className="modal-content">
|
<div className="modal-content">
|
||||||
|
|
||||||
<div className="modal-header bg-danger bg-opacity-25">
|
<div className="modal-header bg-danger bg-opacity-25">
|
||||||
<h5 className="modal-title text-danger">
|
<h5 className="modal-title text-danger">
|
||||||
Confirmação de Exclusão
|
Confirmação de Exclusão
|
||||||
@ -429,12 +550,11 @@ const handleSearchMedicos = (term) => {
|
|||||||
|
|
||||||
<div className="modal-body">
|
<div className="modal-body">
|
||||||
<p className="mb-0 fs-5">
|
<p className="mb-0 fs-5">
|
||||||
Tem certeza que deseja excluir este paciente?
|
Tem certeza que deseja excluir este paciente?
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="modal-footer">
|
<div className="modal-footer">
|
||||||
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
@ -443,7 +563,6 @@ const handleSearchMedicos = (term) => {
|
|||||||
Cancelar
|
Cancelar
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-danger"
|
className="btn btn-danger"
|
||||||
@ -454,11 +573,10 @@ const handleSearchMedicos = (term) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>)}
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default Agendamento;
|
export default Agendamento;
|
||||||
|
|||||||
145
src/pages/DisponibilidadesDoctorPage.jsx
Normal file
145
src/pages/DisponibilidadesDoctorPage.jsx
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
import React, { useState, useEffect, useCallback } from "react";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
|
const ENDPOINT_LISTAR = "https://mock.apidog.com/m1/1053378-0-default/rest/v1/doctor_availability";
|
||||||
|
|
||||||
|
const DisponibilidadesDoctorPage = () => {
|
||||||
|
const [disponibilidades, setDisponibilidades] = useState([]);
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [filtroMedicoId, setFiltroMedicoId] = useState("");
|
||||||
|
const [filtroActive, setFiltroActive] = useState("true");
|
||||||
|
const [medicoValido, setMedicoValido] = useState(false);
|
||||||
|
|
||||||
|
const fetchDisponibilidades = useCallback(async (doctorId, activeStatus) => {
|
||||||
|
setLoading(true);
|
||||||
|
let url = `${ENDPOINT_LISTAR}?select=*`;
|
||||||
|
if (doctorId) url += `&doctor_id=eq.${doctorId}`;
|
||||||
|
if (activeStatus === "true" || activeStatus === "false") url += `&active=eq.${activeStatus}`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(url);
|
||||||
|
const result = await response.json();
|
||||||
|
setDisponibilidades(Array.isArray(result) ? result : []);
|
||||||
|
setMedicoValido(Array.isArray(result) && result.length > 0);
|
||||||
|
} catch (error) {
|
||||||
|
setDisponibilidades([]);
|
||||||
|
setMedicoValido(false);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (filtroMedicoId) {
|
||||||
|
fetchDisponibilidades(filtroMedicoId, filtroActive);
|
||||||
|
} else {
|
||||||
|
setDisponibilidades([]);
|
||||||
|
setMedicoValido(false);
|
||||||
|
}
|
||||||
|
}, [filtroMedicoId, filtroActive, fetchDisponibilidades]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div id="main-content">
|
||||||
|
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
|
||||||
|
<h1 style={{ fontSize: "1.5rem", fontWeight: "bold", color: "#333" }}>
|
||||||
|
Disponibilidades por Médico
|
||||||
|
</h1>
|
||||||
|
<Link
|
||||||
|
to={medicoValido ? `../medicos/${filtroMedicoId}/edit` : "#"}
|
||||||
|
className="btn-primary"
|
||||||
|
style={{
|
||||||
|
padding: "10px 20px",
|
||||||
|
fontSize: "14px",
|
||||||
|
whiteSpace: "nowrap",
|
||||||
|
textDecoration: "none",
|
||||||
|
display: "inline-block",
|
||||||
|
opacity: medicoValido ? 1 : 0.6,
|
||||||
|
pointerEvents: medicoValido ? "auto" : "none",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
+ Gerenciar Disponibilidades
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="atendimento-eprocura">
|
||||||
|
<div className="busca-atendimento">
|
||||||
|
<div>
|
||||||
|
<i className="fa-solid fa-user-doctor"></i>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Filtrar por ID do Médico..."
|
||||||
|
value={filtroMedicoId}
|
||||||
|
onChange={(e) => setFiltroMedicoId(e.target.value)}
|
||||||
|
style={{ border: "1px solid #ccc", borderRadius: "4px", padding: "5px" }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<i className="fa-solid fa-check-circle"></i>
|
||||||
|
<select
|
||||||
|
value={filtroActive}
|
||||||
|
onChange={(e) => setFiltroActive(e.target.value)}
|
||||||
|
style={{ padding: "8px", border: "1px solid #ccc", borderRadius: "4px" }}
|
||||||
|
>
|
||||||
|
<option value="true">Ativas</option>
|
||||||
|
<option value="false">Inativas</option>
|
||||||
|
<option value="">Todas</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<section className="calendario-ou-filaespera">
|
||||||
|
<div className="fila-container">
|
||||||
|
<h2 className="fila-titulo">
|
||||||
|
Disponibilidades Encontradas ({disponibilidades.length})
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
{loading ? (
|
||||||
|
<p className="text-center py-10">Carregando disponibilidades...</p>
|
||||||
|
) : disponibilidades.length === 0 ? (
|
||||||
|
<p className="text-center py-10">
|
||||||
|
Nenhuma disponibilidade encontrada para os filtros aplicados.
|
||||||
|
</p>
|
||||||
|
) : (
|
||||||
|
<table className="fila-tabela" style={{ width: "100%", borderCollapse: "collapse" }}>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
{["ID", "ID Médico", "Dia da Semana", "Início", "Término", "Intervalo (min)", "Tipo Consulta", "Status"].map(
|
||||||
|
(header) => (
|
||||||
|
<th
|
||||||
|
key={header}
|
||||||
|
style={{ padding: "10px", borderBottom: "2px solid #ddd", textAlign: "left" }}
|
||||||
|
>
|
||||||
|
{header}
|
||||||
|
</th>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{disponibilidades.map((disp, index) => (
|
||||||
|
<tr key={disp.id || index} style={{ borderBottom: "1px solid #eee" }}>
|
||||||
|
<td style={{ padding: "10px", fontSize: "0.9em" }}>{disp.id || "N/A"}</td>
|
||||||
|
<td style={{ padding: "10px", fontSize: "0.9em" }}>{disp.doctor_id}</td>
|
||||||
|
<td style={{ padding: "10px", fontSize: "0.9em" }}>{disp.weekday}</td>
|
||||||
|
<td style={{ padding: "10px", fontSize: "0.9em" }}>{disp.start_time || "N/A"}</td>
|
||||||
|
<td style={{ padding: "10px", fontSize: "0.9em" }}>{disp.end_time || "N/A"}</td>
|
||||||
|
<td style={{ padding: "10px", fontSize: "0.9em" }}>{disp.slot_minutes}</td>
|
||||||
|
<td style={{ padding: "10px", fontSize: "0.9em" }}>{disp.appointment_type}</td>
|
||||||
|
<td style={{ padding: "10px", fontSize: "0.9em" }}>
|
||||||
|
<span className={`status-tag ${disp.active ? "legenda-item-realizado" : "legenda-item-cancelado"}`}>
|
||||||
|
{disp.active ? "Ativa" : "Inativa"}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DisponibilidadesDoctorPage;
|
||||||
@ -1,77 +1,146 @@
|
|||||||
import React from 'react'
|
import React, { useEffect, useState, useCallback } from "react";
|
||||||
import { GetDoctorByID } from '../components/utils/Functions-Endpoints/Doctor'
|
import { useParams, useSearchParams } from "react-router-dom";
|
||||||
import DoctorForm from '../components/doctors/DoctorForm'
|
import { GetDoctorByID } from "../components/utils/Functions-Endpoints/Doctor";
|
||||||
import { useAuth } from '../components/utils/AuthProvider'
|
import DoctorForm from "../components/doctors/DoctorForm";
|
||||||
import {useEffect, useState} from 'react'
|
import { useAuth } from "../components/utils/AuthProvider";
|
||||||
import { useParams } from 'react-router-dom'
|
import API_KEY from "../components/utils/apiKeys";
|
||||||
import API_KEY from '../components/utils/apiKeys'
|
|
||||||
|
const ENDPOINT_AVAILABILITY =
|
||||||
|
"https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/doctor_availability";
|
||||||
|
|
||||||
const DoctorEditPage = () => {
|
const DoctorEditPage = () => {
|
||||||
const {getAuthorizationHeader, isAuthenticated} = useAuth();
|
const { getAuthorizationHeader } = useAuth();
|
||||||
const [DoctorToPUT, setDoctorPUT] = useState({})
|
const [DoctorToPUT, setDoctorPUT] = useState({});
|
||||||
|
|
||||||
const Parametros = useParams()
|
|
||||||
|
|
||||||
const DoctorID = Parametros.id
|
const Parametros = useParams();
|
||||||
|
const [searchParams] = useSearchParams();
|
||||||
|
const DoctorID = Parametros.id;
|
||||||
|
const availabilityId = searchParams.get("availabilityId");
|
||||||
|
|
||||||
useEffect(() => {
|
const [availabilityToPATCH, setAvailabilityToPATCH] = useState(null);
|
||||||
|
const [mode, setMode] = useState("doctor");
|
||||||
const authHeader = getAuthorizationHeader()
|
|
||||||
|
|
||||||
GetDoctorByID(DoctorID, authHeader)
|
useEffect(() => {
|
||||||
.then((data) => {
|
const authHeader = getAuthorizationHeader();
|
||||||
console.log(data, "médico vindo da API");
|
|
||||||
setDoctorPUT(data[0])
|
if (availabilityId) {
|
||||||
; // supabase retorna array
|
setMode("availability");
|
||||||
|
|
||||||
|
fetch(`${ENDPOINT_AVAILABILITY}?id=eq.${availabilityId}&select=*`, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
apikey: API_KEY,
|
||||||
|
Authorization: authHeader,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
.catch((err) => console.error("Erro ao buscar paciente:", err));
|
.then((res) => res.json())
|
||||||
|
.then((data) => {
|
||||||
|
if (data && data.length > 0) {
|
||||||
|
setAvailabilityToPATCH(data[0]);
|
||||||
|
console.log("Disponibilidade vinda da API:", data[0]);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => console.error("Erro ao buscar disponibilidade:", err));
|
||||||
|
} else {
|
||||||
|
setMode("doctor");
|
||||||
|
GetDoctorByID(DoctorID, authHeader)
|
||||||
|
.then((data) => {
|
||||||
|
console.log(data, "médico vindo da API");
|
||||||
|
setDoctorPUT(data[0]);
|
||||||
|
})
|
||||||
|
.catch((err) => console.error("Erro ao buscar paciente:", err));
|
||||||
|
}
|
||||||
|
}, [DoctorID, availabilityId, getAuthorizationHeader]);
|
||||||
|
|
||||||
|
|
||||||
}, [])
|
|
||||||
const HandlePutDoctor = async () => {
|
const HandlePutDoctor = async () => {
|
||||||
const authHeader = getAuthorizationHeader()
|
const authHeader = getAuthorizationHeader();
|
||||||
|
|
||||||
|
|
||||||
var myHeaders = new Headers();
|
var myHeaders = new Headers();
|
||||||
myHeaders.append('apikey', API_KEY)
|
myHeaders.append("apikey", API_KEY);
|
||||||
myHeaders.append("Authorization", authHeader);
|
myHeaders.append("Authorization", authHeader);
|
||||||
myHeaders.append("Content-Type", "application/json");
|
myHeaders.append("Content-Type", "application/json");
|
||||||
|
|
||||||
var raw = JSON.stringify(DoctorToPUT);
|
var raw = JSON.stringify(DoctorToPUT);
|
||||||
|
|
||||||
console.log("Enviando médico para atualização:", DoctorToPUT);
|
console.log("Enviando médico para atualização (PUT):", DoctorToPUT);
|
||||||
|
|
||||||
var requestOptions = {
|
var requestOptions = {
|
||||||
method: 'PUT',
|
method: "PUT",
|
||||||
headers: myHeaders,
|
headers: myHeaders,
|
||||||
body: raw,
|
body: raw,
|
||||||
redirect: 'follow'
|
redirect: "follow",
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/doctors?id=eq.${DoctorID}`,
|
||||||
|
requestOptions
|
||||||
|
);
|
||||||
|
console.log("Resposta PUT Doutor:", response);
|
||||||
|
alert("Dados do médico atualizados com sucesso!");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Erro ao atualizar médico:", error);
|
||||||
|
alert("Erro ao atualizar dados do médico.");
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
// 2. Função para Atualizar DISPONIBILIDADE (PATCH)
|
||||||
const response = await fetch(`https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/doctors?id=eq.${DoctorID}`,requestOptions);
|
const HandlePatchAvailability = async (data) => {
|
||||||
console.log(response)
|
const authHeader = getAuthorizationHeader();
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Erro ao atualizar paciente:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
var myHeaders = new Headers();
|
||||||
|
myHeaders.append("apikey", API_KEY);
|
||||||
|
myHeaders.append("Authorization", authHeader);
|
||||||
|
myHeaders.append("Content-Type", "application/json");
|
||||||
|
|
||||||
|
var raw = JSON.stringify(data);
|
||||||
|
|
||||||
|
console.log("Enviando disponibilidade para atualização (PATCH):", data);
|
||||||
|
|
||||||
|
var requestOptions = {
|
||||||
|
method: "PATCH",
|
||||||
|
headers: myHeaders,
|
||||||
|
body: raw,
|
||||||
|
redirect: "follow",
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`${ENDPOINT_AVAILABILITY}?id=eq.${availabilityId}`,
|
||||||
|
requestOptions
|
||||||
|
);
|
||||||
|
console.log("Resposta PATCH Disponibilidade:", response);
|
||||||
|
alert("Disponibilidade atualizada com sucesso!");
|
||||||
|
// Opcional: Redirecionar de volta para a lista de disponibilidades
|
||||||
|
// navigate('/disponibilidades');
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Erro ao atualizar disponibilidade:", error);
|
||||||
|
alert("Erro ao atualizar disponibilidade.");
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
<h1 className="text-2xl font-bold mb-4">
|
||||||
|
{mode === "availability"
|
||||||
|
? `Editar Horário Disponível (ID: ${availabilityId.substring(0, 8)})`
|
||||||
|
: `Editar Médico (ID: ${DoctorID})`}
|
||||||
|
</h1>
|
||||||
|
|
||||||
<DoctorForm
|
<DoctorForm
|
||||||
onSave={HandlePutDoctor}
|
onSave={
|
||||||
|
mode === "availability" ? HandlePatchAvailability : HandlePutDoctor
|
||||||
formData={DoctorToPUT}
|
}
|
||||||
setFormData={setDoctorPUT}
|
formData={mode === "availability" ? availabilityToPATCH : DoctorToPUT}
|
||||||
|
setFormData={
|
||||||
/>
|
mode === "availability" ? setAvailabilityToPATCH : setDoctorPUT
|
||||||
|
}
|
||||||
|
isEditingAvailability={mode === "availability"}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default DoctorEditPage
|
export default DoctorEditPage;
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
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 HorariosDisponibilidade from "../../components/doctors/HorariosDisponibilidade";
|
||||||
import SecretariaItems from "../../data/sidebar-items-secretaria.json";
|
import SecretariaItems from "../../data/sidebar-items-secretaria.json";
|
||||||
import Inicio from "../../pages/Inicio";
|
import Inicio from "../../pages/Inicio";
|
||||||
import TablePaciente from "../../pages/TablePaciente";
|
import TablePaciente from "../../pages/TablePaciente";
|
||||||
@ -16,6 +16,7 @@ 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";
|
||||||
import ExcecoesDisponibilidade from "../../pages/ExcecoesDisponibilidade";
|
import ExcecoesDisponibilidade from "../../pages/ExcecoesDisponibilidade";
|
||||||
|
import DisponibilidadesDoctorPage from "../../pages/DisponibilidadesDoctorPage"
|
||||||
import AgendamentoEditPage from "../../pages/AgendamentoEditPage";
|
import AgendamentoEditPage from "../../pages/AgendamentoEditPage";
|
||||||
|
|
||||||
function PerfilSecretaria({ onLogout }) {
|
function PerfilSecretaria({ onLogout }) {
|
||||||
@ -36,9 +37,11 @@ function PerfilSecretaria({ onLogout }) {
|
|||||||
<Route path="medicos/:id/edit" element={<DoctorEditPage />} />
|
<Route path="medicos/:id/edit" element={<DoctorEditPage />} />
|
||||||
<Route path="agendamento" element={<Agendamento />} />
|
<Route path="agendamento" element={<Agendamento />} />
|
||||||
<Route path="agendamento/:id/edit" element={<AgendamentoEditPage/>} />
|
<Route path="agendamento/:id/edit" element={<AgendamentoEditPage/>} />
|
||||||
<Route path="laudo" element={<LaudoManager />} />
|
<Route path="laudo" element={<LaudoManager />} />
|
||||||
<Route path="*" element={<h2>Página não encontrada</h2>} />
|
<Route path="disponibilidade" element={<DisponibilidadesDoctorPage />} />
|
||||||
|
<Route path="horarios" element={<HorariosDisponibilidade/>}/>
|
||||||
<Route path="excecoes-disponibilidade" element={<ExcecoesDisponibilidade />} />
|
<Route path="excecoes-disponibilidade" element={<ExcecoesDisponibilidade />} />
|
||||||
|
<Route path="*" element={<h2>Página não encontrada</h2>} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user