import axios from 'axios'; import Swal from 'sweetalert2'; const baseURL = import.meta.env.VITE_API_SERVER; const instance = axios.create({ baseURL, withCredentials: true, }); // axios khusus refresh const refreshApi = axios.create({ baseURL, withCredentials: true, }); instance.interceptors.response.use( (response) => response, async (error) => { const originalRequest = error.config; console.error('🚨 Response Error Interceptor:', { status: error.response?.status, url: originalRequest.url, message: error.response?.data?.message, hasRetried: originalRequest._retry, }); if (error.response?.status === 401 && !originalRequest._retry) { originalRequest._retry = true; try { console.log('🔄 Refresh token dipanggil...'); const refreshRes = await refreshApi.post('/auth/refresh-token'); const newAccessToken = refreshRes.data.data.accessToken; localStorage.setItem('token', newAccessToken); console.log('✅ Token refreshed successfully'); // update token di header instance.defaults.headers.common['Authorization'] = `Bearer ${newAccessToken}`; originalRequest.headers['Authorization'] = `Bearer ${newAccessToken}`; console.log('🔁 Retrying original request...'); return instance(originalRequest); } catch (refreshError) { console.error( '❌ Refresh token gagal:', refreshError.response?.data || refreshError.message ); localStorage.clear(); window.location.href = '/signin'; } } return Promise.reject(error); } ); async function ApiRequest({ method = 'GET', params = {}, prefix = '/', token = true } = {}) { const isFormData = params instanceof FormData; const request = { method, url: prefix, data: params, headers: { 'Accept-Language': 'en_US', ...(isFormData ? {} : { 'Content-Type': 'application/json' }), }, }; const rawToken = localStorage.getItem('token'); if (token && rawToken) { const cleanToken = rawToken.replace(/"/g, ''); request.headers['Authorization'] = `Bearer ${cleanToken}`; console.log('🔐 Sending request with token:', cleanToken.substring(0, 20) + '...'); } else { console.warn('⚠️ No token found in localStorage'); } console.log('📤 API Request:', { method, url: prefix, hasToken: !!rawToken }); try { const response = await instance(request); console.log('✅ API Response:', { url: prefix, status: response.status, statusCode: response.data?.statusCode, }); return { ...response, error: false }; } catch (error) { const status = error?.response?.status || 500; const message = error?.response?.data?.message || error.message || 'Something Wrong'; console.error('❌ API Error:', { url: prefix, status, message, fullError: error?.response?.data, }); if (status !== 401) { await cekError(status, message); } return { ...error.response, error: true }; } } async function cekError(status, message = '') { if (status === 403) { await Swal.fire({ icon: 'warning', title: 'Forbidden', text: message, }); } else if (status >= 500) { await Swal.fire({ icon: 'error', title: 'Server Error', text: message, }); } else { await Swal.fire({ icon: 'warning', title: 'Peringatan', text: message, }); } } const SendRequest = async (queryParams) => { try { const response = await ApiRequest(queryParams); console.log('📦 SendRequest response:', { hasError: response.error, status: response.status, statusCode: response.data?.statusCode, data: response.data, }); // If ApiRequest returned error flag, return error structure if (response.error) { const errorMsg = response.data?.message || response.statusText || 'Request failed'; console.error('❌ SendRequest error response:', errorMsg); // Return consistent error structure instead of empty array return { statusCode: response.status || 500, message: errorMsg, data: null, error: true, }; } return response || { statusCode: 200, data: [], message: 'Success' }; } catch (error) { console.error('❌ SendRequest catch error:', error); // Don't show Swal here, let the calling code handle it // This allows better error handling in each API call return { statusCode: 500, message: error.message || 'Something went wrong', data: null, error: true, }; } }; export { ApiRequest, SendRequest };