Files
biblical-guide.com/app/[locale]/prayers/page.tsx
andupetcu a0969e88df Implement complete multi-language support with Romanian/English
- Added next-intl for internationalization with Romanian as default locale
- Restructured app directory with [locale] routing (/ro, /en)
- Created comprehensive translation files for both languages
- Fixed Next.js 15 async params compatibility in layout components
- Updated all components to use proper i18n hooks and translations
- Configured middleware for locale routing and fallbacks
- Fixed FloatingChat component translation array handling
- Restored complete home page with internationalized content
- Fixed Material-UI Slide component prop error (mountOnExit → unmountOnExit)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-20 15:43:51 +03:00

381 lines
13 KiB
TypeScript

'use client'
import {
Container,
Grid,
Card,
CardContent,
Typography,
Box,
TextField,
Button,
Paper,
Avatar,
Chip,
IconButton,
Dialog,
DialogTitle,
DialogContent,
DialogActions,
Fab,
List,
ListItem,
ListItemAvatar,
ListItemText,
MenuItem,
useTheme,
} from '@mui/material'
import {
Favorite,
Add,
Close,
Person,
AccessTime,
FavoriteBorder,
Share,
MoreVert,
} from '@mui/icons-material'
import { Navigation } from '@/components/layout/navigation'
import { useState, useEffect } from 'react'
interface PrayerRequest {
id: string
title: string
description: string
category: string
author: string
timestamp: Date
prayerCount: number
isPrayedFor: boolean
}
export default function PrayersPage() {
const theme = useTheme()
const [prayers, setPrayers] = useState<PrayerRequest[]>([])
const [openDialog, setOpenDialog] = useState(false)
const [newPrayer, setNewPrayer] = useState({
title: '',
description: '',
category: 'personal',
})
const [loading, setLoading] = useState(true)
const categories = [
{ value: 'personal', label: 'Personal', color: 'primary' },
{ value: 'family', label: 'Familie', color: 'secondary' },
{ value: 'health', label: 'Sănătate', color: 'error' },
{ value: 'work', label: 'Muncă', color: 'warning' },
{ value: 'ministry', label: 'Serviciu', color: 'success' },
{ value: 'world', label: 'Lume', color: 'info' },
]
// Sample data - in real app this would come from API
useEffect(() => {
// Simulate loading prayers
setTimeout(() => {
setPrayers([
{
id: '1',
title: 'Rugăciune pentru vindecare',
description: 'Te rog să te rogi pentru tatăl meu care se află în spital. Are nevoie de vindecarea lui Dumnezeu.',
category: 'health',
author: 'Maria P.',
timestamp: new Date(Date.now() - 2 * 60 * 60 * 1000), // 2 hours ago
prayerCount: 23,
isPrayedFor: false,
},
{
id: '2',
title: 'Îndrumarea lui Dumnezeu în carieră',
description: 'Caut direcția lui Dumnezeu pentru următorul pas în cariera mea. Te rog să te rogi pentru claritate și pace.',
category: 'work',
author: 'Alexandru M.',
timestamp: new Date(Date.now() - 5 * 60 * 60 * 1000), // 5 hours ago
prayerCount: 15,
isPrayedFor: true,
},
{
id: '3',
title: 'Unitatea în familia noastră',
description: 'Rugați-vă pentru restaurarea relațiilor în familia noastră și pentru iertarea reciprocă.',
category: 'family',
author: 'Anonim',
timestamp: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000), // 1 day ago
prayerCount: 41,
isPrayedFor: false,
},
])
setLoading(false)
}, 1000)
}, [])
const handleSubmitPrayer = async () => {
if (!newPrayer.title.trim() || !newPrayer.description.trim()) return
const prayer: PrayerRequest = {
id: Date.now().toString(),
title: newPrayer.title,
description: newPrayer.description,
category: newPrayer.category,
author: 'Tu', // In real app, get from auth
timestamp: new Date(),
prayerCount: 0,
isPrayedFor: false,
}
setPrayers([prayer, ...prayers])
setNewPrayer({ title: '', description: '', category: 'personal' })
setOpenDialog(false)
// In real app, send to API
try {
await fetch('/api/prayers', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(prayer),
})
} catch (error) {
console.error('Error submitting prayer:', error)
}
}
const handlePrayFor = async (prayerId: string) => {
setPrayers(prayers.map(prayer =>
prayer.id === prayerId
? { ...prayer, prayerCount: prayer.prayerCount + 1, isPrayedFor: true }
: prayer
))
// In real app, send to API
try {
await fetch(`/api/prayers/${prayerId}/pray`, { method: 'POST' })
} 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 now = new Date()
const diff = now.getTime() - timestamp.getTime()
const hours = Math.floor(diff / (1000 * 60 * 60))
const days = Math.floor(hours / 24)
if (days > 0) return `${days} zile în urmă`
if (hours > 0) return `${hours} ore în urmă`
return 'Acum câteva minute'
}
return (
<Box>
<Navigation />
<Container maxWidth="lg" sx={{ py: 4 }}>
{/* Header */}
<Box sx={{ mb: 4, textAlign: 'center' }}>
<Typography variant="h3" component="h1" gutterBottom>
<Favorite sx={{ fontSize: 40, mr: 2, verticalAlign: 'middle', color: 'error.main' }} />
Peretele de rugăciuni
</Typography>
<Typography variant="body1" color="text.secondary">
Partajează rugăciuni și roagă-te împreună cu comunitatea
</Typography>
</Box>
<Grid container spacing={4}>
{/* Categories Filter */}
<Grid item xs={12} md={3}>
<Card>
<CardContent>
<Typography variant="h6" gutterBottom>
Categorii
</Typography>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
{categories.map((category) => (
<Chip
key={category.value}
label={category.label}
color={category.color as any}
variant="outlined"
size="small"
sx={{ justifyContent: 'flex-start' }}
/>
))}
</Box>
<Typography variant="h6" sx={{ mt: 3, mb: 1 }}>
Statistici
</Typography>
<Typography variant="body2" color="text.secondary">
{prayers.length} cereri active<br />
{prayers.reduce((sum, p) => sum + p.prayerCount, 0)} rugăciuni totale<br />
{prayers.filter(p => p.isPrayedFor).length} cereri la care te-ai rugat
</Typography>
</CardContent>
</Card>
</Grid>
{/* Prayer Requests */}
<Grid item xs={12} md={9}>
{loading ? (
<Typography textAlign="center">Se încarcă rugăciunile...</Typography>
) : (
<Box>
{prayers.map((prayer) => {
const categoryInfo = getCategoryInfo(prayer.category)
return (
<Card key={prayer.id} sx={{ mb: 3 }}>
<CardContent>
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', mb: 2 }}>
<Box sx={{ flexGrow: 1 }}>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, mb: 1 }}>
<Typography variant="h6" component="h3">
{prayer.title}
</Typography>
<Chip
label={categoryInfo.label}
color={categoryInfo.color as any}
size="small"
variant="outlined"
/>
</Box>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2, mb: 2 }}>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
<Avatar sx={{ width: 24, height: 24, bgcolor: 'primary.main' }}>
<Person sx={{ fontSize: 16 }} />
</Avatar>
<Typography variant="body2" color="text.secondary">
{prayer.author}
</Typography>
</Box>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
<AccessTime sx={{ fontSize: 16, color: 'text.secondary' }} />
<Typography variant="body2" color="text.secondary">
{formatTimestamp(prayer.timestamp)}
</Typography>
</Box>
</Box>
<Typography variant="body1" sx={{ mb: 2 }}>
{prayer.description}
</Typography>
</Box>
<IconButton size="small">
<MoreVert />
</IconButton>
</Box>
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<Box sx={{ display: 'flex', gap: 1 }}>
<Button
variant={prayer.isPrayedFor ? "contained" : "outlined"}
color="primary"
size="small"
startIcon={prayer.isPrayedFor ? <Favorite /> : <FavoriteBorder />}
onClick={() => handlePrayFor(prayer.id)}
disabled={prayer.isPrayedFor}
>
{prayer.isPrayedFor ? 'M-am rugat' : 'Mă rog'}
</Button>
<Button
variant="outlined"
size="small"
startIcon={<Share />}
>
Partajează
</Button>
</Box>
<Typography variant="body2" color="text.secondary">
{prayer.prayerCount} {prayer.prayerCount === 1 ? 'rugăciune' : 'rugăciuni'}
</Typography>
</Box>
</CardContent>
</Card>
)
})}
</Box>
)}
</Grid>
</Grid>
{/* Add Prayer FAB */}
<Fab
color="primary"
aria-label="add prayer"
sx={{ position: 'fixed', bottom: 24, right: 24 }}
onClick={() => setOpenDialog(true)}
>
<Add />
</Fab>
{/* Add Prayer Dialog */}
<Dialog
open={openDialog}
onClose={() => setOpenDialog(false)}
maxWidth="sm"
fullWidth
>
<DialogTitle>
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
Adaugă o cerere de rugăciune
<IconButton onClick={() => setOpenDialog(false)} size="small">
<Close />
</IconButton>
</Box>
</DialogTitle>
<DialogContent>
<TextField
fullWidth
label="Titlu"
value={newPrayer.title}
onChange={(e) => setNewPrayer({ ...newPrayer, title: e.target.value })}
sx={{ mb: 2, mt: 1 }}
/>
<TextField
fullWidth
label="Categoria"
select
value={newPrayer.category}
onChange={(e) => setNewPrayer({ ...newPrayer, category: e.target.value })}
sx={{ mb: 2 }}
>
{categories.map((option) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</TextField>
<TextField
fullWidth
label="Descriere"
multiline
rows={4}
value={newPrayer.description}
onChange={(e) => setNewPrayer({ ...newPrayer, description: e.target.value })}
placeholder="Descrie cererea ta de rugăciune..."
/>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpenDialog(false)}>
Anulează
</Button>
<Button
onClick={handleSubmitPrayer}
variant="contained"
disabled={!newPrayer.title.trim() || !newPrayer.description.trim()}
>
Adaugă rugăciunea
</Button>
</DialogActions>
</Dialog>
</Container>
</Box>
)
}