From 436667893598955855f1a03f9e727b1a9cb6fffb Mon Sep 17 00:00:00 2001 From: ryan Date: Thu, 19 Jun 2025 14:45:59 +0300 Subject: [PATCH] feat(api): implement ApiClient class with CRUD operations and error handling --- src/lib/api-client.ts | 115 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 src/lib/api-client.ts diff --git a/src/lib/api-client.ts b/src/lib/api-client.ts new file mode 100644 index 0000000..057bd17 --- /dev/null +++ b/src/lib/api-client.ts @@ -0,0 +1,115 @@ +// Client-side API functions +import { Item } from '@/types/database'; +import { API_ENDPOINTS, ErrorResponse } from '@/types/api'; + +// API Client class +export class ApiClient { + private baseUrl: string; + + constructor(baseUrl: string = '') { + this.baseUrl = baseUrl; + } + + // Helper method for making requests with error handling + private async makeRequest( + url: string, + options: RequestInit = {} + ): Promise { + const fullUrl = `${this.baseUrl}${url}`; + console.log('[API CLIENT] Making request to:', fullUrl); + + try { + const response = await fetch(fullUrl, { + headers: { + 'Content-Type': 'application/json', + ...options.headers, + }, + ...options, + }); + + if (!response.ok) { + const errorData: ErrorResponse = await response.json().catch(() => ({ + error: `HTTP ${response.status}: ${response.statusText}`, + })); + + console.error('[API CLIENT] Request failed:', errorData); + throw new Error(errorData.error || `Request failed with status ${response.status}`); + } + + const data = await response.json(); + console.log('[API CLIENT] Request successful'); + return data; + } catch (error) { + console.error('[API CLIENT] Network error:', error); + throw error; + } + } + + // Get items by URL + async getItemsByUrl(url: string): Promise { + console.log('[API CLIENT] Fetching items for URL:', url); + const encodedUrl = encodeURIComponent(url); + return this.makeRequest(API_ENDPOINTS.ITEMS(encodedUrl)); + } + + // Create/update item + async saveItem(url: string, item: Item): Promise { + console.log('[API CLIENT] Saving item - ID:', item.id, 'Name:', item.name); + const encodedUrl = encodeURIComponent(url); + + return this.makeRequest(API_ENDPOINTS.ITEMS(encodedUrl), { + method: 'POST', + body: JSON.stringify(item), + }); + } + + // Delete item + async deleteItem(url: string, itemId: string): Promise { + console.log('[API CLIENT] Deleting item:', itemId, 'from URL:', url); + const encodedUrl = encodeURIComponent(url); + + await this.makeRequest(API_ENDPOINTS.ITEM(encodedUrl, itemId), { + method: 'DELETE', + }); + } + + // Get selected properties + async getSelectedProperties(url: string): Promise { + console.log('[API CLIENT] Fetching properties for URL:', url); + const encodedUrl = encodeURIComponent(url); + return this.makeRequest(API_ENDPOINTS.PROPERTIES(encodedUrl)); + } + + // Add selected property + async addProperty(url: string, property: string): Promise { + console.log('[API CLIENT] Adding property:', property, 'to URL:', url); + const encodedUrl = encodeURIComponent(url); + + await this.makeRequest(API_ENDPOINTS.PROPERTIES(encodedUrl), { + method: 'POST', + body: JSON.stringify(property), + }); + } + + // Delete property + async deleteProperty(url: string, property: string): Promise { + console.log('[API CLIENT] Deleting property:', property, 'from URL:', url); + const encodedUrl = encodeURIComponent(url); + const encodedProperty = encodeURIComponent(property); + + await this.makeRequest(API_ENDPOINTS.PROPERTY(encodedUrl, encodedProperty), { + method: 'DELETE', + }); + } +} + +// Default API client instance +export const apiClient = new ApiClient(); + +// Individual functions (for backward compatibility) +export const loadItemsFromDb = (url: string) => apiClient.getItemsByUrl(url); +export const saveItemToDb = (url: string, item: Item) => apiClient.saveItem(url, item); +export const deleteItemFromDb = (url: string, itemId: string) => apiClient.deleteItem(url, itemId); +export const getSelectedPropertiesFromDb = (url: string) => apiClient.getSelectedProperties(url); +export const addPropertyToDb = (url: string, property: string) => apiClient.addProperty(url, property); +export const deletePropertyFromDb = (url: string, property: string) => apiClient.deleteProperty(url, property); \ No newline at end of file