feat: implement reading progress tracking system
Database & API: - Enhanced ReadingHistory model with versionId field and unique constraint per user/version - Created /api/user/reading-progress endpoint (GET/POST) for saving and retrieving progress - Upsert operation ensures one reading position per user per Bible version Bible Reader Features: - Auto-save reading position after 2 seconds of inactivity - Auto-restore last reading position on page load (respects URL parameters) - Visual progress bar showing completion percentage based on chapters read - Calculate progress across entire Bible (current chapter / total chapters) - Client-side only loading to prevent hydration mismatches Bug Fixes: - Remove 200 version limit when loading "all versions" - now loads ALL versions - Fix version selection resetting to favorite when user manually selects different version - Transform books API response to include chaptersCount property - Update service worker cache version to force client updates - Add comprehensive SEO URL logging for debugging 404 issues 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -15,6 +15,8 @@ interface PageProps {
|
||||
// Helper function to convert readable names to IDs
|
||||
async function getResourceIds(versionSlug: string, bookSlug: string, chapterNum: string) {
|
||||
try {
|
||||
console.log('[SEO URL] Looking for version:', versionSlug, 'book:', bookSlug, 'chapter:', chapterNum)
|
||||
|
||||
// Find version by abbreviation (slug)
|
||||
const version = await prisma.bibleVersion.findFirst({
|
||||
where: {
|
||||
@@ -26,9 +28,12 @@ async function getResourceIds(versionSlug: string, bookSlug: string, chapterNum:
|
||||
})
|
||||
|
||||
if (!version) {
|
||||
console.log('[SEO URL] Version not found:', versionSlug)
|
||||
return null
|
||||
}
|
||||
|
||||
console.log('[SEO URL] Found version:', version.abbreviation, version.id)
|
||||
|
||||
// Find book by bookKey (slug) within this version
|
||||
const book = await prisma.bibleBook.findFirst({
|
||||
where: {
|
||||
@@ -41,12 +46,23 @@ async function getResourceIds(versionSlug: string, bookSlug: string, chapterNum:
|
||||
})
|
||||
|
||||
if (!book) {
|
||||
console.log('[SEO URL] Book not found for bookKey:', bookSlug, 'in version:', version.abbreviation)
|
||||
// List available books for debugging
|
||||
const availableBooks = await prisma.bibleBook.findMany({
|
||||
where: { versionId: version.id },
|
||||
select: { bookKey: true, name: true },
|
||||
take: 5
|
||||
})
|
||||
console.log('[SEO URL] Sample available books:', availableBooks)
|
||||
return null
|
||||
}
|
||||
|
||||
console.log('[SEO URL] Found book:', book.name, book.id)
|
||||
|
||||
// Validate chapter number
|
||||
const chapter = parseInt(chapterNum)
|
||||
if (isNaN(chapter) || chapter < 1) {
|
||||
console.log('[SEO URL] Invalid chapter number:', chapterNum)
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -59,9 +75,12 @@ async function getResourceIds(versionSlug: string, bookSlug: string, chapterNum:
|
||||
})
|
||||
|
||||
if (!chapterRecord) {
|
||||
console.log('[SEO URL] Chapter not found:', chapter, 'in book:', book.name)
|
||||
return null
|
||||
}
|
||||
|
||||
console.log('[SEO URL] Successfully resolved:', version.abbreviation, book.name, chapter)
|
||||
|
||||
return {
|
||||
versionId: version.id,
|
||||
bookId: book.id,
|
||||
@@ -70,7 +89,7 @@ async function getResourceIds(versionSlug: string, bookSlug: string, chapterNum:
|
||||
book: book
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error resolving resource IDs:', error)
|
||||
console.error('[SEO URL] Error resolving resource IDs:', error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user