oh
This commit is contained in:
@@ -47,6 +47,96 @@ export interface CustomerResponse {
|
||||
success?: boolean;
|
||||
}
|
||||
|
||||
// Add cache invalidation and order refresh utilities
|
||||
interface CacheEntry {
|
||||
data: any;
|
||||
timestamp: number;
|
||||
ttl: number; // Time to live in milliseconds
|
||||
}
|
||||
|
||||
class ApiCache {
|
||||
private cache = new Map<string, CacheEntry>();
|
||||
private orderRefreshCallbacks = new Set<() => void>();
|
||||
|
||||
get(key: string): any | null {
|
||||
const entry = this.cache.get(key);
|
||||
if (!entry) return null;
|
||||
|
||||
if (Date.now() - entry.timestamp > entry.ttl) {
|
||||
this.cache.delete(key);
|
||||
return null;
|
||||
}
|
||||
|
||||
return entry.data;
|
||||
}
|
||||
|
||||
set(key: string, data: any, ttl: number = 60000): void { // Default 1 minute TTL
|
||||
this.cache.set(key, {
|
||||
data,
|
||||
timestamp: Date.now(),
|
||||
ttl
|
||||
});
|
||||
}
|
||||
|
||||
invalidate(pattern?: string): void {
|
||||
if (pattern) {
|
||||
// Remove entries matching pattern
|
||||
for (const [key] of this.cache) {
|
||||
if (key.includes(pattern)) {
|
||||
this.cache.delete(key);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Clear all cache
|
||||
this.cache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// Order-specific cache invalidation
|
||||
invalidateOrderData(orderId?: string): void {
|
||||
if (orderId) {
|
||||
this.invalidate(`orders/${orderId}`);
|
||||
this.invalidate(`orders?`); // Invalidate order lists
|
||||
} else {
|
||||
this.invalidate('orders');
|
||||
}
|
||||
|
||||
// Show a subtle notification when data is refreshed
|
||||
if (typeof window !== 'undefined') {
|
||||
console.log('🔄 Order data cache invalidated, refreshing components...');
|
||||
}
|
||||
|
||||
// Trigger order refresh callbacks
|
||||
this.orderRefreshCallbacks.forEach(callback => {
|
||||
try {
|
||||
callback();
|
||||
} catch (error) {
|
||||
console.error('Error in order refresh callback:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Register callback for order data refresh
|
||||
onOrderRefresh(callback: () => void): () => void {
|
||||
this.orderRefreshCallbacks.add(callback);
|
||||
|
||||
// Return unsubscribe function
|
||||
return () => {
|
||||
this.orderRefreshCallbacks.delete(callback);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Global cache instance
|
||||
const apiCache = new ApiCache();
|
||||
|
||||
// Export cache utilities
|
||||
export const cacheUtils = {
|
||||
invalidateOrderData: (orderId?: string) => apiCache.invalidateOrderData(orderId),
|
||||
onOrderRefresh: (callback: () => void) => apiCache.onOrderRefresh(callback),
|
||||
invalidateAll: () => apiCache.invalidate(),
|
||||
};
|
||||
|
||||
/**
|
||||
* Normalizes a URL to ensure it has the correct /api prefix
|
||||
* This prevents double prefixing which causes API errors
|
||||
@@ -261,4 +351,46 @@ export const getCustomers = async (page: number = 1, limit: number = 25): Promis
|
||||
*/
|
||||
export const getCustomerDetails = async (userId: string): Promise<CustomerStats> => {
|
||||
return clientFetch(`/customers/${userId}`);
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Enhanced client-side fetch function with caching and automatic invalidation
|
||||
*/
|
||||
export async function clientFetchWithCache<T = any>(
|
||||
url: string,
|
||||
options: RequestInit = {},
|
||||
cacheKey?: string,
|
||||
ttl?: number
|
||||
): Promise<T> {
|
||||
// Check cache first for GET requests
|
||||
if (options.method === 'GET' || !options.method) {
|
||||
const cached = apiCache.get(cacheKey || url);
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
||||
}
|
||||
|
||||
// Make the request
|
||||
const result = await clientFetch<T>(url, options);
|
||||
|
||||
// Cache GET requests
|
||||
if ((options.method === 'GET' || !options.method) && cacheKey) {
|
||||
apiCache.set(cacheKey, result, ttl);
|
||||
}
|
||||
|
||||
// Invalidate cache for mutations that affect orders
|
||||
if (options.method && ['PUT', 'POST', 'DELETE', 'PATCH'].includes(options.method)) {
|
||||
if (url.includes('/orders/') && url.includes('/status')) {
|
||||
// Order status update - invalidate order cache
|
||||
const orderIdMatch = url.match(/\/orders\/([^\/]+)\/status/);
|
||||
if (orderIdMatch) {
|
||||
apiCache.invalidateOrderData(orderIdMatch[1]);
|
||||
}
|
||||
} else if (url.includes('/orders')) {
|
||||
// General order mutation
|
||||
apiCache.invalidateOrderData();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
Reference in New Issue
Block a user