/* * File: PatientCard.tsx * Description: Enhanced patient card component for displaying DICOM medical case information * Design & Developed by Tech4Biz Solutions * Copyright (c) Spurrin Innovations. All rights reserved. */ import React from 'react'; import { View, Text, TouchableOpacity, StyleSheet, } from 'react-native'; import { theme } from '../../../theme/theme'; import Icon from 'react-native-vector-icons/Feather'; import { PatientData } from '../redux/patientCareSlice'; // ============================================================================ // INTERFACES // ============================================================================ interface PatientCardProps { patient: PatientData; onPress: () => void; onEmergencyPress?: () => void; } // ============================================================================ // PATIENT CARD COMPONENT // ============================================================================ /** * PatientCard Component * * Purpose: Display DICOM medical case information in a modern, enhanced card format * * Features: * - Enhanced visual hierarchy with modern design * - Improved status indicators and color coding * - Better spacing and typography * - Enhanced shadows and elevation * - More intuitive information layout * - Emergency alert for critical cases * - Modern ER-focused design with better UX */ const PatientCard: React.FC = ({ patient, onPress, onEmergencyPress, }) => { // ============================================================================ // UTILITY FUNCTIONS // ============================================================================ /** * Get Status Color Configuration * * Purpose: Get enhanced color and icon based on processing status * * @param status - Processing status * @returns Enhanced color configuration object */ const getStatusConfig = (status: string) => { switch (status.toLowerCase()) { case 'processed': return { color: '#10B981', icon: 'check-circle', bgColor: '#ECFDF5', borderColor: '#D1FAE5' }; case 'pending': return { color: '#F59E0B', icon: 'clock', bgColor: '#FFFBEB', borderColor: '#FEF3C7' }; case 'error': return { color: '#EF4444', icon: 'alert-triangle', bgColor: '#FEF2F2', borderColor: '#FECACA' }; default: return { color: '#3B82F6', icon: 'info', bgColor: '#EFF6FF', borderColor: '#DBEAFE' }; } }; /** * Get Modality Color * * Purpose: Get enhanced color based on imaging modality * * @param modality - Imaging modality * @returns Enhanced color code */ const getModalityColor = (modality: string) => { switch (modality.toUpperCase()) { case 'CT': return '#3B82F6'; case 'MR': return '#8B5CF6'; case 'DX': return '#10B981'; case 'DICOM': return '#EF4444'; default: return theme.colors.textSecondary; } }; /** * Format Date * * Purpose: Format date string to readable format * * @param dateString - ISO date string * @returns Formatted date string */ const formatDate = (dateString: string) => { return new Date(dateString).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric', hour: '2-digit', minute: '2-digit' }); }; /** * Get Time Since Processed * * Purpose: Get human-readable time since last processed * * @param dateString - ISO date string * @returns Formatted time string */ const getTimeSinceProcessed = (dateString: string) => { const now = new Date(); const processed = new Date(dateString); const diffInMinutes = Math.floor((now.getTime() - processed.getTime()) / (1000 * 60)); if (diffInMinutes < 1) return 'Just now'; if (diffInMinutes < 60) return `${diffInMinutes}m ago`; if (diffInMinutes < 1440) return `${Math.floor(diffInMinutes / 60)}h ago`; return `${Math.floor(diffInMinutes / 1440)}d ago`; }; // ============================================================================ // DATA EXTRACTION // ============================================================================ const patientInfo = patient.patient_info; const seriesCount = patient.series_summary.length; const statusConfig = getStatusConfig(patientInfo.status); const isCritical = patientInfo.report_status === 'Critical' || patientInfo.status === 'Error'; // ============================================================================ // RENDER HELPERS // ============================================================================ /** * Render Enhanced Status Badge * * Purpose: Render improved processing status indicator badge */ const renderStatusBadge = () => ( {patientInfo.status} ); /** * Render Enhanced Emergency Button * * Purpose: Render improved emergency alert button for critical cases */ const renderEmergencyButton = () => { if (!isCritical) { return null; } return ( ALERT ); }; /** * Render Enhanced Modality Badge * * Purpose: Render improved modality indicator */ const renderModalityBadge = () => ( {patientInfo.modality || 'N/A'} ); // ============================================================================ // MAIN RENDER // ============================================================================ return ( {/* Enhanced Header Section */} {patientInfo.name || 'Unknown Patient'} {renderModalityBadge()} ID: {patient.patid} • {patientInfo.age || 'N/A'}y • {patientInfo.sex || 'N/A'} {renderStatusBadge()} {renderEmergencyButton()} {/* Enhanced Medical Information Section */} {patient.total_files_processed || 0} Files {seriesCount} Series {patientInfo.report_status || 'Pending'} Report {/* Enhanced Institution Row */} {patientInfo.institution || 'Unknown Institution'} {/* Enhanced Series Information */} Series Details {seriesCount} Series Available {patientInfo.frame_count || 0} Total Frames {/* Enhanced Footer */} {formatDate(patientInfo.date)} Processed {getTimeSinceProcessed(patient.last_processed_at)} Case #{patient.patid} ); }; // ============================================================================ // ENHANCED STYLES // ============================================================================ const styles = StyleSheet.create({ container: { backgroundColor: theme.colors.background, borderRadius: 16, padding: theme.spacing.md, marginHorizontal: theme.spacing.md, marginVertical: theme.spacing.xs, shadowColor: '#000000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.06, shadowRadius: 8, elevation: 3, borderWidth: 1, borderColor: theme.colors.border, borderLeftWidth: 4, }, containerCritical: { borderColor: theme.colors.error, borderWidth: 2, backgroundColor: '#FEF2F2', shadowColor: theme.colors.error, shadowOpacity: 0.15, }, // Enhanced Header Section header: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: theme.spacing.sm, }, headerLeft: { flex: 1, marginRight: theme.spacing.md, }, headerRight: { flexDirection: 'row', alignItems: 'center', gap: theme.spacing.sm, }, patientNameRow: { flexDirection: 'row', alignItems: 'center', marginBottom: theme.spacing.xs, gap: theme.spacing.xs, }, patientName: { fontSize: 20, color: theme.colors.textPrimary, fontFamily: theme.typography.fontFamily.bold, flex: 1, }, patientInfo: { fontSize: 14, color: theme.colors.textSecondary, fontFamily: theme.typography.fontFamily.medium, lineHeight: 20, }, // Enhanced Status Badge statusBadge: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 12, paddingVertical: 6, borderRadius: 20, borderWidth: 1.5, gap: theme.spacing.xs, }, statusText: { fontSize: 11, fontFamily: theme.typography.fontFamily.bold, textTransform: 'uppercase', letterSpacing: 0.5, }, // Enhanced Emergency Button emergencyButton: { flexDirection: 'row', alignItems: 'center', backgroundColor: theme.colors.error, paddingHorizontal: 12, paddingVertical: 6, borderRadius: 20, gap: theme.spacing.xs, shadowColor: theme.colors.error, shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.3, shadowRadius: 4, elevation: 3, }, emergencyButtonText: { fontSize: 11, fontFamily: theme.typography.fontFamily.bold, color: theme.colors.background, letterSpacing: 0.5, }, // Enhanced Modality Badge modalityBadge: { paddingHorizontal: 8, paddingVertical: 4, borderRadius: 12, borderWidth: 1.5, }, modalityText: { fontSize: 10, fontFamily: theme.typography.fontFamily.bold, textTransform: 'uppercase', letterSpacing: 0.5, }, // Enhanced Medical Section medicalSection: { marginBottom: theme.spacing.sm, paddingBottom: theme.spacing.sm, borderBottomWidth: 1, borderBottomColor: theme.colors.border, }, infoGrid: { flexDirection: 'row', justifyContent: 'space-between', marginBottom: theme.spacing.sm, gap: theme.spacing.sm, }, infoCard: { flex: 1, alignItems: 'center', paddingVertical: theme.spacing.xs, backgroundColor: theme.colors.backgroundAlt, borderRadius: 12, paddingHorizontal: theme.spacing.sm, gap: theme.spacing.xs, }, infoLabel: { fontSize: 10, color: theme.colors.textMuted, textTransform: 'uppercase', fontFamily: theme.typography.fontFamily.medium, letterSpacing: 0.5, textAlign: 'center', }, infoValue: { fontSize: 14, fontFamily: theme.typography.fontFamily.medium, color: theme.colors.textPrimary, textAlign: 'center', }, // Enhanced Institution Row institutionRow: { flexDirection: 'row', alignItems: 'center', backgroundColor: theme.colors.backgroundAlt, padding: theme.spacing.sm, borderRadius: 12, gap: theme.spacing.sm, }, institutionIcon: { width: 32, height: 32, borderRadius: 16, backgroundColor: theme.colors.primary + '20', justifyContent: 'center', alignItems: 'center', }, institutionText: { fontSize: 14, color: theme.colors.textSecondary, flex: 1, fontFamily: theme.typography.fontFamily.medium, }, // Enhanced Series Section seriesSection: { backgroundColor: theme.colors.backgroundAlt, borderRadius: 12, padding: theme.spacing.sm, marginBottom: theme.spacing.sm, }, seriesHeader: { flexDirection: 'row', alignItems: 'center', marginBottom: theme.spacing.sm, gap: theme.spacing.xs, }, seriesLabel: { fontSize: 13, fontFamily: theme.typography.fontFamily.medium, color: theme.colors.textSecondary, textTransform: 'uppercase', letterSpacing: 0.5, }, seriesInfo: { gap: theme.spacing.xs, }, seriesText: { fontSize: 15, color: theme.colors.textPrimary, fontFamily: theme.typography.fontFamily.medium, }, frameText: { fontSize: 13, color: theme.colors.textSecondary, fontFamily: theme.typography.fontFamily.regular, }, // Enhanced Footer Section footer: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingTop: theme.spacing.sm, borderTopWidth: 1, borderTopColor: theme.colors.border, }, footerLeft: { flex: 1, }, dateText: { fontSize: 13, color: theme.colors.textMuted, fontFamily: theme.typography.fontFamily.medium, marginBottom: 2, }, processedText: { fontSize: 12, color: theme.colors.textSecondary, fontFamily: theme.typography.fontFamily.regular, }, footerRight: { flexDirection: 'row', alignItems: 'center', gap: theme.spacing.sm, }, caseId: { fontSize: 12, color: theme.colors.textSecondary, fontFamily: theme.typography.fontFamily.medium, }, chevronContainer: { width: 32, height: 32, borderRadius: 16, backgroundColor: theme.colors.primary + '20', justifyContent: 'center', alignItems: 'center', }, }); export default PatientCard; /* * End of File: PatientCard.tsx * Design & Developed by Tech4Biz Solutions * Copyright (c) Spurrin Innovations. All rights reserved. */