Initial Claude Run
This commit is contained in:
177
frontend/src/services/api.js
Normal file
177
frontend/src/services/api.js
Normal file
@@ -0,0 +1,177 @@
|
||||
import axios from 'axios';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
// Base API configuration
|
||||
const API_BASE_URL = process.env.REACT_APP_API_URL || 'http://localhost:5000/api';
|
||||
|
||||
// Create axios instance
|
||||
const apiClient = axios.create({
|
||||
baseURL: API_BASE_URL,
|
||||
timeout: 10000,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
// Request interceptor to add auth token
|
||||
apiClient.interceptors.request.use(
|
||||
(config) => {
|
||||
const token = localStorage.getItem('authToken');
|
||||
if (token) {
|
||||
config.headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
return config;
|
||||
},
|
||||
(error) => {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
// Response interceptor for error handling
|
||||
apiClient.interceptors.response.use(
|
||||
(response) => response,
|
||||
(error) => {
|
||||
// Handle specific error codes
|
||||
if (error.response?.status === 401) {
|
||||
// Unauthorized - clear token and redirect to login
|
||||
localStorage.removeItem('authToken');
|
||||
window.location.href = '/login';
|
||||
} else if (error.response?.status === 403) {
|
||||
// Forbidden
|
||||
toast.error('You do not have permission to perform this action');
|
||||
} else if (error.response?.status >= 500) {
|
||||
// Server error
|
||||
toast.error('Server error. Please try again later.');
|
||||
} else if (error.code === 'ECONNABORTED') {
|
||||
// Timeout
|
||||
toast.error('Request timeout. Please check your connection.');
|
||||
} else if (!error.response) {
|
||||
// Network error
|
||||
toast.error('Network error. Please check your connection.');
|
||||
}
|
||||
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
// Auth API endpoints
|
||||
export const authAPI = {
|
||||
login: (credentials) => apiClient.post('/auth/login', credentials),
|
||||
register: (userData) => apiClient.post('/auth/register', userData),
|
||||
getCurrentUser: () => apiClient.get('/auth/me'),
|
||||
changePassword: (passwordData) => apiClient.post('/auth/change-password', passwordData),
|
||||
forgotPassword: (email) => apiClient.post('/auth/forgot-password', { email }),
|
||||
};
|
||||
|
||||
// Users API endpoints
|
||||
export const usersAPI = {
|
||||
getProfile: () => apiClient.get('/users/profile'),
|
||||
updateProfile: (userData) => apiClient.put('/users/profile', userData),
|
||||
deleteAccount: () => apiClient.delete('/users/account'),
|
||||
getStats: () => apiClient.get('/users/stats'),
|
||||
};
|
||||
|
||||
// Properties API endpoints
|
||||
export const propertiesAPI = {
|
||||
getAll: () => apiClient.get('/properties'),
|
||||
getById: (id) => apiClient.get(`/properties/${id}`),
|
||||
create: (propertyData) => apiClient.post('/properties', propertyData),
|
||||
update: (id, propertyData) => apiClient.put(`/properties/${id}`, propertyData),
|
||||
delete: (id) => apiClient.delete(`/properties/${id}`),
|
||||
|
||||
// Lawn sections
|
||||
createSection: (propertyId, sectionData) =>
|
||||
apiClient.post(`/properties/${propertyId}/sections`, sectionData),
|
||||
updateSection: (propertyId, sectionId, sectionData) =>
|
||||
apiClient.put(`/properties/${propertyId}/sections/${sectionId}`, sectionData),
|
||||
deleteSection: (propertyId, sectionId) =>
|
||||
apiClient.delete(`/properties/${propertyId}/sections/${sectionId}`),
|
||||
};
|
||||
|
||||
// Equipment API endpoints
|
||||
export const equipmentAPI = {
|
||||
getAll: () => apiClient.get('/equipment'),
|
||||
getById: (id) => apiClient.get(`/equipment/${id}`),
|
||||
create: (equipmentData) => apiClient.post('/equipment', equipmentData),
|
||||
update: (id, equipmentData) => apiClient.put(`/equipment/${id}`, equipmentData),
|
||||
delete: (id) => apiClient.delete(`/equipment/${id}`),
|
||||
getTypes: () => apiClient.get('/equipment/types'),
|
||||
getCalculations: (id, params) => apiClient.get(`/equipment/${id}/calculations`, { params }),
|
||||
};
|
||||
|
||||
// Products API endpoints
|
||||
export const productsAPI = {
|
||||
getAll: (params) => apiClient.get('/products', { params }),
|
||||
getById: (id) => apiClient.get(`/products/${id}`),
|
||||
search: (params) => apiClient.get('/products/search', { params }),
|
||||
getCategories: () => apiClient.get('/products/categories'),
|
||||
|
||||
// User products
|
||||
getUserProducts: () => apiClient.get('/products/user'),
|
||||
createUserProduct: (productData) => apiClient.post('/products/user', productData),
|
||||
getUserProduct: (id) => apiClient.get(`/products/user/${id}`),
|
||||
updateUserProduct: (id, productData) => apiClient.put(`/products/user/${id}`, productData),
|
||||
deleteUserProduct: (id) => apiClient.delete(`/products/user/${id}`),
|
||||
};
|
||||
|
||||
// Applications API endpoints
|
||||
export const applicationsAPI = {
|
||||
// Plans
|
||||
getPlans: (params) => apiClient.get('/applications/plans', { params }),
|
||||
getPlan: (id) => apiClient.get(`/applications/plans/${id}`),
|
||||
createPlan: (planData) => apiClient.post('/applications/plans', planData),
|
||||
updatePlanStatus: (id, status) => apiClient.put(`/applications/plans/${id}/status`, { status }),
|
||||
|
||||
// Logs
|
||||
getLogs: (params) => apiClient.get('/applications/logs', { params }),
|
||||
createLog: (logData) => apiClient.post('/applications/logs', logData),
|
||||
|
||||
// Stats
|
||||
getStats: (params) => apiClient.get('/applications/stats', { params }),
|
||||
};
|
||||
|
||||
// Weather API endpoints
|
||||
export const weatherAPI = {
|
||||
getCurrent: (propertyId) => apiClient.get(`/weather/${propertyId}`),
|
||||
getForecast: (propertyId) => apiClient.get(`/weather/${propertyId}/forecast`),
|
||||
getHistory: (propertyId, params) => apiClient.get(`/weather/${propertyId}/history`, { params }),
|
||||
checkSuitability: (propertyId, params) =>
|
||||
apiClient.get(`/weather/conditions/suitable/${propertyId}`, { params }),
|
||||
};
|
||||
|
||||
// Admin API endpoints
|
||||
export const adminAPI = {
|
||||
getDashboard: () => apiClient.get('/admin/dashboard'),
|
||||
|
||||
// Users management
|
||||
getUsers: (params) => apiClient.get('/admin/users', { params }),
|
||||
updateUserRole: (id, role) => apiClient.put(`/admin/users/${id}/role`, { role }),
|
||||
deleteUser: (id) => apiClient.delete(`/admin/users/${id}`),
|
||||
|
||||
// Products management
|
||||
getProducts: (params) => apiClient.get('/admin/products', { params }),
|
||||
createProduct: (productData) => apiClient.post('/admin/products', productData),
|
||||
updateProduct: (id, productData) => apiClient.put(`/admin/products/${id}`, productData),
|
||||
deleteProduct: (id) => apiClient.delete(`/admin/products/${id}`),
|
||||
|
||||
// System health
|
||||
getSystemHealth: () => apiClient.get('/admin/system/health'),
|
||||
};
|
||||
|
||||
// Utility functions
|
||||
export const handleApiError = (error, defaultMessage = 'An error occurred') => {
|
||||
if (error.response?.data?.message) {
|
||||
return error.response.data.message;
|
||||
}
|
||||
if (error.message) {
|
||||
return error.message;
|
||||
}
|
||||
return defaultMessage;
|
||||
};
|
||||
|
||||
export const formatApiResponse = (response) => {
|
||||
return response.data;
|
||||
};
|
||||
|
||||
// Export the configured axios instance for custom requests
|
||||
export default apiClient;
|
||||
Reference in New Issue
Block a user