Major improvements: Firebase data migration, enhanced loading screens, multi-day prayer tracking

- 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
This commit is contained in:
nmemmert committed 2026-01-19 10:11:57 -05:00
1 parent 2c29fc28d6
commit 67c5ff1b35
13 files changed
+419 -138

No files matched your search

+56 -30
View File
@@ -2,6 +2,9 @@
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;
@@ -11,47 +14,70 @@ 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(() => {
// Check if reminders are enabled and if it's reminder time
const remindersEnabled = localStorage.getItem('prayerRemindersEnabled') === 'true';
const savedTime = localStorage.getItem('prayerReminderTime') || '09:00';
const lastReminderDate = localStorage.getItem('lastPrayerReminderDate');
setReminderTime(savedTime);
if (!user) return;
if (!remindersEnabled) 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);
// 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);
if (!remindersEnabled) return;
// 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
// 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);
if (withinWindow) {
// Check if we already showed reminder today
const today = new Date().toISOString().split('T')[0];
const lastDate = lastReminderDate?.split('T')[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 (lastDate !== today) {
setIsTime(true);
setShowBanner(true);
localStorage.setItem('lastPrayerReminderDate', new Date().toISOString());
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);
}
}
};
checkIfTimeToRemind();
// Check every minute
const interval = setInterval(checkIfTimeToRemind, 60000);
return () => clearInterval(interval);
}, []);
loadSettingsAndCheck();
}, [user]);
if (!showBanner) return null;