291 lines
12 KiB
JavaScript
291 lines
12 KiB
JavaScript
import React, { useState, useEffect } from "react";
|
||
import { useAuth } from "./utils/AuthProvider";
|
||
import API_KEY from "./utils/apiKeys";
|
||
import "./AgendarConsulta/style/formagendamentos.css";
|
||
import { GetAllDoctors } from './utils/Functions-Endpoints/Doctor';
|
||
|
||
|
||
const ENDPOINT_CRIAR_EXCECAO = "https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/doctor_exceptions";
|
||
|
||
const FormCriarExcecao = ({ onCancel, doctorID }) => {
|
||
const { getAuthorizationHeader, user, getUserInfo } = useAuth();
|
||
const [dadosAtendimento, setDadosAtendimento] = useState({
|
||
profissional: doctorID || '',
|
||
tipoAtendimento: '',
|
||
dataAtendimento: '',
|
||
inicio: '',
|
||
termino: '',
|
||
motivo: ''
|
||
});
|
||
|
||
const [todosProfissionais, setTodosProfissionais] = useState([]);
|
||
const [profissionaisFiltrados, setProfissionaisFiltrados] = useState([]);
|
||
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
||
|
||
const [doctorSearchName, setDoctorSearchName] = useState('');
|
||
const [searchingDoctor, setSearchingDoctor] = useState(false);
|
||
|
||
const handleAtendimentoChange = (e) => {
|
||
const { value, name } = e.target;
|
||
setDadosAtendimento(prev => ({
|
||
...prev,
|
||
[name]: value
|
||
}));
|
||
};
|
||
|
||
useEffect(() => {
|
||
const loadDoctors = async () => {
|
||
setSearchingDoctor(true);
|
||
let authHeader = '';
|
||
try { authHeader = getAuthorizationHeader ? getAuthorizationHeader() : ''; } catch {}
|
||
try {
|
||
const Medicos = await GetAllDoctors(authHeader);
|
||
setTodosProfissionais(Array.isArray(Medicos) ? Medicos : []);
|
||
} catch (err) {
|
||
console.error('Erro ao carregar médicos:', err);
|
||
setTodosProfissionais([]);
|
||
} finally {
|
||
setSearchingDoctor(false);
|
||
}
|
||
};
|
||
loadDoctors();
|
||
}, [getAuthorizationHeader]);
|
||
|
||
const handleSearchProfissional = (e) => {
|
||
const term = e.target.value;
|
||
setDoctorSearchName(term);
|
||
if (term.trim() === '') {
|
||
setProfissionaisFiltrados([]);
|
||
setIsDropdownOpen(false);
|
||
return;
|
||
}
|
||
const filtered = todosProfissionais.filter(p =>
|
||
(p.full_name || '').toLowerCase().includes(term.toLowerCase())
|
||
);
|
||
setProfissionaisFiltrados(filtered);
|
||
setIsDropdownOpen(filtered.length > 0);
|
||
};
|
||
|
||
const handleSelectProfissional = (profissional) => {
|
||
setDadosAtendimento(prev => ({
|
||
...prev,
|
||
profissional: profissional.id
|
||
}));
|
||
setDoctorSearchName(profissional.full_name || '');
|
||
setProfissionaisFiltrados([]);
|
||
setIsDropdownOpen(false);
|
||
};
|
||
|
||
// lista simples de valores permitidos
|
||
const ALLOWED_KINDS = ['disponibilidade_extra', 'bloqueio'];
|
||
|
||
const handleSubmitExcecao = async (e) => {
|
||
e.preventDefault();
|
||
console.log("Tentando criar Exceção.");
|
||
|
||
const { profissional, dataAtendimento, tipoAtendimento, inicio, termino, motivo } = dadosAtendimento;
|
||
|
||
if (!profissional || !dataAtendimento || !tipoAtendimento || !motivo) {
|
||
alert("Por favor, preencha o ID do Profissional, Data, Tipo e Motivo.");
|
||
return;
|
||
}
|
||
|
||
// usa diretamente o value selecionado (já definido no <select>) e valida
|
||
const mappedKind = tipoAtendimento;
|
||
if (!ALLOWED_KINDS.includes(mappedKind)) {
|
||
alert(`Tipo inválido: "${tipoAtendimento}". Tipos aceitos: ${ALLOWED_KINDS.join(', ')}`);
|
||
return;
|
||
}
|
||
|
||
const startTime = inicio ? inicio + ":00" : null;
|
||
const endTime = termino ? termino + ":00" : null;
|
||
|
||
let authHeader = "";
|
||
try {
|
||
authHeader = getAuthorizationHeader ? getAuthorizationHeader() : "";
|
||
} catch (err) {
|
||
console.warn("Não foi possível obter Authorization header via useAuth()", err);
|
||
}
|
||
|
||
let createdBy = user?.id || null;
|
||
if (!createdBy && typeof getUserInfo === "function") {
|
||
try {
|
||
const info = await getUserInfo();
|
||
createdBy = info?.id || info?.profile?.id || null;
|
||
} catch (err) {
|
||
console.warn("getUserInfo falhou:", err);
|
||
}
|
||
}
|
||
|
||
if (!createdBy) {
|
||
try {
|
||
const stored = localStorage.getItem("user");
|
||
if (stored) {
|
||
const parsed = JSON.parse(stored);
|
||
createdBy = parsed?.id || parsed?.user?.id || null;
|
||
}
|
||
} catch {}
|
||
}
|
||
|
||
const raw = JSON.stringify({
|
||
doctor_id: profissional,
|
||
date: dataAtendimento,
|
||
kind: mappedKind,
|
||
start_time: startTime,
|
||
end_time: endTime,
|
||
reason: motivo,
|
||
created_by: createdBy
|
||
});
|
||
|
||
var myHeaders = new Headers();
|
||
if (authHeader) myHeaders.append("Authorization", authHeader);
|
||
myHeaders.append("Content-Type", "application/json");
|
||
if (API_KEY) myHeaders.append("apikey", API_KEY);
|
||
|
||
var requestOptions = {
|
||
method: 'POST',
|
||
headers: myHeaders,
|
||
body: raw,
|
||
redirect: 'follow'
|
||
};
|
||
|
||
try {
|
||
const response = await fetch(ENDPOINT_CRIAR_EXCECAO, requestOptions);
|
||
const resultText = await response.text();
|
||
let result;
|
||
try {
|
||
result = JSON.parse(resultText);
|
||
} catch {
|
||
result = { message: resultText || 'Sucesso, mas resposta não é JSON.' };
|
||
}
|
||
|
||
if (response.ok || response.status === 201) {
|
||
console.log("Exceção criada com sucesso:", result);
|
||
alert(`Exceção criada! Detalhes: ${result.id || JSON.stringify(result)}`);
|
||
onCancel(true);
|
||
} else {
|
||
console.error("Erro ao criar exceção:", result);
|
||
alert(`Erro ao criar exceção. Status: ${response.status}. Detalhes: ${result.message || JSON.stringify(result)}`);
|
||
}
|
||
} catch (error) {
|
||
console.error("Erro na requisição para criar exceção:", error);
|
||
alert("Erro de comunicação com o servidor.");
|
||
}
|
||
};
|
||
|
||
return (
|
||
<div className="form-container">
|
||
<form className="form-agendamento" onSubmit={handleSubmitExcecao}>
|
||
<h2 className="section-title">Informações da Nova Exceção</h2>
|
||
|
||
<div className="campo-informacoes-atendimento">
|
||
{/* Busca por nome usando filtragem local */}
|
||
<div className="campo-de-input campo-de-input-container">
|
||
<label>Nome do médico</label>
|
||
<input
|
||
type="text"
|
||
name="doctorSearchName"
|
||
placeholder="Digite o nome do médico"
|
||
value={doctorSearchName}
|
||
onChange={handleSearchProfissional}
|
||
autoComplete="off"
|
||
/>
|
||
{isDropdownOpen && profissionaisFiltrados.length > 0 && (
|
||
<div className="dropdown-profissionais">
|
||
{profissionaisFiltrados.map(p => (
|
||
<div key={p.id} className="dropdown-item" onClick={() => handleSelectProfissional(p)}>
|
||
{p.full_name}
|
||
</div>
|
||
))}
|
||
</div>
|
||
)}
|
||
{searchingDoctor && <small>Carregando médicos...</small>}
|
||
</div>
|
||
|
||
{/* ID do profissional (preenchido ao selecionar) */}
|
||
<div className="campo-de-input">
|
||
<label>ID do profissional *</label>
|
||
<input
|
||
type="text"
|
||
name="profissional"
|
||
required
|
||
value={dadosAtendimento.profissional}
|
||
onChange={handleAtendimentoChange}
|
||
/>
|
||
</div>
|
||
|
||
<div className="campo-de-input">
|
||
<label>Tipo de exceção *</label>
|
||
<select name="tipoAtendimento" onChange={handleAtendimentoChange} value={dadosAtendimento.tipoAtendimento} required>
|
||
<option value="" disabled>Selecione o tipo de exceção</option>
|
||
<option value="disponibilidade_extra" >Liberação</option>
|
||
<option value="bloqueio" >Bloqueio</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
|
||
<section id="informacoes-atendimento-segunda-linha">
|
||
<section id="informacoes-atendimento-segunda-linha-esquerda">
|
||
|
||
<div className="campo-informacoes-atendimento">
|
||
|
||
<div className="campo-de-input">
|
||
<label>Data *</label>
|
||
<input
|
||
type="date"
|
||
name="dataAtendimento"
|
||
required
|
||
value={dadosAtendimento.dataAtendimento}
|
||
onChange={handleAtendimentoChange}
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="campo-informacoes-atendimento">
|
||
<div className="campo-de-input">
|
||
<label>Início (Opcional)</label>
|
||
<input
|
||
type="time"
|
||
name="inicio"
|
||
value={dadosAtendimento.inicio}
|
||
onChange={handleAtendimentoChange}
|
||
/>
|
||
</div>
|
||
|
||
<div className="campo-de-input">
|
||
<label>Término (Opcional)</label>
|
||
<input
|
||
type="time"
|
||
name="termino"
|
||
value={dadosAtendimento.termino}
|
||
onChange={handleAtendimentoChange}
|
||
/>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section className="informacoes-atendimento-segunda-linha-direita">
|
||
<div className="campo-de-input">
|
||
<label>Motivo da exceção *</label>
|
||
<textarea
|
||
name="motivo"
|
||
rows="4"
|
||
cols="1"
|
||
required
|
||
value={dadosAtendimento.motivo}
|
||
onChange={handleAtendimentoChange}
|
||
></textarea>
|
||
</div>
|
||
</section>
|
||
</section>
|
||
|
||
<div className="form-actions">
|
||
<button type="submit" className="btn-primary">Criar Exceção</button>
|
||
<button type="button" className="btn-cancel" onClick={() => onCancel(false)}>Cancelar</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default FormCriarExcecao; |