Implement comprehensive PWA with offline Bible reading capabilities
- Add Web App Manifest with app metadata, icons, and installation support - Create Service Worker with intelligent caching strategies for Bible content, static assets, and dynamic content - Implement IndexedDB-based offline storage system for Bible versions, books, chapters, and verses - Add offline download manager component for browsing and downloading Bible versions - Create offline Bible reader component for seamless offline reading experience - Integrate PWA install prompt with platform-specific instructions - Add offline reading interface to existing Bible reader with download buttons - Create dedicated offline page with tabbed interface for reading and downloading - Add PWA and offline-related translations for English and Romanian locales - Implement background sync for Bible downloads and cache management - Add storage usage monitoring and management utilities - Ensure SSR-safe implementation with dynamic imports for client-side components 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
111
app/[locale]/offline/page.tsx
Normal file
111
app/[locale]/offline/page.tsx
Normal file
@@ -0,0 +1,111 @@
|
||||
'use client'
|
||||
|
||||
import { Suspense, useState, useEffect } from 'react'
|
||||
import dynamic from 'next/dynamic'
|
||||
|
||||
// Dynamic imports to avoid SSR issues with navigator/window
|
||||
const OfflineBibleReader = dynamic(
|
||||
() => import('@/components/bible/offline-bible-reader').then(mod => ({ default: mod.OfflineBibleReader })),
|
||||
{ ssr: false, loading: () => <div>Loading offline reader...</div> }
|
||||
)
|
||||
|
||||
const OfflineDownloadManager = dynamic(
|
||||
() => import('@/components/bible/offline-download-manager').then(mod => ({ default: mod.OfflineDownloadManager })),
|
||||
{ ssr: false, loading: () => <div>Loading download manager...</div> }
|
||||
)
|
||||
|
||||
const InstallPrompt = dynamic(
|
||||
() => import('@/components/pwa/install-prompt').then(mod => ({ default: mod.InstallPrompt })),
|
||||
{ ssr: false }
|
||||
)
|
||||
import {
|
||||
Box,
|
||||
Container,
|
||||
Typography,
|
||||
Tabs,
|
||||
Tab,
|
||||
Paper
|
||||
} from '@mui/material'
|
||||
|
||||
interface BibleVersion {
|
||||
id: string
|
||||
name: string
|
||||
abbreviation: string
|
||||
language: string
|
||||
isDefault?: boolean
|
||||
}
|
||||
|
||||
function OfflinePageContent() {
|
||||
const [tabValue, setTabValue] = useState(0)
|
||||
const [availableVersions, setAvailableVersions] = useState<BibleVersion[]>([])
|
||||
|
||||
useEffect(() => {
|
||||
// Fetch available Bible versions for download
|
||||
fetch('/api/bible/versions?all=true&limit=50')
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if (data.success && data.versions) {
|
||||
setAvailableVersions(data.versions)
|
||||
}
|
||||
})
|
||||
.catch(err => console.error('Failed to fetch versions:', err))
|
||||
}, [])
|
||||
|
||||
const handleTabChange = (event: React.SyntheticEvent, newValue: number) => {
|
||||
setTabValue(newValue)
|
||||
}
|
||||
|
||||
return (
|
||||
<Container maxWidth="lg" sx={{ py: 3 }}>
|
||||
<Box sx={{ mb: 3 }}>
|
||||
<Typography variant="h4" component="h1" gutterBottom>
|
||||
Offline Bible Reading
|
||||
</Typography>
|
||||
<Typography variant="body1" color="text.secondary">
|
||||
Download Bible versions for offline reading and access them without an internet connection.
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Paper sx={{ mb: 3 }}>
|
||||
<Tabs
|
||||
value={tabValue}
|
||||
onChange={handleTabChange}
|
||||
variant="fullWidth"
|
||||
sx={{ borderBottom: 1, borderColor: 'divider' }}
|
||||
>
|
||||
<Tab label="Offline Reader" />
|
||||
<Tab label="Download Manager" />
|
||||
</Tabs>
|
||||
|
||||
<Box sx={{ p: 0 }}>
|
||||
{tabValue === 0 && (
|
||||
<OfflineBibleReader
|
||||
onRequestDownload={() => setTabValue(1)}
|
||||
/>
|
||||
)}
|
||||
{tabValue === 1 && (
|
||||
<OfflineDownloadManager
|
||||
availableVersions={availableVersions}
|
||||
onVersionDownloaded={() => setTabValue(0)}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
</Paper>
|
||||
|
||||
{/* PWA Install Prompt */}
|
||||
<InstallPrompt autoShow={false} />
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
export default function OfflinePage() {
|
||||
return (
|
||||
<Suspense fallback={
|
||||
<Box sx={{ display: 'flex', justifyContent: 'center', p: 4 }}>
|
||||
Loading offline reading interface...
|
||||
</Box>
|
||||
}>
|
||||
<OfflinePageContent />
|
||||
</Suspense>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user