Complete URL restructuring to use path-based version routing
Major changes: - New URL structure: /version/esv/book/Genesis/chapter/1 instead of /book/Genesis/chapter/1?version=esv - Version extracted from URL path instead of query parameters - Component pages restructured: VersionPage, BookListPage, BookPage, ChapterPage - Navigation updated throughout to use new path structure - Routes updated to match new hierarchical structure - Breadcrumb navigation fixed for new paths - Version selector dropdown now navigates between versions This eliminates query parameter state management issues and provides clean, RESTful URLs
This commit is contained in:
@@ -34,17 +34,16 @@ function App() {
|
||||
// Debug logging
|
||||
console.log('App component rendered');
|
||||
|
||||
// Read version from URL on mount and when location changes
|
||||
// Extract version from URL path on mount and when location changes
|
||||
useEffect(() => {
|
||||
const urlParams = new URLSearchParams(location.search);
|
||||
const versionParam = urlParams.get('version');
|
||||
if (versionParam && (versionParam === 'esv' || versionParam === 'nkjv')) {
|
||||
setSelectedVersion(versionParam);
|
||||
} else if (location.pathname === '/' && !urlParams.get('version')) {
|
||||
// If we're at home without version param, clear selection
|
||||
const pathParts = location.pathname.split('/').filter(Boolean);
|
||||
if (pathParts[0] === 'version' && (pathParts[1] === 'esv' || pathParts[1] === 'nkjv')) {
|
||||
setSelectedVersion(pathParts[1]);
|
||||
} else if (location.pathname === '/') {
|
||||
// At root path, no version is selected
|
||||
setSelectedVersion('');
|
||||
}
|
||||
}, [location.search]);
|
||||
}, [location.pathname]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('App useEffect triggered');
|
||||
@@ -56,14 +55,6 @@ function App() {
|
||||
// Load versions when version changes
|
||||
useEffect(() => {
|
||||
loadBooks();
|
||||
// Update URL with version when it changes
|
||||
const url = new URL(window.location.href);
|
||||
if (selectedVersion) { // Add version parameter when selected
|
||||
url.searchParams.set('version', selectedVersion);
|
||||
} else {
|
||||
url.searchParams.delete('version');
|
||||
}
|
||||
window.history.replaceState({}, '', url.toString());
|
||||
|
||||
// Update page title to reflect selected version
|
||||
const versionTitle = selectedVersion ? selectedVersion.toUpperCase() : '';
|
||||
@@ -251,33 +242,40 @@ function App() {
|
||||
// Get current navigation info from URL
|
||||
const getCurrentNavInfo = () => {
|
||||
const pathParts = location.pathname.split('/').filter(Boolean);
|
||||
|
||||
if (pathParts.length === 0) {
|
||||
|
||||
if (pathParts.length < 3 || pathParts[0] !== 'version' || pathParts[2] !== 'book') {
|
||||
return { currentBook: null, currentChapter: null };
|
||||
}
|
||||
|
||||
if (pathParts[0] === 'book' && pathParts[1]) {
|
||||
const currentBook = pathParts[1];
|
||||
const currentChapter = pathParts[2] === 'chapter' && pathParts[3] ? pathParts[3] : null;
|
||||
return { currentBook, currentChapter };
|
||||
}
|
||||
|
||||
return { currentBook: null, currentChapter: null };
|
||||
|
||||
const currentBook = pathParts[3]; // book name from /version/:versionId/book/:bookName
|
||||
const currentChapter = pathParts[4] === 'chapter' && pathParts[5] ? pathParts[5] : null;
|
||||
return { currentBook, currentChapter };
|
||||
};
|
||||
|
||||
const { currentBook, currentChapter } = getCurrentNavInfo();
|
||||
|
||||
// Component for the home page
|
||||
const HomePage = () => {
|
||||
// Component for the version selection page (root)
|
||||
const VersionPage = () => {
|
||||
const handleVersionSelect = (version: 'esv' | 'nkjv') => {
|
||||
setSelectedVersion(version);
|
||||
setVersionSelected(true);
|
||||
navigate(`/version/${version}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<VersionSelector onVersionSelect={handleVersionSelect} />
|
||||
);
|
||||
};
|
||||
|
||||
// Component for book list page (version-specific)
|
||||
const BookListPage = () => {
|
||||
const { versionId } = useParams<{ versionId: string }>();
|
||||
|
||||
const handleBookSelect = (book: string) => {
|
||||
const urlName = getBookUrlName(book);
|
||||
const url = selectedVersion ? `/book/${urlName}?version=${selectedVersion}` : `/book/${urlName}`;
|
||||
navigate(url);
|
||||
navigate(`/version/${versionId}/book/${urlName}`);
|
||||
};
|
||||
|
||||
const handleBack = () => {
|
||||
navigate('/');
|
||||
};
|
||||
|
||||
const handleFavoriteChange = () => {
|
||||
@@ -285,14 +283,6 @@ function App() {
|
||||
setUser((prev: any) => ({ ...prev }));
|
||||
};
|
||||
|
||||
// Show version selector if no version is selected
|
||||
if (!selectedVersion) {
|
||||
return (
|
||||
<VersionSelector onVersionSelect={handleVersionSelect} />
|
||||
);
|
||||
}
|
||||
|
||||
// Show book selector once version is selected
|
||||
return (
|
||||
<BookSelector
|
||||
books={books}
|
||||
@@ -306,15 +296,15 @@ function App() {
|
||||
|
||||
// Component for book chapters page
|
||||
const BookPage = () => {
|
||||
const { bookName } = useParams<{ bookName: string }>();
|
||||
const { versionId, bookName } = useParams<{ versionId: string, bookName: string }>();
|
||||
const actualBookName = bookName ? getBookFromUrl(bookName) : '';
|
||||
|
||||
const handleChapterSelect = (chapter: string) => {
|
||||
navigate(`/book/${bookName}/chapter/${chapter}`);
|
||||
navigate(`/version/${versionId}/book/${bookName}/chapter/${chapter}`);
|
||||
};
|
||||
|
||||
const handleBack = () => {
|
||||
navigate('/');
|
||||
navigate(`/version/${versionId}`);
|
||||
};
|
||||
|
||||
const handleFavoriteChange = () => {
|
||||
@@ -340,11 +330,11 @@ function App() {
|
||||
|
||||
// Component for chapter reading page
|
||||
const ChapterPage = () => {
|
||||
const { bookName, chapterNumber } = useParams<{ bookName: string, chapterNumber: string }>();
|
||||
const { versionId, bookName, chapterNumber } = useParams<{ versionId: string, bookName: string, chapterNumber: string }>();
|
||||
const actualBookName = bookName ? getBookFromUrl(bookName) : '';
|
||||
|
||||
const handleBack = () => {
|
||||
navigate(`/book/${bookName}`);
|
||||
navigate(`/version/${versionId}/book/${bookName}`);
|
||||
};
|
||||
|
||||
const handleFavoriteChange = () => {
|
||||
@@ -412,7 +402,7 @@ function App() {
|
||||
{selectedVersion ? (
|
||||
<select
|
||||
value={selectedVersion}
|
||||
onChange={(e) => setSelectedVersion(e.target.value)}
|
||||
onChange={(e) => navigate(`/version/${e.target.value}`)}
|
||||
className="text-xs text-gray-600 dark:text-gray-400 bg-transparent border-none focus:outline-none cursor-pointer hover:text-blue-600 dark:hover:text-blue-400"
|
||||
>
|
||||
{availableVersions.map((version) => (
|
||||
@@ -434,10 +424,7 @@ function App() {
|
||||
{currentBook && (
|
||||
<>
|
||||
<button
|
||||
onClick={() => {
|
||||
const url = selectedVersion ? `/?version=${selectedVersion}` : '/';
|
||||
navigate(url);
|
||||
}}
|
||||
onClick={() => navigate(`/version/${selectedVersion}`)}
|
||||
className="hover:text-blue-600 dark:hover:text-blue-400"
|
||||
>
|
||||
Books
|
||||
@@ -450,10 +437,7 @@ function App() {
|
||||
<>
|
||||
<ChevronRight className="h-4 w-4" />
|
||||
<button
|
||||
onClick={() => {
|
||||
const url = selectedVersion ? `/book/${currentBook}?version=${selectedVersion}` : `/book/${currentBook}`;
|
||||
navigate(url);
|
||||
}}
|
||||
onClick={() => navigate(`/version/${selectedVersion}/book/${currentBook}`)}
|
||||
className="hover:text-blue-600 dark:hover:text-blue-400"
|
||||
>
|
||||
Chapters
|
||||
@@ -571,9 +555,10 @@ function App() {
|
||||
{/* Main Content */}
|
||||
<main className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
<Routes>
|
||||
<Route path="/" element={<HomePage />} />
|
||||
<Route path="/book/:bookName" element={<BookPage />} />
|
||||
<Route path="/book/:bookName/chapter/:chapterNumber" element={<ChapterPage />} />
|
||||
<Route path="/" element={<VersionPage />} />
|
||||
<Route path="/version/:versionId" element={<BookListPage />} />
|
||||
<Route path="/version/:versionId/book/:bookName" element={<BookPage />} />
|
||||
<Route path="/version/:versionId/book/:bookName/chapter/:chapterNumber" element={<ChapterPage />} />
|
||||
<Route path="/search" element={
|
||||
<SearchComponent
|
||||
formatBookName={formatBookName}
|
||||
|
||||
Reference in New Issue
Block a user