import { useEffect } from 'react'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { X, FolderKanban, Loader2, XCircle } from 'lucide-react'; import { api } from '../api/client'; import { Card, CardContent } from './Card'; import { Button } from './Button'; import { useToast } from '../contexts/ToastContext'; interface BatchProjectModalProps { selectedIds: number[]; onClose: () => void; } export function BatchProjectModal({ selectedIds, onClose }: BatchProjectModalProps) { const queryClient = useQueryClient(); const { showToast } = useToast(); const { data: projects, isLoading } = useQuery({ queryKey: ['projects'], queryFn: () => api.getProjects(), }); // Close on Escape key useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); }; window.addEventListener('keydown', handleKeyDown); return () => window.removeEventListener('keydown', handleKeyDown); }, [onClose]); // Helper to invalidate all project-related queries const invalidateProjectQueries = () => { queryClient.invalidateQueries({ queryKey: ['archives'] }); queryClient.invalidateQueries({ queryKey: ['projects'] }); // Invalidate project detail pages (partial match catches all project IDs) queryClient.invalidateQueries({ queryKey: ['project'] }); queryClient.invalidateQueries({ queryKey: ['project-archives'] }); }; // Assign to project mutation (uses bulk API) const assignMutation = useMutation({ mutationFn: async (projectId: number) => { await api.addArchivesToProject(projectId, selectedIds); return projectId; }, onSuccess: (projectId) => { const project = projects?.find(p => p.id === projectId); invalidateProjectQueries(); showToast(`Added ${selectedIds.length} archive${selectedIds.length !== 1 ? 's' : ''} to "${project?.name}"`); onClose(); }, onError: () => { showToast('Failed to assign project', 'error'); }, }); // Remove from project mutation (updates each archive individually) const removeMutation = useMutation({ mutationFn: async () => { for (const id of selectedIds) { await api.updateArchive(id, { project_id: null }); } return selectedIds.length; }, onSuccess: (count) => { invalidateProjectQueries(); showToast(`Removed ${count} archive${count !== 1 ? 's' : ''} from project`); onClose(); }, onError: () => { showToast('Failed to remove from project', 'error'); }, }); const isPending = assignMutation.isPending || removeMutation.isPending; return (
Assign {selectedIds.length} selected archive{selectedIds.length !== 1 ? 's' : ''} to a project
{isLoading ? (No projects yet. Create one from the Projects page.
)}