// Notifications.jsx
function NotificationsPage() {
const [push, setPush] = React.useState(true);
const [whatsapp, setWhatsapp] = React.useState(true);
const [urgentOnly, setUrgentOnly] = React.useState(false);
const [types, setTypes] = React.useState({
'New job assignment': true,
'Job time or location change': true,
'Urgent dispatch update': true,
'Job cancellation': true,
'Reminder before job starts': true,
'Certification renewal reminder': true,
'Mechanic repair ticket assignment': true,
'Management approval request': false,
});
const reminders = certReminders();
return (
Certification Renewals
{reminders.filter(r => r.state === 'expired').length} expired · {reminders.filter(r => r.state === 'expiring').length} due within {CERT_RENEW_WINDOW_DAYS} days
Auto
{reminders.length === 0 ? (
All operator certifications are current. Reminders fire {CERT_RENEW_WINDOW_DAYS} days before expiry.
) : (
{reminders.map((r, i) => {
const expired = r.state === 'expired';
return (
{r.operator} — {r.code} {expired ? 'expired' : 'renewal due'}
{r.label} · {expired
? expired {fmtCertDate(r.exp)} ({Math.abs(r.days)} days ago) — hidden from booking until renewed
: expires {fmtCertDate(r.exp)} (in {r.days} days)}
Renew via Master Data → Operators
);
})}
)}
Recent Notifications
{NOTIFICATIONS.filter(n => n.unread).length} unread
{NOTIFICATIONS.map(n => {
const icon = n.kind === 'urgent' ? AlertTriangle : n.kind === 'success' ? Check : Bell;
const Ico = icon;
return (
{n.title}
{n.msg}
{n.time}
{n.unread ?
: null}
);
})}
Browser Push
PWA push to phone & desktop
WhatsApp Backup
Sent if push fails after 60s
Urgent Alerts Only
Mute non-urgent between 10pm – 6am
{Object.entries(types).map(([k, v]) => (
{k}
))}
Example Push
Pow Lee Crane Ops
New Work Order Assigned: 50 Ton Crane, Pasir Gudang, 29 April 2026, 8:00 AM.
now · push
);
}
Object.assign(window, { NotificationsPage });