// 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 (
{expired ? : }
{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}
); })}
Channels
Browser Push
PWA push to phone & desktop
WhatsApp Backup
Sent if push fails after 60s
Urgent Alerts Only
Mute non-urgent between 10pm – 6am
Notification Types
{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 });