File size: 4,758 Bytes
25f22bf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
import axios from 'axios'

// Create axios instance
const api = axios.create({
  baseURL: import.meta.env.VITE_API_URL || 'http://localhost:5000/api',
  headers: {
    'Content-Type': 'application/json'
  },
  // Disable caching for API requests to ensure we always get fresh data
  adapter: 'xhr', // Use XHR adapter to avoid service worker caching issues
  withCredentials: true // Send cookies with requests
})

// Add request timeout to prevent hanging requests
api.defaults.timeout = 10000 // 10 seconds timeout

// Environment-specific configuration
const isDevelopment = import.meta.env.VITE_NODE_ENV === 'development'
const isProduction = import.meta.env.VITE_NODE_ENV === 'production'

// Debug logging function for development
const logApiCall = (config) => {
  if (isDevelopment) {
    console.log(`πŸš€ [API] ${config.method?.toUpperCase()} ${config.url}`, {
      data: config.data,
      params: config.params,
      headers: config.headers
    })
  }
}

// Error logging function for development
const logApiError = (error) => {
  if (isDevelopment) {
    console.error(`❌ [API Error] ${error.config?.url || 'Unknown URL'}`, {
      status: error.response?.status,
      statusText: error.response?.statusText,
      data: error.response?.data,
      message: error.message
    })
  }
}

// Request interceptor to add auth token and logging
api.interceptors.request.use(
  (config) => {
    // Add debug logging
    logApiCall(config)
    
    const token = localStorage.getItem('token')
    if (token) {
      config.headers.Authorization = `Bearer ${token}`
    }
    return config
  },
  (error) => {
    logApiError(error)
    return Promise.reject(error)
  }
)

// Add token validation and refresh logic
api.interceptors.request.use(
  async (config) => {
    const token = localStorage.getItem('token')
    if (token) {
      try {
        // Check if token is expired
        const tokenData = JSON.parse(atob(token.split('.')[1]))
        const isExpired = tokenData.exp * 1000 < Date.now()
        
        if (isExpired) {
          // Token is expired, remove it
          localStorage.removeItem('token')
          if (isDevelopment) {
            console.log('πŸ”‘ [Token] Token expired, removed from storage')
          }
          
          // If we're not on the login page, redirect there
          if (!window.location.pathname.includes('/login')) {
            window.location.href = '/login'
          }
        } else {
          // Token is valid, add to headers
          config.headers.Authorization = `Bearer ${token}`
        }
      } catch (error) {
        // Invalid token format, remove it
        localStorage.removeItem('token')
        if (isDevelopment) {
          console.log('πŸ”‘ [Token] Invalid token format, removed from storage')
        }
        
        // If we're not on the login page, redirect there
        if (!window.location.pathname.includes('/login')) {
          window.location.href = '/login'
        }
      }
    }
    return config
  },
  (error) => {
    logApiError(error)
    return Promise.reject(error)
  }
)

// Response interceptor to handle errors and logging
api.interceptors.response.use(
  (response) => {
    if (isDevelopment) {
      console.log(`βœ… [API Response] ${response.config.url}`, {
        status: response.status,
        data: response.data
      })
    }
    return response
  },
  (error) => {
    logApiError(error)
    
    if (error.response?.status === 401) {
      // Only redirect if we're not already on the login page
      if (!window.location.pathname.includes('/login')) {
        localStorage.removeItem('token')
        window.location.href = '/login'
      }
    }
    
    // Add more detailed error handling for different status codes
    if (error.response) {
      // The request was made and the server responded with a status code
      // that falls out of the range of 2xx
      const status = error.response.status
      const data = error.response.data
      
      if (isDevelopment) {
        console.error(`🚨 [API Error ${status}]`, {
          url: error.config.url,
          method: error.config.method,
          data: data,
          headers: error.response.headers
        })
      }
    } else if (error.request) {
      // The request was made but no response was received
      if (isDevelopment) {
        console.error('🚨 [Network Error] No response received:', {
          url: error.config?.url,
          message: error.message
        })
      }
    } else {
      // Something happened in setting up the request that triggered an Error
      if (isDevelopment) {
        console.error('🚨 [Request Error]', error.message)
      }
    }
    
    return Promise.reject(error)
  }
)

export default api