131 lines
4.7 KiB
TypeScript
131 lines
4.7 KiB
TypeScript
import { Eye, Paperclip } from 'lucide-react';
|
|
import { useState } from 'react';
|
|
import { Button } from '@/components/ui/button';
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
} from '@/components/ui/dialog';
|
|
import {
|
|
Tooltip,
|
|
TooltipContent,
|
|
TooltipTrigger,
|
|
} from '@/components/ui/tooltip';
|
|
import { cn } from '@/lib/utils';
|
|
|
|
const IMAGE_EXTENSIONS = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
|
|
const VIDEO_EXTENSIONS = ['mp4', 'webm'];
|
|
|
|
function fileExtension(fileName: string): string {
|
|
return fileName.split('.').pop()?.toLowerCase() ?? '';
|
|
}
|
|
|
|
type AttachmentPreviewDialogProps = {
|
|
fileUrl: string;
|
|
fileName: string;
|
|
className?: string;
|
|
variant?: 'link' | 'icon';
|
|
};
|
|
|
|
export function AttachmentPreviewDialog({
|
|
fileUrl,
|
|
fileName,
|
|
className,
|
|
variant = 'link',
|
|
}: AttachmentPreviewDialogProps) {
|
|
const [open, setOpen] = useState(false);
|
|
const extension = fileExtension(fileName);
|
|
const isImage = IMAGE_EXTENSIONS.includes(extension);
|
|
const isVideo = VIDEO_EXTENSIONS.includes(extension);
|
|
const isPdf = extension === 'pdf';
|
|
|
|
return (
|
|
<>
|
|
{variant === 'icon' ? (
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<Button
|
|
type="button"
|
|
variant="ghost"
|
|
size="icon"
|
|
className={className}
|
|
onClick={() => setOpen(true)}
|
|
>
|
|
<Eye className="h-4 w-4" />
|
|
</Button>
|
|
</TooltipTrigger>
|
|
<TooltipContent side="top">Lihat</TooltipContent>
|
|
</Tooltip>
|
|
) : (
|
|
<button
|
|
type="button"
|
|
onClick={() => setOpen(true)}
|
|
className={cn(
|
|
'inline-flex items-center gap-1 text-primary underline underline-offset-4 hover:text-primary/80',
|
|
className,
|
|
)}
|
|
>
|
|
<Paperclip className="h-3.5 w-3.5 shrink-0" />
|
|
<span className="truncate">{fileName}</span>
|
|
</button>
|
|
)}
|
|
|
|
<Dialog open={open} onOpenChange={setOpen}>
|
|
<DialogContent
|
|
className={cn(
|
|
'flex flex-col overflow-hidden',
|
|
isPdf
|
|
? 'h-[90vh] max-h-[90vh] w-[95vw] max-w-6xl sm:max-w-6xl'
|
|
: 'max-h-[85vh] sm:max-w-lg',
|
|
)}
|
|
>
|
|
<DialogHeader>
|
|
<DialogTitle className="truncate pr-6">
|
|
{fileName}
|
|
</DialogTitle>
|
|
</DialogHeader>
|
|
|
|
<div className="flex min-h-0 flex-1 items-center justify-center overflow-auto rounded-md bg-muted/30">
|
|
{isImage && (
|
|
<img
|
|
src={fileUrl}
|
|
alt={fileName}
|
|
className="max-h-[70vh] max-w-full object-contain"
|
|
/>
|
|
)}
|
|
{isVideo && (
|
|
<video
|
|
src={fileUrl}
|
|
controls
|
|
className="max-h-[70vh] w-full"
|
|
/>
|
|
)}
|
|
{isPdf && (
|
|
<iframe
|
|
src={fileUrl}
|
|
title={fileName}
|
|
className="h-full w-full border-0"
|
|
/>
|
|
)}
|
|
{!isImage && !isVideo && !isPdf && (
|
|
<div className="flex flex-col items-center gap-3 py-16 text-center text-sm text-muted-foreground">
|
|
<Paperclip className="h-8 w-8" />
|
|
<p>Pratinjau tidak tersedia untuk file ini.</p>
|
|
<a
|
|
href={fileUrl}
|
|
target="_blank"
|
|
rel="noreferrer"
|
|
className="text-primary underline underline-offset-4 hover:text-primary/80"
|
|
>
|
|
Buka / unduh file
|
|
</a>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</>
|
|
);
|
|
}
|