feat: add daily prayer reminder push notifications with time picker
This commit is contained in:
1 parent
49d1bdb47d
commit
a3de1aaa1a
2 files changed
+129
-1
No files matched your search
@@ -18,6 +18,86 @@ export default function AboutPage({ userEmail }: AboutPageProps) {
|
||||
const [deleteError, setDeleteError] = useState('');
|
||||
const [verificationMessage, setVerificationMessage] = useState('');
|
||||
const [sendingVerification, setSendingVerification] = useState(false);
|
||||
const [notificationsEnabled, setNotificationsEnabled] = useState(false);
|
||||
const [reminderTime, setReminderTime] = useState('09:00');
|
||||
const [notificationPermission, setNotificationPermission] = useState<NotificationPermission>('default');
|
||||
|
||||
React.useEffect(() => {
|
||||
// Check current notification permission
|
||||
if ('Notification' in window) {
|
||||
setNotificationPermission(Notification.permission);
|
||||
}
|
||||
|
||||
// Load saved settings
|
||||
const savedEnabled = localStorage.getItem('prayerRemindersEnabled') === 'true';
|
||||
const savedTime = localStorage.getItem('prayerReminderTime') || '09:00';
|
||||
setNotificationsEnabled(savedEnabled);
|
||||
setReminderTime(savedTime);
|
||||
}, []);
|
||||
|
||||
const requestNotificationPermission = async () => {
|
||||
if ('Notification' in window) {
|
||||
const permission = await Notification.requestPermission();
|
||||
setNotificationPermission(permission);
|
||||
if (permission === 'granted') {
|
||||
setNotificationsEnabled(true);
|
||||
localStorage.setItem('prayerRemindersEnabled', 'true');
|
||||
scheduleNotification();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const toggleNotifications = async () => {
|
||||
if (!notificationsEnabled && notificationPermission !== 'granted') {
|
||||
await requestNotificationPermission();
|
||||
} else {
|
||||
setNotificationsEnabled(!notificationsEnabled);
|
||||
localStorage.setItem('prayerRemindersEnabled', String(!notificationsEnabled));
|
||||
if (!notificationsEnabled) {
|
||||
scheduleNotification();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleTimeChange = (newTime: string) => {
|
||||
setReminderTime(newTime);
|
||||
localStorage.setItem('prayerReminderTime', newTime);
|
||||
if (notificationsEnabled) {
|
||||
scheduleNotification();
|
||||
}
|
||||
};
|
||||
|
||||
const scheduleNotification = () => {
|
||||
if ('serviceWorker' in navigator && notificationsEnabled) {
|
||||
// Calculate time until next reminder
|
||||
const [hours, minutes] = reminderTime.split(':').map(Number);
|
||||
const now = new Date();
|
||||
const scheduledTime = new Date();
|
||||
scheduledTime.setHours(hours, minutes, 0, 0);
|
||||
|
||||
// If time has passed today, schedule for tomorrow
|
||||
if (scheduledTime <= now) {
|
||||
scheduledTime.setDate(scheduledTime.getDate() + 1);
|
||||
}
|
||||
|
||||
const timeUntilNotification = scheduledTime.getTime() - now.getTime();
|
||||
|
||||
// Schedule notification
|
||||
setTimeout(() => {
|
||||
if (Notification.permission === 'granted') {
|
||||
new Notification('🙏 Time to Pray', {
|
||||
body: 'Take a moment to connect with God and pray.',
|
||||
icon: '/icon-192x192.png',
|
||||
badge: '/icon-192x192.png',
|
||||
tag: 'prayer-reminder',
|
||||
requireInteraction: false,
|
||||
});
|
||||
// Reschedule for next day
|
||||
setTimeout(scheduleNotification, 24 * 60 * 60 * 1000);
|
||||
}
|
||||
}, timeUntilNotification);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gradient-to-b from-slate-900 to-slate-800 p-4 pb-32 pt-8">
|
||||
@@ -108,6 +188,54 @@ export default function AboutPage({ userEmail }: AboutPageProps) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Prayer Reminders Section */}
|
||||
<div className="border-b border-slate-700 pb-6">
|
||||
<h2 className="text-lg font-semibold text-white mb-4">Prayer Reminders</h2>
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-slate-300">Daily Reminders</p>
|
||||
<p className="text-xs text-slate-400">Get notified to pray each day</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={toggleNotifications}
|
||||
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${
|
||||
notificationsEnabled ? 'bg-blue-600' : 'bg-slate-600'
|
||||
}`}
|
||||
>
|
||||
<span
|
||||
className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
|
||||
notificationsEnabled ? 'translate-x-6' : 'translate-x-1'
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{notificationPermission === 'denied' && (
|
||||
<div className="bg-red-900 border border-red-700 text-red-200 px-3 py-2 rounded-lg text-xs">
|
||||
Notifications are blocked. Please enable them in your browser settings.
|
||||
</div>
|
||||
)}
|
||||
|
||||
{notificationsEnabled && (
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-slate-300 mb-2">
|
||||
Reminder Time
|
||||
</label>
|
||||
<input
|
||||
type="time"
|
||||
value={reminderTime}
|
||||
onChange={(e) => handleTimeChange(e.target.value)}
|
||||
className="w-full p-2 bg-slate-700 border border-slate-600 rounded-lg text-white focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||
/>
|
||||
<p className="text-xs text-slate-400 mt-2">
|
||||
You'll receive a notification at {reminderTime} each day
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* App Info Section */}
|
||||
<div className="border-b border-slate-700 pb-6">
|
||||
<h2 className="text-lg font-semibold text-white mb-4">App Info</h2>
|
||||
|
||||
Reference in new issue
Block a user