feat(front+back): pwa added, register parkour update with it, and jeux added in coming soon
Some checks failed
Deploy to Development / build-and-deploy (push) Failing after 20s
Some checks failed
Deploy to Development / build-and-deploy (push) Failing after 20s
This commit is contained in:
159
frontend/src/services/notificationService.js
Normal file
159
frontend/src/services/notificationService.js
Normal file
@@ -0,0 +1,159 @@
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
|
||||
class NotificationService {
|
||||
constructor() {
|
||||
this.pollingInterval = null
|
||||
this.pollInterval = 30000 // 30 secondes
|
||||
this.isPolling = false
|
||||
}
|
||||
|
||||
startPolling() {
|
||||
if (this.isPolling) return
|
||||
|
||||
const authStore = useAuthStore()
|
||||
if (!authStore.isAuthenticated) return
|
||||
|
||||
this.isPolling = true
|
||||
|
||||
// Récupérer immédiatement
|
||||
this.fetchNotifications()
|
||||
|
||||
// Puis toutes les 30 secondes
|
||||
this.pollingInterval = setInterval(() => {
|
||||
this.fetchNotifications()
|
||||
}, this.pollInterval)
|
||||
}
|
||||
|
||||
stopPolling() {
|
||||
if (this.pollingInterval) {
|
||||
clearInterval(this.pollingInterval)
|
||||
this.pollingInterval = null
|
||||
}
|
||||
this.isPolling = false
|
||||
}
|
||||
|
||||
async fetchNotifications() {
|
||||
const authStore = useAuthStore()
|
||||
if (!authStore.isAuthenticated) {
|
||||
this.stopPolling()
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await authStore.fetchNotifications()
|
||||
|
||||
// Si de nouvelles notifications non lues ont été détectées
|
||||
if (result && result.hasNewNotifications && result.newCount > result.previousCount) {
|
||||
// Trouver les nouvelles notifications non lues (les plus récentes en premier)
|
||||
const newUnreadNotifications = authStore.notifications
|
||||
.filter(n => !n.is_read)
|
||||
.sort((a, b) => new Date(b.created_at) - new Date(a.created_at))
|
||||
.slice(0, result.newCount - result.previousCount)
|
||||
|
||||
if (newUnreadNotifications.length > 0) {
|
||||
// Afficher une notification push pour la plus récente
|
||||
const latestNotification = newUnreadNotifications[0]
|
||||
await this.showPushNotification(latestNotification.title, {
|
||||
body: latestNotification.message,
|
||||
link: latestNotification.link || '/',
|
||||
data: { notificationId: latestNotification.id }
|
||||
})
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error polling notifications:', error)
|
||||
}
|
||||
}
|
||||
|
||||
showNotificationBadge() {
|
||||
// Mettre à jour le badge du titre de la page
|
||||
if ('Notification' in window && Notification.permission === 'granted') {
|
||||
// La notification push sera gérée par le service worker
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Gestion des notifications push PWA
|
||||
async requestNotificationPermission() {
|
||||
if (!('Notification' in window)) {
|
||||
console.log('Ce navigateur ne supporte pas les notifications')
|
||||
return false
|
||||
}
|
||||
|
||||
if (Notification.permission === 'granted') {
|
||||
return true
|
||||
}
|
||||
|
||||
if (Notification.permission !== 'denied') {
|
||||
const permission = await Notification.requestPermission()
|
||||
return permission === 'granted'
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
async showPushNotification(title, options = {}) {
|
||||
if (!('Notification' in window)) return
|
||||
|
||||
const hasPermission = await this.requestNotificationPermission()
|
||||
if (!hasPermission) return
|
||||
|
||||
// Si on est dans un service worker, utiliser la notification API du SW
|
||||
if ('serviceWorker' in navigator) {
|
||||
try {
|
||||
const registration = await navigator.serviceWorker.ready
|
||||
await registration.showNotification(title, {
|
||||
icon: '/icon-192x192.png',
|
||||
badge: '/icon-96x96.png',
|
||||
tag: 'lediscord-notification',
|
||||
requireInteraction: false,
|
||||
vibrate: [200, 100, 200],
|
||||
...options
|
||||
})
|
||||
return
|
||||
} catch (error) {
|
||||
console.error('Error showing notification via service worker:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: notification native du navigateur
|
||||
const notification = new Notification(title, {
|
||||
icon: '/icon-192x192.png',
|
||||
badge: '/icon-96x96.png',
|
||||
tag: 'lediscord-notification',
|
||||
requireInteraction: false,
|
||||
...options
|
||||
})
|
||||
|
||||
notification.onclick = () => {
|
||||
window.focus()
|
||||
notification.close()
|
||||
|
||||
if (options.link) {
|
||||
window.location.href = options.link
|
||||
}
|
||||
}
|
||||
|
||||
// Fermer automatiquement après 5 secondes
|
||||
setTimeout(() => {
|
||||
notification.close()
|
||||
}, 5000)
|
||||
|
||||
return notification
|
||||
}
|
||||
|
||||
// Écouter les messages du service worker pour les notifications push
|
||||
setupServiceWorkerListener() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.addEventListener('message', (event) => {
|
||||
if (event.data && event.data.type === 'NOTIFICATION') {
|
||||
const { title, options } = event.data
|
||||
this.showPushNotification(title, options)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new NotificationService()
|
||||
|
||||
Reference in New Issue
Block a user