"use client" import * as React from "react" import { type Table } from "@tanstack/react-table" import { Download, RefreshCcw, Upload, FileText, Loader2, ChevronDown } from "lucide-react" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog" import { Progress } from "@/components/ui/progress" import { Badge } from "@/components/ui/badge" import { toast } from "sonner" import { OcrRow } from "@/db/schema" import { exportTableToExcel } from "@/lib/export_all" import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu" import { getOcrAllRows } from "../service" import { exportOcrDataToExcel } from "./exporft-ocr-data" interface OcrTableToolbarActionsProps { table: Table } interface UploadProgress { stage: string progress: number message: string } export function OcrTableToolbarActions({ table }: OcrTableToolbarActionsProps) { const [isLoading, setIsLoading] = React.useState(false) const [isUploading, setIsUploading] = React.useState(false) const [uploadProgress, setUploadProgress] = React.useState(null) const [isUploadDialogOpen, setIsUploadDialogOpen] = React.useState(false) const [selectedFile, setSelectedFile] = React.useState(null) const fileInputRef = React.useRef(null) const [isExporting, setIsExporting] = React.useState(false) // 다이얼로그 닫기 핸들러 - 업로드 중에는 닫기 방지 const handleDialogOpenChange = (open: boolean) => { // 다이얼로그를 닫으려고 할 때 if (!open) { // 업로드가 진행 중이면 닫기를 방지 if (isUploading && uploadProgress?.stage !== "complete") { toast.warning("Cannot close while processing. Please wait for completion.", { description: "OCR processing is in progress..." }) return // 다이얼로그를 닫지 않음 } // 업로드가 진행 중이 아니거나 완료되었으면 초기화 후 닫기 resetUpload() } setIsUploadDialogOpen(open) } const handleFileSelect = (event: React.ChangeEvent) => { const file = event.target.files?.[0] if (file) { setSelectedFile(file) } } const validateFile = (file: File): string | null => { // 파일 크기 체크 (10MB) if (file.size > 10 * 1024 * 1024) { return "File size must be less than 10MB" } // 파일 타입 체크 const allowedTypes = [ 'application/pdf', 'image/jpeg', 'image/jpg', 'image/png', 'image/tiff', 'image/bmp' ] if (!allowedTypes.includes(file.type)) { return "Only PDF and image files (JPG, PNG, TIFF, BMP) are supported" } return null } const uploadFile = async () => { if (!selectedFile) { toast.error("Please select a file first") return } const validationError = validateFile(selectedFile) if (validationError) { toast.error(validationError) return } try { setIsUploading(true) setUploadProgress({ stage: "preparing", progress: 10, message: "Preparing file upload..." }) const formData = new FormData() formData.append('file', selectedFile) setUploadProgress({ stage: "uploading", progress: 30, message: "Uploading file and processing..." }) const response = await fetch('/api/ocr/enhanced', { method: 'POST', body: formData, }) setUploadProgress({ stage: "processing", progress: 70, message: "Analyzing document with OCR..." }) if (!response.ok) { const errorData = await response.json() throw new Error(errorData.error || 'OCR processing failed') } const result = await response.json() setUploadProgress({ stage: "saving", progress: 90, message: "Saving results to database..." }) if (result.success) { setUploadProgress({ stage: "complete", progress: 100, message: "OCR processing completed successfully!" }) toast.success( `OCR completed! Extracted ${result.metadata.totalRows} rows from ${result.metadata.totalTables} tables`, { description: result.warnings?.length ? `Warnings: ${result.warnings.join(', ')}` : undefined } ) // 성공 후 다이얼로그 닫기 및 상태 초기화 setTimeout(() => { setIsUploadDialogOpen(false) resetUpload() // 테이블 새로고침 window.location.reload() }, 2000) } else { throw new Error(result.error || 'Unknown error occurred') } } catch (error) { console.error('Error uploading file:', error) toast.error( error instanceof Error ? error.message : 'An error occurred while processing the file' ) setUploadProgress(null) } finally { setIsUploading(false) } } const resetUpload = () => { setSelectedFile(null) setUploadProgress(null) if (fileInputRef.current) { fileInputRef.current.value = '' } } // Cancel 버튼 핸들러 const handleCancelClick = () => { if (isUploading && uploadProgress?.stage !== "complete") { // 업로드 진행 중이면 취소 불가능 메시지 toast.warning("Cannot cancel while processing. Please wait for completion.", { description: "OCR processing cannot be interrupted safely." }) } else { // 업로드 중이 아니거나 완료되었으면 다이얼로그 닫기 setIsUploadDialogOpen(false) resetUpload() } } // 현재 페이지 데이터만 내보내기 const exportCurrentPage = () => { exportTableToExcel(table, { filename: "OCR Result (Current Page)", excludeColumns: ["select", "actions"], }) } // 전체 데이터 내보내기 const exportAllData = async () => { if (isExporting) return setIsExporting(true) try { toast.loading("전체 데이터를 가져오는 중...", { description: "잠시만 기다려주세요." }) // 모든 데이터 가져오기 const allData = await getOcrAllRows() toast.dismiss() if (allData.length === 0) { toast.warning("내보낼 데이터가 없습니다.") return } console.log(allData) // 새로운 단순한 export 함수 사용 await exportOcrDataToExcel(allData, `OCR Result (All Data - ${allData.length} rows)`) toast.success(`전체 데이터 ${allData.length}개 행이 성공적으로 내보내졌습니다.`) } catch (error) { console.error('Error exporting all data:', error) toast.error('전체 데이터 내보내기 중 오류가 발생했습니다.') } finally { setIsExporting(false) } } return (
{/* OCR 업로드 다이얼로그 */} { if (isUploading && uploadProgress?.stage !== "complete") { e.preventDefault() toast.warning("Cannot close while processing. Please wait for completion.") } }} // 업로드 중에는 외부 클릭으로도 닫기 방지 onInteractOutside={(e) => { if (isUploading && uploadProgress?.stage !== "complete") { e.preventDefault() toast.warning("Cannot close while processing. Please wait for completion.") } }} > Upload Document for OCR {/* 업로드 중일 때 로딩 인디케이터 표시 */} {isUploading && uploadProgress?.stage !== "complete" && ( )} {isUploading && uploadProgress?.stage !== "complete" ? "Processing in progress. Please do not close this dialog." : "Upload a PDF or image file to extract table data using OCR technology." }
{/* 파일 선택 */}

Supported formats: PDF, JPG, PNG, TIFF, BMP (Max 10MB)

{/* 선택된 파일 정보 */} {selectedFile && (
{selectedFile.name}
Size: {(selectedFile.size / 1024 / 1024).toFixed(2)} MB Type: {selectedFile.type}
)} {/* 업로드 진행상황 */} {uploadProgress && (
Processing... {uploadProgress.stage}

{uploadProgress.message}

{/* 진행 중일 때 안내 메시지 */} {isUploading && uploadProgress.stage !== "complete" && (

Please wait... This dialog will close automatically when complete.

)}
)} {/* 액션 버튼들 */}
{/* Export 버튼 */} {/* Export 드롭다운 메뉴 */} 전체 데이터 내보내기 현재 페이지 내보내기
) }