/* * File: ERDashboardScreen.tsx * Description: Main ER dashboard screen displaying patient list, critical alerts, and department statistics * Design & Developed by Tech4Biz Solutions * Copyright (c) Spurrin Innovations. All rights reserved. */ import React, { useState, useEffect } from 'react'; import { View, Text, StyleSheet, ScrollView, TouchableOpacity, RefreshControl, FlatList, Alert, } from 'react-native'; import { theme } from '../../../theme/theme'; import { ERDashboard, Patient, Alert as AlertType } from '../../../shared/types'; import { PatientCard } from '../components/PatientCard'; import { CriticalAlerts } from '../components/CriticalAlerts'; import { DashboardHeader } from '../components/DashboardHeader'; import { QuickActions } from '../components/QuickActions'; import { DepartmentStats } from '../components/DepartmentStats'; /** * ERDashboardScreenProps Interface * * Purpose: Defines the props required by the ERDashboardScreen component * * Props: * - navigation: React Navigation object for screen navigation */ interface ERDashboardScreenProps { navigation: any; } /** * ERDashboardScreen Component * * Purpose: Main dashboard screen for Emergency Department physicians * * Dashboard Features: * 1. Real-time patient overview with filtering capabilities * 2. Critical alerts display for immediate attention * 3. Quick action buttons for common tasks * 4. Department statistics and bed occupancy * 5. Pull-to-refresh functionality for live updates * 6. Internal data generation for demonstration * * Patient Filtering: * - All: Shows all patients in the system * - Critical: Shows only patients with critical priority * - Active: Shows only patients with active status * * Data Flow: * 1. Generate mock data internally for demonstration * 2. Filter patients based on selected filter * 3. Display critical alerts at the top * 4. Show patient cards in scrollable list * 5. Handle refresh and navigation interactions */ export const ERDashboardScreen: React.FC = ({ navigation, }) => { // ============================================================================ // STATE MANAGEMENT // ============================================================================ // Refresh state for pull-to-refresh functionality const [refreshing, setRefreshing] = useState(false); // Patient filter state to control which patients are displayed const [selectedFilter, setSelectedFilter] = useState<'all' | 'critical' | 'active'>('all'); // Dashboard data state const [dashboard, setDashboard] = useState(null); const [patients, setPatients] = useState([]); const [alerts, setAlerts] = useState([]); const [isLoading, setIsLoading] = useState(true); // ============================================================================ // MOCK DATA GENERATION // ============================================================================ /** * generateMockDashboard Function * * Purpose: Generate mock dashboard data for demonstration * * Returns: ERDashboard object with realistic ER statistics */ const generateMockDashboard = (): ERDashboard => ({ totalPatients: 24, // Total number of patients in ER criticalPatients: 3, // Number of patients requiring immediate attention pendingScans: 8, // Number of scans waiting for review recentReports: 12, // Number of reports generated recently bedOccupancy: 85, // Percentage of beds currently occupied departmentStats: { emergency: 8, // Patients in emergency department trauma: 4, // Patients in trauma department cardiac: 3, // Patients in cardiac department neurology: 2, // Patients in neurology department pediatrics: 5, // Patients in pediatrics department icu: 2, // Patients in ICU }, shiftInfo: { currentShift: 'DAY' as const, // Current shift (DAY/NIGHT) startTime: new Date(), // Shift start time endTime: new Date(), // Shift end time attendingPhysician: 'Dr. Smith', // Lead physician on duty residents: ['Dr. Johnson', 'Dr. Williams'], // Resident physicians nurses: ['Nurse Brown', 'Nurse Davis'], // Nursing staff }, lastUpdated: new Date(), // Last time dashboard was updated }); /** * generateMockPatients Function * * Purpose: Generate mock patient data for demonstration * * Returns: Array of Patient objects with realistic medical data */ const generateMockPatients = (): Patient[] => [ { id: '1', // Unique patient identifier mrn: 'MRN001', // Medical Record Number firstName: 'John', lastName: 'Doe', dateOfBirth: new Date('1985-03-15'), gender: 'MALE' as const, age: 38, bedNumber: 'A1', // Assigned bed number roomNumber: '101', // Room number admissionDate: new Date('2024-01-15'), status: 'ACTIVE' as const, // Current patient status priority: 'CRITICAL' as const, // Priority level for treatment department: 'Emergency', attendingPhysician: 'Dr. Smith', allergies: [ { id: '1', name: 'Penicillin', severity: 'SEVERE' as const, reaction: 'Anaphylaxis' }, ], medications: [ { id: '1', name: 'Morphine', dosage: '2mg', frequency: 'Every 4 hours', route: 'IV', // Administration route startDate: new Date(), status: 'ACTIVE' as const, prescribedBy: 'Dr. Smith', }, ], vitalSigns: { bloodPressure: { systolic: 140, diastolic: 90, timestamp: new Date() }, heartRate: { value: 95, timestamp: new Date() }, temperature: { value: 37.2, timestamp: new Date() }, respiratoryRate: { value: 18, timestamp: new Date() }, oxygenSaturation: { value: 98, timestamp: new Date() }, }, medicalHistory: [], currentDiagnosis: 'Chest pain, rule out MI', // Current medical diagnosis lastUpdated: new Date(), }, { id: '2', mrn: 'MRN002', firstName: 'Jane', lastName: 'Smith', dateOfBirth: new Date('1990-07-22'), gender: 'FEMALE' as const, age: 33, bedNumber: 'B2', roomNumber: '102', admissionDate: new Date('2024-01-15'), status: 'ACTIVE' as const, priority: 'HIGH' as const, department: 'Trauma', attendingPhysician: 'Dr. Johnson', allergies: [], medications: [], vitalSigns: { bloodPressure: { systolic: 120, diastolic: 80, timestamp: new Date() }, heartRate: { value: 88, timestamp: new Date() }, temperature: { value: 36.8, timestamp: new Date() }, respiratoryRate: { value: 16, timestamp: new Date() }, oxygenSaturation: { value: 99, timestamp: new Date() }, }, medicalHistory: [], currentDiagnosis: 'Multiple trauma from MVA', // MVA = Motor Vehicle Accident lastUpdated: new Date(), }, { id: '3', mrn: 'MRN003', firstName: 'Michael', lastName: 'Brown', dateOfBirth: new Date('1978-11-08'), gender: 'MALE' as const, age: 45, bedNumber: 'C3', roomNumber: '103', admissionDate: new Date('2024-01-15'), status: 'PENDING' as const, priority: 'MEDIUM' as const, department: 'Cardiac', attendingPhysician: 'Dr. Williams', allergies: [ { id: '2', name: 'Aspirin', severity: 'MODERATE' as const, reaction: 'Stomach upset' }, ], medications: [ { id: '2', name: 'Nitroglycerin', dosage: '0.4mg', frequency: 'As needed', route: 'Sublingual', startDate: new Date(), status: 'ACTIVE' as const, prescribedBy: 'Dr. Williams', }, ], vitalSigns: { bloodPressure: { systolic: 160, diastolic: 100, timestamp: new Date() }, heartRate: { value: 110, timestamp: new Date() }, temperature: { value: 36.9, timestamp: new Date() }, respiratoryRate: { value: 20, timestamp: new Date() }, oxygenSaturation: { value: 95, timestamp: new Date() }, }, medicalHistory: [], currentDiagnosis: 'Hypertension, chest pain', lastUpdated: new Date(), }, { id: '4', mrn: 'MRN004', firstName: 'Sarah', lastName: 'Wilson', dateOfBirth: new Date('1995-04-12'), gender: 'FEMALE' as const, age: 28, bedNumber: 'D4', roomNumber: '104', admissionDate: new Date('2024-01-15'), status: 'ACTIVE' as const, priority: 'CRITICAL' as const, department: 'Neurology', attendingPhysician: 'Dr. Davis', allergies: [], medications: [ { id: '3', name: 'Mannitol', dosage: '100ml', frequency: 'Every 6 hours', route: 'IV', startDate: new Date(), status: 'ACTIVE' as const, prescribedBy: 'Dr. Davis', }, ], vitalSigns: { bloodPressure: { systolic: 180, diastolic: 110, timestamp: new Date() }, heartRate: { value: 60, timestamp: new Date() }, temperature: { value: 38.5, timestamp: new Date() }, respiratoryRate: { value: 12, timestamp: new Date() }, oxygenSaturation: { value: 92, timestamp: new Date() }, }, medicalHistory: [], currentDiagnosis: 'Suspected intracranial hemorrhage', lastUpdated: new Date(), }, { id: '5', mrn: 'MRN005', firstName: 'David', lastName: 'Miller', dateOfBirth: new Date('1982-09-30'), gender: 'MALE' as const, age: 41, bedNumber: 'E5', roomNumber: '105', admissionDate: new Date('2024-01-15'), status: 'ACTIVE' as const, priority: 'HIGH' as const, department: 'Pediatrics', attendingPhysician: 'Dr. Brown', allergies: [ { id: '3', name: 'Latex', severity: 'SEVERE' as const, reaction: 'Contact dermatitis' }, ], medications: [], vitalSigns: { bloodPressure: { systolic: 110, diastolic: 70, timestamp: new Date() }, heartRate: { value: 85, timestamp: new Date() }, temperature: { value: 37.8, timestamp: new Date() }, respiratoryRate: { value: 22, timestamp: new Date() }, oxygenSaturation: { value: 97, timestamp: new Date() }, }, medicalHistory: [], currentDiagnosis: 'Fever of unknown origin', lastUpdated: new Date(), }, ]; /** * generateMockAlerts Function * * Purpose: Generate mock alert data for demonstration * * Returns: Array of Alert objects with realistic medical alerts */ const generateMockAlerts = (): AlertType[] => [ { id: '1', type: 'CRITICAL_FINDING' as const, // Type of alert priority: 'CRITICAL' as const, // Priority level title: 'Critical Finding Detected', message: 'AI has detected a potential brain bleed in CT scan. Immediate review required.', patientId: '4', // Associated patient patientName: 'Sarah Wilson', bedNumber: 'D4', timestamp: new Date(), // When alert was generated isRead: false, // Whether alert has been read isAcknowledged: false, // Whether alert has been acknowledged actionRequired: true, // Whether action is required }, { id: '2', type: 'VITAL_SIGNS_ALERT' as const, priority: 'HIGH' as const, title: 'Vital Sign Alert', message: 'Blood pressure elevated: 180/110. Patient requires immediate attention.', patientId: '4', patientName: 'Sarah Wilson', bedNumber: 'D4', timestamp: new Date(Date.now() - 300000), // 5 minutes ago isRead: false, isAcknowledged: false, actionRequired: true, }, { id: '3', type: 'MEDICATION_ALERT' as const, priority: 'MEDIUM' as const, title: 'Medication Due', message: 'Morphine due for patient John Doe in 15 minutes.', patientId: '1', patientName: 'John Doe', bedNumber: 'A1', timestamp: new Date(Date.now() - 600000), // 10 minutes ago isRead: true, isAcknowledged: true, actionRequired: false, }, ]; // ============================================================================ // EFFECTS // ============================================================================ /** * useEffect for initial data loading * * Purpose: Load initial mock data when component mounts * * Flow: * 1. Set loading state to true * 2. Generate mock data * 3. Set data in state * 4. Set loading state to false */ useEffect(() => { const loadInitialData = async () => { setIsLoading(true); // Simulate API call delay await new Promise(resolve => setTimeout(resolve, 1000)); // Generate and set mock data setDashboard(generateMockDashboard()); setPatients(generateMockPatients()); setAlerts(generateMockAlerts()); setIsLoading(false); }; loadInitialData(); }, []); // ============================================================================ // EVENT HANDLERS // ============================================================================ /** * handleRefresh Function * * Purpose: Handle pull-to-refresh functionality to update dashboard data * * Flow: * 1. Set refreshing state to true (show loading indicator) * 2. Simulate API call with delay * 3. Update data with fresh mock data * 4. Set refreshing state to false (hide loading indicator) */ const handleRefresh = async () => { setRefreshing(true); // Show refresh indicator // Simulate API call with 1-second delay await new Promise(resolve => setTimeout(resolve, 1000)); // Update data with fresh mock data setDashboard(generateMockDashboard()); setPatients(generateMockPatients()); setAlerts(generateMockAlerts()); setRefreshing(false); // Hide refresh indicator }; /** * handlePatientPress Function * * Purpose: Handle patient card press navigation * * @param patient - Patient object that was pressed */ const handlePatientPress = (patient: Patient) => { // TODO: Navigate to patient details screen console.log('Patient pressed:', patient.firstName, patient.lastName); Alert.alert('Patient Details', `Navigate to ${patient.firstName} ${patient.lastName}'s details`); }; /** * handleAlertPress Function * * Purpose: Handle alert press interaction * * @param alert - Alert object that was pressed */ const handleAlertPress = (alert: AlertType) => { // TODO: Navigate to alert details or patient details console.log('Alert pressed:', alert.title); Alert.alert('Alert Details', alert.message); }; // ============================================================================ // DATA PROCESSING // ============================================================================ /** * filteredPatients - Computed property * * Purpose: Filter patients based on selected filter criteria * * Filter Options: * - 'all': Show all patients regardless of status or priority * - 'critical': Show only patients with CRITICAL priority * - 'active': Show only patients with ACTIVE status */ const filteredPatients = patients.filter(patient => { switch (selectedFilter) { case 'critical': return patient.priority === 'CRITICAL'; // Only critical priority patients case 'active': return patient.status === 'ACTIVE'; // Only active status patients default: return true; // All patients } }); /** * criticalAlerts - Computed property * * Purpose: Extract critical alerts from all alerts for immediate display * * Filter: Only alerts with CRITICAL priority that require immediate attention */ const criticalAlerts = alerts.filter(alert => alert.priority === 'CRITICAL'); /** * pendingScans - Computed property * * Purpose: Identify patients with pending scans or high priority needs * * Filter: Patients with PENDING status or HIGH priority */ const pendingScans = patients.filter(patient => patient.status === 'PENDING' || patient.priority === 'HIGH' ); // ============================================================================ // RENDER FUNCTIONS // ============================================================================ /** * renderPatientCard Function * * Purpose: Render individual patient card component * * @param item - Patient data object * @returns PatientCard component with patient data and press handler */ const renderPatientCard = ({ item }: { item: Patient }) => ( handlePatientPress(item)} // Navigate to patient details /> ); /** * renderHeader Function * * Purpose: Render the dashboard header section with all dashboard components * * Components included: * - DashboardHeader: Shows shift info and key statistics * - CriticalAlerts: Displays urgent alerts requiring attention * - QuickActions: Provides quick access to common functions * - DepartmentStats: Shows department-wise patient distribution * - Filter buttons: Allow filtering of patient list */ const renderHeader = () => ( {/* Dashboard header with shift information and key metrics */} {dashboard && } {/* Critical alerts section - only show if there are critical alerts */} {criticalAlerts.length > 0 && ( )} {/* Quick action buttons for common tasks */} { // TODO: Implement quick action handlers console.log('Quick action:', action); }} /> {/* Department statistics showing patient distribution */} {dashboard && } {/* Patient filter section with filter buttons */} Patients {/* All patients filter button */} setSelectedFilter('all')} > All ({patients.length}) {/* Critical patients filter button */} setSelectedFilter('critical')} > Critical ({patients.filter(p => p.priority === 'CRITICAL').length}) {/* Active patients filter button */} setSelectedFilter('active')} > Active ({patients.filter(p => p.status === 'ACTIVE').length}) ); // ============================================================================ // LOADING STATE // ============================================================================ /** * Loading state render * * Purpose: Show loading indicator while data is being generated */ if (isLoading) { return ( Loading Dashboard... ); } // ============================================================================ // MAIN RENDER // ============================================================================ return ( {/* FlatList for efficient rendering of patient cards */} item.id} // Unique key for each patient ListHeaderComponent={renderHeader} // Header with dashboard components contentContainerStyle={styles.listContainer} // Container styling refreshControl={ } showsVerticalScrollIndicator={false} // Hide scroll indicator for cleaner look /> ); }; // ============================================================================ // STYLES SECTION // ============================================================================ const styles = StyleSheet.create({ // Main container for the dashboard screen container: { flex: 1, backgroundColor: theme.colors.background, }, // Loading container for initial data loading loadingContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: theme.colors.background, }, // Loading text styling loadingText: { fontSize: theme.typography.fontSize.bodyLarge, color: theme.colors.textSecondary, fontFamily: theme.typography.fontFamily.medium, }, // Container for the FlatList content listContainer: { paddingBottom: theme.spacing.lg, // Add bottom padding for tab bar }, // Header section containing dashboard components header: { paddingHorizontal: theme.spacing.md, // Horizontal padding for content }, // Container for patient filter section filterContainer: { marginTop: theme.spacing.lg, // Top margin for separation marginBottom: theme.spacing.md, // Bottom margin for list spacing }, // Section title styling sectionTitle: { fontSize: theme.typography.fontSize.displaySmall, fontFamily: theme.typography.fontFamily.bold, color: theme.colors.textPrimary, marginBottom: theme.spacing.md, }, // Container for filter buttons filterButtons: { flexDirection: 'row', // Horizontal layout gap: theme.spacing.sm, // Space between buttons }, // Individual filter button styling filterButton: { paddingHorizontal: theme.spacing.md, paddingVertical: theme.spacing.sm, borderRadius: theme.borderRadius.medium, borderWidth: 1, borderColor: theme.colors.border, backgroundColor: theme.colors.background, }, // Active filter button styling filterButtonActive: { backgroundColor: theme.colors.primary, // Primary color background borderColor: theme.colors.primary, // Primary color border }, // Filter button text styling filterButtonText: { fontSize: theme.typography.fontSize.bodyMedium, color: theme.colors.textSecondary, fontFamily: theme.typography.fontFamily.medium, }, // Active filter button text styling filterButtonTextActive: { color: theme.colors.background, // White text on primary background }, }); /* * End of File: ERDashboardScreen.tsx * Design & Developed by Tech4Biz Solutions * Copyright (c) Spurrin Innovations. All rights reserved. */