import React, { useState } from 'react'; import api from '../utils/api'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from './ui/dialog'; import { Button } from './ui/button'; import { Label } from './ui/label'; import { Checkbox } from './ui/checkbox'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from './ui/table'; import { Alert, AlertDescription } from './ui/alert'; import { Badge } from './ui/badge'; import { toast } from 'sonner'; import { Loader2, Upload, FileUp, CheckCircle, XCircle, AlertCircle } from 'lucide-react'; const ImportMembersDialog = ({ open, onOpenChange, onSuccess }) => { const [file, setFile] = useState(null); const [updateExisting, setUpdateExisting] = useState(false); const [loading, setLoading] = useState(false); const [dragActive, setDragActive] = useState(false); const [importResult, setImportResult] = useState(null); const handleDrag = (e) => { e.preventDefault(); e.stopPropagation(); if (e.type === "dragenter" || e.type === "dragover") { setDragActive(true); } else if (e.type === "dragleave") { setDragActive(false); } }; const handleDrop = (e) => { e.preventDefault(); e.stopPropagation(); setDragActive(false); if (e.dataTransfer.files && e.dataTransfer.files[0]) { handleFileSelect(e.dataTransfer.files[0]); } }; const handleFileSelect = (selectedFile) => { if (!selectedFile.name.endsWith('.csv')) { toast.error('Please select a CSV file'); return; } setFile(selectedFile); setImportResult(null); }; const handleFileInput = (e) => { if (e.target.files && e.target.files[0]) { handleFileSelect(e.target.files[0]); } }; const handleSubmit = async () => { if (!file) { toast.error('Please select a file'); return; } setLoading(true); try { const formData = new FormData(); formData.append('file', file); formData.append('update_existing', updateExisting); const response = await api.post('/admin/users/import', formData, { headers: { 'Content-Type': 'multipart/form-data', }, }); setImportResult(response.data); if (response.data.status === 'completed') { toast.success('All members imported successfully!'); } else if (response.data.status === 'partial') { toast.warning('Import partially successful. Check errors below.'); } else { toast.error('Import failed. Check errors below.'); } if (onSuccess) onSuccess(); } catch (error) { const errorMessage = error.response?.data?.detail || 'Failed to import members'; toast.error(errorMessage); } finally { setLoading(false); } }; const handleClose = () => { setFile(null); setUpdateExisting(false); setImportResult(null); onOpenChange(false); }; const getStatusIcon = (status) => { if (status === 'completed') { return ; } else if (status === 'partial') { return ; } else { return ; } }; const getStatusBadge = (status) => { const config = { completed: { label: 'Completed', className: 'bg-green-500 text-white' }, partial: { label: 'Partial Success', className: 'bg-orange-500 text-white' }, failed: { label: 'Failed', className: 'bg-red-500 text-white' }, }; const statusConfig = config[status] || config.failed; return ( {statusConfig.label} ); }; return ( {importResult ? 'Import Results' : 'Import Members from CSV'} {importResult ? 'Review the import results below' : 'Upload a CSV file to bulk import members. Ensure the CSV has the required columns.'} {!importResult ? ( // Upload Form
{/* CSV Format Instructions */} Required columns: Email, First Name, Last Name, Phone, Role
Optional columns: Status, Address, City, State, Zipcode, Date of Birth, Member Since
Date format: YYYY-MM-DD (e.g., 2024-01-15)
{/* File Upload Area */}
{file ? (

{file.name}

{(file.size / 1024).toFixed(2)} KB

) : (

Drag and drop your CSV file here

or

)}
{/* Options */}
) : ( // Import Results
{/* Summary Cards */}

Total Rows

{importResult.total_rows}

Successful

{importResult.successful_rows}

Failed

{importResult.failed_rows}

{getStatusIcon(importResult.status)} {getStatusBadge(importResult.status)}
{/* Errors Table */} {importResult.errors && importResult.errors.length > 0 && (

Errors ({importResult.errors.length} {importResult.errors.length === 10 ? '- showing first 10' : ''})

Row Email Error {importResult.errors.map((error, idx) => ( {error.row} {error.email} {error.error} ))}
)}
)} {!importResult ? ( <> ) : ( )}
); }; export default ImportMembersDialog;