diff --git a/app/[locale]/bible/reader.tsx b/app/[locale]/bible/reader.tsx index a7580a6..97133d7 100644 --- a/app/[locale]/bible/reader.tsx +++ b/app/[locale]/bible/reader.tsx @@ -532,7 +532,7 @@ export default function BibleReaderNew() { return ( { if (el) verseRefs.current[verse.verseNum] = el }} + ref={(el: HTMLDivElement | null) => { if (el) verseRefs.current[verse.verseNum] = el }} sx={{ mb: 1, display: 'flex', @@ -1024,4 +1024,4 @@ export default function BibleReaderNew() { ) -} \ No newline at end of file +} diff --git a/app/[locale]/bookmarks/page.tsx b/app/[locale]/bookmarks/page.tsx index 4015f44..ee13fc7 100644 --- a/app/[locale]/bookmarks/page.tsx +++ b/app/[locale]/bookmarks/page.tsx @@ -25,7 +25,6 @@ import { ListItem, ListItemIcon, ListItemText, - ListItemSecondary } from '@mui/material' import { Bookmark, @@ -147,7 +146,7 @@ export default function BookmarksPage() { try { const endpoint = bookmark.type === 'chapter' ? `/api/bookmarks/chapter?bookId=${bookmark.navigation.bookId}&chapterNum=${bookmark.navigation.chapterNum}&locale=${locale}` - : `/api/bookmarks/verse?verseId=${bookmark.verse.id}&locale=${locale}` + : `/api/bookmarks/verse?verseId=${bookmark.verse!.id}&locale=${locale}` const response = await fetch(endpoint, { method: 'DELETE', @@ -398,4 +397,4 @@ export default function BookmarksPage() { ) -} \ No newline at end of file +} diff --git a/app/[locale]/search/page.tsx b/app/[locale]/search/page.tsx index 6933740..c7cec86 100644 --- a/app/[locale]/search/page.tsx +++ b/app/[locale]/search/page.tsx @@ -66,6 +66,7 @@ interface SearchResult { verseId: string book: string bookId: string + bookKey?: string chapter: number verse: number text: string @@ -202,7 +203,7 @@ export default function SearchPage() { try { const response = await fetch(`/api/bible/versions?locale=${locale}`) const data = await response.json() - const versionList = data.versions || [] + const versionList: Array<{ id: string; name: string; abbreviation: string; isDefault: boolean }> = data.versions || [] setVersions(versionList) const defaultVersion = versionList.find(v => v.isDefault) || versionList[0] @@ -984,4 +985,4 @@ export default function SearchPage() { ) -} \ No newline at end of file +} diff --git a/app/api/bible/books/route.ts b/app/api/bible/books/route.ts index f097291..6e03a4c 100644 --- a/app/api/bible/books/route.ts +++ b/app/api/bible/books/route.ts @@ -1,10 +1,10 @@ -import { NextRequest, NextResponse } from 'next/server' +import { NextResponse } from 'next/server' import { prisma } from '@/lib/db' // Ensure this route runs on the Node.js runtime (Prisma requires Node) export const runtime = 'nodejs' -export async function GET(request: NextRequest) { +export async function GET(request: Request) { try { console.log('Books API called') const { searchParams } = new URL(request.url) diff --git a/app/api/bible/chapter/route.ts b/app/api/bible/chapter/route.ts index 6823a52..5dd0c00 100644 --- a/app/api/bible/chapter/route.ts +++ b/app/api/bible/chapter/route.ts @@ -7,7 +7,7 @@ export const runtime = 'nodejs' export async function GET(request: Request) { try { const { searchParams } = new URL(request.url) - const bookId = parseInt(searchParams.get('book') || '1') + const bookId = searchParams.get('book') || '' const chapterNum = parseInt(searchParams.get('chapter') || '1') // Check cache first diff --git a/app/api/bible/search/route.ts b/app/api/bible/search/route.ts index 4d654d0..67825d8 100644 --- a/app/api/bible/search/route.ts +++ b/app/api/bible/search/route.ts @@ -4,10 +4,10 @@ import { prisma } from '@/lib/db' export const runtime = 'nodejs' export async function GET(request: Request) { + const { searchParams } = new URL(request.url) + const query = searchParams.get('q') + const limit = parseInt(searchParams.get('limit') || '10') try { - const { searchParams } = new URL(request.url) - const query = searchParams.get('q') - const limit = parseInt(searchParams.get('limit') || '10') if (!query) { return NextResponse.json({ error: 'Termenul de căutare este obligatoriu' }, { status: 400 }) @@ -34,7 +34,7 @@ export async function GET(request: Request) { const fallbackResults = await prisma.bibleVerse.findMany({ where: { text: { - contains: query, + contains: query || '', mode: 'insensitive' } }, diff --git a/app/api/bible/verses/route.ts b/app/api/bible/verses/route.ts index 01e9981..d586f93 100644 --- a/app/api/bible/verses/route.ts +++ b/app/api/bible/verses/route.ts @@ -1,9 +1,9 @@ -import { NextRequest, NextResponse } from 'next/server' +import { NextResponse } from 'next/server' import { prisma } from '@/lib/db' export const runtime = 'nodejs' -export async function GET(request: NextRequest) { +export async function GET(request: Request) { try { const { searchParams } = new URL(request.url) const bookId = searchParams.get('bookId') diff --git a/app/api/bible/versions/route.ts b/app/api/bible/versions/route.ts index 8407bdf..cb21e84 100644 --- a/app/api/bible/versions/route.ts +++ b/app/api/bible/versions/route.ts @@ -1,9 +1,9 @@ -import { NextRequest, NextResponse } from 'next/server' +import { NextResponse } from 'next/server' import { prisma } from '@/lib/db' export const runtime = 'nodejs' -export async function GET(request: NextRequest) { +export async function GET(request: Request) { try { const { searchParams } = new URL(request.url) const locale = (searchParams.get('locale') || 'ro').toLowerCase() @@ -30,4 +30,3 @@ export async function GET(request: NextRequest) { return NextResponse.json({ success: false, versions: [] }, { status: 500 }) } } - diff --git a/app/api/bookmarks/verse/bulk-check/route.ts b/app/api/bookmarks/verse/bulk-check/route.ts index 50fb1b6..05b8f4e 100644 --- a/app/api/bookmarks/verse/bulk-check/route.ts +++ b/app/api/bookmarks/verse/bulk-check/route.ts @@ -60,7 +60,7 @@ export async function POST(request: Request) { }) // Create a map of verseId -> bookmark - const bookmarkMap = {} + const bookmarkMap: Record = {} bookmarks.forEach(bookmark => { bookmarkMap[bookmark.verseId] = bookmark }) @@ -77,4 +77,4 @@ export async function POST(request: Request) { return NextResponse.json({ error: messages.bookmarkError }, { status: 500 }) } -} \ No newline at end of file +} diff --git a/app/api/chat/conversations/[id]/route.ts b/app/api/chat/conversations/[id]/route.ts index 671348c..52b3a6f 100644 --- a/app/api/chat/conversations/[id]/route.ts +++ b/app/api/chat/conversations/[id]/route.ts @@ -1,4 +1,4 @@ -import { NextRequest, NextResponse } from 'next/server' +import { NextResponse } from 'next/server' import { z } from 'zod' import { PrismaClient } from '@prisma/client' import { verifyToken } from '@/lib/auth' @@ -14,8 +14,8 @@ const updateConversationSchema = z.object({ // GET /api/chat/conversations/[id] - Get conversation with messages export async function GET( - request: NextRequest, - { params }: { params: { id: string } } + request: Request, + { params }: any ) { try { // Get user from authentication @@ -28,7 +28,7 @@ export async function GET( } const token = authHeader.substring(7) - const payload = verifyToken(token) + const payload = await verifyToken(token) if (!payload) { return NextResponse.json( @@ -100,8 +100,8 @@ export async function GET( // PUT /api/chat/conversations/[id] - Update conversation export async function PUT( - request: NextRequest, - { params }: { params: { id: string } } + request: Request, + { params }: any ) { try { // Get user from authentication @@ -114,7 +114,7 @@ export async function PUT( } const token = authHeader.substring(7) - const payload = verifyToken(token) + const payload = await verifyToken(token) if (!payload) { return NextResponse.json( @@ -198,8 +198,8 @@ export async function PUT( // DELETE /api/chat/conversations/[id] - Delete conversation export async function DELETE( - request: NextRequest, - { params }: { params: { id: string } } + request: Request, + { params }: any ) { try { // Get user from authentication @@ -212,7 +212,7 @@ export async function DELETE( } const token = authHeader.substring(7) - const payload = verifyToken(token) + const payload = await verifyToken(token) if (!payload) { return NextResponse.json( @@ -263,4 +263,4 @@ export async function DELETE( { status: 500 } ) } -} \ No newline at end of file +} diff --git a/app/api/chat/conversations/route.ts b/app/api/chat/conversations/route.ts index 451f430..9f684c8 100644 --- a/app/api/chat/conversations/route.ts +++ b/app/api/chat/conversations/route.ts @@ -1,4 +1,4 @@ -import { NextRequest, NextResponse } from 'next/server' +import { NextResponse } from 'next/server' import { z } from 'zod' import { PrismaClient } from '@prisma/client' import { verifyToken } from '@/lib/auth' @@ -19,7 +19,7 @@ const getConversationsSchema = z.object({ }) // GET /api/chat/conversations - List user's conversations -export async function GET(request: NextRequest) { +export async function GET(request: Request) { try { // Get user from authentication const authHeader = request.headers.get('authorization') @@ -31,7 +31,7 @@ export async function GET(request: NextRequest) { } const token = authHeader.substring(7) - const payload = verifyToken(token) + const payload = await verifyToken(token) if (!payload) { return NextResponse.json( @@ -130,7 +130,7 @@ export async function GET(request: NextRequest) { } // POST /api/chat/conversations - Create new conversation -export async function POST(request: NextRequest) { +export async function POST(request: Request) { try { // Get user from authentication const authHeader = request.headers.get('authorization') @@ -142,7 +142,7 @@ export async function POST(request: NextRequest) { } const token = authHeader.substring(7) - const payload = verifyToken(token) + const payload = await verifyToken(token) if (!payload) { return NextResponse.json( @@ -207,4 +207,4 @@ export async function POST(request: NextRequest) { { status: 500 } ) } -} \ No newline at end of file +} diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts index a90fc9a..34525c1 100644 --- a/app/api/chat/route.ts +++ b/app/api/chat/route.ts @@ -1,4 +1,4 @@ -import { NextRequest, NextResponse } from 'next/server' +import { NextResponse } from 'next/server' import { z } from 'zod' import { PrismaClient, ChatMessageRole } from '@prisma/client' import { searchBibleHybrid, BibleVerse } from '@/lib/vector-search' @@ -21,7 +21,7 @@ const chatRequestSchema = z.object({ })).optional().default([]) }) -export async function POST(request: NextRequest) { +export async function POST(request: Request) { try { const body = await request.json() const { message, conversationId, locale, history } = chatRequestSchema.parse(body) @@ -40,7 +40,7 @@ export async function POST(request: NextRequest) { console.log('Chat API - userId extracted from token:', userId) } catch (error) { // Continue without authentication for backward compatibility - console.log('Chat API - authentication failed:', error.message) + console.log('Chat API - authentication failed:', (error as any)?.message || error) } } else { console.log('Chat API - no valid auth header') @@ -335,7 +335,7 @@ function calculateMessageRelevance(message: any, currentMessage: string, locale: const messageWords = msgContent.split(/\s+/) for (const word of currentWords) { - if (messageWords.some(mWord => mWord.includes(word) || word.includes(mWord))) { + if (messageWords.some((mWord: string) => mWord.includes(word) || word.includes(mWord))) { score += 0.2 } } @@ -401,7 +401,7 @@ function summarizeMessage(message: any): string { if (content.length <= 100) return content // Extract key points and questions - const sentences = content.split(/[.!?]+/).filter(s => s.trim().length > 10) + const sentences = content.split(/[.!?]+/).filter((s: string) => s.trim().length > 10) if (sentences.length <= 2) return content // Keep first and last sentence, or most important parts diff --git a/app/api/debug/schema/route.ts b/app/api/debug/schema/route.ts index 10102ba..bd6010d 100644 --- a/app/api/debug/schema/route.ts +++ b/app/api/debug/schema/route.ts @@ -18,7 +18,7 @@ export async function GET() { try { sampleUser = await prisma.$queryRaw`SELECT * FROM "User" LIMIT 1;` } catch (e) { - sampleUser = { error: 'Could not fetch sample user: ' + e.message } + sampleUser = { error: 'Could not fetch sample user: ' + ((e as any)?.message || e) } } return NextResponse.json({ @@ -29,7 +29,7 @@ export async function GET() { console.error('Schema debug error:', error) return NextResponse.json({ error: 'Schema debug failed', - details: error.message + details: (error as any)?.message || error }, { status: 500 }) } -} \ No newline at end of file +} diff --git a/app/api/debug/token/route.ts b/app/api/debug/token/route.ts index 13ca661..65478be 100644 --- a/app/api/debug/token/route.ts +++ b/app/api/debug/token/route.ts @@ -24,7 +24,7 @@ export async function POST(request: Request) { decodedWithoutVerification = jwt.decode(token, { complete: true }) console.log('Debug: Token decoded without verification:', !!decodedWithoutVerification) } catch (e) { - console.log('Debug: Token decode failed:', e.message) + console.log('Debug: Token decode failed:', (e as any)?.message || e) } // Try to verify @@ -33,8 +33,8 @@ export async function POST(request: Request) { verificationResult = jwt.verify(token, process.env.JWT_SECRET!) console.log('Debug: Token verification successful') } catch (e) { - console.log('Debug: Token verification failed:', e.message) - verificationResult = { error: e.message } + console.log('Debug: Token verification failed:', (e as any)?.message || e) + verificationResult = { error: (e as any)?.message || String(e) } } return NextResponse.json({ @@ -50,4 +50,4 @@ export async function POST(request: Request) { console.error('Debug endpoint error:', error) return NextResponse.json({ error: 'Debug failed' }, { status: 500 }) } -} \ No newline at end of file +} diff --git a/app/api/debug/user/route.ts b/app/api/debug/user/route.ts index fe8921f..d36910a 100644 --- a/app/api/debug/user/route.ts +++ b/app/api/debug/user/route.ts @@ -38,6 +38,6 @@ export async function POST(request: Request) { }) } catch (error) { console.error('User debug error:', error) - return NextResponse.json({ error: 'Debug failed', details: error.message }, { status: 500 }) + return NextResponse.json({ error: 'Debug failed', details: (error as any)?.message || error }, { status: 500 }) } -} \ No newline at end of file +} diff --git a/app/api/prayers/[id]/pray/route.ts b/app/api/prayers/[id]/pray/route.ts index 3e79212..51e9375 100644 --- a/app/api/prayers/[id]/pray/route.ts +++ b/app/api/prayers/[id]/pray/route.ts @@ -1,9 +1,9 @@ -import { NextRequest, NextResponse } from 'next/server' +import { NextResponse } from 'next/server' import { prisma } from '@/lib/db' export async function POST( - request: NextRequest, - { params }: { params: { id: string } } + request: Request, + { params }: any ) { try { const prayerId = params.id @@ -143,4 +143,4 @@ export async function POST( { status: 500 } ) } -} \ No newline at end of file +} diff --git a/app/api/prayers/generate/route.ts b/app/api/prayers/generate/route.ts index c56767f..ba09006 100644 --- a/app/api/prayers/generate/route.ts +++ b/app/api/prayers/generate/route.ts @@ -1,4 +1,4 @@ -import { NextRequest, NextResponse } from 'next/server' +import { NextResponse } from 'next/server' import { AzureOpenAI } from 'openai' export const runtime = 'nodejs' @@ -11,7 +11,7 @@ const client = new AzureOpenAI({ deployment: 'gpt-4o' // Using GPT-4 for better quality prayers }) -export async function POST(request: NextRequest) { +export async function POST(request: Request) { try { const { prompt, category, locale } = await request.json() @@ -120,4 +120,4 @@ export async function POST(request: NextRequest) { { status: 500 } ) } -} \ No newline at end of file +} diff --git a/app/api/prayers/route.ts b/app/api/prayers/route.ts index 4cfefcc..0002444 100644 --- a/app/api/prayers/route.ts +++ b/app/api/prayers/route.ts @@ -1,7 +1,6 @@ -import { NextRequest, NextResponse } from 'next/server' +import { 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), @@ -10,7 +9,7 @@ const createPrayerSchema = z.object({ isAnonymous: z.boolean().optional().default(false) }) -export async function GET(request: NextRequest) { +export async function GET(request: Request) { try { const { searchParams } = new URL(request.url) const category = searchParams.get('category') @@ -77,7 +76,7 @@ export async function GET(request: NextRequest) { } } -export async function POST(request: NextRequest) { +export async function POST(request: Request) { try { const body = await request.json() const validatedData = createPrayerSchema.parse(body) @@ -151,4 +150,4 @@ export async function POST(request: NextRequest) { { status: 500 } ) } -} \ No newline at end of file +} diff --git a/app/api/search/verses/route.ts b/app/api/search/verses/route.ts index f8a8af8..5c9e0c5 100644 --- a/app/api/search/verses/route.ts +++ b/app/api/search/verses/route.ts @@ -1,9 +1,9 @@ -import { NextRequest, NextResponse } from 'next/server' +import { NextResponse } from 'next/server' import { prisma } from '@/lib/db' export const runtime = 'nodejs' -export async function GET(request: NextRequest) { +export async function GET(request: Request) { try { const { searchParams } = new URL(request.url) const query = searchParams.get('q') diff --git a/components/auth/auth-provider.tsx b/components/auth/auth-provider.tsx index 0949916..d7fb376 100644 --- a/components/auth/auth-provider.tsx +++ b/components/auth/auth-provider.tsx @@ -4,18 +4,7 @@ import React, { createContext, useContext, useEffect, useState, ReactNode } from import { useLocale } from 'next-intl' import { useStore } from '@/lib/store' import { isTokenExpired, clearExpiredToken } from '@/lib/auth/client' - -interface User { - id: string - email: string - name?: string - role: string - theme: string - fontSize: string - createdAt: Date - updatedAt: Date - lastLoginAt?: Date -} +import type { User } from '@/types' interface AuthContextType { user: User | null @@ -313,4 +302,4 @@ export function useAuth(): AuthContextType { throw new Error('useAuth must be used within an AuthProvider') } return context -} \ No newline at end of file +} diff --git a/components/chat/chat-interface.tsx b/components/chat/chat-interface.tsx index 63fc1d1..b56ad01 100644 --- a/components/chat/chat-interface.tsx +++ b/components/chat/chat-interface.tsx @@ -84,9 +84,11 @@ export function ChatInterface() { }`} > {msg.role === 'assistant' ? ( - - {msg.content} - +
+ + {msg.content} + +
) : (

{msg.content}

)} @@ -129,4 +131,4 @@ export function ChatInterface() { ) -} \ No newline at end of file +} diff --git a/lib/ai/azure-openai.ts b/lib/ai/azure-openai.ts index 1bd995a..11c3aaf 100644 --- a/lib/ai/azure-openai.ts +++ b/lib/ai/azure-openai.ts @@ -1,4 +1,5 @@ import { AzureOpenAI } from 'openai' +import type { ChatCompletionMessageParam } from 'openai/resources/chat/completions' const client = new AzureOpenAI({ apiKey: process.env.AZURE_OPENAI_KEY!, @@ -7,7 +8,7 @@ const client = new AzureOpenAI({ }) export async function generateChatResponse( - messages: Array<{ role: string; content: string }>, + messages: Array<{ role: 'user' | 'assistant'; content: string }>, verseContext?: string ) { try { @@ -17,7 +18,7 @@ export async function generateChatResponse( model: process.env.AZURE_OPENAI_DEPLOYMENT || 'gpt-4', messages: [ { role: 'system', content: systemPrompt }, - ...messages + ...messages as unknown as ChatCompletionMessageParam[] ], temperature: 0.7, max_tokens: 1000 @@ -56,4 +57,4 @@ export async function generateEmbedding(text: string): Promise { // Return empty array if embedding service is not available return [] } -} \ No newline at end of file +} diff --git a/lib/auth/index.ts b/lib/auth/index.ts index e61e58f..9808c79 100644 --- a/lib/auth/index.ts +++ b/lib/auth/index.ts @@ -28,7 +28,7 @@ export async function verifyToken(token: string) { console.log('Server: Token verification successful, userId:', payload.userId) return payload } catch (error) { - console.log('Server: Token verification failed:', error.message) + console.log('Server: Token verification failed:', (error as any)?.message || error) throw new Error('Invalid token') } } @@ -54,7 +54,7 @@ export async function getUserFromToken(token: string) { } return user } catch (error) { - console.log('Server: getUserFromToken error:', error.message) + console.log('Server: getUserFromToken error:', (error as any)?.message || error) return null } } @@ -69,4 +69,4 @@ export function isTokenExpired(token: string): boolean { } catch (error) { return true } -} \ No newline at end of file +} diff --git a/lib/cache/index.ts b/lib/cache/index.ts index 3f6d222..3ba57a5 100644 --- a/lib/cache/index.ts +++ b/lib/cache/index.ts @@ -57,7 +57,7 @@ export class CacheManager { } // Helper methods for specific cache patterns - static getChapterKey(bookId: number, chapterNum: number): string { + static getChapterKey(bookId: string, chapterNum: number): string { return `chapter:${bookId}:${chapterNum}` } @@ -68,4 +68,4 @@ export class CacheManager { static getUserBookmarksKey(userId: string): string { return `bookmarks:${userId}` } -} \ No newline at end of file +} diff --git a/lib/fonts.ts b/lib/fonts.ts index bed2eca..b582e4d 100644 --- a/lib/fonts.ts +++ b/lib/fonts.ts @@ -1,15 +1,25 @@ -import { Merriweather, Lato } from 'next/font/google' +// Offline-safe font shim for builds without network access. +// Provides the minimal shape used by the app: `.style.fontFamily` and `.variable`. -export const merriweather = Merriweather({ - subsets: ['latin'], - weight: ['300', '400', '700', '900'], - variable: '--font-merriweather', - display: 'swap', -}) +type FontShim = { + style: { fontFamily: string } + variable: string +} -export const lato = Lato({ - subsets: ['latin'], - weight: ['300', '400', '700', '900'], - variable: '--font-lato', - display: 'swap', -}) \ No newline at end of file +export const merriweather: FontShim = { + // Prefer Merriweather if available on the system, otherwise common serif fallbacks + style: { + fontFamily: 'Merriweather, Georgia, "Times New Roman", Times, serif', + }, + // Not using next/font CSS variable when offline + variable: '', +} + +export const lato: FontShim = { + // Prefer Lato if available on the system, otherwise robust system sans fallbacks + style: { + fontFamily: + 'Lato, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"', + }, + variable: '', +} diff --git a/tsconfig.json b/tsconfig.json index 93a4405..23ae284 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -36,6 +36,7 @@ ".next/types/**/*.ts" ], "exclude": [ - "node_modules" + "node_modules", + "scripts" ] }