157 lines
3.4 KiB
JavaScript
157 lines
3.4 KiB
JavaScript
class ApiService {
|
|
constructor() {
|
|
this.baseUrl = '/api';
|
|
this.token = localStorage.getItem('dashy_token');
|
|
this.subscribers = new Set();
|
|
}
|
|
|
|
subscribe(fn) {
|
|
this.subscribers.add(fn);
|
|
return () => this.subscribers.delete(fn);
|
|
}
|
|
|
|
notify() {
|
|
for (const fn of this.subscribers) fn();
|
|
}
|
|
|
|
async request(endpoint, options = {}) {
|
|
const headers = {
|
|
'Content-Type': 'application/json',
|
|
...options.headers,
|
|
};
|
|
if (this.token) {
|
|
headers['Authorization'] = `Bearer ${this.token}`;
|
|
}
|
|
|
|
const response = await fetch(`${this.baseUrl}${endpoint}`, {
|
|
...options,
|
|
headers,
|
|
});
|
|
|
|
if (!response.ok) {
|
|
if (response.status === 401) {
|
|
this.logout();
|
|
}
|
|
throw new Error(`API Error: ${response.statusText}`);
|
|
}
|
|
|
|
return response.json();
|
|
}
|
|
|
|
async login(id, password) {
|
|
const response = await fetch(`${this.baseUrl}/token`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ id, password }),
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error('Login failed');
|
|
}
|
|
|
|
const data = await response.json();
|
|
this.token = data.access_token;
|
|
localStorage.setItem('dashy_token', this.token);
|
|
this.notify();
|
|
return data;
|
|
}
|
|
|
|
logout() {
|
|
this.token = null;
|
|
localStorage.removeItem('dashy_token');
|
|
this.notify();
|
|
}
|
|
|
|
async getUsers() {
|
|
return this.request('/users');
|
|
}
|
|
|
|
async createUser(userData) {
|
|
const data = await this.request('/users', {
|
|
method: 'POST',
|
|
body: JSON.stringify(userData),
|
|
});
|
|
this.notify();
|
|
return data;
|
|
}
|
|
|
|
async updateUser(id, updates) {
|
|
const data = await this.request(`/users/${id}`, {
|
|
method: 'PATCH',
|
|
body: JSON.stringify(updates),
|
|
});
|
|
this.notify();
|
|
return data;
|
|
}
|
|
|
|
async deleteUser(id) {
|
|
const data = await this.request(`/users/${id}`, {
|
|
method: 'DELETE',
|
|
});
|
|
this.notify();
|
|
return data;
|
|
}
|
|
|
|
async changePassword(id, oldPassword, newPassword) {
|
|
const response = await fetch(`${this.baseUrl}/users/${id}/password`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
...(this.token ? { Authorization: `Bearer ${this.token}` } : {}),
|
|
},
|
|
body: JSON.stringify({ old_password: oldPassword, new_password: newPassword }),
|
|
});
|
|
if (!response.ok) {
|
|
let detail = response.statusText;
|
|
try { const j = await response.json(); if (j.detail) detail = j.detail; } catch {}
|
|
throw new Error(detail);
|
|
}
|
|
return response.json();
|
|
}
|
|
|
|
async getTasks() {
|
|
return this.request('/tasks');
|
|
}
|
|
|
|
async getAudit() {
|
|
return this.request('/audit');
|
|
}
|
|
|
|
async createTask(taskData) {
|
|
const data = await this.request('/tasks', {
|
|
method: 'POST',
|
|
body: JSON.stringify(taskData),
|
|
});
|
|
this.notify();
|
|
return data;
|
|
}
|
|
|
|
async updateTask(id, updates) {
|
|
const data = await this.request(`/tasks/${id}`, {
|
|
method: 'PATCH',
|
|
body: JSON.stringify(updates),
|
|
});
|
|
this.notify();
|
|
return data;
|
|
}
|
|
|
|
async deleteTask(id) {
|
|
const data = await this.request(`/tasks/${id}`, {
|
|
method: 'DELETE',
|
|
});
|
|
this.notify();
|
|
return data;
|
|
}
|
|
|
|
async addAudit(auditData) {
|
|
const data = await this.request('/audit', {
|
|
method: 'POST',
|
|
body: JSON.stringify(auditData),
|
|
});
|
|
this.notify();
|
|
return data;
|
|
}
|
|
}
|
|
|
|
window.api = new ApiService();
|