Style: Unify cart Continue Shopping button with wishlist style

Updated cart dropdown Continue Shopping buttons to use btn-outline
class (matching wishlist style) instead of btn-text across all pages.

Changes:
- shop.html: btn-text → btn-outline
- contact.html: btn-text → btn-outline
- product.html: btn-text → btn-outline
- about.html: btn-text → btn-outline

All cart Continue Shopping buttons now have consistent styling
with the wishlist Continue Shopping button (purple outline style).
This commit is contained in:
Local Server
2026-01-14 20:47:32 -06:00
parent a888d70174
commit f818fff3a5
7 changed files with 114 additions and 46 deletions

View File

@@ -11,28 +11,28 @@ class APICache {
this.cache = new Map();
this.pendingRequests = new Map();
this.defaultTTL = 5 * 60 * 1000; // 5 minutes default
// Custom TTL for different endpoints
this.ttlConfig = {
'/api/products': 5 * 60 * 1000, // 5 min
'/api/products/featured': 10 * 60 * 1000, // 10 min
'/api/categories': 30 * 60 * 1000, // 30 min
'/api/portfolio/projects': 10 * 60 * 1000, // 10 min
'/api/blog/posts': 5 * 60 * 1000, // 5 min
'/api/pages': 10 * 60 * 1000, // 10 min
"/api/products": 5 * 60 * 1000, // 5 min
"/api/products/featured": 10 * 60 * 1000, // 10 min
"/api/categories": 30 * 60 * 1000, // 30 min
"/api/portfolio/projects": 10 * 60 * 1000, // 10 min
"/api/blog/posts": 5 * 60 * 1000, // 5 min
"/api/pages": 10 * 60 * 1000, // 10 min
};
// Start periodic cleanup
this.startCleanup();
}
/**
* Get cache key from URL
*/
getCacheKey(url) {
return url;
}
/**
* Get TTL for specific endpoint
*/
@@ -45,46 +45,46 @@ class APICache {
}
return this.defaultTTL;
}
/**
* Check if cache entry is valid
*/
isValid(entry) {
return entry && Date.now() - entry.timestamp < entry.ttl;
}
/**
* Get from cache
*/
get(url) {
const key = this.getCacheKey(url);
const entry = this.cache.get(key);
if (this.isValid(entry)) {
console.log(`[Cache] HIT: ${url}`);
return entry.data;
}
console.log(`[Cache] MISS: ${url}`);
return null;
}
/**
* Set cache entry
*/
set(url, data) {
const key = this.getCacheKey(url);
const ttl = this.getTTL(url);
this.cache.set(key, {
data,
timestamp: Date.now(),
ttl
ttl,
});
console.log(`[Cache] SET: ${url} (TTL: ${ttl}ms)`);
}
/**
* Clear specific cache entry
*/
@@ -93,24 +93,24 @@ class APICache {
this.cache.delete(key);
console.log(`[Cache] CLEAR: ${url}`);
}
/**
* Clear all cache
*/
clearAll() {
this.cache.clear();
console.log('[Cache] CLEARED ALL');
console.log("[Cache] CLEARED ALL");
}
/**
* Fetch with caching and deduplication
*/
async fetch(url, options = {}) {
// Only cache GET requests
if (options.method && options.method !== 'GET') {
if (options.method && options.method !== "GET") {
return fetch(url, options);
}
// Check cache first
const cached = this.get(url);
if (cached) {
@@ -118,51 +118,51 @@ class APICache {
json: async () => cached,
ok: true,
status: 200,
fromCache: true
fromCache: true,
};
}
// Check if request is already pending
if (this.pendingRequests.has(url)) {
console.log(`[Cache] DEDUP: ${url} - Waiting for pending request`);
return this.pendingRequests.get(url);
}
// Make new request
console.log(`[Cache] FETCH: ${url}`);
const requestPromise = fetch(url, options)
.then(async response => {
.then(async (response) => {
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const data = await response.json();
// Cache successful response
this.set(url, data);
// Remove from pending
this.pendingRequests.delete(url);
return {
json: async () => data,
ok: true,
status: response.status,
fromCache: false
fromCache: false,
};
})
.catch(error => {
.catch((error) => {
// Remove from pending on error
this.pendingRequests.delete(url);
throw error;
});
// Store as pending
this.pendingRequests.set(url, requestPromise);
return requestPromise;
}
/**
* Periodic cleanup of expired entries
*/
@@ -180,7 +180,7 @@ class APICache {
}
}, 60000); // Run every minute
}
/**
* Get cache statistics
*/
@@ -192,8 +192,8 @@ class APICache {
url: key,
age: Date.now() - entry.timestamp,
ttl: entry.ttl,
valid: this.isValid(entry)
}))
valid: this.isValid(entry),
})),
};
}
}