- 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>
381 lines
13 KiB
TypeScript
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>
|
|
)
|
|
} |