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:
@@ -119,7 +119,7 @@
|
||||
<a href="/checkout" class="btn-primary-full"
|
||||
>Proceed to Checkout</a
|
||||
>
|
||||
<a href="/shop" class="btn-text">Continue Shopping</a>
|
||||
<a href="/shop" class="btn-outline">Continue Shopping</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -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),
|
||||
})),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
<a href="/checkout" class="btn-primary-full"
|
||||
>Proceed to Checkout</a
|
||||
>
|
||||
<a href="/shop" class="btn-text">Continue Shopping</a>
|
||||
<a href="/shop" class="btn-outline">Continue Shopping</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -153,7 +153,7 @@
|
||||
<a href="/checkout" class="btn-primary-full"
|
||||
>Proceed to Checkout</a
|
||||
>
|
||||
<a href="/shop" class="btn-text">Continue Shopping</a>
|
||||
<a href="/shop" class="btn-outline">Continue Shopping</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -259,7 +259,9 @@
|
||||
"Fetching product from API:",
|
||||
`/api/products/${productId}`
|
||||
);
|
||||
const response = await window.apiCache.fetch(`/api/products/${productId}`);
|
||||
const response = await window.apiCache.fetch(
|
||||
`/api/products/${productId}`
|
||||
);
|
||||
const data = await response.json();
|
||||
console.log("API response:", data);
|
||||
|
||||
|
||||
@@ -684,7 +684,7 @@
|
||||
<a href="/checkout" class="btn-primary-full"
|
||||
>Proceed to Checkout</a
|
||||
>
|
||||
<a href="/shop" class="btn-text">Continue Shopping</a>
|
||||
<a href="/shop" class="btn-outline">Continue Shopping</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user