import { useRef, useState } from 'react'; import { api } from '../../api'; import { useQueryClient } from '@tanstack/react-query'; interface UploadResult { filename: string; rms_total: number; rms_ra: number; rms_dec: number; duration_min?: number; camera_name?: string; exposure_ms?: number; mount_name?: string; session_date?: string; error?: string; duplicate?: { id: number; message: string }; } interface Props { onUploaded?: (id: number) => void; } export default function PHD2UploadZone({ onUploaded }: Props) { const inputRef = useRef(null); const [uploading, setUploading] = useState(false); const [results, setResults] = useState([]); const qc = useQueryClient(); const handleFiles = async (files: FileList | null) => { if (!files || files.length === 0) return; setUploading(true); setResults([]); const uploadedIds: number[] = []; for (let i = 0; i < files.length; i++) { const file = files[i]; const fd = new FormData(); fd.append('file', file); try { const res = await api.phd2.upload(fd); if (res.duplicate) { setResults(prev => [...prev, { filename: file.name, rms_total: 0, rms_ra: 0, rms_dec: 0, duplicate: { id: res.duplicate_id || 0, message: res.message || `Duplicate session detected (ID: ${res.duplicate_id})` } }]); } else { const analysis = res.analysis as any; setResults(prev => [...prev, { filename: file.name, rms_total: analysis.rms_total_arcsec, rms_ra: analysis.rms_ra_arcsec, rms_dec: analysis.rms_dec_arcsec, duration_min: analysis.duration_min, camera_name: analysis.camera_name, exposure_ms: analysis.exposure_ms, mount_name: analysis.mount_name, session_date: analysis.session_date, }]); uploadedIds.push(res.id); } } catch (e) { setResults(prev => [...prev, { filename: file.name, rms_total: 0, rms_ra: 0, rms_dec: 0, error: `Parse failed: ${e instanceof Error ? e.message : 'Unknown error'}` }]); } } qc.invalidateQueries({ queryKey: ['phd2'] }); uploadedIds.forEach(id => onUploaded?.(id)); setUploading(false); }; return (
inputRef.current?.click()} style={{ border: '1px dashed var(--border)', borderRadius: 3, padding: '10px 14px', cursor: 'pointer', color: 'var(--text-lo)', fontFamily: 'var(--font-mono)', fontSize: 11, background: 'var(--bg-deep)', }} > {uploading ? 'Parsing PHD2 logs...' : '↑ Upload PHD2 log(s) (.log)'}
handleFiles(e.target.files)} /> {results.map((result, idx) => (
{result.filename}
{result.error && (
✗ {result.error}
)} {result.duplicate && (
⚠ {result.duplicate.message}
)} {!result.error && !result.duplicate && (
✓ RMS: {result.rms_total.toFixed(2)}″ (RA: {result.rms_ra.toFixed(2)}″ Dec: {result.rms_dec.toFixed(2)}″)
{result.session_date && (
Date: {result.session_date}
)} {result.duration_min !== undefined && (
Duration: {result.duration_min}m
)} {(result.camera_name || result.mount_name) && (
{result.camera_name &&
Camera: {result.camera_name}
} {result.mount_name &&
Mount: {result.mount_name}
} {result.exposure_ms &&
Exposure: {result.exposure_ms}ms
}
)}
)}
))}
); }