Endpoints de Pacientes finalizados e com o token funcionando

This commit is contained in:
jp-lima 2025-09-27 16:11:00 -03:00
parent 4b9ebd76be
commit 1efbe20640
10 changed files with 218 additions and 103 deletions

View File

@ -1,49 +1,90 @@
import React, { createContext, useContext, useState } from 'react';
import React, { createContext, useContext, useState, useEffect } from 'react';
// 1. Criação do Contexto
const AuthContext = createContext();
const AuthContext = createContext(null);
// Função que será usada para envolver a aplicação
// Hook customizado para facilitar o uso nos componentes
export function useAuth() {
const context = useContext(AuthContext);
if (!context) {
// Isso é crucial para evitar o erro "useAuth() is undefined"
throw new Error('useAuth must be used within an AuthProvider');
}
return context;
}
// O Provedor Principal
export function AuthProvider({ children }) {
// 2. Estado para armazenar o token e o tipo de token
const [accessToken, setAccessToken] = useState(null);
const [tokenType, setTokenType] = useState(null);
const [refreshToken, setRefreshToken] = useState(null);
// Função para salvar o token recebido após o login/refresh
// 🔑 Carrega o token do localStorage na inicialização
useEffect(() => {
// Essa lógica garante que o token permanece após o refresh da página
const storedToken = localStorage.getItem('access_token');
const storedTokenType = localStorage.getItem('token_type');
const storedRefreshToken = localStorage.getItem('refresh_token');
if (storedToken && storedTokenType) {
setAccessToken(storedToken);
setTokenType(storedTokenType);
// O refreshToken é essencial para a renovação futura
setRefreshToken(storedRefreshToken);
}
}, []);
// --- FUNÇÕES DE MUDANÇA (SET/CLEAR) ---
/**
* Função para salvar os tokens após um login ou renovação (refresh).
* @param {Object} tokenResponse O objeto completo retornado pelo Supabase Auth.
*/
const setAuthTokens = (tokenResponse) => {
// Certifique-se de que a resposta contém os tokens
if (tokenResponse && tokenResponse.access_token && tokenResponse.token_type) {
// 1. Atualiza o estado do React
setAccessToken(tokenResponse.access_token);
setTokenType(tokenResponse.token_type);
setRefreshToken(tokenResponse.refresh_token);
// OPCIONAL: Salvar no localStorage para persistência entre recargas de página
// 2. Persiste no localStorage (para não perder ao recarregar a página)
localStorage.setItem('access_token', tokenResponse.access_token);
localStorage.setItem('token_type', tokenResponse.token_type);
localStorage.setItem('refresh_token', tokenResponse.refresh_token);
}
};
// Função para remover o token no logout
/**
* Função para remover todos os tokens (Logout).
*/
const clearAuthTokens = () => {
setAccessToken(null);
setTokenType(null);
setRefreshToken(null);
// Remove do localStorage
localStorage.removeItem('access_token');
localStorage.removeItem('token_type');
localStorage.removeItem('refresh_token');
};
// 3. O valor que será fornecido a todos os componentes
// --- FUNÇÕES DE USO (GET) ---
/**
* Retorna a string completa para o cabeçalho Authorization (ex: "Bearer <token>").
*/
const getAuthorizationHeader = () =>
accessToken && tokenType ? `${tokenType} ${accessToken}` : '';
// --- VALOR DO CONTEXTO ---
const contextValue = {
// O valor do token para usar em requisições
accessToken,
tokenType,
// A função para salvar o token após o login/refresh
setAuthTokens,
// A função de logout
clearAuthTokens,
// Um helper para saber se está logado
refreshToken,
isAuthenticated: !!accessToken,
// Helper para montar o cabeçalho 'Authorization'
getAuthorizationHeader: () =>
accessToken && tokenType ? `${tokenType} ${accessToken}` : ''
setAuthTokens, // Usado para CRIAR/MUDAR (Login/Refresh)
clearAuthTokens, // Usado para MUDAR (Logout)
getAuthorizationHeader, // Usado para PEGAR (Endpoints)
};
return (
@ -52,8 +93,3 @@ export function AuthProvider({ children }) {
</AuthContext.Provider>
);
}
// 4. Hook customizado para facilitar o uso nos componentes
export function useAuth() {
return useContext(AuthContext);
}

View File

@ -0,0 +1,25 @@
import API_KEY from "../apiKeys";
const GetByID = async (ID,authHeader) => {
console.log(authHeader, 'mostrando autorização dentro da função')
var myHeaders = new Headers();
myHeaders.append('apikey', API_KEY)
myHeaders.append('Authorization', authHeader)
var requestOptions = {
method: 'GET',
redirect: 'follow',
headers:myHeaders
};
const result = await fetch(`https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/patients?id=eq.${ID}`, requestOptions)
const DictPaciente = await result.json()
return DictPaciente
}
export {GetByID}

View File

@ -3,11 +3,14 @@ import ReactDOM from 'react-dom/client';
import './assets/scss/bootstrap.scss';
import './assets/scss/app.scss';
import App from './App';
import { AuthProvider } from "./components/utils/AuthProvider";
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<AuthProvider>
<App />
</AuthProvider>
</React.StrictMode>,
);

View File

@ -1,10 +1,16 @@
import React, { useEffect, useState } from "react";
import avatarPlaceholder from '../assets/images/avatar_placeholder.png';
import { useParams } from "react-router-dom";
import API_KEY from "../components/utils/apiKeys";
import {GetByID} from "../components/utils/Functions-Endpoints/Patient"
import { useAuth } from "../components/utils/AuthProvider";
const Details = () => {
const parametros = useParams();
const {getAuthorizationHeader, isAuthenticated} = useAuth();
const [paciente, setPaciente] = useState({});
const [anexos, setAnexos] = useState([]);
const [selectedFile, setSelectedFile] = useState(null);
@ -15,17 +21,20 @@ const Details = () => {
useEffect(() => {
if (!patientID) return;
console.log(patientID, 'teu id')
fetch(`https://mock.apidog.com/m1/1053378-0-default/pacientes/${patientID}`)
.then(res => res.json())
const authHeader = getAuthorizationHeader()
.then(result => {console.log(result.data)})
.catch(err => console.error("Erro ao buscar paciente:", err));
GetByID(patientID, authHeader)
.then((data) => {
console.log(data, "paciente vindo da API");
setPaciente(data[0]); // supabase retorna array
})
.catch((err) => console.error("Erro ao buscar paciente:", err));
fetch(`https://mock.apidog.com/m1/1053378-0-default/pacientes/${patientID}/anexos`)
/*fetch(`https://mock.apidog.com/m1/1053378-0-default/pacientes/${patientID}/anexos`)
.then(res => res.json())
.then(data => setAnexos(data.data || []))
.catch(err => console.error("Erro ao buscar anexos:", err));
*/
}, [patientID]);
const handleUpload = async () => {
@ -101,7 +110,7 @@ const Details = () => {
<div className="row">
<div className="col-md-6 mb-3">
<label className="font-extrabold">Nome:</label>
<p>{paciente.nome || "-"}</p>
<p>{paciente.full_name || "-"}</p>
</div>
<div className="col-md-6 mb-3">
<label className="font-extrabold">Nome social:</label>
@ -109,11 +118,11 @@ const Details = () => {
</div>
<div className="col-md-6 mb-3">
<label className="font-extrabold">Data de nascimento:</label>
<p>{paciente.data_nascimento || "-"}</p>
<p>{paciente.birth_date || "-"}</p>
</div>
<div className="col-md-6 mb-3">
<label className="font-extrabold">Gênero:</label>
<p>{paciente.sexo || "-"}</p>
<p>{paciente.sex || "-"}</p>
</div>
<div className="col-md-6 mb-3">
<label className="font-extrabold">CPF:</label>

View File

@ -1,13 +1,15 @@
import React, { useState } from 'react';
// Importamos os dois novos componentes que criamos
import { useAuth } from '../components/utils/AuthProvider';
import DoctorForm from '../components/doctors/DoctorForm';
import API_KEY from '../components/utils/apiKeys';
function DoctorCadastroManager( ) {
// Este estado vai controlar qual "tela" mostrar: 'list' (lista) ou 'form' (formulário)
const { getAuthorizationHeader, isAuthenticated } = useAuth();
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
@ -16,27 +18,39 @@ function DoctorCadastroManager( ) {
const [showModal, setShowModal] = useState(false);
const [modalMsg, setModalMsg] = useState('');
// Função que será chamada para "salvar" o paciente
const handleSavePatient = (patientData) => {
console.log('Salvando médico:', patientData);
// Função que será chamada para salvar o médico no banco de dados
const handleSaveDoctor = async (doctorData) => {
const authHeader = getAuthorizationHeader();
var raw = JSON.stringify(patientData)
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("apikey", API_KEY)
myHeaders.append("Authorization", authHeader)
console.log('Salvando paciente:', doctorData);
var raw = JSON.stringify(doctorData);
console.log(doctorData, 'aqui')
var requestOptions = {
method: 'POST',
header: myHeaders,
headers: myHeaders,
body: raw,
redirect: 'follow'
};
try {
const response = await fetch("https://yuanqfswhberkoevtmfr.supabase.co/rest/v1//doctors", requestOptions);
const result = await response.json();
console.log("Médico salvo no backend:", result);
return result;
} catch (error) {
console.error("Erro ao salvar Médico:", error);
throw error;
}
fetch("https://mock.apidog.com/m1/1053378-0-default/pacientes", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
setModalMsg(`Médico "${patientData.nome}" salvo com sucesso!`);
setShowModal(true);
};
return (
@ -68,7 +82,7 @@ function DoctorCadastroManager( ) {
<div className="col-12">
<DoctorForm
onSave={handleSavePatient}
onSave={handleSaveDoctor}
onCancel={console.log('hsh')}
PatientDict={{}}
/>

View File

@ -1,6 +1,11 @@
import React, { useState, useEffect } from "react";
import API_KEY from "../components/utils/apiKeys";
import { useAuth } from "../components/utils/AuthProvider";
function TableDoctor({ setCurrentPage, setPatientID }) {
const {getAuthorizationHeader, isAuthenticated} = useAuth();
const [medicos, setMedicos] = useState([]);
const [search, setSearch] = useState("");
const [filtroAniversariante, setFiltroAniversariante] = useState(false);
@ -40,10 +45,14 @@ function TableDoctor({ setCurrentPage, setPatientID }) {
// Buscar médicos da API
useEffect(() => {
const authHeader = getAuthorizationHeader()
console.log(authHeader, 'aqui autorização')
var myHeaders = new Headers();
myHeaders.append("apikey", API_KEY);
myHeaders.append("Authorization", `${authHeader}`);
var requestOptions = {
method: 'GET',
headers: myHeaders,

View File

@ -3,32 +3,39 @@ import React from 'react'
import PatientForm from '../components/patients/PatientForm'
import {useEffect, useState} from 'react'
import { GetByID } from '../components/utils/Functions-Endpoints/Patient'
import API_KEY from '../components/utils/apiKeys'
import { useParams } from 'react-router-dom'
import { useAuth } from '../components/utils/AuthProvider'
const EditPage = ( {id, setCurrentPage}) => {
const Parametros = useParams()
const [PatientToPUT, setPatientPUT] = useState({})
var requestOptions = {
method: 'GET',
redirect: 'follow'
};
const { getAuthorizationHeader, isAuthenticated } = useAuth();
const PatientID = Parametros.id
useEffect(() => {
const authHeader = getAuthorizationHeader()
GetByID(PatientID, authHeader)
.then((data) => {
console.log(data[0], "paciente vindo da API");
setPatientPUT(data[0]); // supabase retorna array
})
.catch((err) => console.error("Erro ao buscar paciente:", err));
fetch(`https://mock.apidog.com/m1/1053378-0-default/pacientes/${id}`, requestOptions)
.then(response => response.json())
.then(result => result.data)
.then(data => setPatientPUT(data))
.catch(error => console.log('error', error));
}, [id,requestOptions])
}, [PatientID])
const HandlePutPatient = async () => {
const authHeader = getAuthorizationHeader()
var myHeaders = new Headers();
myHeaders.append("Authorization", "Bearer <token>");
myHeaders.append('apikey', API_KEY)
myHeaders.append("Authorization", authHeader);
myHeaders.append("Content-Type", "application/json");
var raw = JSON.stringify(PatientToPUT);
@ -43,10 +50,7 @@ const HandlePutPatient = async () => {
};
try {
const response = await fetch(
"https://mock.apidog.com/m1/1053378-0-default/pacientes/" + PatientToPUT.id,
requestOptions
);
const response = await fetch(`https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/patients?id=eq.${PatientID}`,requestOptions);
// se o backend retorna JSON
const result = await response.json();

View File

@ -33,7 +33,7 @@ function Inicio({ setCurrentPage }) {
fetch("https://yuanqfswhberkoevtmfr.supabase.co/auth/v1/token?grant_type=password", requestOptions)
.then(response => response.json())
.then(result => console.log(result.access_token))
.then(result => {setAuthTokens(result); console.log(result)})
.catch(error => console.log('error', error));

View File

@ -1,17 +1,23 @@
import {useState} from 'react';
import PatientForm from '../components/patients/PatientForm';
import API_KEY from '../components/utils/apiKeys';
import { useAuth } from '../components/utils/AuthProvider';
function PatientCadastroManager( {setCurrentPage} ) {
const { getAuthorizationHeader, isAuthenticated } = useAuth();
const [formData, setFormData] = useState({})
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("apikey", API_KEY)
myHeaders.append("Authorization", `Bearer eyJhbGciOiJIUzI1NiIsImtpZCI6ImJGVUlxQzNzazNjUms5RlMiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL3l1YW5xZnN3aGJlcmtvZXZ0bWZyLnN1cGFiYXNlLmNvL2F1dGgvdjEiLCJzdWIiOiJjN2ZjZDcwMi05YTZlLTRiN2MtYWJkMy05NTZiMjVhZjQwN2QiLCJhdWQiOiJhdXRoZW50aWNhdGVkIiwiZXhwIjoxNzU4OTczMTkxLCJpYXQiOjE3NTg5Njk1OTEsImVtYWlsIjoicmlzZXVwQHBvcGNvZGUuY29tLmJyIiwicGhvbmUiOiIiLCJhcHBfbWV0YWRhdGEiOnsicHJvdmlkZXIiOiJlbWFpbCIsInByb3ZpZGVycyI6WyJlbWFpbCJdfSwidXNlcl9tZXRhZGF0YSI6eyJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZnVsbF9uYW1lIjoiUmlzZVVwIFBvcGNvZGUifSwicm9sZSI6ImF1dGhlbnRpY2F0ZWQiLCJhYWwiOiJhYWwxIiwiYW1yIjpbeyJtZXRob2QiOiJwYXNzd29yZCIsInRpbWVzdGFtcCI6MTc1ODk2OTU5MX1dLCJzZXNzaW9uX2lkIjoiNzc1ZTA4NGYtM2RhNi00NjE5LWE5MmUtMDUwY2ZmMWU4NTg4IiwiaXNfYW5vbnltb3VzIjpmYWxzZX0.80loeCsbb7zsS5FYYh-KwhYi3frbBeZogXHF0rHZfLE`)
// Função que será chamada para "salvar" o paciente
const handleSavePatient = async (patientData) => {
const authHeader = getAuthorizationHeader();
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("apikey", API_KEY)
myHeaders.append("Authorization", authHeader)
console.log('Salvando paciente:', patientData);
var raw = JSON.stringify(patientData);

View File

@ -19,7 +19,7 @@ function TablePaciente({ setCurrentPage, setPatientID }) {
const [showDeleteModal, setShowDeleteModal] = useState(false);
const [selectedPatientId, setSelectedPatientId] = useState(null);
console.log(getAuthorizationHeader(), 'aqui' )
const GetAnexos = async (id) => {
var myHeaders = new Headers();
@ -73,20 +73,22 @@ function TablePaciente({ setCurrentPage, setPatientID }) {
// função de exclusão atualizada
const deletePatient = async (id) => {
const authHeader = getAuthorizationHeader()
console.log(id)
var myHeaders = new Headers();
myHeaders.append('apikey', API_KEY);
myHeaders.append("Authorization", `Bearer eyJhbGciOiJIUzI1NiIsImtpZCI6ImJGVUlxQzNzazNjUms5RlMiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL3l1YW5xZnN3aGJlcmtvZXZ0bWZyLnN1cGFiYXNlLmNvL2F1dGgvdjEiLCJzdWIiOiJjN2ZjZDcwMi05YTZlLTRiN2MtYWJkMy05NTZiMjVhZjQwN2QiLCJhdWQiOiJhdXRoZW50aWNhdGVkIiwiZXhwIjoxNzU4OTc3NTg5LCJpYXQiOjE3NTg5NzM5ODksImVtYWlsIjoicmlzZXVwQHBvcGNvZGUuY29tLmJyIiwicGhvbmUiOiIiLCJhcHBfbWV0YWRhdGEiOnsicHJvdmlkZXIiOiJlbWFpbCIsInByb3ZpZGVycyI6WyJlbWFpbCJdfSwidXNlcl9tZXRhZGF0YSI6eyJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZnVsbF9uYW1lIjoiUmlzZVVwIFBvcGNvZGUifSwicm9sZSI6ImF1dGhlbnRpY2F0ZWQiLCJhYWwiOiJhYWwxIiwiYW1yIjpbeyJtZXRob2QiOiJwYXNzd29yZCIsInRpbWVzdGFtcCI6MTc1ODk3Mzk4OX1dLCJzZXNzaW9uX2lkIjoiNGI2NzY4YTEtMmE5Yi00NjhkLWJlYjItZjhhMDQ0NjU5MGFjIiwiaXNfYW5vbnltb3VzIjpmYWxzZX0.9lV7msK_taipCOrSxeRud2a8aEo8N6wR9Wc5xFjci2A`)
myHeaders.append("Prefer", "return=minimal")
myHeaders.append("Authorization", authHeader)
var requestOptions = { method: "DELETE", redirect: "follow", headers:myHeaders };
try {
const result = await fetch(
`https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/patients/?id=eq.${id}`,
`https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/patients?id=eq.${id}`,
requestOptions
);
//setPacientes((prev) => prev.filter((p) => p.id !== id));
setPacientes((prev) => prev.filter((p) => p.id !== id));
console.log(result)
} catch (error) {
console.log("Deu problema", error);
@ -97,9 +99,14 @@ function TablePaciente({ setCurrentPage, setPatientID }) {
// Requisição inicial para buscar pacientes
useEffect(() => {
const authHeader = getAuthorizationHeader()
console.log(authHeader, 'aqui autorização')
var myHeaders = new Headers();
myHeaders.append("apikey", API_KEY);
myHeaders.append("Authorization", `Bearer eyJhbGciOiJIUzI1NiIsImtpZCI6ImJGVUlxQzNzazNjUms5RlMiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL3l1YW5xZnN3aGJlcmtvZXZ0bWZyLnN1cGFiYXNlLmNvL2F1dGgvdjEiLCJzdWIiOiJjN2ZjZDcwMi05YTZlLTRiN2MtYWJkMy05NTZiMjVhZjQwN2QiLCJhdWQiOiJhdXRoZW50aWNhdGVkIiwiZXhwIjoxNzU4OTc3NTg5LCJpYXQiOjE3NTg5NzM5ODksImVtYWlsIjoicmlzZXVwQHBvcGNvZGUuY29tLmJyIiwicGhvbmUiOiIiLCJhcHBfbWV0YWRhdGEiOnsicHJvdmlkZXIiOiJlbWFpbCIsInByb3ZpZGVycyI6WyJlbWFpbCJdfSwidXNlcl9tZXRhZGF0YSI6eyJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZnVsbF9uYW1lIjoiUmlzZVVwIFBvcGNvZGUifSwicm9sZSI6ImF1dGhlbnRpY2F0ZWQiLCJhYWwiOiJhYWwxIiwiYW1yIjpbeyJtZXRob2QiOiJwYXNzd29yZCIsInRpbWVzdGFtcCI6MTc1ODk3Mzk4OX1dLCJzZXNzaW9uX2lkIjoiNGI2NzY4YTEtMmE5Yi00NjhkLWJlYjItZjhhMDQ0NjU5MGFjIiwiaXNfYW5vbnltb3VzIjpmYWxzZX0.9lV7msK_taipCOrSxeRud2a8aEo8N6wR9Wc5xFjci2A`);
myHeaders.append("Authorization", `${authHeader}`);
var requestOptions = {
method: 'GET',
headers: myHeaders,
@ -275,6 +282,7 @@ function TablePaciente({ setCurrentPage, setPatientID }) {
</button>
</Link>
<Link to={`/pacientes/${paciente.id}/edit`}>
<button
className="btn btn-sm"
style={{
@ -288,6 +296,7 @@ function TablePaciente({ setCurrentPage, setPatientID }) {
>
<i className="bi bi-pencil me-1"></i> Editar
</button>
</Link>
{/* Botão que abre o modal */}
<button