/* * File: DicomViewerModal.tsx * Description: Reusable modal component for DICOM image viewing * Design & Developed by Tech4Biz Solutions * Copyright (c) Spurrin Innovations. All rights reserved. */ import React, { useState } from 'react'; import { View, Text, StyleSheet, TouchableOpacity, Modal, SafeAreaView, StatusBar, Dimensions, Alert, } from 'react-native'; import { theme } from '../../theme/theme'; import Icon from 'react-native-vector-icons/Feather'; import DicomViewer from './DicomViewer'; // ============================================================================ // INTERFACES // ============================================================================ /** * DicomViewerModalProps Interface * * Purpose: Defines the props required by the DicomViewerModal component * * Props: * - visible: Whether the modal is visible * - dicomUrl: URL of the DICOM file to display * - onClose: Callback function when modal is closed * - title: Optional title for the modal header * - patientName: Optional patient name for context * - studyDescription: Optional study description */ interface DicomViewerModalProps { visible: boolean; dicomUrl: string; onClose: () => void; title?: string; patientName?: string; studyDescription?: string; } // ============================================================================ // DICOM VIEWER MODAL COMPONENT // ============================================================================ /** * DicomViewerModal Component * * Purpose: Provides a full-screen modal for viewing DICOM medical images * * Features: * - Full-screen DICOM image viewing * - Modal overlay with close functionality * - Error handling and display * - Loading states * - Header with patient/study information * - Responsive design for different screen sizes * - Proper medical image viewing environment (dark background) */ export const DicomViewerModal: React.FC = ({ visible, dicomUrl, onClose, title = 'DICOM Viewer', patientName, studyDescription, }) => { // ============================================================================ // STATE MANAGEMENT // ============================================================================ const [isLoading, setIsLoading] = useState(false); const [hasError, setHasError] = useState(false); // ============================================================================ // EVENT HANDLERS // ============================================================================ /** * Handle DICOM viewer load completion */ const handleDicomLoad = () => { setIsLoading(false); setHasError(false); }; /** * Handle DICOM viewer errors * @param error - Error message from DICOM viewer */ const handleDicomError = (error: string) => { setIsLoading(false); setHasError(true); // Show error alert to user Alert.alert( 'DICOM Loading Error', `Failed to load DICOM file: ${error}`, [ { text: 'Retry', onPress: () => { setHasError(false); setIsLoading(true); }, }, { text: 'Close', onPress: onClose, style: 'cancel', }, ] ); }; /** * Handle modal close request */ const handleClose = () => { // Reset states when closing setIsLoading(false); setHasError(false); onClose(); }; /** * Handle back button press (Android) */ const handleRequestClose = () => { handleClose(); }; // ============================================================================ // RENDER HEADER // ============================================================================ /** * Render modal header with title and close button */ const renderHeader = () => ( {/* Title and Patient Info */} {title} {patientName && ( Patient: {patientName} )} {studyDescription && ( Study: {studyDescription} )} {/* Close Button */} ); // ============================================================================ // RENDER CONTENT // ============================================================================ /** * Render DICOM viewer content */ const renderContent = () => { if (!dicomUrl) { return ( No DICOM URL provided Close ); } return ( ); }; // ============================================================================ // MAIN RENDER // ============================================================================ return ( {/* Set status bar to light content for dark background */} {/* Header */} {renderHeader()} {/* Content */} {renderContent()} ); }; // ============================================================================ // STYLES // ============================================================================ const { width: screenWidth, height: screenHeight } = Dimensions.get('window'); const styles = StyleSheet.create({ // Main container container: { flex: 1, backgroundColor: '#000000', }, // Header section header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: theme.spacing.lg, paddingVertical: theme.spacing.md, backgroundColor: 'rgba(0, 0, 0, 0.9)', borderBottomWidth: 1, borderBottomColor: 'rgba(255, 255, 255, 0.1)', }, // Header content headerContent: { flex: 1, marginRight: theme.spacing.md, }, // Header title headerTitle: { fontSize: theme.typography.fontSize.displaySmall, fontFamily: theme.typography.fontFamily.bold, color: theme.colors.background, marginBottom: 2, }, // Header subtitle headerSubtitle: { fontSize: theme.typography.fontSize.bodyMedium, fontFamily: theme.typography.fontFamily.regular, color: 'rgba(255, 255, 255, 0.8)', lineHeight: theme.typography.fontSize.bodyMedium * 1.2, }, // Close button closeButton: { width: 40, height: 40, borderRadius: 20, backgroundColor: 'rgba(255, 255, 255, 0.1)', justifyContent: 'center', alignItems: 'center', borderWidth: 1, borderColor: 'rgba(255, 255, 255, 0.2)', }, // DICOM viewer container viewerContainer: { flex: 1, backgroundColor: '#000000', }, // Empty state container emptyContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#000000', paddingHorizontal: theme.spacing.xl, }, // Empty state text emptyText: { fontSize: theme.typography.fontSize.bodyLarge, fontFamily: theme.typography.fontFamily.medium, color: theme.colors.textMuted, textAlign: 'center', marginTop: theme.spacing.md, marginBottom: theme.spacing.xl, }, // Secondary close button closeButtonSecondary: { backgroundColor: theme.colors.primary, paddingHorizontal: theme.spacing.xl, paddingVertical: theme.spacing.md, borderRadius: theme.borderRadius.medium, ...theme.shadows.primary, }, // Close button text closeButtonText: { fontSize: theme.typography.fontSize.bodyLarge, fontFamily: theme.typography.fontFamily.bold, color: theme.colors.background, }, }); // ============================================================================ // EXPORT // ============================================================================ export default DicomViewerModal; /* * End of File: DicomViewerModal.tsx * Design & Developed by Tech4Biz Solutions * Copyright (c) Spurrin Innovations. All rights reserved. */