import axios from 'axios'; import { toast } from 'sonner'; import { useUserStore } from '../store/userStore'; const baseURL = process.env.NEXT_PUBLIC_API_URL || (process.env.NODE_ENV === 'development' ? 'http://localhost:4001/api' : '/api'); export interface ApiErrorPayload { success: boolean; statusCode: number; message: string; code: string; details?: Array<{ field: string; message: string }> | Record; timestamp?: string; path?: string; } const api = axios.create({ baseURL, timeout: 10000, headers: { 'Content-Type': 'application/json', }, }); // Interceptor to add auth token in request headers api.interceptors.request.use( (config) => { let token: string | null = null; if (typeof window !== 'undefined' && window.localStorage) { try { token = localStorage.getItem('accessToken'); } catch (e) { console.warn('Storage access restricted:', e); } } if (token && config.headers) { config.headers.Authorization = `Bearer ${token}`; } return config; }, (error) => Promise.reject(error) ); // Interceptor to handle 401/403 and present standardized Farsi toasts api.interceptors.response.use( (response) => response, (error) => { if (typeof window !== 'undefined') { const responseData = error.response?.data as ApiErrorPayload | undefined; const status = error.response?.status; const farsiMessage = responseData?.message || 'خطایی در ارتباط با سرور رخ داده است.'; // Handle 401 Unauthorized globally - trigger Auth Modal if (status === 401) { if (window.localStorage) { try { localStorage.removeItem('accessToken'); localStorage.removeItem('refreshToken'); } catch {} } try { useUserStore.getState().logout(); } catch { // Ignore if store not ready } } else if (status === 403) { if (window.localStorage) { try { localStorage.removeItem('accessToken'); localStorage.removeItem('refreshToken'); } catch {} } try { useUserStore.getState().logout(); } catch { // Ignore if store not ready } } // Show formatted Farsi toast if not explicitly suppressed and not 401/403/404 if (!error.config?.hideErrorToast && status !== 401 && status !== 403 && status !== 404) { if (responseData?.details && Array.isArray(responseData.details) && responseData.details.length > 0) { const firstDetailMessage = responseData.details[0]?.message || farsiMessage; toast.error(firstDetailMessage); } else { toast.error(farsiMessage); } } } return Promise.reject(error); } ); export default api;