Spaces:
Sleeping
Sleeping
| import React from "react"; | |
| import { motion } from "framer-motion"; | |
| import { FileText, ZoomIn, ZoomOut, RotateCw, Maximize2 } from "lucide-react"; | |
| import { Button } from "@/components/ui/button"; | |
| export default function DocumentPreview({ file, isProcessing }) { | |
| // Mock preview - in real app would show actual document | |
| const mockPages = [1, 2, 3]; | |
| return ( | |
| <div className="h-full flex flex-col bg-white rounded-2xl border border-slate-200 overflow-hidden"> | |
| {/* Header */} | |
| <div className="flex items-center justify-between px-5 py-4 border-b border-slate-100"> | |
| <div className="flex items-center gap-3"> | |
| <div className="h-8 w-8 rounded-lg bg-indigo-50 flex items-center justify-center"> | |
| <FileText className="h-4 w-4 text-indigo-600" /> | |
| </div> | |
| <div> | |
| <h3 className="font-semibold text-slate-800 text-sm">Document Preview</h3> | |
| <p className="text-xs text-slate-400">{file?.name || "No file selected"}</p> | |
| </div> | |
| </div> | |
| {file && ( | |
| <div className="flex items-center gap-1"> | |
| <Button | |
| variant="ghost" | |
| size="icon" | |
| className="h-8 w-8 text-slate-400 hover:text-slate-600" | |
| > | |
| <ZoomOut className="h-4 w-4" /> | |
| </Button> | |
| <span className="text-xs text-slate-500 w-12 text-center">100%</span> | |
| <Button | |
| variant="ghost" | |
| size="icon" | |
| className="h-8 w-8 text-slate-400 hover:text-slate-600" | |
| > | |
| <ZoomIn className="h-4 w-4" /> | |
| </Button> | |
| <div className="w-px h-4 bg-slate-200 mx-2" /> | |
| <Button | |
| variant="ghost" | |
| size="icon" | |
| className="h-8 w-8 text-slate-400 hover:text-slate-600" | |
| > | |
| <RotateCw className="h-4 w-4" /> | |
| </Button> | |
| <Button | |
| variant="ghost" | |
| size="icon" | |
| className="h-8 w-8 text-slate-400 hover:text-slate-600" | |
| > | |
| <Maximize2 className="h-4 w-4" /> | |
| </Button> | |
| </div> | |
| )} | |
| </div> | |
| {/* Preview Area */} | |
| <div className="flex-1 p-6 bg-slate-50/50 overflow-auto"> | |
| {!file ? ( | |
| <div className="h-full flex items-center justify-center"> | |
| <div className="text-center"> | |
| <div className="h-20 w-20 mx-auto rounded-2xl bg-slate-100 flex items-center justify-center mb-4"> | |
| <FileText className="h-10 w-10 text-slate-300" /> | |
| </div> | |
| <p className="text-slate-400 text-sm">Upload a document to preview</p> | |
| </div> | |
| </div> | |
| ) : ( | |
| <div className="space-y-4"> | |
| {mockPages.map((page, index) => ( | |
| <motion.div | |
| key={page} | |
| initial={{ opacity: 0, y: 20 }} | |
| animate={{ opacity: 1, y: 0 }} | |
| transition={{ delay: index * 0.1 }} | |
| className="relative bg-white rounded-xl shadow-sm border border-slate-200 aspect-[8.5/11] overflow-hidden" | |
| > | |
| {/* Mock document content */} | |
| <div className="absolute inset-0 p-8"> | |
| {/* Header simulation */} | |
| <div className="flex items-center gap-4 mb-8"> | |
| <div className="h-12 w-12 rounded-lg bg-slate-100" /> | |
| <div className="space-y-2"> | |
| <div className="h-3 w-32 bg-slate-100 rounded" /> | |
| <div className="h-2 w-24 bg-slate-50 rounded" /> | |
| </div> | |
| </div> | |
| {/* Text lines simulation */} | |
| <div className="space-y-3"> | |
| {[...Array(12)].map((_, i) => ( | |
| <div | |
| key={i} | |
| className="h-2 bg-slate-100 rounded" | |
| style={{ width: `${Math.random() * 40 + 60}%` }} | |
| /> | |
| ))} | |
| </div> | |
| {/* Table simulation */} | |
| <div className="mt-6 border border-slate-100 rounded-lg overflow-hidden"> | |
| {[...Array(4)].map((_, i) => ( | |
| <div key={i} className="flex border-b border-slate-50 last:border-0"> | |
| {[...Array(3)].map((_, j) => ( | |
| <div | |
| key={j} | |
| className="flex-1 p-3 border-r border-slate-50 last:border-0" | |
| > | |
| <div className="h-2 bg-slate-100 rounded w-3/4" /> | |
| </div> | |
| ))} | |
| </div> | |
| ))} | |
| </div> | |
| </div> | |
| {/* Processing overlay */} | |
| {isProcessing && ( | |
| <motion.div | |
| initial={{ opacity: 0 }} | |
| animate={{ opacity: 1 }} | |
| className="absolute inset-0 bg-indigo-600/5 backdrop-blur-[1px]" | |
| > | |
| <motion.div | |
| initial={{ top: 0 }} | |
| animate={{ top: "100%" }} | |
| transition={{ | |
| duration: 2, | |
| repeat: Infinity, | |
| ease: "linear", | |
| }} | |
| className="absolute left-0 right-0 h-1 bg-gradient-to-r from-transparent via-indigo-500 to-transparent" | |
| /> | |
| </motion.div> | |
| )} | |
| {/* Page number */} | |
| <div className="absolute bottom-3 right-3 text-xs text-slate-400 bg-white/90 px-2 py-1 rounded"> | |
| Page {page} | |
| </div> | |
| </motion.div> | |
| ))} | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| ); | |
| } | |