riseup-squad23/src/components/FormCriarExcecao.jsx
2025-11-04 16:20:14 -03:00

291 lines
12 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;