"use client";
import { useState } from "react";
import {
FileText,
Download,
Share2,
Printer,
Trash2,
ChevronLeft,
ChevronRight,
Image as ImageIcon,
File,
FileCode,
ExternalLink,
Copy,
Check,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import { Badge } from "@/components/ui/badge";
import { cn } from "@/lib/utils";
type FileItem = {
id: string;
name: string;
type: "image" | "pdf" | "text" | "code" | "other";
size: string;
modified: string;
preview?: string;
};
const mockFiles: FileItem[] = [
{
id: "1",
name: "project-screenshot.png",
type: "image",
size: "2.4 MB",
modified: "Dec 10, 2024",
preview: "https://picsum.photos/seed/doc1/800/600",
},
{
id: "2",
name: "quarterly-report.pdf",
type: "pdf",
size: "1.8 MB",
modified: "Dec 8, 2024",
},
{
id: "3",
name: "config.json",
type: "code",
size: "4.2 KB",
modified: "Dec 5, 2024",
},
];
const getFileIcon = (type: FileItem["type"]) => {
switch (type) {
case "image":
return ImageIcon;
case "pdf":
return FileText;
case "code":
return FileCode;
default:
return File;
}
};
export const title = "React Dialog Block File Preview";
export default function DialogFilePreview() {
const [open, setOpen] = useState(false);
const [currentIndex, setCurrentIndex] = useState(0);
const [copied, setCopied] = useState(false);
const currentFile = mockFiles[currentIndex];
const FileIcon = getFileIcon(currentFile.type);
const handlePrevious = () => {
setCurrentIndex((prev) => (prev > 0 ? prev - 1 : mockFiles.length - 1));
};
const handleNext = () => {
setCurrentIndex((prev) => (prev < mockFiles.length - 1 ? prev + 1 : 0));
};
const handleCopyLink = async () => {
await navigator.clipboard.writeText(`https://app.com/files/${currentFile.id}`);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
};
const handleDownload = () => {
// In real app: trigger download
console.log("Downloading:", currentFile.name);
};
const handleShare = () => {
// In real app: open share dialog
console.log("Sharing:", currentFile.name);
};
return (
<Dialog open={open} onOpenChange={setOpen}>
<div className="flex min-h-[350px] items-center justify-center">
<DialogTrigger asChild>
<Button variant="outline">
<FileText className="mr-2 h-4 w-4" />
Preview File
</Button>
</DialogTrigger>
</div>
<DialogContent className="sm:max-w-lg p-0 overflow-hidden">
<DialogHeader className="p-4 pb-0">
<div className="flex items-start justify-between">
<div className="flex items-center gap-3 min-w-0">
<FileIcon className="h-5 w-5 text-muted-foreground shrink-0" />
<div className="min-w-0">
<DialogTitle className="truncate">{currentFile.name}</DialogTitle>
<div className="flex items-center gap-2 mt-1">
<Badge variant="secondary" className="text-xs">
{currentFile.type.toUpperCase()}
</Badge>
<span className="text-xs text-muted-foreground">
{currentFile.size}
</span>
<span className="text-xs text-muted-foreground">•</span>
<span className="text-xs text-muted-foreground">
{currentFile.modified}
</span>
</div>
</div>
</div>
</div>
</DialogHeader>
{/* Preview Area */}
<div className="relative bg-muted/30 min-h-[300px] flex items-center justify-center mx-4 mt-4 rounded-lg border overflow-hidden">
{currentFile.type === "image" && currentFile.preview ? (
<img
src={currentFile.preview}
alt={currentFile.name}
className="max-h-[400px] w-auto object-contain"
/>
) : currentFile.type === "pdf" ? (
<div className="flex flex-col items-center justify-center py-12 text-center">
<FileText className="h-16 w-16 text-muted-foreground mb-4" />
<p className="text-sm font-medium">PDF Preview</p>
<p className="text-xs text-muted-foreground mt-1">
Click download to view the full document
</p>
</div>
) : currentFile.type === "code" ? (
<div className="w-full p-4 font-mono text-sm overflow-auto max-h-[400px]">
<pre className="text-muted-foreground">
{`{
"name": "my-app",
"version": "1.0.0",
"dependencies": {
"react": "^18.2.0",
"next": "^14.0.0"
}
}`}
</pre>
</div>
) : (
<div className="flex flex-col items-center justify-center py-12 text-center">
<File className="h-16 w-16 text-muted-foreground mb-4" />
<p className="text-sm font-medium">Preview not available</p>
<p className="text-xs text-muted-foreground mt-1">
Download to view this file
</p>
</div>
)}
{/* Navigation */}
{mockFiles.length > 1 && (
<>
<Button
variant="ghost"
size="icon"
className="absolute left-2 top-1/2 -translate-y-1/2 h-8 w-8 rounded-full bg-background/80 backdrop-blur-sm"
onClick={handlePrevious}
>
<ChevronLeft className="h-4 w-4" />
</Button>
<Button
variant="ghost"
size="icon"
className="absolute right-2 top-1/2 -translate-y-1/2 h-8 w-8 rounded-full bg-background/80 backdrop-blur-sm"
onClick={handleNext}
>
<ChevronRight className="h-4 w-4" />
</Button>
<div className="absolute bottom-2 left-1/2 -translate-x-1/2 flex gap-1">
{mockFiles.map((_, index) => (
<button
key={index}
onClick={() => setCurrentIndex(index)}
className={cn(
"h-1.5 w-1.5 rounded-full transition-colors",
index === currentIndex
? "bg-primary"
: "bg-muted-foreground/30"
)}
/>
))}
</div>
</>
)}
</div>
{/* Actions */}
<div className="p-4 border-t">
<div className="flex flex-wrap gap-2">
<Button onClick={handleDownload}>
<Download className="mr-2 h-4 w-4" />
Download
</Button>
<Button variant="outline" onClick={handleShare}>
<Share2 className="mr-2 h-4 w-4" />
Share
</Button>
<Button variant="outline" onClick={handleCopyLink}>
{copied ? (
<>
<Check className="mr-2 h-4 w-4" />
Copied!
</>
) : (
<>
<Copy className="mr-2 h-4 w-4" />
Copy Link
</>
)}
</Button>
<Button variant="outline" size="icon">
<Printer className="h-4 w-4" />
</Button>
<Button variant="outline" size="icon">
<ExternalLink className="h-4 w-4" />
</Button>
<div className="flex-1" />
<Button variant="ghost" size="icon" className="text-destructive hover:text-destructive">
<Trash2 className="h-4 w-4" />
</Button>
</div>
</div>
</DialogContent>
</Dialog>
);
}