({ filePath, fileName, className }: SheetViewerProps)
| 68 | } |
| 69 | |
| 70 | export default function SheetViewer({ filePath, fileName, className }: SheetViewerProps) { |
| 71 | const { t } = useTranslation('chat'); |
| 72 | const [state, setState] = useState<LoadState>({ status: 'idle' }); |
| 73 | const [sheetIndex, setSheetIndex] = useState(0); |
| 74 | const [page, setPage] = useState(0); |
| 75 | const scrollerRef = useRef<HTMLDivElement | null>(null); |
| 76 | |
| 77 | useEffect(() => { |
| 78 | let cancelled = false; |
| 79 | setState({ status: 'loading' }); |
| 80 | setSheetIndex(0); |
| 81 | setPage(0); |
| 82 | |
| 83 | void (async () => { |
| 84 | try { |
| 85 | const res = await readBinaryFile(filePath, { maxBytes: SHEET_MAX_BYTES }); |
| 86 | if (cancelled) return; |
| 87 | if (!res.ok || !res.data) { |
| 88 | if (res.error === 'tooLarge') { |
| 89 | setState({ status: 'tooLarge', size: res.size }); |
| 90 | return; |
| 91 | } |
| 92 | setState({ status: 'error', message: String(res.error ?? 'unknown') }); |
| 93 | return; |
| 94 | } |
| 95 | const xlsx = await import('xlsx'); |
| 96 | const wb = xlsx.read(res.data, { type: 'array', cellDates: true }); |
| 97 | const sheets: SheetSnapshot[] = wb.SheetNames.map((name) => { |
| 98 | const ws = wb.Sheets[name]; |
| 99 | if (!ws) { |
| 100 | return { name, rows: [], columnLetters: [] }; |
| 101 | } |
| 102 | const aoa = xlsx.utils.sheet_to_json<Array<unknown>>(ws, { |
| 103 | header: 1, |
| 104 | defval: '', |
| 105 | blankrows: false, |
| 106 | raw: true, |
| 107 | }); |
| 108 | let maxCols = 0; |
| 109 | for (const row of aoa) { |
| 110 | if (Array.isArray(row) && row.length > maxCols) maxCols = row.length; |
| 111 | } |
| 112 | const columnLetters: string[] = []; |
| 113 | for (let i = 0; i < maxCols; i += 1) columnLetters.push(colLetter(i)); |
| 114 | const rows: string[][] = aoa.map((row) => { |
| 115 | const out = new Array<string>(maxCols).fill(''); |
| 116 | if (!Array.isArray(row)) return out; |
| 117 | for (let i = 0; i < maxCols; i += 1) { |
| 118 | out[i] = formatCellValue(row[i]); |
| 119 | } |
| 120 | return out; |
| 121 | }); |
| 122 | return { name, rows, columnLetters }; |
| 123 | }); |
| 124 | if (cancelled) return; |
| 125 | setState({ status: 'ready', sheets }); |
| 126 | } catch (err) { |
| 127 | if (cancelled) return; |
nothing calls this directly
no test coverage detected