'use client'; import { useState, useEffect, useCallback } from 'react'; import { useApiKey } from '@/components/shared/ApiKeyWidget/apikey-context'; import { Section } from '@/components/shared/Section'; import { ImageGrid } from '@/components/demo/gallery/ImageGrid'; import { EmptyGalleryState } from '@/components/demo/gallery/EmptyGalleryState'; const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000'; const IMAGES_PER_PAGE = 30; type ImageItem = { name: string; url: string; size: number; contentType: string; lastModified: string; }; type ImagesResponse = { success: boolean; data?: { images: ImageItem[]; total: number; offset: number; limit: number; hasMore: boolean; }; error?: string; message?: string; }; type DownloadTimeMap = { [imageId: string]: number; }; export default function GalleryPage() { // API Key from context const { apiKey, apiKeyValidated, focus } = useApiKey(); const [images, setImages] = useState([]); const [offset, setOffset] = useState(0); const [hasMore, setHasMore] = useState(false); const [loading, setLoading] = useState(false); const [loadingMore, setLoadingMore] = useState(false); const [error, setError] = useState(''); const [downloadTimes, setDownloadTimes] = useState({}); useEffect(() => { if (apiKeyValidated) { fetchImages(apiKey, 0); } }, [apiKeyValidated]); const fetchImages = async (keyToUse: string, fetchOffset: number) => { if (fetchOffset === 0) { setLoading(true); } else { setLoadingMore(true); } setError(''); try { const response = await fetch( `${API_BASE_URL}/api/images/generated?limit=${IMAGES_PER_PAGE}&offset=${fetchOffset}`, { headers: { 'X-API-Key': keyToUse, }, } ); if (!response.ok) { const errorData: ImagesResponse = await response.json(); throw new Error(errorData.error || errorData.message || 'Failed to fetch images'); } const result: ImagesResponse = await response.json(); if (result.success && result.data) { const { images: newImages, offset: newOffset, hasMore: newHasMore } = result.data; if (fetchOffset === 0) { setImages(newImages); } else { setImages((prev) => [...prev, ...newImages]); } setOffset(newOffset); setHasMore(newHasMore); } else { throw new Error(result.error || 'Failed to fetch images'); } } catch (error) { setError(error instanceof Error ? error.message : 'Failed to load images'); } finally { setLoading(false); setLoadingMore(false); } }; const handleLoadMore = () => { const newOffset = offset + IMAGES_PER_PAGE; fetchImages(apiKey, newOffset); }; const handleDownloadMeasured = useCallback((imageId: string, downloadMs: number) => { setDownloadTimes((prev) => ({ ...prev, [imageId]: downloadMs, })); }, []); return (

Image Gallery

Browse your AI-generated images

{/* API Key Required Notice - Only show when not validated */} {!apiKeyValidated && (

API Key Required

Enter your API key to browse your images

)} {apiKeyValidated && (
{loading ? (

Loading images...

) : error ? (

{error}

{error.includes('fetch') || error.includes('load') ? 'Unable to load images. Please check your connection and try refreshing the page.' : 'An error occurred while fetching your images. Please try again later.'}

) : images.length === 0 ? ( ) : ( <> {hasMore && (
)} )}
)}
); }