diff --git a/src/components/doctors/DoctorForm.jsx b/src/components/doctors/DoctorForm.jsx
index e7e7bea..5a0befb 100644
--- a/src/components/doctors/DoctorForm.jsx
+++ b/src/components/doctors/DoctorForm.jsx
@@ -126,12 +126,14 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
}
};
- const handleAvailabilityUpdate = useCallback(
- (newAvailability) => {
- setFormData((prev) => ({ ...prev, availability: newAvailability }));
- },
- [setFormData]
- );
+const handleAvailabilityUpdate = useCallback((newAvailability) => {
+ setFormData((prev) => {
+ if (JSON.stringify(prev.availability) !== JSON.stringify(newAvailability)) {
+ return { ...prev, availability: newAvailability };
+ }
+ return prev;
+ });
+}, []);
const handleCepBlur = async () => {
const cep = formData.cep?.replace(/\D/g, "");
@@ -229,25 +231,6 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
}
};
- const handlePatchAvailability = async (id, updatedAvailability) => {
- try {
- const response = await fetch(`${ENDPOINT_AVAILABILITY}?id=${id}`, {
- method: "PATCH",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify(updatedAvailability),
- });
-
- const data = await response.json();
- console.log("Disponibilidade atualizada:", data);
- alert("Disponibilidade atualizada com sucesso!");
-} catch (error) {
- console.error("Erro ao atualizar disponibilidade:", error);
- alert("Erro ao atualizar disponibilidade.");
-}
- };
-
const handleSubmit = async () => {
const missingFields = [];
if (!formData.full_name) missingFields.push("full_name");
@@ -290,20 +273,12 @@ function DoctorForm({ onSave, onCancel, formData, setFormData, isLoading }) {
await onSave({ ...formData });
if (formData.availability && formData.availability.length > 0) {
- if (formData.availabilityId) {
- await handlePatchAvailability(
- formData.availabilityId,
- formData.availability
- );
- } else {
- await handleCreateAvailability(formData.availability);
- }
}
- alert("Médico salvo e disponibilidade enviada ao mock com sucesso!");
+ alert("Médico salvo com sucesso!");
} catch (error) {
- console.error("Erro ao salvar médico ou disponibilidade:", error);
- alert("Erro ao salvar médico ou disponibilidade.");
+ console.error("Erro ao salvar médico:", error);
+ alert("Erro ao salvar médico.");
};
};
diff --git a/src/components/doctors/HorariosDisponibilidade.jsx b/src/components/doctors/HorariosDisponibilidade.jsx
index 793c161..bc8b83b 100644
--- a/src/components/doctors/HorariosDisponibilidade.jsx
+++ b/src/components/doctors/HorariosDisponibilidade.jsx
@@ -1,4 +1,4 @@
-import React, { useState, useEffect, useCallback } from "react";
+import React, { useState, useEffect, useCallback, useRef } from "react";
import { Clock } from "lucide-react";
const initialBlockTemplate = {
@@ -21,21 +21,19 @@ const emptyAvailabilityTemplate = [
const HorariosDisponibilidade = ({
initialAvailability = emptyAvailabilityTemplate,
onUpdate,
+ onCancel,
}) => {
const [availability, setAvailability] = useState(initialAvailability);
+ const isFirstRun = useRef(true);
useEffect(() => {
- if (initialAvailability !== emptyAvailabilityTemplate) {
+ if (initialAvailability && initialAvailability.length > 0) {
setAvailability(initialAvailability);
+ } else {
+ setAvailability(emptyAvailabilityTemplate);
}
}, [initialAvailability]);
- useEffect(() => {
- if (onUpdate) {
- onUpdate(availability);
- }
- }, [availability, onUpdate]);
-
const handleDayCheck = useCallback((dayIndex, currentIsChecked) => {
const isChecked = !currentIsChecked;
@@ -110,6 +108,10 @@ const HorariosDisponibilidade = ({
);
}, []);
+ const handleSave = useCallback(() => {
+ if (onUpdate) onUpdate(availability);
+ }, [availability, onUpdate]);
+
const renderTimeBlock = (dayIndex, bloco) => (
@@ -186,7 +188,12 @@ const HorariosDisponibilidade = ({
@@ -199,13 +206,13 @@ const HorariosDisponibilidade = ({
handleTimeChange(dayIndex, bloco.id, "termino", e.target.value)
}
style={{
- padding: "4px 6px",
- border: "1px solid #d1d5db",
- borderRadius: "6px",
- width: "100%",
- boxSizing: "border-box",
- outline: "none",
- fontSize: "13px",
+ padding: "4px 6px",
+ border: "1px solid #d1d5db",
+ borderRadius: "6px",
+ width: "100%",
+ boxSizing: "border-box",
+ outline: "none",
+ fontSize: "13px",
}}
step="300"
/>
@@ -258,8 +265,7 @@ const HorariosDisponibilidade = ({
marginLeft: window.innerWidth < 640 ? "0" : "16px",
fontWeight: 500,
}}
- >
-
+ >
)}
);
diff --git a/src/pages/DisponibilidadesDoctorPage.jsx b/src/pages/DisponibilidadesDoctorPage.jsx
index a035dfe..e107595 100644
--- a/src/pages/DisponibilidadesDoctorPage.jsx
+++ b/src/pages/DisponibilidadesDoctorPage.jsx
@@ -1,75 +1,68 @@
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";
-
+import HorariosDisponibilidade from "../components/doctors/HorariosDisponibilidade";
+const ENDPOINT =
+ "https://mock.apidog.com/m1/1053378-0-default/rest/v1/doctor_availability";
const MEDICOS_MOCKADOS = [
- { id: 53, nome: " João Silva" },
- { id: 19, nome: " Ana Costa" },
- { id: 11, nome: " Pedro Santos" },
-
+ { id: 53, nome: "João Silva" },
+ { id: 19, nome: "Ana Costa" },
+ { id: 11, nome: "Pedro Santos" },
];
-
const diasDaSemana = ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"];
-
const formatarDataHora = (isoString) => {
if (!isoString) return "N/A";
try {
const data = new Date(isoString);
-
- return data.toLocaleTimeString("pt-BR", { hour: '2-digit', minute: '2-digit', timeZone: 'UTC' });
- } catch (error) {
+ // Usa o toLocaleTimeString para extrair hora e minuto
+ return data.toLocaleTimeString("pt-BR", {
+ hour: "2-digit",
+ minute: "2-digit",
+ timeZone: "UTC",
+ });
+ } catch {
return "Data Inválida";
}
};
-
const DisponibilidadesDoctorPage = () => {
const [disponibilidades, setDisponibilidades] = useState([]);
const [loading, setLoading] = useState(false);
const [filtroMedicoNome, setFiltroMedicoNome] = useState("");
-
- const [medicoEncontradoId, setMedicoEncontradoId] = useState(null);
-
+ const [gerenciarModo, setGerenciarModo] = useState(false);
+ const [editando, setEditando] = useState(null); // ID da disponibilidade sendo editada
const encontrarMedicoIdPorNome = (nome) => {
- if (!nome) return null;
- const termoBusca = nome.toLowerCase();
-
-
- const medico = MEDICOS_MOCKADOS.find(m =>
- m.nome.toLowerCase().includes(termoBusca)
- );
-
- return medico ? medico.id : null;
+ if (!nome) return null;
+ const termo = nome.toLowerCase();
+ const medico = MEDICOS_MOCKADOS.find((m) =>
+ m.nome.toLowerCase().includes(termo)
+ );
+ return medico ? medico.id : null;
};
const fetchDisponibilidades = useCallback(async (nome) => {
setLoading(true);
- setDisponibilidades([]);
- setMedicoEncontradoId(null);
const doctorId = encontrarMedicoIdPorNome(nome);
-
if (!doctorId) {
- setLoading(false);
- return;
+ setLoading(false);
+ return;
}
-
- const url = `${ENDPOINT_LISTAR}?select=*&doctor_id=eq.${doctorId}`;
-
try {
- const response = await fetch(url);
- const result = await response.json();
-
- let dados = Array.isArray(result) ? result : [];
+ const res = await fetch(`${ENDPOINT}?doctor_id=eq.${doctorId}`);
+ const data = await res.json();
- setDisponibilidades(dados);
- setMedicoEncontradoId(doctorId);
- } catch (error) {
+ setDisponibilidades(
+ Array.isArray(data)
+ ? data
+ : data && Array.isArray(data.items)
+ ? data.items
+ : []
+ );
+ } catch (e) {
+ console.error("Erro ao buscar disponibilidades:", e);
setDisponibilidades([]);
} finally {
setLoading(false);
@@ -77,111 +70,244 @@ const DisponibilidadesDoctorPage = () => {
}, []);
useEffect(() => {
+ if (!gerenciarModo && editando) {
+ setEditando(null);
+ }
+ }, [gerenciarModo]);
+
+ useEffect(() => {
+ if (editando) return;
if (filtroMedicoNome) {
const timer = setTimeout(() => {
fetchDisponibilidades(filtroMedicoNome);
- }, 300);
+ }, 300);
return () => clearTimeout(timer);
} else {
- setDisponibilidades([]);
- setMedicoEncontradoId(null);
+ setDisponibilidades([]);
}
- }, [filtroMedicoNome, fetchDisponibilidades]);
+ }, [filtroMedicoNome, fetchDisponibilidades, editando]);
- const rotaGerenciar = medicoEncontradoId
- ? `../medicos/${medicoEncontradoId}/edit`
- : `../medicos/novo/edit`;
+ const atualizarDisponibilidade = async (id, novoIntervalo) => {
+ try {
+ const res = await fetch(`${ENDPOINT}?id=eq.${id}`, {
+ method: "PUT",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ slot_minutes: novoIntervalo }),
+ });
+ if (res.ok) {
+ alert("Disponibilidade atualizada com sucesso!");
+ setEditando(null);
+ fetchDisponibilidades(filtroMedicoNome);
+ } else {
+ alert("Erro ao atualizar disponibilidade");
+ }
+ } catch {
+ alert("Falha ao conectar com o servidor");
+ }
+ };
+ const deletarDisponibilidade = async (id) => {
+ if (!window.confirm("Deseja realmente excluir esta disponibilidade?"))
+ return;
+ try {
+ const res = await fetch(`${ENDPOINT}?id=eq.${id}`, { method: "DELETE" });
+ if (res.ok) {
+ alert("Disponibilidade excluída!");
+ setDisponibilidades((prev) => prev.filter((d) => d.id !== id));
+ } else {
+ alert("Erro ao excluir disponibilidade");
+ }
+ } catch {
+ alert("Erro ao conectar com o servidor");
+ }
+ };
+
+ const disponibilidadeParaEdicao = editando
+ ? disponibilidades.find((d) => d.id === editando)
+ : null;
+
+const initialAvailabilityParaEdicao = diasDaSemana.map((dia, weekdayIndex) => {
+ const blocosDoDia = disponibilidades
+ .filter(d => d.weekday === weekdayIndex)
+ .map(d => ({
+ id: d.id,
+ inicio: d.start_time
+ ? new Date(d.start_time).toISOString().substring(11, 16)
+ : "07:00",
+ termino: d.end_time
+ ? new Date(d.end_time).toISOString().substring(11, 16)
+ : "17:00",
+ isNew: false,
+ slot_minutes: d.slot_minutes,
+ }));
+
+ return {
+ dia,
+ isChecked: blocosDoDia.length > 0,
+ blocos: blocosDoDia,
+ };
+});
+
+ const handleUpdateHorarios = (horariosAtualizados) => {
+ console.log("Horários editados:", horariosAtualizados);
+
+ setEditando(null);
+ fetchDisponibilidades(filtroMedicoNome);
+ };
return (
-
+ {/* Cabeçalho */}
+
Disponibilidades por Médico
-
- {
+ if (editando) {
+ setEditando(null); // Se está editando, volta para a tabela
+ } else {
+ setGerenciarModo((m) => !m); // Senão, alterna o modo de gerenciamento
+ }
+ }}
className="btn-primary"
style={{
padding: "10px 20px",
fontSize: "14px",
whiteSpace: "nowrap",
- textDecoration: "none",
- display: "inline-block",
}}
>
- + Gerenciar Disponibilidades
-
+ {editando
+ ? "← Voltar para Tabela"
+ : gerenciarModo
+ ? "← Voltar"
+ : "+ Gerenciar Disponibilidades"}
+
-
-
-
-
+ {/* Campo de busca - ESCONDIDO NO MODO DE EDIÇÃO */}
+ {!editando && (
+
+ )}
-
-
-
- Disponibilidades Encontradas ({disponibilidades.length})
-
+
+
+
+ {editando
+ ? "Editar Disponibilidade"
+ : gerenciarModo
+ ? "Gerenciar Disponibilidades"
+ : "Disponibilidades Encontradas"}{" "}
+ ({disponibilidades.length})
+
- {loading ? (
-
Carregando disponibilidades...
- ) : (filtroMedicoNome && disponibilidades.length === 0) ? (
-
- Nenhuma disponibilidade encontrada para o nome buscado.
-
- ) : (
-
-
-
- {[ "Dia da Semana", "Início", "Término", "Intervalo", "Tipo Consulta"].map(
- (header) => (
- | Carregando...
+ ) : disponibilidades.length === 0 ? (
+ Nenhuma disponibilidade encontrada.
+ ) : editando ? (
+ <>
+
+
+ >
+ ) : (
+
+
+
+ | Dia da Semana |
+ Início |
+ Término |
+ Intervalo |
+ Tipo Consulta |
+ {gerenciarModo && Ações | }
+
+
+
+ {disponibilidades.map((disp) => (
+
+ | {diasDaSemana[disp.weekday]} |
+ {formatarDataHora(disp.start_time)} |
+ {formatarDataHora(disp.end_time)} |
+ {disp.slot_minutes} |
+ {disp.appointment_type} |
+ {gerenciarModo && (
+
+ {" "}
+
+ |
)}
-
-
- {disponibilidades.map((disp, index) => (
-
- |
- {diasDaSemana[disp.weekday] || disp.weekday}
- |
-
- {formatarDataHora(disp.start_time)}
- |
-
- {formatarDataHora(disp.end_time)}
- |
- {disp.slot_minutes} |
- {disp.appointment_type} |
-
- ))}
-
-
- )}
-
-
-
+ ))}
+
+ |
+ )}
+
+
);
};
-export default DisponibilidadesDoctorPage;
\ No newline at end of file
+export default DisponibilidadesDoctorPage;