fina/backup/first -fina app/app/static/js/service-worker.js
2025-12-26 00:52:56 +00:00

161 lines
4.1 KiB
JavaScript

const CACHE_NAME = 'fina-v1';
const STATIC_CACHE = 'fina-static-v1';
const DYNAMIC_CACHE = 'fina-dynamic-v1';
// Assets to cache on install
const STATIC_ASSETS = [
'/',
'/static/css/style.css',
'/static/js/script.js',
'/static/js/chart.min.js',
'/static/images/fina-logo.png'
];
// Install event - cache static assets
self.addEventListener('install', event => {
console.log('[Service Worker] Installing...');
event.waitUntil(
caches.open(STATIC_CACHE)
.then(cache => {
console.log('[Service Worker] Caching static assets');
return cache.addAll(STATIC_ASSETS);
})
.then(() => self.skipWaiting())
);
});
// Activate event - clean up old caches
self.addEventListener('activate', event => {
console.log('[Service Worker] Activating...');
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames
.filter(name => name !== STATIC_CACHE && name !== DYNAMIC_CACHE)
.map(name => caches.delete(name))
);
}).then(() => self.clients.claim())
);
});
// Fetch event - network first, then cache
self.addEventListener('fetch', event => {
const { request } = event;
// Skip non-GET requests
if (request.method !== 'GET') {
return;
}
// Skip chrome extension and other non-http(s) requests
if (!request.url.startsWith('http')) {
return;
}
// API requests - network first, cache fallback
if (request.url.includes('/api/')) {
event.respondWith(
fetch(request)
.then(response => {
const responseClone = response.clone();
caches.open(DYNAMIC_CACHE).then(cache => {
cache.put(request, responseClone);
});
return response;
})
.catch(() => caches.match(request))
);
return;
}
// Static assets - cache first, network fallback
if (
request.url.includes('/static/') ||
request.url.endsWith('.css') ||
request.url.endsWith('.js') ||
request.url.endsWith('.png') ||
request.url.endsWith('.jpg') ||
request.url.endsWith('.jpeg') ||
request.url.endsWith('.gif') ||
request.url.endsWith('.svg')
) {
event.respondWith(
caches.match(request)
.then(cachedResponse => {
if (cachedResponse) {
return cachedResponse;
}
return fetch(request).then(response => {
const responseClone = response.clone();
caches.open(STATIC_CACHE).then(cache => {
cache.put(request, responseClone);
});
return response;
});
})
);
return;
}
// HTML pages - network first, cache fallback
event.respondWith(
fetch(request)
.then(response => {
const responseClone = response.clone();
caches.open(DYNAMIC_CACHE).then(cache => {
cache.put(request, responseClone);
});
return response;
})
.catch(() => {
return caches.match(request).then(cachedResponse => {
if (cachedResponse) {
return cachedResponse;
}
// Return offline page if available
return caches.match('/');
});
})
);
});
// Handle messages from clients
self.addEventListener('message', event => {
if (event.data && event.data.type === 'SKIP_WAITING') {
self.skipWaiting();
}
});
// Background sync for offline form submissions
self.addEventListener('sync', event => {
if (event.tag === 'sync-expenses') {
event.waitUntil(syncExpenses());
}
});
async function syncExpenses() {
// Placeholder for syncing offline data
console.log('[Service Worker] Syncing expenses...');
}
// Push notifications support (for future feature)
self.addEventListener('push', event => {
const options = {
body: event.data ? event.data.text() : 'New notification from FINA',
icon: '/static/images/fina-logo.png',
badge: '/static/images/fina-logo.png',
vibrate: [200, 100, 200]
};
event.waitUntil(
self.registration.showNotification('FINA', options)
);
});
// Notification click handler
self.addEventListener('notificationclick', event => {
event.notification.close();
event.waitUntil(
clients.openWindow('/')
);
});