diff --git a/app/[locale]/bible/reader.tsx b/app/[locale]/bible/reader.tsx
index f6f3003..1b0e2e5 100644
--- a/app/[locale]/bible/reader.tsx
+++ b/app/[locale]/bible/reader.tsx
@@ -77,7 +77,9 @@ import {
CloudDownload,
WifiOff,
Storage,
- MoreVert
+ MoreVert,
+ Star,
+ StarBorder
} from '@mui/icons-material'
interface BibleVerse {
@@ -329,32 +331,65 @@ export default function BibleReaderNew({ initialVersion, initialBook, initialCha
// Fetch versions based on showAllVersions state and locale
useEffect(() => {
- setVersionsLoading(true)
- const url = showAllVersions
- ? '/api/bible/versions?all=true&limit=200' // Limit to first 200 for performance
- : `/api/bible/versions?language=${locale}`
+ const loadVersions = async () => {
+ setVersionsLoading(true)
+ const url = showAllVersions
+ ? '/api/bible/versions?all=true&limit=200' // Limit to first 200 for performance
+ : `/api/bible/versions?language=${locale}`
+
+ try {
+ const res = await fetch(url)
+ const data = await res.json()
- fetch(url)
- .then(res => res.json())
- .then(data => {
if (data.success && data.versions) {
setVersions(data.versions)
+
// Keep current selection if it exists in new list, otherwise select default/first
const currentVersionExists = data.versions.some((v: BibleVersion) => v.id === selectedVersion)
if (!currentVersionExists || !selectedVersion) {
- const defaultVersion = data.versions.find((v: BibleVersion) => v.isDefault) || data.versions[0]
- if (defaultVersion) {
- setSelectedVersion(defaultVersion.id)
+ // Try to load user's favorite version first
+ let versionToSelect = null
+
+ if (user) {
+ const token = localStorage.getItem('authToken')
+ if (token) {
+ try {
+ const favoriteRes = await fetch('/api/user/favorite-version', {
+ headers: { 'Authorization': `Bearer ${token}` }
+ })
+ const favoriteData = await favoriteRes.json()
+
+ if (favoriteData.success && favoriteData.favoriteBibleVersion) {
+ const favoriteVersion = data.versions.find((v: BibleVersion) => v.id === favoriteData.favoriteBibleVersion)
+ if (favoriteVersion) {
+ versionToSelect = favoriteVersion
+ }
+ }
+ } catch (error) {
+ console.error('Error loading favorite version:', error)
+ }
+ }
+ }
+
+ // Fall back to default version or first version
+ if (!versionToSelect) {
+ versionToSelect = data.versions.find((v: BibleVersion) => v.isDefault) || data.versions[0]
+ }
+
+ if (versionToSelect) {
+ setSelectedVersion(versionToSelect.id)
}
}
}
setVersionsLoading(false)
- })
- .catch(err => {
+ } catch (err) {
console.error('Error fetching versions:', err)
setVersionsLoading(false)
- })
- }, [locale, showAllVersions, selectedVersion])
+ }
+ }
+
+ loadVersions()
+ }, [locale, showAllVersions, selectedVersion, user])
// Handle URL parameters for bookmark navigation
useEffect(() => {
@@ -1000,6 +1035,40 @@ export default function BibleReaderNew({ initialVersion, initialBook, initialCha
}
}
+ const handleSetFavoriteVersion = async () => {
+ if (!user) {
+ router.push(`/${locale}/login?redirect=${encodeURIComponent(`/${locale}/bible?version=${selectedVersion}&book=${selectedBook}&chapter=${selectedChapter}`)}`)
+ return
+ }
+
+ const token = localStorage.getItem('authToken')
+ if (!token) return
+
+ try {
+ const response = await fetch('/api/user/favorite-version', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': `Bearer ${token}`
+ },
+ body: JSON.stringify({ versionId: selectedVersion })
+ })
+
+ const data = await response.json()
+ if (data.success) {
+ setCopyFeedback({
+ open: true,
+ message: 'This version has been set as your default'
+ })
+ } else {
+ alert('Failed to set favorite version')
+ }
+ } catch (error) {
+ console.error('Error setting favorite version:', error)
+ alert('Failed to set favorite version')
+ }
+ }
+
const getThemeStyles = () => {
switch (preferences.theme) {
case 'dark':
@@ -1190,6 +1259,15 @@ export default function BibleReaderNew({ initialVersion, initialBook, initialCha
style: { maxHeight: 400 }
}}
/>
+
+
+
+
+
([])
+ const [favoriteBibleVersion, setFavoriteBibleVersion] = useState(null)
+ const [loadingVersions, setLoadingVersions] = useState(true)
+
+ useEffect(() => {
+ const loadBiblePreferences = async () => {
+ try {
+ // Load available versions (no limit to ensure we get all versions including the favorite)
+ const versionsRes = await fetch('/api/bible/versions?all=true')
+ const versionsData = await versionsRes.json()
+ if (versionsData.success) {
+ console.log('[Settings] Loaded versions:', versionsData.versions.length)
+ setBibleVersions(versionsData.versions)
+ }
+
+ // Load user's favorite version
+ const token = localStorage.getItem('authToken')
+ if (token) {
+ const favoriteRes = await fetch('/api/user/favorite-version', {
+ headers: { 'Authorization': `Bearer ${token}` }
+ })
+ const favoriteData = await favoriteRes.json()
+ console.log('[Settings] Favorite version data:', favoriteData)
+ if (favoriteData.success && favoriteData.favoriteBibleVersion) {
+ console.log('[Settings] Setting favorite version:', favoriteData.favoriteBibleVersion)
+ console.log('[Settings] Type of favorite version:', typeof favoriteData.favoriteBibleVersion)
+ setFavoriteBibleVersion(favoriteData.favoriteBibleVersion)
+ }
+ }
+ } catch (error) {
+ console.error('Error loading Bible preferences:', error)
+ } finally {
+ setLoadingVersions(false)
+ }
+ }
+
+ if (user) {
+ loadBiblePreferences()
+ } else {
+ setLoadingVersions(false)
+ }
+ }, [user])
const handleSettingChange = (setting: string, value: any) => {
setSettings(prev => ({
@@ -51,6 +95,33 @@ export default function SettingsPage() {
}))
}
+ const handleFavoriteVersionChange = async (versionId: string) => {
+ const token = localStorage.getItem('authToken')
+ if (!token) return
+
+ try {
+ const response = await fetch('/api/user/favorite-version', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': `Bearer ${token}`
+ },
+ body: JSON.stringify({ versionId })
+ })
+
+ const data = await response.json()
+ if (data.success) {
+ setFavoriteBibleVersion(versionId)
+ setMessage('Favorite Bible version updated successfully')
+ } else {
+ setMessage('Failed to update favorite version')
+ }
+ } catch (error) {
+ console.error('Error updating favorite version:', error)
+ setMessage('Failed to update favorite version')
+ }
+ }
+
const handleSave = async () => {
try {
// TODO: Implement settings update API
@@ -176,6 +247,69 @@ export default function SettingsPage() {
+ {/* Bible Preferences */}
+
+
+
+
+
+
+ Bible Preferences
+
+
+
+
+ Select your preferred Bible version. This will be loaded automatically when you open the Bible reader.
+
+
+ {loadingVersions ? (
+
+
+
+ ) : (
+
+
+ Favorite Bible Version
+
+
+ {favoriteBibleVersion && (
+
+ ✓ This version will be loaded when you open the Bible reader
+
+ )}
+
+ )}
+
+
+
+
{/* Security Settings */}
diff --git a/app/api/user/favorite-version/route.ts b/app/api/user/favorite-version/route.ts
new file mode 100644
index 0000000..f0ac2e5
--- /dev/null
+++ b/app/api/user/favorite-version/route.ts
@@ -0,0 +1,85 @@
+import { NextResponse } from 'next/server'
+import { prisma } from '@/lib/db'
+import jwt from 'jsonwebtoken'
+
+export const runtime = 'nodejs'
+
+// Get user's favorite Bible version
+export async function GET(request: Request) {
+ try {
+ const authHeader = request.headers.get('authorization')
+ if (!authHeader?.startsWith('Bearer ')) {
+ return NextResponse.json({ success: false, error: 'Unauthorized' }, { status: 401 })
+ }
+
+ const token = authHeader.substring(7)
+ const decoded = jwt.verify(token, process.env.JWT_SECRET!) as { userId: string }
+
+ const user = await prisma.user.findUnique({
+ where: { id: decoded.userId },
+ select: { favoriteBibleVersion: true }
+ })
+
+ if (!user) {
+ return NextResponse.json({ success: false, error: 'User not found' }, { status: 404 })
+ }
+
+ return NextResponse.json({
+ success: true,
+ favoriteBibleVersion: user.favoriteBibleVersion
+ })
+ } catch (error) {
+ console.error('Error getting favorite version:', error)
+ return NextResponse.json(
+ { success: false, error: 'Failed to get favorite version' },
+ { status: 500 }
+ )
+ }
+}
+
+// Set user's favorite Bible version
+export async function POST(request: Request) {
+ try {
+ const authHeader = request.headers.get('authorization')
+ if (!authHeader?.startsWith('Bearer ')) {
+ return NextResponse.json({ success: false, error: 'Unauthorized' }, { status: 401 })
+ }
+
+ const token = authHeader.substring(7)
+ const decoded = jwt.verify(token, process.env.JWT_SECRET!) as { userId: string }
+
+ const body = await request.json()
+ const { versionId } = body
+
+ if (!versionId) {
+ return NextResponse.json({ success: false, error: 'Version ID is required' }, { status: 400 })
+ }
+
+ // Verify that the version exists
+ const version = await prisma.bibleVersion.findUnique({
+ where: { id: versionId }
+ })
+
+ if (!version) {
+ return NextResponse.json({ success: false, error: 'Bible version not found' }, { status: 404 })
+ }
+
+ // Update user's favorite version
+ await prisma.user.update({
+ where: { id: decoded.userId },
+ data: { favoriteBibleVersion: versionId }
+ })
+
+ return NextResponse.json({
+ success: true,
+ message: 'Favorite Bible version updated',
+ favoriteBibleVersion: versionId
+ })
+ } catch (error) {
+ console.error('Error setting favorite version:', error)
+ return NextResponse.json(
+ { success: false, error: 'Failed to set favorite version' },
+ { status: 500 }
+ )
+ }
+}
\ No newline at end of file
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index 5acd01c..1a4ec24 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -8,16 +8,17 @@ datasource db {
}
model User {
- id String @id @default(uuid())
- email String @unique
- passwordHash String
- name String?
- role String @default("user") // "user", "admin", "moderator"
- theme String @default("light")
- fontSize String @default("medium")
- createdAt DateTime @default(now())
- updatedAt DateTime @updatedAt
- lastLoginAt DateTime?
+ id String @id @default(uuid())
+ email String @unique
+ passwordHash String
+ name String?
+ role String @default("user") // "user", "admin", "moderator"
+ theme String @default("light")
+ fontSize String @default("medium")
+ favoriteBibleVersion String? // User's preferred Bible version ID
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ lastLoginAt DateTime?
sessions Session[]
bookmarks Bookmark[]