/** * API Integration Improvements * Enhanced API client with retry logic and better error handling */ (function () { "use strict"; class EnhancedAPIClient { constructor(baseURL = "") { this.baseURL = baseURL; this.retryAttempts = 3; this.retryDelay = 1000; this.cache = new Map(); this.cacheTimeout = 5 * 60 * 1000; // 5 minutes } async requestWithRetry(endpoint, options = {}, attempt = 1) { try { const response = await fetch(this.baseURL + endpoint, { ...options, headers: { "Content-Type": "application/json", ...options.headers, }, }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } const contentType = response.headers.get("content-type"); if (contentType?.includes("application/json")) { return await response.json(); } return await response.text(); } catch (error) { // Retry logic for network errors if (attempt < this.retryAttempts && this.isRetryableError(error)) { await this.delay(this.retryDelay * attempt); return this.requestWithRetry(endpoint, options, attempt + 1); } throw error; } } isRetryableError(error) { // Retry on network errors or 5xx server errors return ( error.message.includes("Failed to fetch") || error.message.includes("NetworkError") || error.message.includes("500") || error.message.includes("502") || error.message.includes("503") ); } delay(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } getCacheKey(endpoint, params) { return endpoint + JSON.stringify(params || {}); } getFromCache(key) { const cached = this.cache.get(key); if (cached && Date.now() - cached.timestamp < this.cacheTimeout) { return cached.data; } this.cache.delete(key); return null; } setCache(key, data) { this.cache.set(key, { data, timestamp: Date.now(), }); } clearCache() { this.cache.clear(); } async get(endpoint, params = {}, useCache = true) { const cacheKey = this.getCacheKey(endpoint, params); if (useCache) { const cached = this.getFromCache(cacheKey); if (cached) return cached; } const queryString = new URLSearchParams(params).toString(); const url = queryString ? `${endpoint}?${queryString}` : endpoint; const data = await this.requestWithRetry(url, { method: "GET" }); if (useCache) { this.setCache(cacheKey, data); } return data; } async post(endpoint, body = {}) { return this.requestWithRetry(endpoint, { method: "POST", body: JSON.stringify(body), }); } async put(endpoint, body = {}) { return this.requestWithRetry(endpoint, { method: "PUT", body: JSON.stringify(body), }); } async delete(endpoint) { return this.requestWithRetry(endpoint, { method: "DELETE" }); } // Product methods with caching async getProducts(params = {}) { return this.get("/api/products", params, true); } async getProduct(id) { return this.get(`/api/products/${id}`, {}, true); } async getFeaturedProducts(limit = 4) { return this.get("/api/products/featured", { limit }, true); } // Pages methods async getPages() { return this.get("/api/pages", {}, true); } async getPage(slug) { return this.get(`/api/pages/${slug}`, {}, true); } // Menu methods async getMenu() { return this.get("/api/menu", {}, true); } } // Replace global API client if it exists if (window.API) { const oldAPI = window.API; window.API = new EnhancedAPIClient(oldAPI.baseURL || ""); } else { window.API = new EnhancedAPIClient(); } })();