diff --git a/frontend/src/api/photos.ts b/frontend/src/api/photos.ts index ebbe18c..f8f7e5d 100644 --- a/frontend/src/api/photos.ts +++ b/frontend/src/api/photos.ts @@ -31,6 +31,12 @@ export interface UploadResponse { errors: string[] } +export interface BulkDeletePhotosResponse { + message: string + deleted_count: number + missing_photo_ids: number[] +} + export const photosApi = { importPhotos: async ( request: PhotoImportRequest @@ -119,6 +125,14 @@ export const photosApi = { return data }, + bulkDeletePhotos: async (photoIds: number[]): Promise => { + const { data } = await apiClient.post( + '/api/v1/photos/bulk-delete', + { photo_ids: photoIds } + ) + return data + }, + openFolder: async (photoId: number): Promise<{ message: string; folder: string }> => { const { data } = await apiClient.post<{ message: string; folder: string }>( `/api/v1/photos/${photoId}/open-folder` diff --git a/frontend/src/pages/Search.tsx b/frontend/src/pages/Search.tsx index d0e2fc9..0f98bfb 100644 --- a/frontend/src/pages/Search.tsx +++ b/frontend/src/pages/Search.tsx @@ -59,6 +59,7 @@ export default function Search() { const [loadingTags, setLoadingTags] = useState(false) const [showDeleteConfirm, setShowDeleteConfirm] = useState(false) const [loadingFavorites, setLoadingFavorites] = useState(false) + const [deletingPhotos, setDeletingPhotos] = useState(false) // Photo viewer const [showPhotoViewer, setShowPhotoViewer] = useState(false) @@ -454,6 +455,41 @@ export default function Search() { } } + const handleDeleteSelectedPhotos = async () => { + if (selectedPhotos.size === 0) { + alert('Please select photos to delete.') + return + } + + const warningLines = [ + `⚠️ WARNING: Permanently delete ${selectedPhotos.size} photo(s)?`, + '', + ] + + warningLines.push('This action CANNOT be undone. Continue?') + + if (!confirm(warningLines.join('\n'))) { + return + } + + setDeletingPhotos(true) + try { + const response = await photosApi.bulkDeletePhotos(Array.from(selectedPhotos)) + const missingNote = response.missing_photo_ids.length > 0 + ? `\nMissing photo IDs: ${response.missing_photo_ids.join(', ')}` + : '' + alert(`${response.message}${missingNote}`) + await performSearch(page) + setSelectedPhotos(new Set()) + } catch (error: any) { + console.error('Error deleting photos:', error) + const errorMessage = error?.response?.data?.detail || error?.message || 'Failed to delete photos.' + alert(`Error deleting photos: ${errorMessage}`) + } finally { + setDeletingPhotos(false) + } + } + const handleToggleFavorite = async (photoId: number) => { try { await photosApi.toggleFavorite(photoId) @@ -747,6 +783,14 @@ export default function Search() { > Tag selected photos +