templates #11

Closed
kayela wants to merge 47 commits from templates into main
2 changed files with 119 additions and 19 deletions
Showing only changes of commit 1acb13ba79 - Show all commits

View File

@@ -54,21 +54,75 @@ export const AuthProvider = ({ children }) => {
}; };
const login = async (email, password) => { const login = async (email, password) => {
const response = await axios.post(`${API_URL}/api/auth/login`, { email, password }); try {
console.log('[AuthContext] Starting login request...');
const response = await axios.post(
`${API_URL}/api/auth/login`,
{ email, password },
{
timeout: 30000, // 30 second timeout
headers: {
'Content-Type': 'application/json'
}
}
);
console.log('[AuthContext] Login response received:', {
status: response.status,
hasToken: !!response.data?.access_token,
hasUser: !!response.data?.user
});
const { access_token, user: userData } = response.data; const { access_token, user: userData } = response.data;
// Store token first
localStorage.setItem('token', access_token); localStorage.setItem('token', access_token);
console.log('[AuthContext] Token stored in localStorage');
// Update state
setToken(access_token); setToken(access_token);
setUser(userData); setUser(userData);
console.log('[AuthContext] User state updated:', {
email: userData.email,
role: userData.role
});
// Fetch user permissions (don't let this fail the login) // Fetch user permissions (don't let this fail the login)
// Use setTimeout to defer permission fetching slightly
setTimeout(async () => {
try { try {
console.log('[AuthContext] Fetching permissions...');
await fetchPermissions(access_token); await fetchPermissions(access_token);
console.log('[AuthContext] Permissions fetched successfully');
} catch (error) { } catch (error) {
console.error('Failed to fetch permissions during login, will retry later:', error); console.error('[AuthContext] Failed to fetch permissions (non-critical):', {
message: error.message,
response: error.response?.data,
status: error.response?.status
});
// Don't throw - permissions can be fetched later if needed // Don't throw - permissions can be fetched later if needed
} }
}, 100); // Small delay to ensure state is settled
return userData; return userData;
} catch (error) {
// Enhanced error logging
console.error('[AuthContext] Login failed:', {
message: error.message,
response: error.response?.data,
status: error.response?.status,
code: error.code,
config: {
url: error.config?.url,
method: error.config?.method,
timeout: error.config?.timeout
}
});
// Re-throw to let Login component handle the error
throw error;
}
}; };
const logout = () => { const logout = () => {

View File

@@ -4,14 +4,60 @@ const API_URL = process.env.REACT_APP_BACKEND_URL;
export const api = axios.create({ export const api = axios.create({
baseURL: `${API_URL}/api`, baseURL: `${API_URL}/api`,
timeout: 30000, // 30 second timeout for all requests
}); });
api.interceptors.request.use((config) => { // Request interceptor - add auth token
api.interceptors.request.use(
(config) => {
const token = localStorage.getItem('token'); const token = localStorage.getItem('token');
if (token) { if (token) {
config.headers.Authorization = `Bearer ${token}`; config.headers.Authorization = `Bearer ${token}`;
} }
return config; return config;
},
(error) => {
console.error('[API] Request error:', error);
return Promise.reject(error);
}
);
// Response interceptor - handle errors and retries
api.interceptors.response.use(
(response) => {
return response;
},
async (error) => {
const config = error.config;
// Don't retry if we've already retried or if it's a client error (4xx)
if (!config || config.__isRetry || (error.response && error.response.status < 500)) {
console.error('[API] Request failed:', {
url: config?.url,
method: config?.method,
status: error.response?.status,
message: error.message,
data: error.response?.data
});
return Promise.reject(error);
}
// Mark as retry to prevent infinite loops
config.__isRetry = true;
// Retry after 1 second for server errors or network issues
console.warn('[API] Retrying request after 1s:', {
url: config.url,
method: config.method,
error: error.message
}); });
return new Promise((resolve) => {
setTimeout(() => {
resolve(api.request(config));
}, 1000);
});
}
);
export default api; export default api;