'use client' import { Container, Card, CardContent, Typography, Box, TextField, Button, Paper, Avatar, Chip, IconButton, Dialog, DialogTitle, DialogContent, DialogActions, ListItemText, MenuItem, useTheme, useMediaQuery, CircularProgress, Skeleton, Alert, Tabs, Tab, FormControlLabel, FormControl, Select, Checkbox, SelectChangeEvent, Switch, Accordion, AccordionSummary, AccordionDetails, } from '@mui/material' import { Favorite, Add, Close, Person, AccessTime, FavoriteBorder, Share, MoreVert, AutoAwesome, Edit, Login, ExpandMore, } from '@mui/icons-material' import { useState, useEffect, useMemo } from 'react' import { useTranslations, useLocale, useFormatter } from 'next-intl' import { useAuth } from '@/hooks/use-auth' import { AuthModal } from '@/components/auth/auth-modal' interface PrayerRequest { id: string title: string description: string category: string author: string timestamp: Date prayerCount: number isPrayedFor: boolean isPublic: boolean language: string isOwner: boolean } export default function PrayersPage() { const theme = useTheme() const locale = useLocale() const t = useTranslations('pages.prayers') const tc = useTranslations('common') const f = useFormatter() const { user } = useAuth() const isMobile = useMediaQuery(theme.breakpoints.down('md')) const [prayers, setPrayers] = useState([]) const [selectedCategory, setSelectedCategory] = useState('all') const [openDialog, setOpenDialog] = useState(false) const [tabValue, setTabValue] = useState(0) // 0 = Write, 1 = AI Generate const [newPrayer, setNewPrayer] = useState({ title: '', description: '', category: 'personal', isPublic: false, }) const [aiPrompt, setAiPrompt] = useState('') const [isGenerating, setIsGenerating] = useState(false) const [loading, setLoading] = useState(true) const [viewMode, setViewMode] = useState<'private' | 'public'>(user ? 'private' : 'public') const [selectedLanguage, setSelectedLanguage] = useState(locale) const [authModalOpen, setAuthModalOpen] = useState(false) const languageOptions = useMemo(() => ([ { value: 'en', label: t('languageFilter.options.en') }, { value: 'ro', label: t('languageFilter.options.ro') }, { value: 'es', label: t('languageFilter.options.es') }, { value: 'it', label: t('languageFilter.options.it') } ]), [t]) const languageLabelMap = useMemo(() => ( languageOptions.reduce((acc, option) => { acc[option.value] = option.label return acc }, {} as Record) ), [languageOptions]) useEffect(() => { if (user) { setViewMode(prev => (prev === 'private' ? prev : 'private')) } else { setViewMode('public') } }, [user]) useEffect(() => { if (viewMode === 'public') { setSelectedLanguage(locale) } }, [locale, viewMode]) const categories = [ { value: 'personal', label: t('categories.personal'), color: 'primary' }, { value: 'family', label: t('categories.family'), color: 'secondary' }, { value: 'health', label: t('categories.health'), color: 'error' }, { value: 'work', label: t('categories.work'), color: 'warning' }, { value: 'ministry', label: t('categories.ministry'), color: 'success' }, { value: 'world', label: t('categories.world'), color: 'info' }, ] // Fetch prayers from API const fetchPrayers = async () => { if (viewMode === 'private' && !user) { setPrayers([]) setLoading(false) return } setLoading(true) try { const params = new URLSearchParams() if (selectedCategory !== 'all') { params.append('category', selectedCategory) } params.append('limit', '50') params.append('visibility', viewMode) if (viewMode === 'public') { params.append('languages', selectedLanguage) } const headers: Record = {} if (typeof window !== 'undefined') { const token = localStorage.getItem('authToken') if (token) { headers['Authorization'] = `Bearer ${token}` } } const response = await fetch(`/api/prayers?${params.toString()}`, { headers }) if (response.ok) { const data = await response.json() setPrayers(data.prayers.map((prayer: any) => ({ ...prayer, timestamp: new Date(prayer.timestamp) }))) } else { if (response.status === 401) { setPrayers([]) } console.error('Failed to fetch prayers') } } catch (error) { console.error('Error fetching prayers:', error) } finally { setLoading(false) } } useEffect(() => { fetchPrayers() }, [selectedCategory, user, viewMode, selectedLanguage]) const handleGenerateAIPrayer = async () => { if (!aiPrompt.trim()) return if (!user) return setIsGenerating(true) try { const response = await fetch('/api/prayers/generate', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('authToken')}` }, body: JSON.stringify({ prompt: aiPrompt, category: newPrayer.category, locale }), }) if (response.ok) { const data = await response.json() setNewPrayer({ title: data.title || '', description: data.prayer || '', category: newPrayer.category, isPublic: newPrayer.isPublic }) setTabValue(0) // Switch to write tab to review generated prayer } else { console.error('Failed to generate prayer') } } catch (error) { console.error('Error generating prayer:', error) } finally { setIsGenerating(false) } } const handleLanguageChange = (event: SelectChangeEvent) => { const value = event.target.value setSelectedLanguage(value) } const handleSubmitPrayer = async () => { if (!newPrayer.title.trim() || !newPrayer.description.trim()) return if (!user) return try { const token = localStorage.getItem('authToken') const response = await fetch('/api/prayers', { method: 'POST', headers: { 'Content-Type': 'application/json', ...(token ? { 'Authorization': `Bearer ${token}` } : {}) }, body: JSON.stringify({ title: newPrayer.title, description: newPrayer.description, category: newPrayer.category, isAnonymous: false, isPublic: newPrayer.isPublic, language: locale }), }) if (response.ok) { await fetchPrayers() setNewPrayer({ title: '', description: '', category: 'personal', isPublic: false }) setAiPrompt('') setTabValue(0) setOpenDialog(false) } else { console.error('Failed to submit prayer') } } catch (error) { console.error('Error submitting prayer:', error) } } const handleOpenDialog = () => { if (!user) { setAuthModalOpen(true) return } setOpenDialog(true) } const handleAuthSuccess = () => { setAuthModalOpen(false) // After successful auth, open the add prayer dialog setOpenDialog(true) } const handlePrayFor = async (prayerId: string) => { try { const headers: HeadersInit = { 'Content-Type': 'application/json' } const authToken = localStorage.getItem('authToken') if (authToken) { headers['Authorization'] = `Bearer ${authToken}` } const response = await fetch(`/api/prayers/${prayerId}/pray`, { method: 'POST', headers }) if (response.ok) { const data = await response.json() setPrayers(prayers.map(prayer => prayer.id === prayerId ? { ...prayer, prayerCount: data.prayerCount || prayer.prayerCount + 1, isPrayedFor: true } : prayer )) } else { console.error('Failed to update prayer count') } } catch (error) { console.error('Error updating prayer count:', error) } } const getCategoryInfo = (category: string) => { return categories.find(cat => cat.value === category) || categories[0] } const formatTimestamp = (timestamp: Date) => { const currentTime = new Date() try { // Use the correct API: relativeTime(date, now) return f.relativeTime(timestamp, currentTime) } catch (e) { // Fallback to simple formatting if relativeTime fails const diff = currentTime.getTime() - timestamp.getTime() const minutes = Math.floor(diff / (1000 * 60)) const hours = Math.floor(minutes / 60) const days = Math.floor(hours / 24) if (days > 0) return locale === 'ro' ? `acum ${days} ${days === 1 ? 'zi' : 'zile'}` : `${days} ${days === 1 ? 'day' : 'days'} ago` if (hours > 0) return locale === 'ro' ? `acum ${hours} ${hours === 1 ? 'oră' : 'ore'}` : `${hours} ${hours === 1 ? 'hour' : 'hours'} ago` if (minutes > 0) return locale === 'ro' ? `acum ${minutes} ${minutes === 1 ? 'minut' : 'minute'}` : `${minutes} ${minutes === 1 ? 'minute' : 'minutes'} ago` return locale === 'ro' ? 'acum' : 'just now' } } return ( {/* Header */} {t('title')} {t('subtitle')} {/* Categories Filter */} {/* Add Prayer Button */} {user ? ( ) : ( )} {/* Categories Accordion */} } aria-controls="categories-content" id="categories-header" > {t('categories.title')} setSelectedCategory('all')} sx={{ justifyContent: 'flex-start', cursor: 'pointer' }} /> {categories.map((category) => ( setSelectedCategory(category.value)} sx={{ justifyContent: 'flex-start', cursor: 'pointer' }} /> ))} {/* Language Filter Accordion */} {viewMode === 'public' && ( } aria-controls="language-content" id="language-header" > {t('languageFilter.title')} {t('languageFilter.helper')} )} {/* Stats Accordion */} } aria-controls="stats-content" id="stats-header" > {t('stats.title')} • {t('stats.activeRequests', { count: prayers.length })}
• {t('stats.totalPrayers', { count: prayers.reduce((sum, p) => sum + p.prayerCount, 0) })}
• {t('stats.youPrayed', { count: prayers.filter(p => p.isPrayedFor).length })}
{/* Prayer Requests */} {user && ( setViewMode(newValue as 'private' | 'public')} sx={{ mb: 3 }} variant="fullWidth" > )} {viewMode === 'private' && ( {t('alerts.privateInfo')} )} {viewMode === 'public' && !user && ( {t('alerts.publicInfo')} )} {loading ? ( {Array.from({ length: 3 }).map((_, index) => ( ))} ) : ( {prayers.length === 0 ? ( {viewMode === 'private' ? t('empty.private') : t('empty.public')} ) : prayers.map((prayer) => { const categoryInfo = getCategoryInfo(prayer.category) const authorName = prayer.isOwner ? (locale === 'en' ? 'You' : 'Tu') : prayer.author const languageLabel = languageLabelMap[prayer.language] || prayer.language.toUpperCase() return ( {prayer.title} {authorName} {formatTimestamp(prayer.timestamp)} {prayer.description} {t('stats.totalPrayers', { count: prayer.prayerCount })} ) })} )}
{/* Add Prayer Dialog */} setOpenDialog(false)} maxWidth="md" fullWidth > {t('dialog.title')} setOpenDialog(false)} size="small"> {/* Tabs for Write vs AI Generate */} setTabValue(newValue)} centered> } label={locale === 'en' ? 'Write Prayer' : 'Scrie rugăciune'} iconPosition="start" /> } label={locale === 'en' ? 'AI Generate' : 'Generează cu AI'} iconPosition="start" /> {/* Write Prayer Tab */} {tabValue === 0 && ( setNewPrayer({ ...newPrayer, title: e.target.value })} sx={{ mb: 2, mt: 1 }} /> setNewPrayer({ ...newPrayer, category: e.target.value })} sx={{ mb: 2 }} > {categories.map((option) => ( {option.label} ))} setNewPrayer({ ...newPrayer, description: e.target.value })} placeholder={t('dialog.placeholder')} /> )} {/* AI Generate Prayer Tab */} {tabValue === 1 && ( {locale === 'en' ? 'Describe what you\'d like to pray about, and AI will help you create a meaningful prayer.' : 'Descrie pentru ce ai vrea să te rogi, iar AI-ul te va ajuta să creezi o rugăciune semnificativă.' } setNewPrayer({ ...newPrayer, category: e.target.value })} sx={{ mb: 2 }} > {categories.map((option) => ( {option.label} ))} setAiPrompt(e.target.value)} placeholder={locale === 'en' ? 'e.g., "Help me find peace during a difficult time at work" or "Guidance for my family\'s health struggles"' : 'ex. "Ajută-mă să găsesc pace într-o perioadă dificilă la muncă" sau "Îndrumarea pentru problemele de sănătate ale familiei mele"' } sx={{ mb: 2 }} /> {newPrayer.title && newPrayer.description && ( {locale === 'en' ? 'Prayer generated! Switch to the "Write Prayer" tab to review and edit before submitting.' : 'Rugăciune generată! Comută la tabul "Scrie rugăciune" pentru a revizui și edita înainte de a trimite.' } )} )} setNewPrayer({ ...newPrayer, isPublic: event.target.checked })} /> } label={t('dialog.makePublic')} /> {newPrayer.isPublic ? t('dialog.visibilityPublic') : t('dialog.visibilityPrivate')} {/* Auth Modal */} setAuthModalOpen(false)} onSuccess={handleAuthSuccess} message={t('authRequired')} defaultTab="login" />
) }