- Migrated all localStorage data to Firebase for cross-device sync
- Prayer drafts now stored in users/{userId}/drafts
- Reminder settings in users/{userId}/settings
- Prayer statistics in users/{userId}/statistics
- Implemented persistent 'most prayed for' tracking in Firebase
- Enhanced loading screen with animated backgrounds and gradients
- Fixed auth session restoration on hard refresh
- Added prayedDates array for multi-day prayer tracking
- Calendar now accurately shows all days a prayer was prayed for
- Enabled Firestore offline persistence for offline-first experience
- Updated Firestore security rules for new data structure
- Improved clock display (removed leading zero from hours)
- Moved clock below date on homepage with appropriate sizing
- Fixed data loading race conditions between auth and Firestore
123 lines
4.1 KiB
TypeScript
123 lines
4.1 KiB
TypeScript
'use client';
|
|
|
|
import React, { useState, useEffect } from 'react';
|
|
import { BellRing, X } from 'lucide-react';
|
|
import { useAuth } from '@/context/AuthContext';
|
|
import { db } from '@/lib/firebase';
|
|
import { doc, getDoc, setDoc } from 'firebase/firestore';
|
|
|
|
interface ReminderBannerProps {
|
|
userEmail?: string;
|
|
}
|
|
|
|
export default function ReminderBanner({ userEmail }: ReminderBannerProps) {
|
|
const [showBanner, setShowBanner] = useState(false);
|
|
const [reminderTime, setReminderTime] = useState('09:00');
|
|
const [isTime, setIsTime] = useState(false);
|
|
const { user } = useAuth();
|
|
|
|
useEffect(() => {
|
|
if (!user) return;
|
|
|
|
// Load settings from Firebase
|
|
const loadSettingsAndCheck = async () => {
|
|
try {
|
|
const settingsRef = doc(db, 'users', user.uid, 'settings', 'notifications');
|
|
const settingsSnap = await getDoc(settingsRef);
|
|
|
|
if (!settingsSnap.exists()) return;
|
|
|
|
const settings = settingsSnap.data();
|
|
const remindersEnabled = settings.enabled || false;
|
|
const savedTime = settings.time || '09:00';
|
|
const lastReminderDate = settings.lastReminderDate;
|
|
|
|
setReminderTime(savedTime);
|
|
|
|
if (!remindersEnabled) return;
|
|
|
|
// Check if we should show the banner
|
|
const checkIfTimeToRemind = () => {
|
|
const now = new Date();
|
|
const [hours, minutes] = savedTime.split(':').map(Number);
|
|
const reminderTodayTime = new Date();
|
|
reminderTodayTime.setHours(hours, minutes, 0, 0);
|
|
|
|
// Check if current time is within 5 minutes of reminder time
|
|
const timeDiff = Math.abs(now.getTime() - reminderTodayTime.getTime());
|
|
const withinWindow = timeDiff < 5 * 60 * 1000; // 5 minute window
|
|
|
|
if (withinWindow) {
|
|
// Check if we already showed reminder today
|
|
const today = new Date().toISOString().split('T')[0];
|
|
const lastDate = lastReminderDate?.split('T')[0];
|
|
|
|
if (lastDate !== today) {
|
|
setIsTime(true);
|
|
setShowBanner(true);
|
|
|
|
// Update last reminder date in Firebase
|
|
setDoc(settingsRef, {
|
|
lastReminderDate: new Date().toISOString()
|
|
}, { merge: true });
|
|
}
|
|
}
|
|
};
|
|
|
|
checkIfTimeToRemind();
|
|
|
|
// Check every minute
|
|
const interval = setInterval(checkIfTimeToRemind, 60000);
|
|
return () => clearInterval(interval);
|
|
} catch (error: any) {
|
|
if (error?.code !== 'unavailable') {
|
|
console.error('Error loading reminder settings:', error);
|
|
}
|
|
}
|
|
};
|
|
|
|
loadSettingsAndCheck();
|
|
}, [user]);
|
|
|
|
if (!showBanner) return null;
|
|
|
|
return (
|
|
<div className="fixed top-0 left-0 right-0 z-40 p-4">
|
|
<div className="max-w-md mx-auto bg-gradient-to-r from-blue-600 to-blue-500 rounded-lg shadow-lg p-4 animate-in slide-in-from-top">
|
|
<div className="flex items-start gap-3">
|
|
<BellRing className="w-6 h-6 text-white mt-1" />
|
|
<div className="flex-1">
|
|
<h3 className="font-semibold text-white">Time to Pray</h3>
|
|
<p className="text-blue-100 text-sm mt-1">
|
|
Take a moment to connect with God and pray.
|
|
</p>
|
|
</div>
|
|
<button
|
|
onClick={() => setShowBanner(false)}
|
|
className="text-blue-200 hover:text-white transition-colors mt-1"
|
|
>
|
|
<X className="w-5 h-5" />
|
|
</button>
|
|
</div>
|
|
<div className="mt-3 flex gap-2">
|
|
<button
|
|
onClick={() => setShowBanner(false)}
|
|
className="flex-1 px-3 py-2 bg-blue-700 hover:bg-blue-800 text-white text-sm font-medium rounded transition-colors"
|
|
>
|
|
Dismiss
|
|
</button>
|
|
<button
|
|
onClick={() => {
|
|
setShowBanner(false);
|
|
window.location.href = '/?tab=compose';
|
|
}}
|
|
className="flex-1 px-3 py-2 bg-white hover:bg-blue-50 text-blue-600 text-sm font-medium rounded transition-colors"
|
|
>
|
|
Compose Prayer
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|