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
This commit is contained in:
174
frontend/js/api.js
Normal file
174
frontend/js/api.js
Normal file
@@ -0,0 +1,174 @@
|
||||
/**
|
||||
* 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;
|
||||
Reference in New Issue
Block a user