Files
Ecobuddy/public/js/apiClient.js
boris 78508a7cbd erm
Signed-off-by: boris <boris@borishub.co.uk>
2025-04-20 16:49:23 +01:00

266 lines
8.5 KiB
JavaScript

/**
* API Client for making authenticated requests to the server
*
* This class provides a wrapper around the Fetch API to handle
* authentication and common request patterns.
*
* The client uses JWT tokens for authentication, which are automatically
* included in requests via the fetchAuth function provided by the simpleAuth service.
*
* NOTE: For authentication (login, logout, token validation), please use the simpleAuth
* service directly instead of this API client.
*/
class ApiClient {
/**
* Constructor
*
* Initialises the API client and sets up the authenticated fetch function.
* Relies on the simpleAuth service being available in the global scope.
*/
constructor() {
// Ensure auth service is available
if (!simpleAuth) {
console.error('Auth service not available');
}
// Use the fetchAuth method from simpleAuth
this.authFetch = async (url, options = {}) => {
try {
// For unauthenticated requests or when authentication is not required
if (!options.requireAuth || !simpleAuth.isAuthenticated()) {
return fetch(url, options);
}
// For authenticated requests
delete options.requireAuth; // Remove the custom property
return simpleAuth.fetchAuth(url, options);
} catch (error) {
console.error('Error in authFetch:', error);
throw error;
}
};
}
/**
* Makes a GET request to the API
*
* This method handles GET requests with query parameters.
* It automatically converts the params object to a query string
* and handles error responses.
*
* @param {string} endpoint - The API endpoint
* @param {Object} params - Query parameters
* @returns {Promise<Object>} The response data
*/
async get(endpoint, params = {}) {
// Build query string
const queryString = Object.keys(params).length > 0
? '?' + new URLSearchParams(params).toString()
: '';
try {
const response = await this.authFetch(`${endpoint}${queryString}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error(`GET request to ${endpoint} failed:`, error);
throw error;
}
}
/**
* Makes a POST request to the API
*
* This method handles POST requests with either JSON data or FormData.
* It automatically sets the appropriate headers and handles error responses.
*
* @param {string} endpoint - The API endpoint
* @param {Object|FormData} data - The data to send
* @returns {Promise<Object>} The response data
*/
async post(endpoint, data = {}) {
try {
// Prepare request options
const options = {
method: 'POST'
};
// Handle FormData or JSON
if (data instanceof FormData) {
options.body = data;
} else {
options.headers = {
'Content-Type': 'application/json'
};
options.body = JSON.stringify(data);
}
const response = await this.authFetch(endpoint, options);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error(`POST request to ${endpoint} failed:`, error);
throw error;
}
}
/**
* Makes a facility-related API request
*
* This is a helper method that simplifies making requests to the facility controller.
* It automatically creates a FormData object with the action and data parameters.
*
* @param {string} action - The action to perform
* @param {Object} data - The data to send
* @returns {Promise<Object>} The response data
*/
async facility(action, data = {}) {
// Create FormData
const formData = new FormData();
formData.append('action', action);
// Add all data to FormData
Object.entries(data).forEach(([key, value]) => {
formData.append(key, value);
});
try {
// Use authenticated fetch for all facility requests
const response = await this.authFetch('/facilitycontroller.php', {
method: 'POST',
body: formData,
requireAuth: true // Explicitly require authentication
});
// Check if response is ok
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
// Parse the JSON response
const jsonData = await response.json();
console.log('Facility API response:', { action, data: jsonData });
return jsonData;
} catch (error) {
console.error('Facility API error:', error);
throw error;
}
}
/**
* Creates a new facility
*
* This method sends a request to create a new facility with the provided data.
*
* @param {Object} facilityData - The facility data
* @returns {Promise<Object>} The response data
*/
async createFacility(facilityData) {
return this.facility('create', facilityData);
}
/**
* Updates a facility
*
* This method sends a request to update an existing facility with the provided data.
*
* @param {Object} facilityData - The facility data
* @returns {Promise<Object>} The response data
*/
async updateFacility(facilityData) {
return this.facility('update', facilityData);
}
/**
* Deletes a facility
*
* This method sends a request to delete a facility with the specified ID.
*
* @param {number|string} id - The facility ID
* @returns {Promise<Object>} The response data
*/
async deleteFacility(id) {
return this.facility('delete', { id });
}
/**
* Gets a facility by ID
*
* This method retrieves a single facility with the specified ID.
*
* @param {number|string} id - The facility ID
* @returns {Promise<Object>} The response data
*/
async getFacility(id) {
return this.facility('read', { id });
}
/**
* Gets statuses for a facility
*
* This method retrieves all status updates for a facility with the specified ID.
*
* @param {number|string} facilityId - The facility ID
* @returns {Promise<Object>} The response data
*/
async getFacilityStatuses(facilityId) {
return this.facility('getStatuses', { facilityId });
}
/**
* Adds a status to a facility
*
* This method adds a new status update to a facility.
*
* @param {number|string} facilityId - The facility ID
* @param {string} statusComment - The status comment
* @returns {Promise<Object>} The response data
*/
async addFacilityStatus(facilityId, statusComment) {
return this.facility('status', {
facilityId: facilityId,
statusComment: statusComment
});
}
/**
* Updates a facility status
*
* This method updates an existing status for a facility.
*
* @param {number|string} statusId - The status ID
* @param {string} editStatus - The updated status comment
* @param {number|string} facilityId - The facility ID
* @returns {Promise<Object>} The response data
*/
async updateFacilityStatus(statusId, editStatus, facilityId) {
return this.facility('editStatus', { statusId, editStatus, facilityId });
}
/**
* Deletes a facility status
*
* This method deletes a status update from a facility.
*
* @param {number|string} statusId - The status ID
* @param {number|string} facilityId - The facility ID
* @returns {Promise<Object>} The response data
*/
async deleteFacilityStatus(statusId, facilityId) {
return this.facility('deleteStatus', { statusId, facilityId });
}
}
// Initialize API client
const api = new ApiClient();
// Export API client
window.api = api;