import { useState, useCallback } from 'react'; import { convertPesToPen, type PesPatternData } from '../utils/pystitchConverter'; import { MachineStatus } from '../types/machine'; import { canUploadPattern, getMachineStateCategory } from '../utils/machineStateHelpers'; import { PatternInfoSkeleton } from './SkeletonLoader'; import { ArrowUpTrayIcon, CheckCircleIcon } from '@heroicons/react/24/solid'; interface FileUploadProps { isConnected: boolean; machineStatus: MachineStatus; uploadProgress: number; onPatternLoaded: (pesData: PesPatternData) => void; onUpload: (penData: Uint8Array, pesData: PesPatternData, fileName: string, patternOffset?: { x: number; y: number }) => void; pyodideReady: boolean; patternOffset: { x: number; y: number }; patternUploaded: boolean; resumeAvailable: boolean; resumeFileName: string | null; pesData: PesPatternData | null; isUploading?: boolean; } export function FileUpload({ isConnected, machineStatus, uploadProgress, onPatternLoaded, onUpload, pyodideReady, patternOffset, patternUploaded, resumeAvailable, resumeFileName, pesData: pesDataProp, isUploading = false, }: FileUploadProps) { const [localPesData, setLocalPesData] = useState(null); const [fileName, setFileName] = useState(''); // Use prop pesData if available (from cached pattern), otherwise use local state const pesData = pesDataProp || localPesData; const displayFileName = resumeFileName || fileName; const [isLoading, setIsLoading] = useState(false); const handleFileChange = useCallback( async (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (!file) return; if (!pyodideReady) { alert('Python environment is still loading. Please wait...'); return; } setIsLoading(true); try { const data = await convertPesToPen(file); setLocalPesData(data); setFileName(file.name); onPatternLoaded(data); } catch (err) { alert( `Failed to load PES file: ${ err instanceof Error ? err.message : 'Unknown error' }` ); } finally { setIsLoading(false); } }, [onPatternLoaded, pyodideReady] ); const handleUpload = useCallback(() => { if (pesData && displayFileName) { onUpload(pesData.penData, pesData, displayFileName, patternOffset); } }, [pesData, displayFileName, onUpload, patternOffset]); return (

Pattern File

{resumeAvailable && resumeFileName && (

Loaded cached pattern: "{resumeFileName}"

)} {patternUploaded && (

Pattern uploaded successfully! The pattern is now locked and cannot be changed. To upload a different pattern, you must first complete or delete the current one.

)} {isLoading && } {!isLoading && pesData && (

Pattern Information

File Name: {displayFileName}
Pattern Size: {((pesData.bounds.maxX - pesData.bounds.minX) / 10).toFixed(1)} x{' '} {((pesData.bounds.maxY - pesData.bounds.minY) / 10).toFixed(1)} mm
Thread Colors:
{pesData.colorCount}
{pesData.threads.slice(0, 5).map((thread, idx) => (
))} {pesData.colorCount > 5 && (
+{pesData.colorCount - 5}
)}
Total Stitches: {pesData.stitchCount.toLocaleString()}
)} {pesData && canUploadPattern(machineStatus) && !patternUploaded && uploadProgress < 100 && ( )} {pesData && !canUploadPattern(machineStatus) && (
Cannot upload pattern while machine is {getMachineStateCategory(machineStatus)}
)} {isUploading && uploadProgress < 100 && (
Uploading to Machine {uploadProgress > 0 ? uploadProgress.toFixed(1) + '%' : 'Starting...'}

Please wait while your pattern is being transferred...

)}
); }