Update SendNotification.tsx #2
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Explanation of Changes and Innovations
Improvements
Error Handling:
Replaced alert with react-toastify for modern, non-blocking notifications. Added specific error messages for different failure scenarios (e.g., timeout, server errors). Centralized environment variable validation (NEXT_PUBLIC_WEB_PUSH_PUBLIC_KEY, NEXT_PUBLIC_API_URL) at component load.
Code Organization:
Moved base64ToUint8Array to a utility file (@/utils/webPushUtils.ts) for reusability: ts// @/utils/webPushUtils.ts
export const base64ToUint8Array = (base64: string) => {
const padding = "=".repeat((4 - (base64.length % 4)) % 4);
const b64 = (base64 + padding).replace(/-/g, "+").replace(/_/g, "/");
const rawData = window.atob(b64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
};
Server API Integration:
Added saveSubscriptionToServer and deleteSubscriptionFromServer functions to interact with a backend API (assumes /api/subscription endpoint). Included preferences in the subscription payload for server-side filtering.
Browser Support Check:
Added isSupported check for PushManager and serviceWorker to provide a fallback UI for unsupported browsers.
Accessibility:
Added aria-label attributes to buttons for screen reader support. Improved button disabled states with explicit disabled:cursor-not-allowed classes.
Timeout Compatibility:
Kept AbortSignal.timeout but added error handling for unsupported browsers (e.g., fallback to a manual timeout if needed).
Innovations
Notification Permission Status:
Added permissionStatus state to display the current notification permission (granted, denied, default). Shows a message guiding users to enable notifications if denied.
Retry Logic:
Implemented retryAsync utility to retry failed subscription/unsubscription attempts (3 retries with 1-second delay).
Notification Preferences:
Added a NotificationPreference interface and UI for toggling notification types (e.g., transaction alerts, system updates). Preferences are sent to the server with the subscription for filtering notifications.
Custom Notification Payload:
Enhanced sendNotificationButtonOnClick to include a custom payload with title, body, icon, and data for richer notifications.
Analytics Tracking:
Added placeholders for analytics tracking (e.g., using mixpanel) for subscription and notification events (commented out; requires integration).
Progressive Enhancement:
Displays a warning if push notifications are not supported, ensuring the UI remains usable in unsupported browsers.
Dependencies
Add react-toastify to your project:
bashnpm install react-toastify
Include the CSS in your root layout (app/layout.tsx): tsximport "react-toastify/dist/ReactToastify.css"; Backend Requirements
The component assumes the following API endpoints:
POST /api/subscription: Save a push subscription with preferences.
DELETE /api/subscription: Delete a push subscription.
POST /api/notification: Send a push notification with a custom payload.
Example backend implementation (Node.js with web-push): js// pages/api/subscription.js
import webPush from "web-push";
export default async function handler(req, res) {
if (req.method === "POST") {
const { subscription, preferences } = req.body;
// Save subscription and preferences to database
res.status(200).json({ success: true });
} else if (req.method === "DELETE") {
const { subscription } = req.body;
// Delete subscription from database
res.status(200).json({ success: true });
} else {
res.status(405).json({ error: "Method not allowed" });
}
}
// pages/api/notification.js
import webPush from "web-push";
export default async function handler(req, res) {
const { subscription, payload } = req.body;
try {
await webPush.sendNotification(subscription, JSON.stringify(payload));
res.status(200).json({ success: true });
} catch (error) {
res.status(500).json({ error: error.message });
}
}
Environment Variables
Ensure the following are set in .env:
textNEXT_PUBLIC_WEB_PUSH_PUBLIC_KEY= NEXT_PUBLIC_API_URL=https://your-api-url
Validation Steps
Test Browser Support:
Open in a modern browser (e.g., Chrome) and verify subscription works. Test in an unsupported browser (e.g., older Safari) to confirm the fallback UI.
Check Permissions:
Deny notification permissions and verify the guidance message appears. Grant permissions and confirm subscription succeeds.
Test API Integration:
Set up the backend endpoints and verify subscription data is saved/deleted. Send a test notification and confirm it appears with the custom payload.
Accessibility:
Use a screen reader (e.g., VoiceOver) to test button navigation and ARIA labels.
Error Handling:
Simulate network failures (e.g., offline mode) to test retry logic and error toasts.
Recommendations
Analytics: Integrate an analytics library (e.g., Mixpanel, Amplitude) to track subscription and notification events.
Service Worker: Ensure the service worker is properly configured with serwist and handles push events correctly.
Security: Validate subscriptions server-side to prevent abuse (e.g., verify VAPID keys).
Testing: Add unit tests for base64ToUint8Array and API calls using Jest.
UI Enhancements: Add a preview of the test notification payload in the UI.