initial commit

This commit is contained in:
2025-08-02 10:49:24 +03:00
committed by jarno
commit 99032bf03c
30 changed files with 4754 additions and 0 deletions

84
frontend/src/utils/api.js Normal file
View File

@@ -0,0 +1,84 @@
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:3000/api';
class ApiError extends Error {
constructor(message, status, data) {
super(message);
this.name = 'ApiError';
this.status = status;
this.data = data;
}
}
const handleResponse = async (response) => {
const contentType = response.headers.get('content-type');
const isJson = contentType && contentType.includes('application/json');
if (!response.ok) {
const errorData = isJson ? await response.json() : await response.text();
throw new ApiError(
errorData.message || `HTTP error! status: ${response.status}`,
response.status,
errorData
);
}
return isJson ? response.json() : response.text();
};
export const api = {
async get(endpoint, options = {}) {
const url = `${API_BASE_URL}${endpoint}`;
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
...options.headers,
},
...options,
});
return handleResponse(response);
},
async post(endpoint, data = {}, options = {}) {
const url = `${API_BASE_URL}${endpoint}`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...options.headers,
},
body: JSON.stringify(data),
...options,
});
return handleResponse(response);
},
async put(endpoint, data = {}, options = {}) {
const url = `${API_BASE_URL}${endpoint}`;
const response = await fetch(url, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
...options.headers,
},
body: JSON.stringify(data),
...options,
});
return handleResponse(response);
},
async delete(endpoint, options = {}) {
const url = `${API_BASE_URL}${endpoint}`;
const response = await fetch(url, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
...options.headers,
},
...options,
});
return handleResponse(response);
},
};
export { ApiError };