import React, { useEffect, useRef, useState } from 'react'; import { X, Trash2, Image, Search } from 'lucide-react'; import { eventPhotoApi } from '../../../services/api'; import type { EventPhotoRow } from '../../../services/api/eventPhoto'; type Props = { open: boolean; eventId: string; eventName?: string; onClose: () => void; }; function formatWhen(iso?: string) { if (!iso) return '—'; try { return new Date(iso).toLocaleString(undefined, { dateStyle: 'medium', timeStyle: 'short' }); } catch { return '—'; } } export function EventPhotoSearchPanel({ open, eventId, eventName, onClose }: Props) { const [loadingPhotos, setLoadingPhotos] = useState(false); const [photos, setPhotos] = useState([]); const [err, setErr] = useState(null); const [files, setFiles] = useState([]); const [uploading, setUploading] = useState(false); const fileInputRef = useRef(null); const [queryFile, setQueryFile] = useState(null); const queryFileInputRef = useRef(null); const [searchResults, setSearchResults] = useState(null); const [searching, setSearching] = useState(false); const [deletedMsg, setDeletedMsg] = useState(null); const loadPhotos = async () => { setLoadingPhotos(true); setErr(null); try { const r = await eventPhotoApi.listEventPhotos(eventId); setPhotos(r.data?.photos ?? []); } catch (e) { setErr(e instanceof Error ? e.message : 'Failed to load photos'); setPhotos([]); } finally { setLoadingPhotos(false); } }; useEffect(() => { if (!open) return; void loadPhotos(); setSearchResults(null); setQueryFile(null); setFiles([]); // eslint-disable-next-line react-hooks/exhaustive-deps }, [open, eventId]); const onUpload = async () => { if (files.length === 0) return; setUploading(true); setErr(null); try { const res = await eventPhotoApi.uploadEventPhoto(eventId, files); if (!res.ok) { let msg = res.statusText; try { const j = await res.json(); msg = j?.error?.message || msg; } catch {} throw new Error(msg); } setFiles([]); if (fileInputRef.current) { fileInputRef.current.value = ""; } await loadPhotos(); } catch (e) { setErr(e instanceof Error ? e.message : 'Upload failed'); } finally { setUploading(false); } }; const onDelete = async (photo: EventPhotoRow) => { const ok = window.confirm(`Delete "${photo.originalFileName}"?`); if (!ok) return; setErr(null); try { const res = await eventPhotoApi.deleteEventPhoto(eventId, photo._id); if (!res.ok) { let msg = res.statusText; try { const j = await res.json(); msg = j?.error?.message || msg; } catch {} throw new Error(msg); } setDeletedMsg('Photo deleted.'); await loadPhotos(); setTimeout(() => setDeletedMsg(null), 1800); } catch (e) { setErr(e instanceof Error ? e.message : 'Delete failed'); } }; const onFindPhotos = async () => { if (!queryFile) return; setSearching(true); setErr(null); // For now, just show a placeholder — backend search integration to be added later. // This simulates a search by showing all photos (no actual vector search yet). try { const r = await eventPhotoApi.searchEventPhotos( eventId, queryFile ); if (!r.ok) { throw new Error("Search failed"); } const data = await r.json(); console.log(data); setSearchResults(data.data.matches ?? []); // setSearchResults(data.matches ?? []); } catch (e) { setErr(e instanceof Error ? e.message : 'Search failed'); setSearchResults(null); } finally { setSearching(false); } }; if (!open) return null; const displayPhotos = searchResults !== null ? searchResults : photos; return ( <>
{/* Header */}

Event Photo Search

{eventName || 'Photos'}

Upload event photos

{/* Upload Section */}
{/* setDocId(e.target.value)} style={{ width: '100%', padding: '8px 10px', border: '1px solid var(--border)', borderRadius: 'var(--radius-button)', background: 'var(--card)', color: 'var(--foreground)', fontSize: 'var(--text-sm)', fontFamily: 'var(--font-noto-sans)', outline: 'none', marginBottom: 8, boxSizing: 'border-box', }} /> */}
{files.length === 0 ? ( "No files selected" ) : ( files.map(f => f.name).join(", ") )}
{ const selected = Array.from(e.target.files || []); setFiles(selected); }} />

Supported: JPEG, PNG, JPG

{/* Find Photos Section */}
Find Photos
{ const f = e.target.files?.[0] || null; setQueryFile(f); if (f) { // Auto-trigger search when file is selected setSearchResults(null); } }} /> {!queryFile ? ( ) : (
{queryFile.name}
)}
{searchResults !== null && (

Showing {searchResults.length} result{searchResults.length === 1 ? '' : 's'}

)}
{/* Photo List */}
{err ? (

{err}

) : null} {deletedMsg ? (

{deletedMsg}

) : null} {loadingPhotos ? (

Loading…

) : displayPhotos.length === 0 ? (

No photos

Upload the first photo for this event.

) : (
{displayPhotos.map((p) => (
{p.url ? ( {p.originalFileName} ) : ( )}

{p.originalFileName}

{/*

Document ID: {p._id}

*/}

{formatWhen(p.uploadedAt)}

{/* {p.embedding_generated && ( Embedding Ready )} */}
))}
)}
); }