import React, { useState } from 'react'; import { Box, Typography, Chip, Paper, IconButton, Tooltip, Stack, CircularProgress, Alert, } from '@mui/material'; import { Security as SecurityIcon, Fingerprint as FingerprintIcon, ContentCopy as CopyIcon, CheckCircle as CheckIcon, Warning as WarningIcon, Error as ErrorIcon, Info as InfoIcon, } from '@mui/icons-material'; import { useTheme } from '../contexts/ThemeContext'; import { useTheme as useMuiTheme } from '@mui/material/styles'; interface FileIntegrityDisplayProps { fileHash?: string; fileName: string; fileSize: number; mimeType: string; createdAt: string; updatedAt: string; userId?: string; username?: string; // Additional metadata fields sourceType?: string; sourcePath?: string; filePermissions?: number; fileOwner?: string; fileGroup?: string; originalCreatedAt?: string; originalModifiedAt?: string; sourceMetadata?: any; compact?: boolean; } const FileIntegrityDisplay: React.FC = ({ fileHash, fileName, fileSize, mimeType, createdAt, updatedAt, userId, username, sourceType, sourcePath, filePermissions, fileOwner, fileGroup, originalCreatedAt, originalModifiedAt, sourceMetadata, compact = false, }) => { const [copied, setCopied] = useState(false); const { modernTokens } = useTheme(); const theme = useMuiTheme(); const copyToClipboard = (text: string) => { navigator.clipboard.writeText(text); setCopied(true); setTimeout(() => setCopied(false), 2000); }; const formatHash = (hash: string) => { if (!hash) return 'Not available'; return `${hash.substring(0, 8)}...${hash.substring(hash.length - 8)}`; }; const getIntegrityStatus = () => { if (!fileHash) { return { status: 'unknown', icon: , color: theme.palette.text.secondary, message: 'Hash not available', }; } // Simple validation - in real implementation you'd verify against stored hash if (fileHash.length === 64) { // SHA256 length return { status: 'verified', icon: , color: theme.palette.success.main, message: 'File integrity verified', }; } return { status: 'warning', icon: , color: theme.palette.warning.main, message: 'Hash format unusual', }; }; const integrityStatus = getIntegrityStatus(); const formatFileSize = (bytes: number): string => { const sizes = ['Bytes', 'KB', 'MB', 'GB']; if (bytes === 0) return '0 Bytes'; const i = Math.floor(Math.log(bytes) / Math.log(1024)); return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i]; }; const formatDate = (dateString: string): string => { return new Date(dateString).toLocaleString('en-US', { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit', }); }; if (compact) { return ( File Integrity Hash (SHA256) {formatHash(fileHash || '')} {fileHash && ( copyToClipboard(fileHash)} sx={{ p: 0.25 }} > )} Size {formatFileSize(fileSize)} ); } return ( {/* Header */} Document Details {/* Hash Information */} SHA256 Hash {fileHash ? ( {fileHash} copyToClipboard(fileHash)} sx={{ ml: 1 }} > ) : ( File hash not available. Enable hash generation in upload settings. )} {/* File Properties */} File Properties File Size {formatFileSize(fileSize)} MIME Type Uploaded {formatDate(createdAt)} {createdAt !== updatedAt && ( Last Modified {formatDate(updatedAt)} )} Uploaded By {fileOwner && ( Owner {fileOwner} )} {sourcePath && ( Source Path {sourcePath} )} {/* Additional Source Information */} {(sourceType || fileGroup || filePermissions) && ( Additional Source Details {sourceType && ( Source Type: )} {fileGroup && ( File Group: {fileGroup} )} {filePermissions && ( Permissions: {filePermissions.toString(8)} ({filePermissions}) )} )} {/* Timestamps */} {(originalCreatedAt || originalModifiedAt) && ( Original Timestamps {originalCreatedAt && ( Original Created: {new Date(originalCreatedAt).toLocaleString()} )} {originalModifiedAt && ( Original Modified: {new Date(originalModifiedAt).toLocaleString()} )} )} {/* Source Metadata - displayed as simple key-value pairs */} {sourceMetadata && Object.keys(sourceMetadata).length > 0 && ( Source Metadata {Object.entries(sourceMetadata).map(([key, value]) => { // Skip null/undefined values and complex objects if (value === null || value === undefined || typeof value === 'object') return null; // Format the key to be more readable const formattedKey = key .replace(/_/g, ' ') .replace(/([A-Z])/g, ' $1') .replace(/^./, str => str.toUpperCase()) .trim(); // Format the value const formattedValue = typeof value === 'boolean' ? (value ? 'Yes' : 'No') : String(value); return ( {formattedKey}: {formattedValue} ); }).filter(Boolean)} )} ); }; export default FileIntegrityDisplay;