This commit is contained in:
client perkafean
2024-09-28 02:53:22 +00:00
parent 69b3fe4347
commit 3869b4d589
8 changed files with 137 additions and 101 deletions

28
public/service-worker.js Normal file
View File

@@ -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}`)
);
});

View File

@@ -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);
});
}

View File

@@ -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 = () => {

View File

@@ -37,6 +37,7 @@ const Modal = ({ shop, isOpen, onClose, modalContent }) => {
×
</button>
{modalContent === "req_notification" && <NotificationBlocked />}
{modalContent === "blocked_notification" && <NotificationBlocked />}
{modalContent === "edit_tables" && <TablesPage shop={shop} />}
{modalContent === "new_transaction" && (
<Transaction propsShopId={shop.cafeId} />

View File

@@ -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) {

View File

@@ -1,16 +1,15 @@
// NotificationBlocked.js
import React from "react";
const NotificationBlocked = () => {
return (
<div style={styles.container}>
<h2 style={styles.header}>Notifications Blocked</h2>
<h2 style={styles.header}>Heads Up! Notifications Are Off</h2>
<p style={styles.message}>
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 youve got notifications turned off. Turning them on will
make sure you get important updates, like new orders or alerts, right on
your device.
</p>
<h3 style={styles.instructionsHeader}>To enable notifications:</h3>
<h3 style={styles.instructionsHeader}>Heres how to turn them on:</h3>
<ol style={styles.instructions}>
<li>Open Chrome and go to our café's website.</li>
<li>Tap the menu (three dots) in the top-right corner.</li>
@@ -19,13 +18,12 @@ const NotificationBlocked = () => {
&gt; <strong>Notifications</strong>.
</li>
<li>
Find our café's site in the list and change the setting to{" "}
<strong>Allow</strong>.
Find our café in the list and set it to <strong>Allow</strong>.
</li>
</ol>
<p style={styles.footer}>
Once you enable notifications, you'll start receiving updates right
away! If you need help, feel free to ask!
Once youve turned on notifications, youll start getting updates
instantly. Need a hand? Just ask!
</p>
</div>
);

View File

@@ -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));
},
};

View File

@@ -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",
},
});
},
};