Files
org-parking/frontend/js/api.js
Stefano Manfredi c74a0ed350 Initial commit: Parking Manager
Features:
- Manager-centric parking spot management
- Fair assignment algorithm (parking/presence ratio)
- Presence tracking calendar
- Closing days (specific & weekly recurring)
- Guarantees and exclusions
- Authelia/LLDAP integration for SSO

Stack:
- FastAPI backend
- SQLite database
- Vanilla JS frontend
- Docker deployment
2025-11-26 23:37:50 +00:00

175 lines
3.7 KiB
JavaScript

/**
* 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;