|
@@ -0,0 +1,72 @@
|
|
|
|
|
+const API = (() => {
|
|
|
|
|
+ function getToken() { return localStorage.getItem('token'); }
|
|
|
|
|
+ function getBaseUrl() { return (window.APP_CONFIG?.apiUrl || 'http://localhost:3000'); }
|
|
|
|
|
+
|
|
|
|
|
+ async function request(method, path, body, isFormData) {
|
|
|
|
|
+ const url = getBaseUrl() + path;
|
|
|
|
|
+ const headers = {};
|
|
|
|
|
+ const token = getToken();
|
|
|
|
|
+ if (token) headers['Authorization'] = 'Bearer ' + token;
|
|
|
|
|
+ if (!isFormData && body) headers['Content-Type'] = 'application/json';
|
|
|
|
|
+
|
|
|
|
|
+ const opts = { method, headers };
|
|
|
|
|
+ if (body) {
|
|
|
|
|
+ opts.body = isFormData ? body : JSON.stringify(body);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const res = await fetch(url, opts);
|
|
|
|
|
+ if (res.status === 401) {
|
|
|
|
|
+ localStorage.removeItem('token');
|
|
|
|
|
+ window.location.reload();
|
|
|
|
|
+ throw new Error('Unauthorized');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const data = await res.json().catch(() => ({}));
|
|
|
|
|
+ if (!res.ok) throw new Error(data.error || 'Request failed');
|
|
|
|
|
+ return data;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return {
|
|
|
|
|
+ // Auth
|
|
|
|
|
+ login: (login, password) => request('POST', '/api/auth/login', { login, password }),
|
|
|
|
|
+ register: (login, email, password) => request('POST', '/api/auth/register', { login, email, password }),
|
|
|
|
|
+ me: () => request('GET', '/api/auth/me'),
|
|
|
|
|
+
|
|
|
|
|
+ // Directories
|
|
|
|
|
+ getDirs: () => request('GET', '/api/directories'),
|
|
|
|
|
+ getDir: (id) => request('GET', `/api/directories/${id}`),
|
|
|
|
|
+ createDir: (name, parentId) => request('POST', '/api/directories', { name, parentId }),
|
|
|
|
|
+ renameDir: (id, name) => request('PUT', `/api/directories/${id}`, { name }),
|
|
|
|
|
+ deleteDir: (id) => request('DELETE', `/api/directories/${id}`),
|
|
|
|
|
+
|
|
|
|
|
+ // Tracks
|
|
|
|
|
+ getTracks: (directoryId) => request('GET', '/api/tracks' + (directoryId !== undefined ? `?directoryId=${directoryId || ''}` : '')),
|
|
|
|
|
+ getTrack: (id) => request('GET', `/api/tracks/${id}`),
|
|
|
|
|
+ getTrackPoints: (id) => request('GET', `/api/tracks/${id}/points`),
|
|
|
|
|
+ uploadTrack: (file, directoryId, name) => {
|
|
|
|
|
+ const fd = new FormData();
|
|
|
|
|
+ fd.append('file', file);
|
|
|
|
|
+ if (directoryId) fd.append('directoryId', directoryId);
|
|
|
|
|
+ if (name) fd.append('name', name);
|
|
|
|
|
+ return request('POST', '/api/tracks/upload', fd, true);
|
|
|
|
|
+ },
|
|
|
|
|
+ updateTrack: (id, data) => request('PUT', `/api/tracks/${id}`, data),
|
|
|
|
|
+ deleteTrack: (id) => request('DELETE', `/api/tracks/${id}`),
|
|
|
|
|
+ createShare: (id) => request('POST', `/api/tracks/${id}/share`),
|
|
|
|
|
+ deleteShare: (id) => request('DELETE', `/api/tracks/${id}/share`),
|
|
|
|
|
+
|
|
|
|
|
+ // Share (public)
|
|
|
|
|
+ getShared: (code) => request('GET', `/api/share/${code}`),
|
|
|
|
|
+
|
|
|
|
|
+ // Stats
|
|
|
|
|
+ getStats: () => request('GET', '/api/stats'),
|
|
|
|
|
+ getDirStats: (id) => request('GET', `/api/stats/directory/${id}`),
|
|
|
|
|
+
|
|
|
|
|
+ // Admin
|
|
|
|
|
+ adminGetUsers: () => request('GET', '/api/admin/users'),
|
|
|
|
|
+ adminActivate: (id, isActive) => request('PUT', `/api/admin/users/${id}/activate`, { isActive }),
|
|
|
|
|
+ adminSetAdmin: (id, isAdmin) => request('PUT', `/api/admin/users/${id}/admin`, { isAdmin }),
|
|
|
|
|
+ adminDeleteUser: (id) => request('DELETE', `/api/admin/users/${id}`),
|
|
|
|
|
+ adminGetUserTracks: (id) => request('GET', `/api/admin/users/${id}/tracks`),
|
|
|
|
|
+ };
|
|
|
|
|
+})();
|