diff --git a/app/[locale]/prayers/page.tsx b/app/[locale]/prayers/page.tsx index d600239..a8c50bf 100644 --- a/app/[locale]/prayers/page.tsx +++ b/app/[locale]/prayers/page.tsx @@ -16,7 +16,6 @@ import { DialogTitle, DialogContent, DialogActions, - Fab, List, ListItem, ListItemAvatar, @@ -45,7 +44,7 @@ import { Login, } from '@mui/icons-material' import { useState, useEffect } from 'react' -import { useTranslations, useLocale, useFormatter } from 'next-intl' +import { useTranslations, useLocale, useFormatter, useNow } from 'next-intl' import { useAuth } from '@/hooks/use-auth' interface PrayerRequest { @@ -65,8 +64,10 @@ export default function PrayersPage() { const t = useTranslations('pages.prayers') const tc = useTranslations('common') const f = useFormatter() + const now = useNow() const { user } = useAuth() 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({ @@ -87,45 +88,39 @@ export default function PrayersPage() { { value: 'world', label: t('categories.world'), color: 'info' }, ] - // Sample data - in real app this would come from API - useEffect(() => { - // Simulate loading prayers - setTimeout(() => { - setPrayers([ - { - id: '1', - title: t('samples.item1.title'), - description: t('samples.item1.description'), - category: 'health', - author: t('samples.item1.author'), - timestamp: new Date(Date.now() - 2 * 60 * 60 * 1000), - prayerCount: 23, - isPrayedFor: false, - }, - { - id: '2', - title: t('samples.item2.title'), - description: t('samples.item2.description'), - category: 'work', - author: t('samples.item2.author'), - timestamp: new Date(Date.now() - 5 * 60 * 60 * 1000), - prayerCount: 15, - isPrayedFor: true, - }, - { - id: '3', - title: t('samples.item3.title'), - description: t('samples.item3.description'), - category: 'family', - author: t('samples.item3.author'), - timestamp: new Date(Date.now() - 1 * 24 * 60 * 60 * 1000), - prayerCount: 41, - isPrayedFor: false, - }, - ]) + // Fetch prayers from API + const fetchPrayers = async () => { + setLoading(true) + try { + const params = new URLSearchParams() + if (selectedCategory !== 'all') { + params.append('category', selectedCategory) + } + params.append('limit', '50') + if (user?.id) { + params.append('userId', user.id) + } + + const response = await fetch(`/api/prayers?${params.toString()}`) + if (response.ok) { + const data = await response.json() + setPrayers(data.prayers.map((prayer: any) => ({ + ...prayer, + timestamp: new Date(prayer.timestamp) + }))) + } else { + console.error('Failed to fetch prayers') + } + } catch (error) { + console.error('Error fetching prayers:', error) + } finally { setLoading(false) - }, 1000) - }, [locale]) + } + } + + useEffect(() => { + fetchPrayers() + }, [selectedCategory, user]) const handleGenerateAIPrayer = async () => { if (!aiPrompt.trim()) return @@ -179,22 +174,34 @@ export default function PrayersPage() { isPrayedFor: false, } - setPrayers([prayer, ...prayers]) - setNewPrayer({ title: '', description: '', category: 'personal' }) - setAiPrompt('') - setTabValue(0) - setOpenDialog(false) - - // In real app, send to API try { - await fetch('/api/prayers', { + const response = await fetch('/api/prayers', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('authToken')}` }, - body: JSON.stringify(prayer), + body: JSON.stringify({ + title: newPrayer.title, + description: newPrayer.description, + category: newPrayer.category, + isAnonymous: false + }), }) + + if (response.ok) { + const data = await response.json() + setPrayers([{ + ...data.prayer, + timestamp: new Date(data.prayer.timestamp) + }, ...prayers]) + setNewPrayer({ title: '', description: '', category: 'personal' }) + setAiPrompt('') + setTabValue(0) + setOpenDialog(false) + } else { + console.error('Failed to submit prayer') + } } catch (error) { console.error('Error submitting prayer:', error) } @@ -209,15 +216,31 @@ export default function PrayersPage() { } 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' }) + 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) } @@ -228,7 +251,6 @@ export default function PrayersPage() { } const formatTimestamp = (timestamp: Date) => { - const now = new Date() const diff = now.getTime() - timestamp.getTime() const minutes = Math.floor(diff / (1000 * 60)) const hours = Math.floor(minutes / 60) @@ -260,18 +282,55 @@ export default function PrayersPage() { + {/* Add Prayer Button */} + {user ? ( + + ) : ( + + )} + {t('categories.title')} + setSelectedCategory('all')} + sx={{ justifyContent: 'flex-start', cursor: 'pointer' }} + /> {categories.map((category) => ( setSelectedCategory(category.value)} + sx={{ justifyContent: 'flex-start', cursor: 'pointer' }} /> ))} @@ -403,30 +462,6 @@ export default function PrayersPage() { - {/* Add Prayer FAB */} - {user ? ( - - - - ) : ( - { - // Could redirect to login page or show login modal - console.log('Please login to add prayers') - }} - > - - - )} - {/* Add Prayer Dialog */} new Date()) { + userId = session.userId + } + } + + // Get client IP for anonymous counting + const ip = request.headers.get('x-forwarded-for') || + request.headers.get('x-real-ip') || + 'unknown' + + // Start a transaction to update both the prayer count and user prayer record + const result = await prisma.$transaction(async (tx) => { + // Check if prayer request exists + const prayerRequest = await tx.prayerRequest.findUnique({ + where: { id: prayerId } + }) + + if (!prayerRequest) { + throw new Error('Prayer request not found') + } + + // If user is logged in, track user prayer + if (userId) { + // Check if user already prayed for this + const existingUserPrayer = await tx.userPrayer.findUnique({ + where: { + userId_requestId: { + userId: userId, + requestId: prayerId + } + } + }) + + if (!existingUserPrayer) { + // Create user prayer record + await tx.userPrayer.create({ + data: { + userId: userId, + requestId: prayerId + } + }) + + // Increment prayer count + await tx.prayerRequest.update({ + where: { id: prayerId }, + data: { + prayerCount: { + increment: 1 + } + } + }) + } + } else { + // For anonymous users, track by IP + const existingPrayer = await tx.prayer.findUnique({ + where: { + requestId_ipAddress: { + requestId: prayerId, + ipAddress: ip + } + } + }) + + if (!existingPrayer) { + // Create anonymous prayer record + await tx.prayer.create({ + data: { + requestId: prayerId, + ipAddress: ip + } + }) + + // Increment prayer count + await tx.prayerRequest.update({ + where: { id: prayerId }, + data: { + prayerCount: { + increment: 1 + } + } + }) + } + } + + return prayerRequest + }) return NextResponse.json({ success: true, - message: 'Prayer count updated successfully' + message: 'Prayer count updated successfully', + prayerCount: result.prayerCount + 1 }) - } catch (error) { + } catch (error: any) { console.error('Error updating prayer count:', error) + + if (error.message === 'Prayer request not found') { + return NextResponse.json( + { + success: false, + error: 'Prayer request not found' + }, + { status: 404 } + ) + } + return NextResponse.json( { success: false, diff --git a/app/api/prayers/generate/route.ts b/app/api/prayers/generate/route.ts index f0adbb6..c56767f 100644 --- a/app/api/prayers/generate/route.ts +++ b/app/api/prayers/generate/route.ts @@ -1,7 +1,16 @@ import { NextRequest, NextResponse } from 'next/server' +import { AzureOpenAI } from 'openai' export const runtime = 'nodejs' +// Initialize Azure OpenAI client +const client = new AzureOpenAI({ + apiKey: process.env.AZURE_OPENAI_KEY || '', + endpoint: process.env.AZURE_OPENAI_ENDPOINT || '', + apiVersion: process.env.AZURE_OPENAI_API_VERSION || '2024-05-01-preview', + deployment: 'gpt-4o' // Using GPT-4 for better quality prayers +}) + export async function POST(request: NextRequest) { try { const { prompt, category, locale } = await request.json() @@ -13,89 +22,97 @@ export async function POST(request: NextRequest) { ) } - // In a real implementation, you would call an AI service like OpenAI - // For now, we'll create a mock response based on the prompt and locale + // Call Azure OpenAI to generate a prayer const isRomanian = locale === 'ro' - // Mock AI-generated prayer based on category and prompt - const prayers = { - personal: { - en: { - title: "Personal Guidance Prayer", - prayer: `Heavenly Father, I come before You seeking Your guidance and wisdom. ${prompt} I trust in Your perfect plan for my life and ask for strength to walk in Your ways. Help me to find peace in Your presence and confidence in Your love. Grant me clarity in my decisions and courage to follow Your will. In Jesus' name, Amen.` - }, - ro: { - title: "Rugăciune pentru îndrumarea personală", - prayer: `Tatăl ceresc, vin înaintea Ta căutând îndrumarea și înțelepciunea Ta. ${prompt} Mă încred în planul Tău perfect pentru viața mea și îți cer putere să umblu pe căile Tale. Ajută-mă să găsesc pace în prezența Ta și încredere în dragostea Ta. Dă-mi claritate în deciziile mele și curaj să urmez voia Ta. În numele lui Isus, Amin.` - } - }, - family: { - en: { - title: "Family Blessing Prayer", - prayer: `Lord God, I lift up my family to You today. ${prompt} Bless each member of our household with Your love, protection, and guidance. Strengthen our bonds of love and help us to support one another through all of life's challenges. May Your peace fill our home and Your wisdom guide our relationships. Keep us united in faith and love. In Christ's name, Amen.` - }, - ro: { - title: "Rugăciune pentru binecuvântarea familiei", - prayer: `Doamne Dumnezeule, îmi ridic familia către Tine astăzi. ${prompt} Binecuvântează fiecare membru al casei noastre cu dragostea, protecția și îndrumarea Ta. Întărește legăturile noastre de dragoste și ajută-ne să ne sprijinim unii pe alții prin toate provocările vieții. Să umple pacea Ta casa noastră și înțelepciunea Ta să ne călăuzească relațiile. Păstrează-ne uniți în credință și dragoste. În numele lui Hristos, Amin.` - } - }, - health: { - en: { - title: "Healing and Health Prayer", - prayer: `Great Physician, I bring before You our need for healing and health. ${prompt} You are the source of all healing and restoration. I pray for Your healing touch upon every area of concern. Grant wisdom to medical professionals, comfort to those who suffer, and strength to caregivers. May Your peace that surpasses understanding guard our hearts and minds. I trust in Your goodness and mercy. In Jesus' healing name, Amen.` - }, - ro: { - title: "Rugăciune pentru vindecarea și sănătatea", - prayer: `Mare Doctor, aduc înaintea Ta nevoia noastră de vindecare și sănătate. ${prompt} Tu ești sursa oricărei vindecări și restaurări. Mă rog pentru atingerea Ta vindecătoare asupra fiecărei zone de îngrijorare. Dă înțelepciune profesioniștilor medicali, mângâiere celor care suferă, și putere îngrijitorilor. Să păzească pacea Ta care întrece orice pricepere, inimile și mințile noastre. Mă încred în bunătatea și mila Ta. În numele vindecător al lui Isus, Amin.` - } - }, - work: { - en: { - title: "Workplace and Career Prayer", - prayer: `Lord of all creation, I bring my work and career before You. ${prompt} Guide my steps in my professional life and help me to be a light for You wherever You place me. Grant me wisdom in my decisions, integrity in my actions, and favor in my relationships. May I work with excellence and find fulfillment in serving others through my calling. Bless the work of my hands. In Your name, Amen.` - }, - ro: { - title: "Rugăciune pentru locul de muncă și carieră", - prayer: `Doamne al întregii creații, îmi aduc munca și cariera înaintea Ta. ${prompt} Călăuzește-mi pașii în viața mea profesională și ajută-mă să fiu o lumină pentru Tine oriunde mă pui. Dă-mi înțelepciune în deciziile mele, integritate în acțiunile mele, și favoare în relațiile mele. Să lucrez cu excelență și să găsesc împlinire în a-i sluji pe alții prin chemarea mea. Binecuvântează lucrarea mâinilor mele. În numele Tău, Amin.` - } - }, - ministry: { - en: { - title: "Ministry and Service Prayer", - prayer: `Heavenly Father, I dedicate my service to You and Your kingdom. ${prompt} Use me as an instrument of Your love and grace in this world. Fill me with Your Spirit and equip me for every good work You have prepared for me. Help me to serve with humility, compassion, and wisdom. May Your glory be revealed through my life and ministry. Strengthen me for the journey ahead. In Christ's name, Amen.` - }, - ro: { - title: "Rugăciune pentru serviciu și lucrare", - prayer: `Tatăl ceresc, îmi dedic slujirea către Tine și împărăția Ta. ${prompt} Folosește-mă ca un instrument al dragostei și harului Tău în această lume. Umple-mă cu Duhul Tău și echipează-mă pentru orice lucrare bună pe care ai pregătit-o pentru mine. Ajută-mă să slujesc cu smerenie, compasiune și înțelepciune. Să se reveleze gloria Ta prin viața și lucrarea mea. Întărește-mă pentru călătoria care urmează. În numele lui Hristos, Amin.` - } - }, - world: { - en: { - title: "Global and World Prayer", - prayer: `Sovereign Lord, You rule over all nations and peoples. ${prompt} I pray for Your kingdom to come and Your will to be done on earth as it is in heaven. Bring peace where there is conflict, hope where there is despair, and healing where there is brokenness. Raise up leaders who will serve with righteousness and justice. May Your love transform our world. Come, Lord Jesus. Amen.` - }, - ro: { - title: "Rugăciune pentru lume și global", - prayer: `Domn Suveran, Tu domnești peste toate națiunile și popoarele. ${prompt} Mă rog ca împărăția Ta să vină și voia Ta să se facă pe pământ cum se face în cer. Adu pace unde este conflict, speranță unde este deznădejde, și vindecare unde este zdrobire. Ridică conducători care să slujească cu dreptate și neprihănire. Să transforme dragostea Ta lumea noastră. Vino, Doamne Isuse. Amin.` - } + // Create system prompt for the AI + const systemPrompt = isRomanian + ? `Ești un asistent creștin care ajută oamenii să formuleze rugăciuni sincere și biblice. + Creează rugăciuni care sunt: + - Respectuoase și reverenți față de Dumnezeu + - Bazate pe principii și învățături biblice + - Personale și pline de compasiune + - Încurajatoare și pline de speranță + - Scurte și concise (maxim 150 de cuvinte) + - Potrivite pentru categoria: ${category} + - În limba română` + : `You are a Christian assistant helping people formulate sincere and biblical prayers. + Create prayers that are: + - Respectful and reverent toward God + - Based on biblical principles and teachings + - Personal and compassionate + - Encouraging and hopeful + - Brief and concise (maximum 150 words) + - Appropriate for the category: ${category} + - In English` + + // Create user prompt + const userPrompt = isRomanian + ? `Te rog să creezi o rugăciune sinceră pentru următoarea situație: ${prompt} + Categoria: ${category} + Răspunde în format JSON cu structura: {"title": "titlul rugăciunii", "prayer": "textul rugăciunii"}` + : `Please create a sincere prayer for the following situation: ${prompt} + Category: ${category} + Respond in JSON format with structure: {"title": "prayer title", "prayer": "prayer text"}` + + try { + // Call Azure OpenAI + const completion = await client.chat.completions.create({ + model: 'gpt-4o', + messages: [ + { role: 'system', content: systemPrompt }, + { role: 'user', content: userPrompt } + ], + temperature: 0.7, + max_tokens: 500, + response_format: { type: 'json_object' } + }) + + const responseText = completion.choices[0]?.message?.content || '{}' + const prayerData = JSON.parse(responseText) + + return NextResponse.json({ + title: prayerData.title || (isRomanian ? 'Rugăciune generată' : 'Generated Prayer'), + prayer: prayerData.prayer || (isRomanian ? 'Nu s-a putut genera rugăciunea.' : 'Could not generate prayer.'), + category, + generated: true + }) + } catch (aiError) { + console.error('Error calling Azure OpenAI:', aiError) + + // Fallback to template-based generation + const categoryTemplates = { + personal: isRomanian + ? { title: 'Rugăciune personală', prayer: `Doamne, îți aduc înaintea Ta această cerere personală: ${prompt}. Te rog să mă îndrumi și să-mi dai pace. În numele lui Isus, Amin.` } + : { title: 'Personal Prayer', prayer: `Lord, I bring before You this personal request: ${prompt}. Please guide me and grant me peace. In Jesus' name, Amen.` }, + family: isRomanian + ? { title: 'Rugăciune pentru familie', prayer: `Tată ceresc, îți încredințez familia mea. ${prompt}. Binecuvântează-ne și păstrează-ne uniți în dragoste. În numele lui Isus, Amin.` } + : { title: 'Family Prayer', prayer: `Heavenly Father, I entrust my family to You. ${prompt}. Bless us and keep us united in love. In Jesus' name, Amen.` }, + health: isRomanian + ? { title: 'Rugăciune pentru sănătate', prayer: `Mare Vindecător, vin la Tine cu această nevoie de sănătate: ${prompt}. Te rog pentru vindecare și restaurare. În numele lui Isus, Amin.` } + : { title: 'Health Prayer', prayer: `Great Healer, I come to You with this health need: ${prompt}. I pray for healing and restoration. In Jesus' name, Amen.` }, + work: isRomanian + ? { title: 'Rugăciune pentru muncă', prayer: `Doamne, îți aduc situația mea profesională: ${prompt}. Îndrumă-mă și binecuvântează munca mâinilor mele. În numele lui Isus, Amin.` } + : { title: 'Work Prayer', prayer: `Lord, I bring my professional situation: ${prompt}. Guide me and bless the work of my hands. In Jesus' name, Amen.` }, + ministry: isRomanian + ? { title: 'Rugăciune pentru lucrare', prayer: `Doamne, îți dedic această lucrare: ${prompt}. Folosește-mă pentru gloria Ta. În numele lui Isus, Amin.` } + : { title: 'Ministry Prayer', prayer: `Lord, I dedicate this ministry to You: ${prompt}. Use me for Your glory. In Jesus' name, Amen.` }, + world: isRomanian + ? { title: 'Rugăciune pentru lume', prayer: `Domn Suveran, mă rog pentru această situație globală: ${prompt}. Fie voia Ta pe pământ. În numele lui Isus, Amin.` } + : { title: 'World Prayer', prayer: `Sovereign Lord, I pray for this global situation: ${prompt}. May Your will be done on earth. In Jesus' name, Amen.` } } + + const template = categoryTemplates[category as keyof typeof categoryTemplates] || categoryTemplates.personal + + return NextResponse.json({ + title: template.title, + prayer: template.prayer, + category, + generated: true + }) } - const language = isRomanian ? 'ro' : 'en' - const categoryPrayers = prayers[category as keyof typeof prayers] || prayers.personal - const prayerData = categoryPrayers[language] - - // Simulate AI processing delay - await new Promise(resolve => setTimeout(resolve, 1500)) - - return NextResponse.json({ - title: prayerData.title, - prayer: prayerData.prayer, - category, - generated: true - }) - } catch (error) { console.error('Error generating prayer:', error) return NextResponse.json( diff --git a/app/api/prayers/route.ts b/app/api/prayers/route.ts index 773b650..4cfefcc 100644 --- a/app/api/prayers/route.ts +++ b/app/api/prayers/route.ts @@ -1,11 +1,13 @@ import { NextRequest, NextResponse } from 'next/server' import { z } from 'zod' +import { prisma } from '@/lib/db' +import { getServerSession } from 'next-auth' const createPrayerSchema = z.object({ title: z.string().min(1).max(200), description: z.string().min(1).max(1000), category: z.enum(['personal', 'family', 'health', 'work', 'ministry', 'world']), - author: z.string().optional().default('Anonim') + isAnonymous: z.boolean().optional().default(false) }) export async function GET(request: NextRequest) { @@ -13,89 +15,54 @@ export async function GET(request: NextRequest) { const { searchParams } = new URL(request.url) const category = searchParams.get('category') const limit = parseInt(searchParams.get('limit') || '20') + const userId = searchParams.get('userId') - // Mock prayer data for now - // TODO: Replace with actual database queries - const allPrayers = [ - { - 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), - 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), - 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), - prayerCount: 41, - isPrayedFor: false, - }, - { - id: '4', - title: 'Pentru misionarii din Africa', - description: 'Rugați-vă pentru protecția și proviziunea pentru misionarii noștri care lucrează în Africa.', - category: 'ministry', - author: 'Pavel R.', - timestamp: new Date(Date.now() - 6 * 60 * 60 * 1000), - prayerCount: 12, - isPrayedFor: false, - }, - { - id: '5', - title: 'Pace în Ucraina', - description: 'Să ne rugăm pentru pace și protecție pentru poporul ucrainean în aceste timpuri dificile.', - category: 'world', - author: 'Comunitatea', - timestamp: new Date(Date.now() - 12 * 60 * 60 * 1000), - prayerCount: 89, - isPrayedFor: true, - }, - { - id: '6', - title: 'Trecerea prin depresie', - description: 'Am nevoie de rugăciuni pentru a trece prin această perioadă grea de depresie și anxietate.', - category: 'personal', - author: 'Anonim', - timestamp: new Date(Date.now() - 8 * 60 * 60 * 1000), - prayerCount: 34, - isPrayedFor: false, - } - ] - - let filteredPrayers = allPrayers - - // Apply category filter - if (category && category !== 'all') { - filteredPrayers = allPrayers.filter(prayer => prayer.category === category) + // Build the where clause + const where: any = { + isActive: true } - // Apply limit - filteredPrayers = filteredPrayers.slice(0, limit) + if (category && category !== 'all') { + where.category = category + } - // Sort by timestamp (newest first) - filteredPrayers.sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime()) + // Fetch prayers from database with user prayer status + const prayers = await prisma.prayerRequest.findMany({ + where, + take: limit, + orderBy: { + createdAt: 'desc' + }, + include: { + user: { + select: { + name: true + } + }, + userPrayers: userId ? { + where: { + userId: userId + } + } : false + } + }) + + // Format prayers for response + const formattedPrayers = prayers.map(prayer => ({ + id: prayer.id, + title: prayer.title, + description: prayer.description, + category: prayer.category, + author: prayer.isAnonymous ? 'Anonim' : prayer.author, + timestamp: prayer.createdAt, + prayerCount: prayer.prayerCount, + isPrayedFor: userId && prayer.userPrayers ? prayer.userPrayers.length > 0 : false + })) return NextResponse.json({ success: true, - prayers: filteredPrayers, - total: filteredPrayers.length + prayers: formattedPrayers, + total: formattedPrayers.length }) } catch (error) { console.error('Error fetching prayers:', error) @@ -115,25 +82,51 @@ export async function POST(request: NextRequest) { const body = await request.json() const validatedData = createPrayerSchema.parse(body) - // Create new prayer object - const newPrayer = { - id: Date.now().toString(), - title: validatedData.title, - description: validatedData.description, - category: validatedData.category, - author: validatedData.author, - timestamp: new Date(), - prayerCount: 0, - isPrayedFor: false, + // Get user from auth token if available + const authHeader = request.headers.get('authorization') + let userId: string | null = null + let userName: string = 'Anonim' + + if (authHeader && authHeader.startsWith('Bearer ')) { + const token = authHeader.slice(7) + // Verify token and get user + const session = await prisma.session.findUnique({ + where: { token }, + include: { user: true } + }) + + if (session && session.expiresAt > new Date()) { + userId = session.userId + userName = session.user.name || 'Anonim' + } } - // TODO: Save to database - // For now, just return the created prayer - console.log('New prayer created:', newPrayer) + // Create new prayer in database + const newPrayer = await prisma.prayerRequest.create({ + data: { + title: validatedData.title, + description: validatedData.description, + category: validatedData.category, + author: validatedData.isAnonymous ? 'Anonim' : userName, + isAnonymous: validatedData.isAnonymous, + userId: validatedData.isAnonymous ? null : userId, + prayerCount: 0, + isActive: true + } + }) return NextResponse.json({ success: true, - prayer: newPrayer, + prayer: { + id: newPrayer.id, + title: newPrayer.title, + description: newPrayer.description, + category: newPrayer.category, + author: newPrayer.author, + timestamp: newPrayer.createdAt, + prayerCount: newPrayer.prayerCount, + isPrayedFor: false + }, message: 'Prayer request submitted successfully' }, { status: 201 }) } catch (error) { diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 7fcc4a0..71e9e93 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -25,6 +25,7 @@ model User { notes Note[] chatMessages ChatMessage[] prayerRequests PrayerRequest[] + userPrayers UserPrayer[] readingHistory ReadingHistory[] preferences UserPreference[] @@ -186,16 +187,23 @@ model Note { model PrayerRequest { id String @id @default(uuid()) userId String? - content String @db.Text - isAnonymous Boolean @default(true) + title String + description String @db.Text + category String // personal, family, health, work, ministry, world + author String // Display name (can be "Anonymous" or user's name) + isAnonymous Boolean @default(false) prayerCount Int @default(0) + isActive Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User? @relation(fields: [userId], references: [id], onDelete: Cascade) prayers Prayer[] + userPrayers UserPrayer[] @@index([createdAt]) + @@index([category]) + @@index([isActive]) } model Prayer { @@ -209,6 +217,20 @@ model Prayer { @@unique([requestId, ipAddress]) } +model UserPrayer { + id String @id @default(uuid()) + userId String + requestId String + createdAt DateTime @default(now()) + + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + request PrayerRequest @relation(fields: [requestId], references: [id], onDelete: Cascade) + + @@unique([userId, requestId]) + @@index([userId]) + @@index([requestId]) +} + model ReadingHistory { id String @id @default(uuid()) userId String diff --git a/scripts/seed-prayers.ts b/scripts/seed-prayers.ts new file mode 100644 index 0000000..881d7e5 --- /dev/null +++ b/scripts/seed-prayers.ts @@ -0,0 +1,94 @@ +import { PrismaClient } from '@prisma/client' + +const prisma = new PrismaClient() + +async function main() { + console.log('Seeding prayer requests...') + + const prayers = [ + { + 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 și de putere pentru a trece prin această perioadă dificilă.', + category: 'health', + author: 'Maria P.', + isAnonymous: false, + prayerCount: 23 + }, + { + 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 în luarea acestei decizii importante.', + category: 'work', + author: 'Alexandru M.', + isAnonymous: false, + prayerCount: 15 + }, + { + title: 'Unitatea în familia noastră', + description: 'Rugați-vă pentru restaurarea relațiilor în familia noastră și pentru iertarea reciprocă. Avem nevoie de vindecarea rănilor din trecut.', + category: 'family', + author: 'Anonim', + isAnonymous: true, + prayerCount: 41 + }, + { + title: 'Pentru misionarii din Africa', + description: 'Rugați-vă pentru protecția și proviziunea pentru misionarii noștri care lucrează în Africa de Vest, în special pentru familia Popescu.', + category: 'ministry', + author: 'Pavel R.', + isAnonymous: false, + prayerCount: 12 + }, + { + title: 'Pace în Ucraina', + description: 'Să ne rugăm pentru pace și protecție pentru poporul ucrainean în aceste timpuri dificile. Pentru familiile despărțite și pentru cei care suferă.', + category: 'world', + author: 'Comunitatea', + isAnonymous: false, + prayerCount: 89 + }, + { + title: 'Trecerea prin depresie', + description: 'Am nevoie de rugăciuni pentru a trece prin această perioadă grea de depresie și anxietate. Cred că Dumnezeu poate să mă vindece.', + category: 'personal', + author: 'Anonim', + isAnonymous: true, + prayerCount: 34 + }, + { + title: 'Protecție pentru copiii noștri', + description: 'Rugați-vă pentru protecția copiilor noștri la școală și pentru înțelepciune în creșterea lor în credință.', + category: 'family', + author: 'Elena și Mihai', + isAnonymous: false, + prayerCount: 28 + }, + { + title: 'Vindecare de cancer', + description: 'Sora mea a fost diagnosticată cu cancer. Credem în puterea vindecătoare a lui Dumnezeu și avem nevoie de susținerea voastră în rugăciune.', + category: 'health', + author: 'Andreea S.', + isAnonymous: false, + prayerCount: 67 + } + ] + + for (const prayer of prayers) { + await prisma.prayerRequest.create({ + data: { + ...prayer, + isActive: true + } + }) + } + + console.log('Prayer requests seeded successfully!') +} + +main() + .catch((e) => { + console.error(e) + process.exit(1) + }) + .finally(async () => { + await prisma.$disconnect() + }) \ No newline at end of file diff --git a/scripts/test-prayers.ts b/scripts/test-prayers.ts new file mode 100644 index 0000000..5b593b4 --- /dev/null +++ b/scripts/test-prayers.ts @@ -0,0 +1,141 @@ +const BASE_URL = 'http://localhost:3010' + +async function testPrayerAPI() { + console.log('🧪 Testing Prayer API Endpoints...\n') + + // Test 1: Get all prayers + console.log('📋 Test 1: Fetching all prayers...') + try { + const response = await fetch(`${BASE_URL}/api/prayers?limit=10`) + const data = await response.json() + console.log(`✅ Success: Retrieved ${data.prayers?.length || 0} prayers`) + console.log(` First prayer: ${data.prayers?.[0]?.title || 'N/A'}\n`) + } catch (error) { + console.log(`❌ Error fetching prayers: ${error}\n`) + } + + // Test 2: Get prayers by category + console.log('📋 Test 2: Fetching prayers by category (health)...') + try { + const response = await fetch(`${BASE_URL}/api/prayers?category=health&limit=5`) + const data = await response.json() + console.log(`✅ Success: Retrieved ${data.prayers?.length || 0} health prayers\n`) + } catch (error) { + console.log(`❌ Error fetching category prayers: ${error}\n`) + } + + // Test 3: Create a new prayer + console.log('📋 Test 3: Creating a new prayer request...') + try { + const newPrayer = { + title: 'Test Prayer Request', + description: 'This is a test prayer request created by the testing script.', + category: 'personal', + isAnonymous: false + } + + const response = await fetch(`${BASE_URL}/api/prayers`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(newPrayer) + }) + + const data = await response.json() + if (response.ok) { + console.log(`✅ Success: Created prayer with ID: ${data.prayer?.id}`) + console.log(` Title: ${data.prayer?.title}\n`) + return data.prayer?.id // Return ID for next test + } else { + console.log(`❌ Error: ${data.error}\n`) + } + } catch (error) { + console.log(`❌ Error creating prayer: ${error}\n`) + } + + // Test 4: Update prayer count (pray for a prayer) + console.log('📋 Test 4: Testing prayer count update...') + try { + // Get first prayer ID + const getResponse = await fetch(`${BASE_URL}/api/prayers?limit=1`) + const getData = await getResponse.json() + const prayerId = getData.prayers?.[0]?.id + + if (prayerId) { + const response = await fetch(`${BASE_URL}/api/prayers/${prayerId}/pray`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' } + }) + + const data = await response.json() + if (response.ok) { + console.log(`✅ Success: Updated prayer count`) + console.log(` New count: ${data.prayerCount}\n`) + } else { + console.log(`❌ Error: ${data.error}\n`) + } + } else { + console.log('❌ No prayer found to test with\n') + } + } catch (error) { + console.log(`❌ Error updating prayer count: ${error}\n`) + } + + // Test 5: Generate AI prayer + console.log('📋 Test 5: Testing AI prayer generation...') + try { + const aiRequest = { + prompt: 'I need strength to overcome my anxiety about the future', + category: 'personal', + locale: 'en' + } + + const response = await fetch(`${BASE_URL}/api/prayers/generate`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(aiRequest) + }) + + const data = await response.json() + if (response.ok) { + console.log(`✅ Success: Generated AI prayer`) + console.log(` Title: ${data.title}`) + console.log(` Prayer preview: ${data.prayer?.substring(0, 100)}...\n`) + } else { + console.log(`❌ Error: ${data.error}\n`) + } + } catch (error) { + console.log(`❌ Error generating AI prayer: ${error}\n`) + } + + // Test 6: Generate Romanian AI prayer + console.log('📋 Test 6: Testing Romanian AI prayer generation...') + try { + const aiRequest = { + prompt: 'Am nevoie de înțelepciune pentru o decizie importantă', + category: 'personal', + locale: 'ro' + } + + const response = await fetch(`${BASE_URL}/api/prayers/generate`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(aiRequest) + }) + + const data = await response.json() + if (response.ok) { + console.log(`✅ Success: Generated Romanian AI prayer`) + console.log(` Title: ${data.title}`) + console.log(` Prayer preview: ${data.prayer?.substring(0, 100)}...\n`) + } else { + console.log(`❌ Error: ${data.error}\n`) + } + } catch (error) { + console.log(`❌ Error generating Romanian AI prayer: ${error}\n`) + } + + console.log('✨ Prayer API testing completed!') +} + +// Run tests +testPrayerAPI().catch(console.error) \ No newline at end of file