'use client'; import { useState, useEffect } from 'react'; import { useAuth } from '@/context/AuthContext'; import Login from '@/components/Login'; import Admin from '@/components/Admin'; import Profile from '@/components/Profile'; import { db } from '@/lib/firebase'; import { doc, setDoc, collection, addDoc, getDocs, updateDoc, query, where, getDoc } from 'firebase/firestore'; import emailjs from '@emailjs/browser'; import jsPDF from 'jspdf'; import { CSVLink } from 'react-csv'; interface Prayer { id: string; userId?: string; date: string; type: 'prayer' | 'praise'; text: string; journal: string; email: string; prayFor: string; archived?: boolean; reminderFrequency?: 'daily' | 'weekly' | 'monthly' | 'never'; includeActiveSummary?: boolean; answered?: boolean; answeredDate?: string; } export default function Home() { const [prayers, setPrayers] = useState([]); const [sharedPrayers, setSharedPrayers] = useState([]); const [form, setForm] = useState({ date: new Date().toISOString().split('T')[0], type: 'prayer' as 'prayer' | 'praise', text: '', journal: '', email: '', prayFor: '', reminderFrequency: 'never' as 'daily' | 'weekly' | 'monthly' | 'never', includeActiveSummary: false, }); const [showAdmin, setShowAdmin] = useState(false); const [showProfile, setShowProfile] = useState(false); const [searchTerm, setSearchTerm] = useState(''); const [currentPage, setCurrentPage] = useState(1); const [activeTab, setActiveTab] = useState<'add' | 'active' | 'archived' | 'search' | 'community'>('add'); const itemsPerPage = 10; const { user, loading, logout, isAdmin } = useAuth(); const [showLoadingScreen, setShowLoadingScreen] = useState(true); const [editingPrayer, setEditingPrayer] = useState(null); const [dateFrom, setDateFrom] = useState(''); const [dateTo, setDateTo] = useState(''); const [typeFilter, setTypeFilter] = useState<'all' | 'prayer' | 'praise'>('all'); const [userProfile, setUserProfile] = useState({}); // Ensure loading screen shows for at least 5 seconds useEffect(() => { const timer = setTimeout(() => { setShowLoadingScreen(false); }, 5000); // 5 seconds minimum return () => clearTimeout(timer); }, []); // Load prayers from Firestore const loadPrayers = async () => { if (!user) return; try { const prayersRef = collection(db, 'prayers'); const q = query(prayersRef, where('userId', '==', user.uid)); const querySnapshot = await getDocs(q); const loadedPrayers: Prayer[] = []; querySnapshot.forEach((doc) => { loadedPrayers.push({ id: doc.id, ...doc.data() } as Prayer); }); setPrayers(loadedPrayers); } catch (error) { console.error('Error loading prayers:', error); } }; // Load shared prayers const loadSharedPrayers = async () => { try { const sharedRef = collection(db, 'sharedPrayers'); const querySnapshot = await getDocs(sharedRef); const loadedShared: Prayer[] = []; querySnapshot.forEach((doc) => { loadedShared.push({ id: doc.id, ...doc.data() } as Prayer); }); setSharedPrayers(loadedShared); } catch (error) { console.error('Error loading shared prayers:', error); } }; // Load prayers when user changes useEffect(() => { if (user) { loadPrayers(); } else { setPrayers([]); // Clear prayers when user logs out } }, [user]); // Load shared prayers on mount useEffect(() => { loadSharedPrayers(); }, []); // Load user profile useEffect(() => { const loadUserProfile = async () => { if (!user) return; try { const docRef = doc(db, 'users', user.uid); const docSnap = await getDoc(docRef); if (docSnap.exists()) { setUserProfile(docSnap.data()); } } catch (error) { console.error('Error loading user profile:', error); } }; loadUserProfile(); }, [user]); // Export functions const exportToPDF = (prayerList: Prayer[], title: string) => { const doc = new jsPDF(); doc.text(title, 10, 10); let y = 20; prayerList.forEach((prayer, index) => { if (y > 270) { doc.addPage(); y = 10; } doc.text(`${index + 1}. ${prayer.date} - ${prayer.type.toUpperCase()}: ${prayer.text}`, 10, y); y += 10; if (prayer.prayFor) { doc.text(`Praying for: ${prayer.prayFor}`, 10, y); y += 10; } if (prayer.journal) { doc.text(`Journal: ${prayer.journal}`, 10, y); y += 10; } y += 5; }); doc.save(`${title.replace(/\s+/g, '_')}.pdf`); }; const exportToJSON = (prayerList: Prayer[], title: string) => { const dataStr = JSON.stringify(prayerList, null, 2); const dataUri = 'data:application/json;charset=utf-8,'+ encodeURIComponent(dataStr); const exportFileDefaultName = `${title.replace(/\s+/g, '_')}.json`; const linkElement = document.createElement('a'); linkElement.setAttribute('href', dataUri); linkElement.setAttribute('download', exportFileDefaultName); linkElement.click(); }; const getCSVData = (prayerList: Prayer[]) => { return prayerList.map(prayer => ({ Date: prayer.date, Type: prayer.type, Text: prayer.text, PrayFor: prayer.prayFor, Journal: prayer.journal, Email: prayer.email, Archived: prayer.archived ? 'Yes' : 'No' })); }; // Auto-populate email field with user's email useEffect(() => { if (user?.email) { setForm(prev => ({ ...prev, email: user.email! })); } }, [user]); // Load draft from localStorage useEffect(() => { const draft = localStorage.getItem('prayerDraft'); if (draft) { try { setForm(JSON.parse(draft)); } catch (e) { console.error('Error loading draft:', e); } } }, []); // Save draft to localStorage useEffect(() => { localStorage.setItem('prayerDraft', JSON.stringify(form)); }, [form]); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!user) { alert('Please log in to save prayers'); return; } try { const prayerData = { userId: user.uid, date: form.date, type: form.type, text: form.text, journal: form.journal, email: form.email, prayFor: form.prayFor, reminderFrequency: form.reminderFrequency, includeActiveSummary: form.includeActiveSummary, archived: editingPrayer ? editingPrayer.archived : false, }; if (editingPrayer) { // Update existing prayer await updateDoc(doc(db, 'prayers', editingPrayer.id), prayerData); // Update local state setPrayers(prev => prev.map(p => p.id === editingPrayer.id ? { ...p, ...prayerData } : p )); // Reset editing state setEditingPrayer(null); } else { // Add new prayer const docRef = await addDoc(collection(db, 'prayers'), prayerData); // Add to local state with Firestore ID const newPrayer: Prayer = { id: docRef.id, ...prayerData, }; setPrayers(prev => [...prev, newPrayer]); // Store user reminder preferences in Firestore if (form.reminderFrequency !== 'never') { await setDoc(doc(db, 'users', user.uid), { email: form.email, reminderFrequency: form.reminderFrequency, includeActiveSummary: form.includeActiveSummary, lastEmailSent: null, }, { merge: true }); console.log('✅ Reminder preferences saved'); } // Send immediate email using EmailJS if reminder frequency is set if (form.reminderFrequency !== 'never' && form.email) { try { // EmailJS configuration - you'll need to set these up at emailjs.com const serviceId = process.env.NEXT_PUBLIC_EMAILJS_SERVICE_ID || 'your_service_id'; const templateId = process.env.NEXT_PUBLIC_EMAILJS_TEMPLATE_ID || 'your_template_id'; const publicKey = process.env.NEXT_PUBLIC_EMAILJS_PUBLIC_KEY || 'your_public_key'; const templateParams = { to_email: form.email, from_name: 'Prayer App', to_name: user.displayName || user.email?.split('@')[0] || 'Prayer User', subject: `New ${form.type} added - ${form.reminderFrequency} reminders enabled`, message: `Date: ${form.date}\n\n${form.text}\n\nJournal: ${form.journal || 'None'}${form.prayFor ? `\n\nPraying for: ${form.prayFor}` : ''}`, prayer_type: form.type, prayer_date: form.date, prayer_text: form.text, prayer_journal: form.journal || 'None', praying_for: form.prayFor || 'Not specified', reminder_frequency: form.reminderFrequency, }; // Only send if EmailJS is properly configured if (serviceId !== 'your_service_id' && templateId !== 'your_template_id' && publicKey !== 'your_public_key') { await emailjs.send(serviceId, templateId, templateParams, publicKey); console.log('✅ Email sent via EmailJS'); } else { console.log('ℹ️ EmailJS not configured - email sending skipped (this is normal)'); } } catch (emailError) { console.error('❌ EmailJS error:', emailError); // Don't fail the prayer submission if email fails } } } // Reset form setForm({ date: new Date().toISOString().split('T')[0], type: 'prayer', text: '', journal: '', email: user.email || '', prayFor: '', reminderFrequency: 'never', includeActiveSummary: false, }); } catch (error) { console.error('Error saving prayer:', error); alert('Failed to save prayer. Please try again.'); } }; const activePrayers = prayers.filter(prayer => !prayer.archived); const archivedPrayers = prayers.filter(prayer => prayer.archived); // Enhanced filtering function const applyFilters = (prayerList: Prayer[]) => { return prayerList.filter(prayer => { // Keyword search const matchesSearch = !searchTerm || prayer.text.toLowerCase().includes(searchTerm.toLowerCase()) || prayer.journal.toLowerCase().includes(searchTerm.toLowerCase()) || prayer.type.toLowerCase().includes(searchTerm.toLowerCase()) || prayer.prayFor.toLowerCase().includes(searchTerm.toLowerCase()); // Date range filter const prayerDate = new Date(prayer.date); const fromDate = dateFrom ? new Date(dateFrom) : null; const toDateFilter = dateTo ? new Date(dateTo) : null; const matchesDateFrom = !fromDate || prayerDate >= fromDate; const matchesDateTo = !toDateFilter || prayerDate <= toDateFilter; // Type filter const matchesType = typeFilter === 'all' || prayer.type === typeFilter; return matchesSearch && matchesDateFrom && matchesDateTo && matchesType; }); }; // Apply filters to each prayer list const filteredActivePrayers = applyFilters(activePrayers); const filteredArchivedPrayers = applyFilters(archivedPrayers); // For search tab, combine all filtered prayers const allPrayers = [...activePrayers, ...archivedPrayers]; const filteredSearchPrayers = applyFilters(allPrayers); // Pagination logic const totalActivePages = Math.ceil(filteredActivePrayers.length / itemsPerPage); const totalArchivedPages = Math.ceil(filteredArchivedPrayers.length / itemsPerPage); const totalSearchPages = Math.ceil(filteredSearchPrayers.length / itemsPerPage); const paginatedActivePrayers = filteredActivePrayers.slice( (currentPage - 1) * itemsPerPage, currentPage * itemsPerPage ); const paginatedArchivedPrayers = filteredArchivedPrayers.slice( (currentPage - 1) * itemsPerPage, currentPage * itemsPerPage ); const paginatedSearchPrayers = filteredSearchPrayers.slice( (currentPage - 1) * itemsPerPage, currentPage * itemsPerPage ); const currentPrayers = activeTab === 'active' ? paginatedActivePrayers : activeTab === 'archived' ? paginatedArchivedPrayers : activeTab === 'search' ? paginatedSearchPrayers : sharedPrayers; // Community const currentTotalPages = activeTab === 'active' ? totalActivePages : activeTab === 'archived' ? totalArchivedPages : activeTab === 'search' ? totalSearchPages : 1; // Community const groupedPrayers = currentPrayers.reduce((acc, prayer) => { if (!acc[prayer.date]) acc[prayer.date] = []; acc[prayer.date].push(prayer); return acc; }, {} as Record); const sharePrayer = async (prayer: Prayer) => { const shareText = `${prayer.type.toUpperCase()}: ${prayer.text}${prayer.journal ? `\n\nJournal: ${prayer.journal}` : ''}`; if (navigator.share) { try { await navigator.share({ title: `Shared ${prayer.type}`, text: shareText, }); // Show success feedback const button = document.activeElement as HTMLElement; if (button) { const originalText = button.textContent; button.textContent = '✅ Shared!'; button.classList.add('bg-green-600', 'hover:bg-green-700'); setTimeout(() => { button.textContent = originalText; button.classList.remove('bg-green-600', 'hover:bg-green-700'); }, 2000); } } catch (err) { console.log('Share cancelled'); } } else { // Fallback: copy to clipboard try { await navigator.clipboard.writeText(shareText); // Show success feedback const button = document.activeElement as HTMLElement; if (button) { const originalText = button.textContent; button.textContent = '📋 Copied!'; button.classList.add('bg-green-600', 'hover:bg-green-700'); setTimeout(() => { button.textContent = originalText; button.classList.remove('bg-green-600', 'hover:bg-green-700'); }, 2000); } } catch (clipboardErr) { alert('Prayer copied to clipboard!'); } } }; const shareToCommunity = async (prayer: Prayer) => { try { await addDoc(collection(db, 'sharedPrayers'), { ...prayer, userId: null, // Anonymous sharedAt: new Date(), }); loadSharedPrayers(); // Reload alert('Prayer shared to community!'); } catch (error) { console.error('Error sharing to community:', error); } }; // Archive/unarchive prayers in Firestore const toggleArchivePrayer = async (prayerId: string, archived: boolean) => { try { await updateDoc(doc(db, 'prayers', prayerId), { archived: archived }); // Update local state setPrayers(prev => prev.map(p => p.id === prayerId ? { ...p, archived: archived } : p )); } catch (error) { console.error('Error updating prayer archive status:', error); alert('Failed to update prayer. Please try again.'); } }; // Mark prayer as answered/unanswered const toggleAnsweredPrayer = async (prayerId: string, answered: boolean) => { try { const updateData: any = { answered }; if (answered) { updateData.answeredDate = new Date().toISOString().split('T')[0]; } else { updateData.answeredDate = null; } await updateDoc(doc(db, 'prayers', prayerId), updateData); // Update local state setPrayers(prev => prev.map(p => p.id === prayerId ? { ...p, answered, answeredDate: answered ? new Date().toISOString().split('T')[0] : undefined } : p )); // Send notification if answered and notifications are enabled if (answered && userProfile.notificationsEnabled) { // This would trigger a server-side notification via Firebase Functions console.log('Prayer answered - notification would be sent'); } } catch (error) { console.error('Error updating prayer answered status:', error); alert('Failed to update prayer. Please try again.'); } }; // Start editing a prayer const startEditing = (prayer: Prayer) => { setEditingPrayer(prayer); setForm({ date: prayer.date, type: prayer.type, text: prayer.text, journal: prayer.journal || '', email: prayer.email, prayFor: prayer.prayFor || '', reminderFrequency: prayer.reminderFrequency || 'never', includeActiveSummary: prayer.includeActiveSummary || false, }); setActiveTab('add'); // Switch to add tab to show form }; // Cancel editing const cancelEditing = () => { setEditingPrayer(null); setForm({ date: new Date().toISOString().split('T')[0], type: 'prayer', text: '', journal: '', email: user?.email || '', prayFor: '', reminderFrequency: 'never', includeActiveSummary: false, }); }; if (loading || showLoadingScreen) { return (
{/* Animated prayer icon */}
{/* Outer ring */}
{/* Inner ring */}
{/* Center icon */}
🙏
{/* Floating particles */}
{/* Loading text */}

Prayer App

Preparing your spiritual journey...

{/* Inspirational quote */}
"Be anxious for nothing, but in everything by prayer and supplication, with thanksgiving, let your requests be made known to God."
— Philippians 4:6
{/* Progress dots */}
); } if (!user) { return ; } return (

Prayer App

{editingPrayer ? 'Edit Prayer or Praise' : activeTab === 'add' ? 'Add New Prayer or Praise' : activeTab === 'search' ? 'Search Results' : `${activeTab.charAt(0).toUpperCase() + activeTab.slice(1)} Prayers`}

{isAdmin && ( )}
{showAdmin && } {showProfile && } {(activeTab === 'active' || activeTab === 'archived') && (
!p.archived) : prayers.filter(p => p.archived))} filename={`${activeTab}_prayers.csv`} className="px-4 py-2 bg-green-600 hover:bg-green-700 text-white text-sm font-medium rounded-lg transition-all duration-200 inline-block" > Export CSV
)} {activeTab === 'add' && (
setForm(prev => ({ ...prev, date: e.target.value }))} className="w-full p-3 bg-gray-800 border border-gray-600 rounded text-base" required />
setForm(prev => ({ ...prev, prayFor: e.target.value }))} className="w-full p-3 bg-gray-800 border border-gray-600 rounded text-base" placeholder="Name of person to pray for..." />