import React, { useEffect, useState, useRef } from 'react'; import { axiosInstance } from '../../../services/axios'; import * as XLSX from 'xlsx'; interface SpreadsheetThumbnailProps { url: string; fallback: React.ReactNode; } export const SpreadsheetThumbnail: React.FC = ({ url, fallback }) => { const parentRef = useRef(null); const [html, setHtml] = useState(''); const [scale, setScale] = useState(0.2); const [loading, setLoading] = useState(true); const [error, setError] = useState(false); useEffect(() => { let isMounted = true; axiosInstance.get(url, { responseType: 'arraybuffer' }) .then(res => { if (!isMounted) return; try { const workbook = XLSX.read(res.data, { type: 'array' }); const sheetName = workbook.SheetNames[0]; const worksheet = workbook.Sheets[sheetName]; const sheetHtml = XLSX.utils.sheet_to_html(worksheet, { header: '', footer: '' }); if (isMounted) { setHtml(sheetHtml); setLoading(false); } } catch (err) { console.error('[SpreadsheetThumbnail] Render error:', err); if (isMounted) { setError(true); setLoading(false); } } }) .catch(err => { console.error('[SpreadsheetThumbnail] Fetch error:', err); if (isMounted) { setError(true); setLoading(false); } }); return () => { isMounted = false; }; }, [url]); useEffect(() => { if (!parentRef.current) return; const updateScale = () => { if (parentRef.current) { const width = parentRef.current.offsetWidth || 280; setScale(width / 900); } }; updateScale(); const observer = new ResizeObserver(updateScale); observer.observe(parentRef.current); return () => observer.disconnect(); }, []); if (error) return <>{fallback}; return (
{loading && (
)}
); };