import axios from 'axios'; import { toast } from 'sonner'; 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 = null; if (typeof window !== 'undefined') { token = localStorage.getItem('accessToken'); } 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 if (status === 401 || status === 403) { localStorage.removeItem('accessToken'); localStorage.removeItem('refreshToken'); try { const { useUserStore } = require('../store/userStore'); useUserStore.getState().logout(); } catch { // Ignore if store not ready } } // Show formatted Farsi toast if not explicitly suppressed if (!error.config?.hideErrorToast) { 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;