# Push Notifications (Firebase Cloud Messaging)

> ⚠️ **Warning:** To manage push notifications, your backend must expose FCM (Firebase Cloud Messaging) services for token registration and removal. Without these endpoints, push notification integration will not work correctly.

This guide explains how to enable and manage push notifications using Firebase Cloud Messaging (FCM) in your project.

## 1. Firebase Configuration

Retrieve the configuration from the [Firebase Console](https://console.firebase.google.com):

```ts
const config = {
  apiKey: '<API_KEY>',
  authDomain: '<PROJECT_ID>.firebaseapp.com',
  projectId: '<PROJECT_ID>',
  storageBucket: '<PROJECT_ID>.appspot.com',
  messagingSenderId: '<SENDER_ID>',
  appId: '<APP_ID>',
  vapidKey: '<VAPID_KEY>', // From Cloud Messaging > Web Push certificates
  apiUrl: 'https://api.yourdomain.com' // Backend endpoint for token registration
};
```

## 2. Automatic Enablement in ApplicaAdmin

To enable push notifications throughout the application, simply pass the configuration as a prop to `ApplicaAdmin`:

```tsx
import { ApplicaAdmin } from '@/ApplicaAdmin';

<ApplicaAdmin
  // ...other props
  pushNotifications={config}
/>;
```

This will ensure that:

- Push notifications are managed globally.
- The toggle to enable/disable notifications is already integrated in the notifications interface (header).
- Push messages received in the foreground will automatically update the notifications panel.

## 3. Manual Use of the Toggle Button

If you want to show a button to enable/disable notifications in a specific part of the app:

```tsx
import { PushNotificationToggleButton } from '@/components/ra-buttons/PushNotificationToggleButton';

<PushNotificationToggleButton config={config} />;
```

## 4. Technical Details & Lifecycle

The system:

- Automatically registers the service worker `/firebase-messaging-sw.js` (must be present in the public root).
- Requests user permission for notifications.
- Registers the FCM token on the backend via `{apiUrl}/fcm/register` (POST) and removes it with `{apiUrl}/fcm/{token}` (DELETE).
- Manages state: `enabled`, `disabled`, `pending`, `error`.
- Exposes functions to enable/disable/toggle/listen to notifications via the `usePushNotifications` hook.
- In case of error, shows a notification using the react-admin system.

### Advanced Example with Hook

```tsx
import { usePushNotifications } from '@/hooks/usePushNotifications';

const { status, enable, disable, toggle, listen } = usePushNotifications(config);

useEffect(() => {
  const unsubscribe = listen(({ title, message, url }) => {
    // Show a custom notification or update the UI
  });
  return unsubscribe;
}, [listen]);
```

## 5. Requirements & Notes

- The file `/firebase-messaging-sw.js` must be present in the public root of the project.
- The backend must expose the endpoints for FCM token registration/removal.
- Push notification support depends on the browser and user permissions.
- The system is designed to integrate with React-Admin and ApplicaAdmin, but can also be used in other contexts.

---

For details on backend configuration and troubleshooting, see the official Firebase Cloud Messaging documentation.

## 6. Service Worker Template

Copy the following file as `/public/firebase-messaging-sw.js` in your project. Remember to replace the Firebase configuration with your own!

```js
/* public/firebase-messaging-sw.js */
importScripts('https://www.gstatic.com/firebasejs/12.8.0/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/12.8.0/firebase-messaging-compat.js');

firebase.initializeApp({
  apiKey: '<API_KEY>',
  authDomain: '<PROJECT_ID>.firebaseapp.com',
  projectId: '<PROJECT_ID>',
  storageBucket: '<PROJECT_ID>.appspot.com',
  messagingSenderId: '<SENDER_ID>',
  appId: '<APP_ID>',
  measurementId: '<MEASUREMENT_ID>'
});

const messaging = firebase.messaging();

messaging.onBackgroundMessage((payload) => {
  const title = payload?.data?.title || 'Notification';
  const body = payload?.data?.message || '';
  const url = payload?.data?.url || '/';

  self.registration.showNotification(title, {
    body,
    data: { url }
  });
});

self.addEventListener('notificationclick', (event) => {
  event.notification.close();
  const url = event.notification?.data?.url || '/';

  event.waitUntil(
    (async () => {
      const allClients = await clients.matchAll({ type: 'window', includeUncontrolled: true });
      for (const client of allClients) {
        if ('focus' in client) {
          client.navigate(url);
          return client.focus();
        }
      }
      if (clients.openWindow) return clients.openWindow(url);
    })()
  );
});
```

> ⚠️ **Note:** Replace the configuration values with those from your Firebase project!
