/** * 🔧 Auto-Fix Component * * Autonomous data quality fixes: * - Missing value imputation * - Outlier detection & handling * - Duplicate removal * - Data type corrections * - Date feature enrichment */ import React, { useState, useCallback } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { useDropzone } from 'react-dropzone'; import { Wrench, Upload, FileSpreadsheet, CheckCircle, AlertCircle, Loader, Download, Trash2, TrendingUp, AlertTriangle, Zap, Sparkles, RotateCcw, Settings, } from 'lucide-react'; interface AutoFixReport { original_shape: { rows: number; cols: number }; final_shape: { rows: number; cols: number }; fixes_applied: Array<{ operation: string; column: string | null; rows_affected: number; description: string; }>; enrichments_added: string[]; quality_improvement: { before: number; after: number; improvement: number; }; processing_time_ms: number; } interface AutoFixProps { theme: { isDark: boolean; bgColor: string; cardBg: string; textPrimary: string; textMuted: string; borderColor: string; }; userId?: string; onFixComplete?: (fixedFile: string, report: AutoFixReport) => void; } const AutoFix: React.FC = ({ theme, userId = 'default', onFixComplete }) => { const [file, setFile] = useState(null); const [loading, setLoading] = useState(false); const [detecting, setDetecting] = useState(false); const [report, setReport] = useState(null); const [detectedIssues, setDetectedIssues] = useState(null); const [error, setError] = useState(null); const [showOptions, setShowOptions] = useState(false); // Fix options const [options, setOptions] = useState({ fix_missing: true, fix_outliers: true, fix_duplicates: true, fix_types: true, enrich_dates: true, aggressive: false, }); const onDrop = useCallback((acceptedFiles: File[]) => { if (acceptedFiles.length > 0) { setFile(acceptedFiles[0]); setReport(null); setDetectedIssues(null); setError(null); } }, []); const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop, accept: { 'text/csv': ['.csv'], 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': ['.xlsx'], 'application/vnd.ms-excel': ['.xls'], }, maxFiles: 1, }); const handleDetectIssues = async () => { if (!file) return; setDetecting(true); setError(null); try { const formData = new FormData(); formData.append('file', file); const response = await fetch('/api/v2/autonomous/detect-issues', { method: 'POST', body: formData, }); const data = await response.json(); if (data.success) { setDetectedIssues(data); } else { setError(data.detail || 'Detection failed'); } } catch (err) { setError('Failed to detect issues'); console.error('Detect error:', err); } finally { setDetecting(false); } }; const handleAutoFix = async () => { if (!file) return; setLoading(true); setError(null); try { const formData = new FormData(); formData.append('file', file); formData.append('user_id', userId); // Add options Object.entries(options).forEach(([key, value]) => { formData.append(key, String(value)); }); const response = await fetch('/api/v2/autonomous/auto-fix', { method: 'POST', body: formData, }); const data = await response.json(); if (data.success) { setReport(data.report); if (onFixComplete) { onFixComplete(data.fixed_file, data.report); } } else { setError(data.detail || 'Auto-fix failed'); } } catch (err) { setError('Failed to process file'); console.error('Auto-fix error:', err); } finally { setLoading(false); } }; const getOperationIcon = (operation: string) => { switch (operation) { case 'remove_duplicates': return Trash2; case 'impute_missing': return Wrench; case 'cap_outliers': return AlertTriangle; case 'convert_to_numeric': return TrendingUp; case 'convert_to_datetime': return Sparkles; default: return CheckCircle; } }; const reset = () => { setFile(null); setReport(null); setDetectedIssues(null); setError(null); }; return (
{/* File Upload */} {!file && (

Auto-Fix Your Data

Drop a CSV or Excel file to automatically fix data quality issues

)} {/* File Selected */} {file && !report && (

{file.name}

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

{/* Options Toggle */} {/* Options Panel */} {showOptions && ( {Object.entries(options).map(([key, value]) => ( ))} )} {/* Detected Issues */} {detectedIssues && (

Issues Detected:

    {detectedIssues.issues.missing_values?.length > 0 && (
  • {detectedIssues.issues.missing_values.length} columns with missing values
  • )} {detectedIssues.issues.duplicates?.length > 0 && (
  • Duplicate rows detected
  • )} {detectedIssues.issues.outliers?.length > 0 && (
  • {detectedIssues.issues.outliers.length} columns with outliers
  • )}

{detectedIssues.recommendation}

)} {/* Error */} {error && (
{error}
)} {/* Action Buttons */}
)} {/* Fix Report */} {report && ( {/* Success Header */}

Data Fixed!

Quality improved from {(report.quality_improvement.before * 100).toFixed(0)}% to{' '} {(report.quality_improvement.after * 100).toFixed(0)}%

{/* Summary Stats */}

Original Rows

{report.original_shape.rows.toLocaleString()}

Final Rows

{report.final_shape.rows.toLocaleString()}

Fixes Applied

{report.fixes_applied.length}

Processing Time

{report.processing_time_ms}ms

{/* Fixes Applied */} {report.fixes_applied.length > 0 && (

Fixes Applied:

{report.fixes_applied.map((fix, index) => { const Icon = getOperationIcon(fix.operation); return (
{fix.description} {fix.rows_affected > 0 && ( {fix.rows_affected} rows )}
); })}
)} {/* Enrichments */} {report.enrichments_added.length > 0 && (

New Features Added:

{report.enrichments_added.map((feature, index) => ( {feature} ))}
)} {/* Actions */}
)}
); }; export default AutoFix;