diff --git a/src/components/Global/ApiRequest.jsx b/src/components/Global/ApiRequest.jsx index c0f8c67..ad37baa 100644 --- a/src/components/Global/ApiRequest.jsx +++ b/src/components/Global/ApiRequest.jsx @@ -1,19 +1,54 @@ import axios from "axios"; import Swal from "sweetalert2"; +const baseURL = import.meta.env.VITE_API_SERVER; + +const instance = axios.create({ + baseURL, + withCredentials: true, +}); + +instance.interceptors.response.use( + (response) => response, + async (error) => { + const originalRequest = error.config; + + if (error.response?.status === 401 && !originalRequest._retry) { + originalRequest._retry = true; + + try { + const refreshRes = await axios.post( + `${baseURL}/auth/refresh`, + {}, + { withCredentials: true } + ); + + const newAccessToken = refreshRes.data.accessToken; + localStorage.setItem("token", newAccessToken); + + instance.defaults.headers.common["Authorization"] = `Bearer ${newAccessToken}`; + originalRequest.headers["Authorization"] = `Bearer ${newAccessToken}`; + + return instance(originalRequest); + } catch (refreshError) { + console.error("Refresh token gagal:", refreshError); + localStorage.clear(); + window.location.href = "/signin"; + } + } + + return Promise.reject(error); + } +); + async function ApiRequest({ method = "GET", params = {}, - url = "", prefix = "/", token = true, } = {}) { - const baseURL = url || import.meta.env.VITE_API_SERVER; - const instance = axios.create({ baseURL }); - const isFormData = params instanceof FormData; - // request config const request = { method, url: prefix, @@ -25,20 +60,10 @@ async function ApiRequest({ withCredentials: true, }; - // handle download (doc) - if (params === "doc") { - request.responseType = "blob"; - } - - // ambil token - const rawToken = - sessionStorage.getItem("token_redirect") || localStorage.getItem("token"); + const rawToken = localStorage.getItem("token"); if (token && rawToken) { - const cleanToken = rawToken.replace(/"/g, ""); - instance.defaults.headers.common[ - "Authorization" - ] = `Bearer ${cleanToken}`; + request.headers["Authorization"] = `Bearer ${rawToken.replace(/"/g, "")}`; } try { @@ -46,31 +71,27 @@ async function ApiRequest({ return { ...response, error: false }; } catch (error) { const status = error?.response?.status || 500; - const message = - error?.response?.data?.message || error.message || "Something Wrong"; + const message = error?.response?.data?.message || error.message || "Something Wrong"; - cekError(status, message); + await cekError(status, message); return { ...error.response, error: true }; } } -// global error handler +// =============================== +// Global error handler +// =============================== async function cekError(status, message = "") { - console.log("status code", status); - if (status === 401) { - Swal.fire({ + await Swal.fire({ icon: "warning", title: "Peringatan", text: `${message}, Silahkan login`, - }).then((result) => { - if (result.isConfirmed) { - localStorage.clear(); - location.replace("/signin"); - } }); + localStorage.clear(); + window.location.href = "/signin"; } else { - Swal.fire({ + await Swal.fire({ icon: "warning", title: "Peringatan", text: message, @@ -78,14 +99,16 @@ async function cekError(status, message = "") { } } -// wrapper biar frontend lebih simple +// =============================== +// Wrapper simpler +// =============================== const SendRequest = async (queryParams) => { try { const response = await ApiRequest(queryParams); return response?.data || []; } catch (error) { console.error("Request error:", error); - Swal.fire({ icon: "error", text: error.message || "Something went wrong" }); + await Swal.fire({ icon: "error", text: error.message || "Something went wrong" }); return []; } };