'use client' import React, { useState, useEffect } from 'react' import { X, Download, MagnifyingGlassPlus, MagnifyingGlassMinus } from '@phosphor-icons/react' import mammoth from 'mammoth' import * as XLSX from 'xlsx' import { PDFViewer } from './PDFViewer' interface FilePreviewProps { file: { name: string path: string extension?: string size?: number } onClose: () => void onDownload: () => void passkey?: string isPublic?: boolean } export function FilePreview({ file, onClose, onDownload, passkey, isPublic = true }: FilePreviewProps) { const [content, setContent] = useState(null) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [scale, setScale] = useState(1) // Excel specific state const [activeSheet, setActiveSheet] = useState(0) // For secure data, we read directly from /api/data // For public, use the download API const previewUrl = isPublic ? `/api/download?path=${encodeURIComponent(file.path)}&preview=true` : `/api/data?key=${encodeURIComponent(passkey || '')}&path=${encodeURIComponent(file.path)}` const ext = file.extension?.toLowerCase() || '' useEffect(() => { loadFileContent() }, [file]) const loadFileContent = async () => { setLoading(true) setError(null) try { switch (ext) { case 'docx': case 'doc': await loadWordDocument() break case 'xlsx': case 'xls': await loadExcelDocument() break case 'pptx': case 'ppt': await loadPowerPointDocument() break case 'txt': case 'md': case 'json': case 'js': case 'ts': case 'jsx': case 'tsx': case 'css': case 'html': case 'xml': case 'py': case 'java': case 'cpp': case 'c': case 'h': case 'sh': case 'yaml': case 'yml': case 'dart': case 'tex': await loadTextFile() break case 'csv': await loadCSVFile() break default: setContent(null) } } catch (err) { setError(err instanceof Error ? err.message : 'Failed to load file') } finally { setLoading(false) } } const loadWordDocument = async () => { try { const response = await fetch(previewUrl) const arrayBuffer = await response.arrayBuffer() const result = await mammoth.convertToHtml({ arrayBuffer }) setContent({ type: 'html', data: result.value }) } catch (err) { throw new Error('Failed to load Word document') } } const loadExcelDocument = async () => { try { const response = await fetch(previewUrl) const arrayBuffer = await response.arrayBuffer() const workbook = XLSX.read(arrayBuffer, { type: 'array' }) // Convert all sheets to HTML const sheets = workbook.SheetNames.map(name => ({ name, html: XLSX.utils.sheet_to_html(workbook.Sheets[name], { header: '', footer: '
' }) })) setContent({ type: 'excel', data: sheets }) } catch (err) { throw new Error('Failed to load Excel document') } } const loadPowerPointDocument = async () => { // For PowerPoint, we'll show a message to download // Full PowerPoint rendering requires more complex libraries setContent({ type: 'powerpoint', data: null }) } const loadTextFile = async () => { try { // For secure data files, read from /api/data which returns file list with content if (!isPublic && passkey) { const response = await fetch(`/api/data?key=${encodeURIComponent(passkey)}&folder=`) const data = await response.json() const fileData = data.files?.find((f: any) => f.name === file.name) if (fileData && fileData.content) { setContent({ type: 'text', data: fileData.content }) } else { throw new Error('File content not available') } } else { const response = await fetch(previewUrl) const text = await response.text() setContent({ type: 'text', data: text }) } } catch (err) { throw new Error('Failed to load text file') } } const loadCSVFile = async () => { try { const response = await fetch(previewUrl) const text = await response.text() const workbook = XLSX.read(text, { type: 'string' }) const sheet = workbook.Sheets[workbook.SheetNames[0]] const html = XLSX.utils.sheet_to_html(sheet, { header: '', footer: '
' }) setContent({ type: 'html', data: html }) } catch (err) { throw new Error('Failed to load CSV file') } } const renderContent = () => { if (loading) { return (
Loading...
) } if (error) { return (

{error}

) } // PDF files if (ext === 'pdf') { return ( setScale(prev => Math.min(2, prev + 0.1))} onZoomOut={() => setScale(prev => Math.max(0.5, prev - 0.1))} /> ) } // Image files if (['jpg', 'jpeg', 'png', 'gif', 'svg', 'webp', 'bmp'].includes(ext)) { return (
{file.name}
{Math.round(scale * 100)}%
) } // HTML content (Word docs, converted HTML) if (content?.type === 'html') { return (
) } // Excel sheets if (content?.type === 'excel') { return (
{content.data.map((sheet: any, index: number) => ( ))}
) } // Text files if (content?.type === 'text') { return (
            {content.data}
          
) } // PowerPoint placeholder if (content?.type === 'powerpoint') { return (
📊

PowerPoint presentation

Preview requires download

) } // Default fallback return (