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:
1 parent
2c29fc28d6
commit
67c5ff1b35
13 files changed
+419
-138
No files matched your search
+24
-22
@@ -14,6 +14,7 @@ interface Prayer {
|
||||
answerDetails?: string;
|
||||
prayFrequency?: number; // 1-7 times per week
|
||||
lastPrayedFor?: string; // ISO date string
|
||||
prayedDates?: string[]; // Array of dates when prayed for
|
||||
}
|
||||
|
||||
interface HomePageProps {
|
||||
@@ -22,9 +23,10 @@ interface HomePageProps {
|
||||
onStartPraying: () => void;
|
||||
onSelectPrayer: (prayer: Prayer) => void;
|
||||
userName?: string;
|
||||
mostPrayedFor?: string;
|
||||
}
|
||||
|
||||
export default function HomePage({ prayers, todayCount, onStartPraying, onSelectPrayer, userName }: HomePageProps) {
|
||||
export default function HomePage({ prayers, todayCount, onStartPraying, onSelectPrayer, userName, mostPrayedFor }: HomePageProps) {
|
||||
const today = new Date().toISOString().split('T')[0];
|
||||
const todayPrayers = prayers.filter(p => p.date === today);
|
||||
const recentPrayers = prayers.slice(0, 5);
|
||||
@@ -55,7 +57,12 @@ export default function HomePage({ prayers, todayCount, onStartPraying, onSelect
|
||||
const activePrayerCount = prayers.filter(p => !p.answered).length;
|
||||
|
||||
// Count how many active prayers were prayed for today
|
||||
const prayedTodayCount = prayers.filter(p => !p.answered && p.lastPrayedFor === today).length;
|
||||
const prayedTodayCount = prayers.filter(p =>
|
||||
!p.answered && (
|
||||
p.prayedDates?.includes(today) ||
|
||||
p.lastPrayedFor === today
|
||||
)
|
||||
).length;
|
||||
|
||||
// Calculate actual streak - consecutive days with prayers
|
||||
const calculateStreak = () => {
|
||||
@@ -65,8 +72,13 @@ export default function HomePage({ prayers, todayCount, onStartPraying, onSelect
|
||||
const activityDates = new Set<string>();
|
||||
prayers.forEach(p => {
|
||||
activityDates.add(p.date); // Date prayer was created
|
||||
if (p.lastPrayedFor) {
|
||||
activityDates.add(p.lastPrayedFor); // Date marked as prayed for
|
||||
|
||||
// Add all prayed dates from the array
|
||||
if (p.prayedDates && p.prayedDates.length > 0) {
|
||||
p.prayedDates.forEach((date: string) => activityDates.add(date));
|
||||
} else if (p.lastPrayedFor) {
|
||||
// Backward compatibility
|
||||
activityDates.add(p.lastPrayedFor);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -101,15 +113,6 @@ export default function HomePage({ prayers, todayCount, onStartPraying, onSelect
|
||||
? Math.round((answeredPrayers / totalPrayers) * 100)
|
||||
: 0;
|
||||
|
||||
// Get most prayed for person/topic based on lastPrayedFor clicks
|
||||
const prayerForCounts: Record<string, number> = {};
|
||||
prayers.forEach(p => {
|
||||
if (p.prayFor && p.lastPrayedFor) {
|
||||
prayerForCounts[p.prayFor] = (prayerForCounts[p.prayFor] || 0) + 1;
|
||||
}
|
||||
});
|
||||
const mostPrayedFor = Object.entries(prayerForCounts).sort((a, b) => b[1] - a[1])[0];
|
||||
|
||||
// Recent answered prayers
|
||||
const recentAnswered = prayers.filter(p => p.answered).slice(0, 3);
|
||||
|
||||
@@ -122,15 +125,8 @@ export default function HomePage({ prayers, todayCount, onStartPraying, onSelect
|
||||
<div className="absolute bottom-20 left-10 w-72 h-72 bg-purple-500/10 rounded-full blur-3xl"></div>
|
||||
</div>
|
||||
|
||||
{/* Clock */}
|
||||
<div className="max-w-md mx-auto mb-12">
|
||||
<div className="text-center">
|
||||
<Clock />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Header with Personalized Greeting */}
|
||||
<div className="max-w-md mx-auto mb-12 text-center">
|
||||
<div className="max-w-md mx-auto mb-8 text-center">
|
||||
<img src="/icon-192x192.png" alt="Haver icon" className="w-12 h-12 mx-auto mb-3 rounded" />
|
||||
<h1 className="text-4xl font-bold bg-gradient-to-r from-blue-400 to-purple-400 bg-clip-text text-transparent mb-3">
|
||||
{getGreeting()}, {getFirstName()}!
|
||||
@@ -151,9 +147,15 @@ export default function HomePage({ prayers, todayCount, onStartPraying, onSelect
|
||||
All caught up! Start a new prayer to keep your journey going.
|
||||
</p>
|
||||
)}
|
||||
<p className="text-slate-400 mt-2">
|
||||
<p className="text-slate-400 mt-4 text-sm">
|
||||
{new Date().toLocaleDateString('en-US', { weekday: 'long', month: 'long', day: 'numeric' })}
|
||||
</p>
|
||||
{/* Clock - Below Date */}
|
||||
<div className="mt-3 flex justify-center">
|
||||
<div className="scale-75">
|
||||
<Clock />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Stats Grid */}
|
||||
|
||||
Reference in new issue
Block a user