import React, { useState, useEffect, useMemo } from 'react' import classNames from 'classnames' import { FaUpload, FaCheckCircle, FaRegBell, FaClock, FaSync, FaEye, FaTrashAlt, FaDownload, FaFileExcel, FaFileAlt, FaExclamationTriangle, FaChevronDown, FaChevronUp, } from 'react-icons/fa' import { FileUploadArea } from './FileUploadArea' import { ImportPreview } from './ImportPreview' import { ImportProgress } from './ImportProgress' import { ListFormImportDto, ListFormImportLogDto } from '@/proxy/imports/models' import { ImportService } from '@/services/import.service' import { GridDto } from '@/proxy/form/models' import { useLocalization } from '@/utils/hooks/useLocalization' import { useDialogContext } from '@/components/ui/Dialog/Dialog' interface ImportDashboardProps { gridDto: GridDto } export type TabNames = 'import' | 'preview' | 'history' export const ImportDashboard: React.FC = ({ gridDto }) => { const { translate } = useLocalization() const [activeTab, setActiveTab] = useState('import') const [currentSession, setCurrentSession] = useState(null) const [importHistory, setImportHistory] = useState([]) const [loading, setLoading] = useState(false) const importService = useMemo(() => new ImportService(), []) const [generating, setGenerating] = useState(false) const [expandedSessions, setExpandedSessions] = useState>(new Set()) const [sessionExecutes, setSessionExecutes] = useState< Record >({}) const [loadingExecutes, setLoadingExecutes] = useState>(new Set()) useEffect(() => { loadImportHistory() }, []) const loadImportHistory = async () => { try { const history = await importService.getListFormImportByListFormCode( gridDto.gridOptions.listFormCode || '', ) setImportHistory(history) // Execute cache'ini temizle çünkü history değişmiş olabilir setSessionExecutes({}) setExpandedSessions(new Set()) } catch (error) { console.error('Failed to load import history:', error) } } const toggleSessionExecutes = async (sessionId: string) => { // Toggle expanded state const newExpandedSessions = new Set(expandedSessions) if (expandedSessions.has(sessionId)) { newExpandedSessions.delete(sessionId) setExpandedSessions(newExpandedSessions) } else { newExpandedSessions.add(sessionId) setExpandedSessions(newExpandedSessions) // Her zaman fresh data çek - cache'e güvenme setLoadingExecutes((prev) => new Set([...prev, sessionId])) try { const executes = await importService.getListFormImportLogs(sessionId) setSessionExecutes((prev) => ({ ...prev, [sessionId]: executes, })) } catch (error) { console.error('Failed to load import executes:', error) } finally { setLoadingExecutes((prev) => { const newSet = new Set(prev) newSet.delete(sessionId) return newSet }) } } } const handleFileUpload = async (file: File) => { setLoading(true) try { let session = await importService.uploadFile(file, gridDto.gridOptions.listFormCode || '') setCurrentSession(session) setActiveTab('preview') // Start polling for status updates - continue until fully processed if (session.status !== 'failed') { // Daha uzun süreli ve gerçekçi bir progression setTimeout(async () => { session = await importService.updateSession(session.id, { status: 'validating', listFormCode: gridDto.gridOptions.listFormCode || '', }) setCurrentSession(session) }, 1000) // 1 saniye sonra validating setTimeout(async () => { session = await importService.updateSession(session.id, { status: 'processing', listFormCode: gridDto.gridOptions.listFormCode || '', }) setCurrentSession(session) }, 2000) // 2 saniye sonra processing başlangıç setTimeout(async () => { session = await importService.updateSession(session.id, { status: 'uploaded', listFormCode: gridDto.gridOptions.listFormCode || '', }) setCurrentSession(session) }, 3000) // 3 saniye sonra uploaded pollImportStatus(session.id) } // Load import history to refresh the data await loadImportHistory() } catch (error) { console.error('File upload failed:', error) } finally { setLoading(false) } } const pollImportStatus = async (sessionId: string) => { try { const session = await importService.getListFormImport(sessionId) setCurrentSession(session) if (session.status === 'uploaded' || session.status === 'failed') { loadImportHistory() } } catch (error) { console.error('Failed to get import status:', error) } } const handleImportLog = async ( sessionId: string, listFormCode: string, selectedRows?: number[], ) => { setLoading(true) try { const session = await importService.executeImport(sessionId, listFormCode, selectedRows) pollImportStatus(session.importId) await loadImportHistory() // Execute sonrası History sekmesine geç ki kullanıcı yeni execute'i görebilsin setActiveTab('history') } catch (error) { console.error('Import execution failed:', error) } finally { setLoading(false) } } const getStatusIcon = (status: string) => { switch (status) { case 'uploaded': case 'executed': return case 'executed_with_errors': return case 'failed': case 'execute_failed': return case 'processing': case 'validating': return default: return } } const getStatusColor = (status: string) => { switch (status) { case 'uploaded': case 'executed': return 'bg-green-50 text-green-700 border-green-200 dark:bg-green-950/30 dark:text-green-300 dark:border-green-900/60' case 'executed_with_errors': return 'bg-orange-50 text-orange-700 border-orange-200 dark:bg-orange-950/30 dark:text-orange-300 dark:border-orange-900/60' case 'failed': case 'execute_failed': return 'bg-red-50 text-red-700 border-red-200 dark:bg-red-950/30 dark:text-red-300 dark:border-red-900/60' case 'processing': case 'validating': return 'bg-blue-50 text-blue-700 border-blue-200 dark:bg-blue-950/30 dark:text-blue-300 dark:border-blue-900/60' default: return 'bg-yellow-50 text-yellow-700 border-yellow-200 dark:bg-yellow-950/30 dark:text-yellow-300 dark:border-yellow-900/60' } } const getSessionStatusLabel = (status: string) => { switch (status) { case 'uploading': return translate('::App.Listforms.ImportManager.Uploading') case 'validating': return translate('::App.Listforms.ImportManager.Validating') case 'processing': return translate('::App.Listforms.ImportManager.Processing') case 'uploaded': return translate('::App.Listforms.ImportManager.Uploaded') case 'failed': return translate('::App.Listforms.ImportManager.Failed') case 'executed': return translate('::App.Listforms.ImportManager.Executed') case 'executed_with_errors': return translate('::App.Listforms.ImportManager.ExecutedWithErrors') case 'execute_failed': return translate('::App.Listforms.ImportManager.ExecuteFailed') default: return status.charAt(0).toUpperCase() + status.slice(1) } } const getSessionGuidance = (status: string) => { switch (status) { case 'uploaded': return translate('::App.Listforms.ImportManager.UploadedDescription') case 'executed': return translate('::App.Listforms.ImportManager.ExecutedDescription') case 'executed_with_errors': return translate('::App.Listforms.ImportManager.ExecutedWithErrorsDescription') case 'execute_failed': return translate('::App.Listforms.ImportManager.ExecuteFailedDescription') case 'failed': return translate('::App.Listforms.ImportManager.FailedDescription') default: return null } } const getExecuteStatusIcon = (status: string) => { switch (status) { case 'completed': return case 'completed_with_errors': return case 'processing': return case 'validating': return case 'failed': return default: return null } } const getExecuteStatusColor = (status: string) => { switch (status) { case 'completed': return 'text-green-600 dark:text-green-300' case 'completed_with_errors': return 'text-orange-600 dark:text-orange-300' case 'processing': return 'text-blue-600 dark:text-blue-300' case 'validating': return 'text-yellow-600 dark:text-yellow-300' case 'failed': return 'text-red-600 dark:text-red-300' default: return 'text-slate-600 dark:text-slate-400' } } const getExecuteStatusLabel = (status: string) => { if (status === 'completed_with_errors') return 'Completed with errors' return status.charAt(0).toUpperCase() + status.slice(1) } const [expandedErrors, setExpandedErrors] = useState>(new Set()) const toggleErrors = (executeId: string) => { setExpandedErrors((prev) => { const next = new Set(prev) if (next.has(executeId)) next.delete(executeId) else next.add(executeId) return next }) } const parseErrors = (errorsJson?: string): { row: number; message: string }[] => { if (!errorsJson) return [] try { return JSON.parse(errorsJson) } catch { return [] } } const generateTemplate = async (format: 'excel' | 'csv') => { setGenerating(true) try { const blob = await importService.generateTemplate(gridDto, format) const filename = `${gridDto.gridOptions.listFormCode}_template.${format === 'excel' ? 'xlsx' : 'csv'}` importService.downloadGenerateTemplate(blob, filename) } catch (error) { console.error('Template generation failed:', error) } finally { setGenerating(false) } } const getEditableColumns = () => { return gridDto.columnFormats.filter((col: any) => col.canCreate && col.fieldName !== 'Id') } const editableColumns = getEditableColumns() const { isMaximized } = useDialogContext() return (
{/* Navigation Tabs */}
{['import', 'preview', 'history'].map((tab) => ( ))}
{/* Content */}
{activeTab === 'import' && (
{/* Template Generator & File Upload - Side by Side */}
{/* Template Generator - 2/3 width on large screens, full width on mobile */}

{translate('::App.Listforms.ImportManager.TemplateColumns')} ( {editableColumns.length})

{/* Template Options */}
{editableColumns.map((column: any) => ( ))}
{translate('::App.Listform.ListformField.Column')} {translate('::ListForms.ListFormEdit.Type')} {translate('::App.Required')} {translate('::Abp.Mailing.Default')}
{column.fieldName} {column.dataType} {column.validationRuleDto.some( (rule: any) => rule.type === 'required', ) ? ( {translate('::App.Listforms.ImportManager.Yes')} ) : ( {translate('::App.Listforms.ImportManager.No')} )} {typeof column.defaultValue === 'object' ? JSON.stringify(column.defaultValue) : column.defaultValue}
{generating && (
{translate('::App.Listforms.ImportManager.GeneratingTemplate')}
)}
{/* File Upload - 1/3 width on large screens, full width on mobile */}

{translate('::App.Listforms.ImportManager.UploadData')}

)} {activeTab === 'preview' && (
{currentSession ? (
{currentSession.status === 'validating' || currentSession.status === 'uploading' || currentSession.status === 'processing' ? ( ) : (
)}
) : (
{translate('::App.Listforms.ImportManager.NoDataToPreview')}
{translate('::App.Listforms.ImportManager.UploadFileToPreview')}
)}
)} {activeTab === 'history' && (

{translate('::App.Listforms.ImportManager.ImportHistory')}

{importHistory.map((session) => (
{getStatusIcon(session.status)}
{session.blobName}
{new Date(session.creationTime).toLocaleString()}
{currentSession?.id === session.id && ( {translate('::App.Status.Active')} )}
{session.totalRows} {translate('::App.Listforms.ImportManager.TotalRows')}
{getSessionStatusLabel(session.status)}
{/* Guidance message */} {getSessionGuidance(session.status) && (
{session.status === 'executed_with_errors' || session.status === 'failed' || session.status === 'execute_failed' ? ( ) : session.status === 'uploaded' ? ( ) : ( )} {getSessionGuidance(session.status)}
)} {/* Execute Details Section */} {expandedSessions.has(session.id) && (
{loadingExecutes.has(session.id) ? (
{translate('::App.Listforms.ImportManager.LoadingExecutionDetails')}
) : sessionExecutes[session.id] && sessionExecutes[session.id].length > 0 ? (
{sessionExecutes[session.id].map((execute) => (
{/* Sol: Tarih */}
{new Date(execute.creationTime).toLocaleString()}
{/* Orta: Executed, Valid, Errors */}
{execute.execRows}
{translate('::App.Listforms.ImportManager.Executed')}
{execute.validRows}
{translate('::App.Listforms.ImportManager.Valid')}
{execute.errorRows}
{translate('::App.Listforms.ImportManager.Errors')}
{/* Sağ: Status */}
{getExecuteStatusIcon(execute.status)}
{getExecuteStatusLabel(execute.status)} {execute.status === 'processing' && ` (${execute.progress}%)`}
{/* Error Details */} {(execute.status === 'completed_with_errors' || execute.status === 'failed') && execute.errorRows > 0 && (
{expandedErrors.has(execute.id) && (
{parseErrors(execute.errorsJson).length > 0 ? ( {parseErrors(execute.errorsJson).map((err, idx) => ( ))}
Satır Hata Mesajı
{err.row} {err.message}
) : (

Hata detayı mevcut değil.

)}
)}
)}
))}
) : (
{translate('::App.Listforms.ImportManager.NoExecutionRecords')}
)}
)}
))} {importHistory.length === 0 && (
{translate('::App.Listforms.ImportManager.NoImportHistory')}
{translate('::App.Listforms.ImportManager.ImportHistoryHint')}
)}
)}
) }