erp-platform/ui/src/views/project/components/DocumentViewerModal.tsx
2025-09-15 12:31:47 +03:00

205 lines
6.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React from "react";
import {
FaTimes,
FaDownload,
FaFileAlt,
FaFilePdf,
FaFileWord,
FaFileExcel,
FaFilePowerpoint,
FaFileImage,
} from "react-icons/fa";
import { PsProjectDocument } from "../../../types/ps";
import dayjs from "dayjs";
import { getPsDocumentTypeText } from "../../../utils/erp";
interface DocumentViewerModalProps {
isOpen: boolean;
onClose: () => void;
document: PsProjectDocument | null;
onDownload?: (document: PsProjectDocument) => void;
}
const DocumentViewerModal: React.FC<DocumentViewerModalProps> = ({
isOpen,
onClose,
document,
onDownload,
}) => {
const getFileIcon = (fileName: string) => {
const extension = fileName.toLowerCase().split(".").pop();
switch (extension) {
case "pdf":
return <FaFilePdf className="w-8 h-8 text-red-500" />;
case "doc":
case "docx":
return <FaFileWord className="w-8 h-8 text-blue-500" />;
case "xls":
case "xlsx":
return <FaFileExcel className="w-8 h-8 text-green-500" />;
case "ppt":
case "pptx":
return <FaFilePowerpoint className="w-8 h-8 text-orange-500" />;
case "jpg":
case "jpeg":
case "png":
case "gif":
return <FaFileImage className="w-8 h-8 text-purple-500" />;
default:
return <FaFileAlt className="w-8 h-8 text-gray-500" />;
}
};
const formatFileSize = (sizeInMB: number): string => {
if (sizeInMB < 1) {
return `${(sizeInMB * 1024).toFixed(0)} KB`;
}
return `${sizeInMB.toFixed(2)} MB`;
};
const handleDownload = () => {
if (document && onDownload) {
onDownload(document);
} else if (document) {
// Fallback: create a download link
const link = window.document.createElement("a");
link.href = document.filePath;
link.download = document.documentName;
link.click();
}
};
const isImageFile = (fileName: string): boolean => {
const extension = fileName.toLowerCase().split(".").pop();
return ["jpg", "jpeg", "png", "gif"].includes(extension || "");
};
const isPdfFile = (fileName: string): boolean => {
const extension = fileName.toLowerCase().split(".").pop();
return extension === "pdf";
};
if (!isOpen || !document) return null;
return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white rounded-lg w-full max-w-4xl max-h-[90vh] overflow-hidden flex flex-col">
{/* Header */}
<div className="flex items-center justify-between p-3 border-b border-gray-200">
<div className="flex items-center space-x-3">
{getFileIcon(document.documentName)}
<div>
<h2 className="text-lg font-semibold text-gray-900">
{document.documentName}
</h2>
<p className="text-sm text-gray-500">
{getPsDocumentTypeText(document.documentType)} {" "}
{formatFileSize(document.fileSize)}
</p>
</div>
</div>
<div className="flex items-center space-x-2">
<button
onClick={handleDownload}
className="flex items-center space-x-2 px-3 py-1 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
>
<FaDownload className="w-4 h-4" />
<span>İndir</span>
</button>
<button
onClick={onClose}
className="text-gray-400 hover:text-gray-600 p-2"
>
<FaTimes className="w-4 h-4" />
</button>
</div>
</div>
{/* Document Info */}
<div className="px-4 py-2 bg-gray-50 border-b border-gray-200">
<div className="grid grid-cols-2 md:grid-cols-4 gap-3 text-sm">
<div>
<span className="font-medium text-gray-700">Yükleyen:</span>
<p className="text-gray-600">{document.uploadedBy}</p>
</div>
<div>
<span className="font-medium text-gray-700">
Yüklenme Tarihi:
</span>
<p className="text-gray-600">
{dayjs(document.uploadedAt).format("DD.MM.YYYY HH:mm")}
</p>
</div>
<div>
<span className="font-medium text-gray-700">Versiyon:</span>
<p className="text-gray-600">v{document.version}</p>
</div>
<div>
<span className="font-medium text-gray-700">Dosya Boyutu:</span>
<p className="text-gray-600">
{formatFileSize(document.fileSize)}
</p>
</div>
</div>
</div>
{/* Document Preview */}
<div className="flex-1 p-3 overflow-auto">
{isImageFile(document.documentName) ? (
<div className="flex items-center justify-center h-full">
<img
src={document.filePath}
alt={document.documentName}
className="max-w-full max-h-full object-contain"
onError={(e) => {
const target = e.target as HTMLImageElement;
target.style.display = "none";
}}
/>
</div>
) : isPdfFile(document.documentName) ? (
<div className="h-full">
<iframe
src={document.filePath}
className="w-full h-full border-0"
title={document.documentName}
/>
</div>
) : (
<div className="flex flex-col items-center justify-center h-full text-center">
{getFileIcon(document.documentName)}
<h3 className="mt-4 text-lg font-medium text-gray-900">
Önizleme Mevcut Değil
</h3>
<p className="mt-2 text-sm text-gray-500">
Bu dosya türü için önizleme desteklenmiyor.
</p>
<p className="text-sm text-gray-500">
Dosyayı görüntülemek için indirin.
</p>
</div>
)}
</div>
{/* Footer */}
<div className="px-4 py-2 bg-gray-50 border-t border-gray-200">
<div className="flex items-center justify-between">
<div className="text-sm text-gray-500">
Son güncelleme:{" "}
{dayjs(document.uploadedAt).format("DD.MM.YYYY HH:mm")}
</div>
<button
onClick={onClose}
className="px-3 py-1 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50"
>
Kapat
</button>
</div>
</div>
</div>
</div>
);
};
export default DocumentViewerModal;