- Standardize script loading on faq, privacy, returns, shipping-info pages - Archive 14 unused JS files (cart-functions, shopping, cart.js, enhanced versions, etc.) - Archive 2 unused CSS files (responsive-enhanced, responsive-fixes) - All pages now use consistent script loading order - Eliminated shopping.js dependency (not needed after standardization)
161 lines
4.0 KiB
JavaScript
161 lines
4.0 KiB
JavaScript
/**
|
|
* 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();
|
|
}
|
|
})();
|