Files
biblical-guide.com/app/[locale]/bible/[version]/[book]/[chapter]/page.tsx
Andrei 44831a096f fix: improve Bible reader loading UX with skeleton states
- Remove full-screen loading backdrop that hides entire UI
- Add skeleton loading components for chapter headers and verses
- Implement smooth content transitions without UI disappearance
- Change initial loading state to prevent immediate UI hide
- Enhance Suspense fallbacks with better loading messages
- Keep Bible reader interface visible during all loading states

Fixes issue where:
- Entire reader disappeared during chapter changes
- Users saw only header/footer during loading
- Poor perceived performance with jarring transitions

Now provides professional skeleton loading within the reader
interface for a smooth, responsive user experience.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-29 20:14:51 +00:00

144 lines
3.4 KiB
TypeScript

import { Suspense } from 'react'
import { notFound } from 'next/navigation'
import BibleReader from '../../../reader'
import { prisma } from '@/lib/db'
interface PageProps {
params: Promise<{
locale: string
version: string
book: string
chapter: string
}>
}
// Helper function to convert readable names to IDs
async function getResourceIds(versionSlug: string, bookSlug: string, chapterNum: string) {
try {
// Find version by abbreviation (slug)
const version = await prisma.bibleVersion.findFirst({
where: {
abbreviation: {
equals: versionSlug,
mode: 'insensitive'
}
}
})
if (!version) {
return null
}
// Find book by bookKey (slug) within this version
const book = await prisma.bibleBook.findFirst({
where: {
versionId: version.id,
bookKey: {
equals: bookSlug,
mode: 'insensitive'
}
}
})
if (!book) {
return null
}
// Validate chapter number
const chapter = parseInt(chapterNum)
if (isNaN(chapter) || chapter < 1) {
return null
}
// Check if chapter exists
const chapterRecord = await prisma.bibleChapter.findFirst({
where: {
bookId: book.id,
chapterNum: chapter
}
})
if (!chapterRecord) {
return null
}
return {
versionId: version.id,
bookId: book.id,
chapter: chapter,
version: version,
book: book
}
} catch (error) {
console.error('Error resolving resource IDs:', error)
return null
}
}
// Generate metadata for SEO
export async function generateMetadata({ params }: PageProps) {
const { version, book, chapter } = await params
const resources = await getResourceIds(version, book, chapter)
if (!resources) {
return {
title: 'Bible Chapter Not Found',
description: 'The requested Bible chapter could not be found.'
}
}
const title = `${resources.book.name} ${chapter} - ${resources.version.name} | Biblical Guide`
const description = `Read ${resources.book.name} chapter ${chapter} in the ${resources.version.name} translation. Free online Bible study with AI chat and prayer community.`
return {
title,
description,
openGraph: {
title,
description,
type: 'article',
url: `https://biblical-guide.com/${(await params).locale}/bible/${version}/${book}/${chapter}`,
},
twitter: {
card: 'summary',
title,
description,
},
alternates: {
canonical: `https://biblical-guide.com/${(await params).locale}/bible/${version}/${book}/${chapter}`,
}
}
}
export default async function BibleChapterPage({ params }: PageProps) {
const { version, book, chapter } = await params
const resources = await getResourceIds(version, book, chapter)
if (!resources) {
notFound()
}
// Pass the parameters as props instead of URLSearchParams
return (
<Suspense fallback={
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
minHeight: '200px'
}}>
Loading Bible reader...
</div>
}>
<BibleReader
initialVersion={resources.versionId}
initialBook={resources.bookId}
initialChapter={chapter}
/>
</Suspense>
)
}
// Note: generateStaticParams removed for now to avoid complexity
// Can be added later for better performance with popular Bible chapters