Add catalog search on timeline header and fix Back to Timeline navigation.

Public GET /api/search over artists, movements, and paintings with a debounced header bar on the timeline; Back to Timeline resets zoom and gallery session.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Danila Khodjaef
2026-07-15 10:34:29 +03:00
co-authored by Cursor
parent 50fc253ab2
commit acc4a91a08
17 changed files with 827 additions and 12 deletions
+28 -5
View File
@@ -7,7 +7,9 @@ import PaintingDetailView from '../components/PaintingDetail';
import ArtistBio from '../components/ArtistBio';
import CheckupPage from '../pages/CheckupPage';
import CuratorLoginModal from '../components/CuratorLoginModal';
import CatalogSearchBar from '../components/CatalogSearchBar';
import GalleryLoadingMarker from '../components/GalleryLoadingMarker';
import '../components/CatalogSearchBar.css';
import '../components/CuratorLoginModal.css';
import { useAuth } from '../context/AuthContext';
import { api, type FixPaintingImageResult, type FixArtistPortraitResult } from '../api/client';
@@ -183,6 +185,17 @@ export default function HomePage() {
viewChangeScheduler.current.schedule(start, end);
}, []);
const goToTimelineHome = useCallback(() => {
detailReturnToRef.current = { type: 'timeline' };
setGallerySession(null);
setHoveredLifespan(null);
setGalleryEntryLoading(null);
setViewStart(bounds.min);
setViewEnd(bounds.max);
setGalleryRevision((revision) => revision + 1);
setView({ type: 'timeline' });
}, [bounds.min, bounds.max]);
const toggleDebugMode = () => {
setDebugMode((prev) => {
const next = !prev;
@@ -215,7 +228,7 @@ export default function HomePage() {
writeDebugMode(false);
setDebugMode(false);
if (view.type === 'checkup') {
setView({ type: 'timeline' });
goToTimelineHome();
}
};
@@ -621,7 +634,7 @@ export default function HomePage() {
active={galleryActive}
onPaintingClick={handlePaintingClick}
onNavigateArtist={handleArtistClick}
onBack={() => setView({ type: 'timeline' })}
onBack={goToTimelineHome}
onBioClick={() =>
handleBioClick(displayGallery.data, {
type: 'gallery',
@@ -638,7 +651,7 @@ export default function HomePage() {
imageRevisions={imageRevisions}
active={galleryActive}
onPaintingClick={handlePaintingClick}
onBack={() => setView({ type: 'timeline' })}
onBack={goToTimelineHome}
/>
)}
</div>
@@ -650,7 +663,12 @@ export default function HomePage() {
key={view.paintingId}
data={view.data}
artistPaintings={sortedDetailArtistPaintings}
backLabel={view.returnTo.type === 'timeline' ? '← Back to Timeline' : '← Back to Gallery'}
onBack={() => {
if (view.returnTo.type === 'timeline') {
goToTimelineHome();
return;
}
const returnTo = view.returnTo;
if (
returnTo.type === 'gallery' &&
@@ -708,7 +726,7 @@ export default function HomePage() {
{view.type === 'checkup' && (
isCurator ? (
<CheckupPage
onBack={() => setView({ type: 'timeline' })}
onBack={goToTimelineHome}
onOpenPainting={handlePaintingClick}
/>
) : (
@@ -719,7 +737,7 @@ export default function HomePage() {
<button type="button" className="checkup-link-btn" onClick={() => openCuratorLogin('checkup')}>
Curator login
</button>
<button type="button" className="debug-mode-toggle" onClick={() => setView({ type: 'timeline' })}>
<button type="button" className="debug-mode-toggle" onClick={goToTimelineHome}>
Back to gallery
</button>
</div>
@@ -794,6 +812,11 @@ export default function HomePage() {
</div>
<h1>Virtual Art Gallery</h1>
<p className="site-subtitle">Watch art movements branch forward through time each flowing from what came before</p>
<CatalogSearchBar
onSelectArtist={handleArtistClick}
onSelectMovement={handleMovementClick}
onSelectPainting={handlePaintingClick}
/>
</header>
<div className="home-timeline-stack">