Problema de token expirado resolvido e modal dos erros

This commit is contained in:
joao_pedro 2025-10-21 09:14:58 -03:00
parent fe488e4dd0
commit edfe985512
4 changed files with 104 additions and 22 deletions

View File

@ -1,5 +1,5 @@
import React, { createContext, useContext, useState, useEffect } from 'react'; import React, { createContext, useContext, useState, useEffect } from 'react';
import API_KEY from './apiKeys';
// 1. Criação do Contexto // 1. Criação do Contexto
const AuthContext = createContext(null); const AuthContext = createContext(null);
@ -41,6 +41,8 @@ export function AuthProvider({ children }) {
* @param {Object} tokenResponse O objeto completo retornado pelo Supabase Auth. * @param {Object} tokenResponse O objeto completo retornado pelo Supabase Auth.
*/ */
const setAuthTokens = (tokenResponse) => { const setAuthTokens = (tokenResponse) => {
console.log("TOKEN ADICIONADO")
if (tokenResponse && tokenResponse.access_token && tokenResponse.token_type) { if (tokenResponse && tokenResponse.access_token && tokenResponse.token_type) {
// 1. Atualiza o estado do React // 1. Atualiza o estado do React
setAccessToken(tokenResponse.access_token); setAccessToken(tokenResponse.access_token);
@ -77,6 +79,29 @@ export function AuthProvider({ children }) {
// --- VALOR DO CONTEXTO --- // --- VALOR DO CONTEXTO ---
const RefreshingToken = () => {
console.log("refresh token", refreshToken)
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("apikey", API_KEY)
var raw = JSON.stringify({
"refresh_token": refreshToken
});
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
fetch(`https://yuanqfswhberkoevtmfr.supabase.co/auth/v1/token?grant_type=refresh_token`, requestOptions)
.then(response => response.json())
.then(result => setAuthTokens(result))
.catch(error => console.log('error', error));
}
const contextValue = { const contextValue = {
accessToken, accessToken,
tokenType, tokenType,
@ -85,8 +110,11 @@ export function AuthProvider({ children }) {
setAuthTokens, // Usado para CRIAR/MUDAR (Login/Refresh) setAuthTokens, // Usado para CRIAR/MUDAR (Login/Refresh)
clearAuthTokens, // Usado para MUDAR (Logout) clearAuthTokens, // Usado para MUDAR (Logout)
getAuthorizationHeader, // Usado para PEGAR (Endpoints) getAuthorizationHeader, // Usado para PEGAR (Endpoints)
RefreshingToken
}; };
return ( return (
<AuthContext.Provider value={contextValue}> <AuthContext.Provider value={contextValue}>
{children} {children}

View File

@ -1,10 +1,19 @@
import React from "react"; import React from "react";
import { useState } from "react"; import { useState, useEffect } from "react";
import { useAuth } from "../AuthProvider";
function ModalErro ({showModal, setShowModal, ErrorData}) {
const {RefreshingToken} = useAuth()
function ModalErro ({showModal, setShowModal}) { console.log("eerrroror", ErrorData)
//const [showModal, setShowModal] = useState()
useEffect(() => {
if( ErrorData.httpStatus === 401){
setShowModal(false)
RefreshingToken()
console.log('uaua')
}
}, [])
return( return(
@ -15,24 +24,21 @@ return(
<div className="modal-overlay"> <div className="modal-overlay">
<div className="modal-content"> <div className="modal-content">
<div className="modal-header"> <div className="modal-header bg-danger">
<h5 className="modal-title">Atenção</h5> <h5 className="modal-title">{`(Erro ${ErrorData.httpStatus})`}</h5>
<button
className="modal-close-btn"
>
×
</button>
</div> </div>
<div className="modal-body"> <div className="modal-body">
{ErrorData.message}
</div> </div>
<div className="modal-footer"> <div className="modal-footer">
<button <button
className="modal-confirm-btn" className="modal-confirm-btn"
onClick={setShowModal(false)} onClick={ () => setShowModal(false)}
> >
Fechar Fechar
</button> </button>

View File

@ -3,10 +3,10 @@ import { Link } from "react-router-dom";
import API_KEY from "../components/utils/apiKeys"; import API_KEY from "../components/utils/apiKeys";
import { useAuth } from "../components/utils/AuthProvider"; import { useAuth } from "../components/utils/AuthProvider";
import "./style/TablePaciente.css"; import "./style/TablePaciente.css";
import ModalErro from "../components/utils/fetchErros/ModalErro";
function TablePaciente({ setCurrentPage, setPatientID }) { function TablePaciente({ setCurrentPage, setPatientID }) {
const { getAuthorizationHeader, isAuthenticated } = useAuth(); const { getAuthorizationHeader, isAuthenticated, RefreshingToken } = useAuth();
const [pacientes, setPacientes] = useState([]); const [pacientes, setPacientes] = useState([]);
const [search, setSearch] = useState(""); const [search, setSearch] = useState("");
@ -24,6 +24,10 @@ function TablePaciente({ setCurrentPage, setPatientID }) {
const [showDeleteModal, setShowDeleteModal] = useState(false); const [showDeleteModal, setShowDeleteModal] = useState(false);
const [selectedPatientId, setSelectedPatientId] = useState(null); const [selectedPatientId, setSelectedPatientId] = useState(null);
const [showModalError, setShowModalError] = useState(false);
const [ ErrorInfo, setErrorInfo] = useState({})
const GetAnexos = async (id) => { const GetAnexos = async (id) => {
var myHeaders = new Headers(); var myHeaders = new Headers();
myHeaders.append("Authorization", "Bearer <token>"); myHeaders.append("Authorization", "Bearer <token>");
@ -114,10 +118,53 @@ function TablePaciente({ setCurrentPage, setPatientID }) {
redirect: 'follow' redirect: 'follow'
}; };
fetch("https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/patients", requestOptions) fetch("https://yuanqfswhberkoevtmfr.supabase.co/rest/v1/patients", requestOptions) // <-- Verifique se a URL está correta (patients)
.then(response => response.json()) .then(response => {
.then(result => setPacientes(result))
.catch(error => console.log('error', error)); // 1. VERIFICAÇÃO DO STATUS HTTP (Se não for 2xx)
if (!response.ok) {
// Lemos o corpo do erro JSON (PostgREST envia o JSON mesmo no 404/401)
return response.json().then(errorData => {
// 2. CRIAMOS O OBJETO DE ERRO CUSTOMIZADO COM TODOS OS DADOS NECESSÁRIOS
const errorObject = {
httpStatus: response.status, // 404, 401, 400, etc.
apiCode: errorData.code, // PGRST205, 42501, etc.
message: errorData.message || response.statusText,
details: errorData.details,
hint: errorData.hint
};
// 3. LOG (para debug)
console.error("ERRO DETALHADO:", errorObject);
// 4. FORÇAMOS A FALHA DA PROMISE LANÇANDO O OBJETO CUSTOMIZADO
// NOTA: Ao lançar um objeto customizado, ele se torna o argumento 'error' no .catch
throw errorObject;
});
}
// 3. Se a resposta for OK (2xx), processamos o JSON normalmente
return response.json();
})
.then(result => {
// 4. Bloco de SUCESSO
setPacientes(result);
console.log("Sucesso:", result);
// IMPORTANTE: Se o modal estava aberto, feche-o no sucesso
setShowModalError(false);
})
.catch(error => {
// 5. Bloco de ERRO (Captura erros de rede ou o erro lançado pelo 'throw')
//console.error('Falha na requisição:', error.message);
if(error.httpStatus === 401){
RefreshingToken()
}
setErrorInfo(error)
setShowModalError(true);
});
}, [isAuthenticated, getAuthorizationHeader]); }, [isAuthenticated, getAuthorizationHeader]);
const ehAniversariante = (dataNascimento) => { const ehAniversariante = (dataNascimento) => {
@ -199,11 +246,12 @@ function TablePaciente({ setCurrentPage, setPatientID }) {
}) : []; }) : [];
useEffect(() => { useEffect(() => {
console.log(` Pacientes totais: ${pacientes.length}, Filtrados: ${pacientesFiltrados.length}`); console.log(` Pacientes totais: ${pacientes?.length}, Filtrados: ${pacientesFiltrados?.length}`);
}, [pacientes, pacientesFiltrados, search]); }, [pacientes, pacientesFiltrados, search]);
return ( return (
<> <>
<ModalErro showModal={showModalError} setShowModal={setShowModalError} ErrorData={ErrorInfo}/>
<div className="page-heading"> <div className="page-heading">
<h3>Lista de Pacientes</h3> <h3>Lista de Pacientes</h3>
</div> </div>
@ -382,7 +430,7 @@ function TablePaciente({ setCurrentPage, setPatientID }) {
<div className="mb-3"> <div className="mb-3">
<span className="badge results-badge"> <span className="badge results-badge">
{pacientesFiltrados.length} de {pacientes.length} pacientes encontrados {pacientesFiltrados?.length} de {pacientes?.length} pacientes encontrados
</span> </span>
</div> </div>