From 3869b4d58986c21dfcf734b6abecfbca9276effa Mon Sep 17 00:00:00 2001 From: client perkafean Date: Sat, 28 Sep 2024 02:53:22 +0000 Subject: [PATCH] ok --- public/service-worker.js | 28 ++++++++ public/sw.js | 19 +++-- src/App.js | 105 ++++++++++++++++++++++------ src/components/Modal.js | 1 + src/pages/CafePage.js | 14 ++-- src/pages/NotificationBlocked.js | 18 +++-- src/services/notificationService.js | 26 ------- src/services/subscriptionService.js | 27 ------- 8 files changed, 137 insertions(+), 101 deletions(-) create mode 100644 public/service-worker.js delete mode 100644 src/services/notificationService.js delete mode 100644 src/services/subscriptionService.js diff --git a/public/service-worker.js b/public/service-worker.js new file mode 100644 index 0000000..9c2c93c --- /dev/null +++ b/public/service-worker.js @@ -0,0 +1,28 @@ +// public/firebase-messaging-sw.js +self.addEventListener('push', function(event) { + const data = event.data.json(); + const options = { + body: data.body, + icon: 'https://i.pinimg.com/originals/3c/44/67/3c446785968272f79aaac7ace5ded0fe.jpg', // Path to your icon + badge: 'badge.png', // Path to your badge + data: { // Add data to the notification + cafeId: data.cafeId, + transactionId: data.transactionId, + } + }; + + event.waitUntil( + self.registration.showNotification(data.title, options) + ); +}); + +self.addEventListener('notificationclick', (event) => { + event.notification.close(); // Close the notification + + const { cafeId, transactionId } = event.notification.data; // Get the notification data + + // Open the URL with the cafeId and transactionId + event.waitUntil( + clients.openWindow(`https://r7l7gs-3000.csb.app/${cafeId}modal=new_transaction&transactionId=${transactionId}`) + ); +}); diff --git a/public/sw.js b/public/sw.js index 32f36cb..1eca9e4 100644 --- a/public/sw.js +++ b/public/sw.js @@ -1,12 +1,9 @@ -if ("serviceWorker" in navigator) { - window.addEventListener("load", () => { - navigator.serviceWorker - .register("/service-worker.js") - .then((registration) => { - console.log( - "Service Worker registered with scope:", - registration.scope - ); - }); - }); +if ('serviceWorker' in navigator) { + navigator.serviceWorker.register('/service-worker.js') + .then((registration) => { + console.log('Service Worker registered with scope:', registration.scope); + }) + .catch((error) => { + console.error('Service Worker registration failed:', error); + }); } diff --git a/src/App.js b/src/App.js index 02c8425..6936b0f 100644 --- a/src/App.js +++ b/src/App.js @@ -9,8 +9,8 @@ import { useLocation, } from "react-router-dom"; import socket from "./services/socketService"; -import { SubscriptionService } from "./services/subscriptionService"; -import { NotificationService } from "./services/notificationService"; + +import API_BASE_URL from "./config.js"; import Dashboard from "./pages/Dashboard"; import ScanMeja from "./pages/ScanMeja"; @@ -138,20 +138,74 @@ function App() { setGuestSides(sessionLeft.guestSideList); }; - const checkNotifications = async (userId) => { - try { - const permissionGranted = - await NotificationService.requestNotificationPermission(setModal); - if (permissionGranted) { - await SubscriptionService.subscribeUserToNotifications(userId); - } else { - setModal("blocked_notification"); - console.log("req notif"); - } - } catch (error) { - console.error("Error handling notifications:", error); + // const checkNotifications = async (userId) => { + // try { + // const permissionGranted = + // await NotificationService.requestNotificationPermission(setModal); + // if (permissionGranted) { + // await SubscriptionService.subscribeUserToNotifications(userId); + // } else { + // setModal("blocked_notification"); + // console.log("req notif"); + // } + // } catch (error) { + // console.error("Error handling notifications:", error); + // } + // }; + useEffect(() => { + const getVapidKey = async () => { + const response = await fetch(`${API_BASE_URL}/vapid-key`); + const { publicVapidKey } = await response.json(); + return publicVapidKey; + }; + + const askNotificationPermission = async () => { + const permission = await Notification.requestPermission(); + if (permission === 'granted') { + console.log('Notification permission granted.'); + const publicVapidKey = await getVapidKey(); + await subscribeUser(publicVapidKey); + } else { + console.error('Notification permission denied.'); + } + }; + +// Utility function to convert base64 to Uint8Array +function urlBase64ToUint8Array(base64String) { + const padding = '='.repeat((4 - base64String.length % 4) % 4); + const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/'); + const rawData = window.atob(base64); + return Uint8Array.from([...rawData].map(char => char.charCodeAt(0))); +} + const subscribeUser = async (publicVapidKey) => { + try { + const registration = await navigator.serviceWorker.register('/service-worker.js'); + console.log('Service Worker registered with scope:', registration.scope); + + const subscription = await registration.pushManager.subscribe({ + userVisibleOnly: true, + applicationServerKey: urlBase64ToUint8Array(publicVapidKey), + }); + + await fetch(`${API_BASE_URL}/subscribe`, { + method: 'POST', + body: JSON.stringify(subscription), + headers: { + 'Content-Type': 'application/json', + }, + }); + } catch (error) { + console.error('Subscription failed:', error); + } + }; + + if ('serviceWorker' in navigator) { + window.addEventListener('load', async () => { + await askNotificationPermission(); + }); } - }; +}, []); + useEffect(() => { if (socket == null) return; @@ -226,7 +280,7 @@ function App() { console.log("getting guest side"); setDeviceType("clerk"); - checkNotifications(data.data.user.userId); + // checkNotifications(data.data.user.userId); } else { setDeviceType("guestDevice"); } @@ -278,19 +332,24 @@ function App() { // Function to open the modal const setModal = (content, params = {}) => { // Prepare query parameters - const queryParams = new URLSearchParams({ - modal: content, - ...params, // Spread additional parameters - }).toString(); + const queryParams = new URLSearchParams(location.search); + + // Update the modal and any additional params + queryParams.set("modal", content); + Object.entries(params).forEach(([key, value]) => { + queryParams.set(key, value); + }); + // Update URL with new parameters - navigate(`?${queryParams}`, { replace: true }); - + navigate(`?${queryParams.toString()}`, { replace: true }); + // Prevent scrolling when modal is open document.body.style.overflow = "hidden"; - + setIsModalOpen(true); setModalContent(content); }; + // Function to close the modal const closeModal = () => { diff --git a/src/components/Modal.js b/src/components/Modal.js index b66d314..71285c6 100644 --- a/src/components/Modal.js +++ b/src/components/Modal.js @@ -37,6 +37,7 @@ const Modal = ({ shop, isOpen, onClose, modalContent }) => { × {modalContent === "req_notification" && } + {modalContent === "blocked_notification" && } {modalContent === "edit_tables" && } {modalContent === "new_transaction" && ( diff --git a/src/pages/CafePage.js b/src/pages/CafePage.js index f7e644d..0c601d6 100644 --- a/src/pages/CafePage.js +++ b/src/pages/CafePage.js @@ -1,7 +1,7 @@ // src/CafePage.js import React, { useState, useEffect } from "react"; -import { useParams, useSearchParams, useNavigate } from "react-router-dom"; +import { useParams, useSearchParams, useNavigate, useLocation } from "react-router-dom"; import "../App.css"; import SearchInput from "../components/SearchInput"; @@ -33,6 +33,7 @@ function CafePage({ removeConnectedGuestSides, setModal, }) { + const location = useLocation(); const [searchParams] = useSearchParams(); const token = searchParams.get("token"); const { shopId, tableCode } = useParams(); @@ -50,10 +51,15 @@ function CafePage({ const [filterId, setFilterId] = useState(0); useEffect(() => { - if (user.cafeId != null && user.cafeId != shopId) { - navigate("/" + user.cafeId); + if (user.cafeId != null && user.cafeId !== shopId) { + // Preserve existing query parameters + const currentParams = new URLSearchParams(location.search).toString(); + + // Navigate to the new cafeId while keeping existing params + navigate(`/${user.cafeId}?${currentParams}`, { replace: true }); } - }, [user]); + }, [user, shopId]); + useEffect(() => { if (token) { diff --git a/src/pages/NotificationBlocked.js b/src/pages/NotificationBlocked.js index 46b1108..fbfd9df 100644 --- a/src/pages/NotificationBlocked.js +++ b/src/pages/NotificationBlocked.js @@ -1,16 +1,15 @@ -// NotificationBlocked.js import React from "react"; const NotificationBlocked = () => { return (
-

Notifications Blocked

+

Heads Up! Notifications Are Off

- It looks like notifications are currently blocked in your browser. - Enabling notifications will help you receive important updates, such as - new orders or alerts, directly on your device. + It looks like you’ve got notifications turned off. Turning them on will + make sure you get important updates, like new orders or alerts, right on + your device.

-

To enable notifications:

+

Here’s how to turn them on:

  1. Open Chrome and go to our café's website.
  2. Tap the menu (three dots) in the top-right corner.
  3. @@ -19,13 +18,12 @@ const NotificationBlocked = () => { > Notifications.
  4. - Find our café's site in the list and change the setting to{" "} - Allow. + Find our café in the list and set it to Allow.

- Once you enable notifications, you'll start receiving updates right - away! If you need help, feel free to ask! + Once you’ve turned on notifications, you’ll start getting updates + instantly. Need a hand? Just ask!

); diff --git a/src/services/notificationService.js b/src/services/notificationService.js deleted file mode 100644 index 7ec8452..0000000 --- a/src/services/notificationService.js +++ /dev/null @@ -1,26 +0,0 @@ -import API_BASE_URL from "../config.js"; -export const NotificationService = { - async fetchVapidPublicKey() { - const response = await fetch(API_BASE_URL + "/vapid-public-key"); // Adjust URL if necessary - const data = await response.json(); - return data.publicKey; - }, - - async requestNotificationPermission(setModal) { - if (!("Notification" in window)) { - throw new Error("This browser does not support desktop notification"); - } - setModal("req_notification"); - const permission = await Notification.requestPermission(); - return permission === "granted"; - }, - - urlB64ToUint8Array(base64String) { - const padding = "=".repeat((4 - (base64String.length % 4)) % 4); - const base64 = (base64String + padding) - .replace(/-/g, "+") - .replace(/_/g, "/"); - const rawData = window.atob(base64); - return Uint8Array.from(rawData, (char) => char.charCodeAt(0)); - }, -}; diff --git a/src/services/subscriptionService.js b/src/services/subscriptionService.js deleted file mode 100644 index 9188d81..0000000 --- a/src/services/subscriptionService.js +++ /dev/null @@ -1,27 +0,0 @@ -import API_BASE_URL from "../config.js"; -import { NotificationService } from "./notificationService"; - -export const SubscriptionService = { - async subscribeUserToNotifications(userId) { - const registration = await navigator.serviceWorker.ready; - - const publicKey = await NotificationService.fetchVapidPublicKey(); // Fetch the public key - const subscription = await registration.pushManager.subscribe({ - userVisibleOnly: true, - applicationServerKey: NotificationService.urlB64ToUint8Array(publicKey), - }); - - await this.saveSubscription(userId, subscription); - console.log("User is subscribed:", subscription); - }, - - async saveSubscription(userId, subscription) { - await fetch(API_BASE_URL + "/subscribe", { - method: "POST", - body: JSON.stringify({ userId, subscription }), - headers: { - "Content-Type": "application/json", - }, - }); - }, -};