Add influence rework, image checkup, debug mode, and fetched paintings.
Support artist and movement influence links with web discovery, a developer checkup table with gallery/detail thumbnails, and debug image search with fix-it workflow. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
0ece1195fa
commit
bf7db9b25e
@@ -4,13 +4,16 @@ import MovementBands from '../components/MovementBands';
|
||||
import VirtualGallery from '../components/VirtualGallery';
|
||||
import PaintingDetailView from '../components/PaintingDetail';
|
||||
import ArtistBio from '../components/ArtistBio';
|
||||
import CheckupPage from '../pages/CheckupPage';
|
||||
import { api } from '../api/client';
|
||||
import type { TimelineData, Artist, ArtistDetail, Painting, PaintingDetail } from '../types';
|
||||
import { sortArtistPaintingsChronological } from '../utils/paintingUtils';
|
||||
import { readDebugMode, writeDebugMode } from '../utils/debugMode';
|
||||
import './HomePage.css';
|
||||
|
||||
type View =
|
||||
| { type: 'timeline' }
|
||||
| { type: 'checkup' }
|
||||
| { type: 'gallery'; artistId: number; data: ArtistDetail }
|
||||
| { type: 'painting'; paintingId: number; data: PaintingDetail; returnTo: View }
|
||||
| { type: 'bio'; artistId: number; data: ArtistDetail; returnTo: View };
|
||||
@@ -28,6 +31,7 @@ export default function HomePage() {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [detailArtistPaintings, setDetailArtistPaintings] = useState<Painting[]>([]);
|
||||
const [debugMode, setDebugMode] = useState(readDebugMode);
|
||||
const detailReturnToRef = useRef<View>({ type: 'timeline' });
|
||||
|
||||
useEffect(() => {
|
||||
@@ -76,6 +80,51 @@ export default function HomePage() {
|
||||
setViewEnd(end);
|
||||
};
|
||||
|
||||
const toggleDebugMode = () => {
|
||||
setDebugMode((prev) => {
|
||||
const next = !prev;
|
||||
writeDebugMode(next);
|
||||
return next;
|
||||
});
|
||||
};
|
||||
|
||||
const handlePaintingImageFixed = useCallback(async (paintingId: number) => {
|
||||
const data = await api.getPainting(paintingId);
|
||||
setView((current) =>
|
||||
current.type === 'painting' && current.paintingId === paintingId
|
||||
? { ...current, data }
|
||||
: current
|
||||
);
|
||||
setDetailArtistPaintings((list) =>
|
||||
list.map((p) =>
|
||||
p.id === paintingId
|
||||
? { ...p, image_path: data.painting.image_path, thumbnail_path: data.painting.thumbnail_path }
|
||||
: p
|
||||
)
|
||||
);
|
||||
if (gallerySession?.artistId === data.painting.artist_id) {
|
||||
setGallerySession((session) =>
|
||||
session
|
||||
? {
|
||||
...session,
|
||||
data: {
|
||||
...session.data,
|
||||
paintings: session.data.paintings.map((p) =>
|
||||
p.id === paintingId
|
||||
? {
|
||||
...p,
|
||||
image_path: data.painting.image_path,
|
||||
thumbnail_path: data.painting.thumbnail_path,
|
||||
}
|
||||
: p
|
||||
),
|
||||
},
|
||||
}
|
||||
: session
|
||||
);
|
||||
}
|
||||
}, [gallerySession]);
|
||||
|
||||
const handleArtistClick = async (artistId: number) => {
|
||||
try {
|
||||
const data = await api.getArtist(artistId);
|
||||
@@ -182,6 +231,9 @@ export default function HomePage() {
|
||||
const artistData = await api.getArtist(view.data.painting.artist_id);
|
||||
setView({ type: 'bio', artistId: artistData.artist.id, data: artistData, returnTo: view });
|
||||
}}
|
||||
onInfluenceArtistClick={handleArtistClick}
|
||||
debugMode={debugMode}
|
||||
onPaintingImageFixed={handlePaintingImageFixed}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@@ -198,9 +250,34 @@ export default function HomePage() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{view.type === 'checkup' && (
|
||||
<CheckupPage
|
||||
onBack={() => setView({ type: 'timeline' })}
|
||||
onOpenPainting={handlePaintingClick}
|
||||
/>
|
||||
)}
|
||||
|
||||
{view.type === 'timeline' && (
|
||||
<div className="home-page">
|
||||
<header className="site-header">
|
||||
<div className="site-dev-tools">
|
||||
<button
|
||||
type="button"
|
||||
className={`debug-mode-toggle${debugMode ? ' debug-mode-toggle-active' : ''}`}
|
||||
onClick={toggleDebugMode}
|
||||
title="Toggle developer image audit mode on painting details"
|
||||
>
|
||||
Debug mode{debugMode ? ': ON' : ''}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="checkup-link-btn"
|
||||
onClick={() => setView({ type: 'checkup' })}
|
||||
title="Open painting image checkup table"
|
||||
>
|
||||
Checkup
|
||||
</button>
|
||||
</div>
|
||||
<h1>Virtual Art Gallery</h1>
|
||||
<p className="site-subtitle">Watch art movements branch forward through time — each flowing from what came before</p>
|
||||
</header>
|
||||
|
||||
Reference in New Issue
Block a user