/** * API Client Wrapper * Centralized API communication with auth handling */ const api = { /** * Get the auth token from localStorage */ getToken() { return localStorage.getItem('access_token'); }, /** * Set the auth token */ setToken(token) { localStorage.setItem('access_token', token); }, /** * Clear the auth token */ clearToken() { localStorage.removeItem('access_token'); }, /** * Check if user is authenticated */ isAuthenticated() { return !!this.getToken(); }, /** * Redirect to login if not authenticated */ requireAuth() { if (!this.isAuthenticated()) { window.location.href = '/login'; return false; } return true; }, /** * Make an API request */ async request(method, url, data = null) { const options = { method, headers: {} }; const token = this.getToken(); if (token) { options.headers['Authorization'] = `Bearer ${token}`; } if (data) { options.headers['Content-Type'] = 'application/json'; options.body = JSON.stringify(data); } const response = await fetch(url, options); // Handle 401 - redirect to login if (response.status === 401) { this.clearToken(); window.location.href = '/login'; return null; } return response; }, /** * GET request */ async get(url) { return this.request('GET', url); }, /** * POST request */ async post(url, data) { return this.request('POST', url, data); }, /** * PUT request */ async put(url, data) { return this.request('PUT', url, data); }, /** * PATCH request */ async patch(url, data) { return this.request('PATCH', url, data); }, /** * DELETE request */ async delete(url) { return this.request('DELETE', url); }, /** * Get current user info */ async getCurrentUser() { const response = await this.get('/api/auth/me'); if (response && response.ok) { return await response.json(); } return null; }, /** * Login */ async login(email, password) { const response = await fetch('/api/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }) }); if (response.ok) { const data = await response.json(); this.setToken(data.access_token); return { success: true }; } const error = await response.json(); return { success: false, error: error.detail || 'Login failed' }; }, /** * Register */ async register(email, password, name, officeId = null) { const response = await fetch('/api/auth/register', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password, name, office_id: officeId }) }); if (response.ok) { const data = await response.json(); this.setToken(data.access_token); return { success: true }; } const error = await response.json(); return { success: false, error: error.detail || 'Registration failed' }; }, /** * Logout */ async logout() { await this.post('/api/auth/logout', {}); this.clearToken(); window.location.href = '/login'; } }; // Make globally available window.api = api;