/* * File: HospitalSelectionStep.tsx * Description: Hospital selection step component for signup flow * Design & Developed by Tech4Biz Solutions * Copyright (c) Spurrin Innovations. All rights reserved. */ import React, { useState, useMemo } from 'react'; import { View, Text, TouchableOpacity, StyleSheet, ScrollView, FlatList, ActivityIndicator, TextInput, KeyboardAvoidingView, Platform, } from 'react-native'; import { theme } from '../../../../theme/theme'; import { HospitalSelectionStepProps, Hospital } from '../../types/signup'; import Icon from 'react-native-vector-icons/Feather'; // ============================================================================ // HOSPITAL SELECTION STEP COMPONENT // ============================================================================ /** * HospitalSelectionStep Component * * Purpose: Fifth step of signup flow - hospital selection * * Features: * - Hospital list display from Redux state * - Hospital selection with visual feedback * - Search functionality for hospitals * - Loading states and error handling * - Continue button with validation (sticky bottom) * - Back navigation with modern header * - Scrollable hospital list */ const HospitalSelectionStep: React.FC = ({ onContinue, onBack, data, isLoading, hospitals, hospitalLoading, }) => { // ============================================================================ // STATE MANAGEMENT // ============================================================================ const [selectedHospitalId, setSelectedHospitalId] = useState(data.hospital_id || ''); const [searchQuery, setSearchQuery] = useState(''); // ============================================================================ // COMPUTED VALUES // ============================================================================ /** * Filtered Hospitals * * Purpose: Filter hospitals based on search query */ const filteredHospitals = useMemo(() => { if (!hospitals) return []; if (!searchQuery.trim()) return hospitals; const query = searchQuery.toLowerCase(); return hospitals.filter(hospital => hospital.hospital_name?.toLowerCase().includes(query) ); }, [hospitals, searchQuery]); // ============================================================================ // HANDLERS // ============================================================================ /** * Handle Hospital Selection * * Purpose: Select a hospital */ const handleHospitalSelect = (hospitalId: string) => { setSelectedHospitalId(hospitalId); }; /** * Handle Continue * * Purpose: Validate selection and proceed to next step */ const handleContinue = () => { if (!selectedHospitalId) { // Show error or alert return; } onContinue(selectedHospitalId); }; /** * Handle Search Input Change * * Purpose: Update search query */ const handleSearchChange = (text: string) => { setSearchQuery(text); }; /** * Clear Search * * Purpose: Clear search query */ const handleClearSearch = () => { setSearchQuery(''); }; // ============================================================================ // RENDER FUNCTIONS // ============================================================================ /** * Render Hospital Item * * Purpose: Render individual hospital item */ const renderHospitalItem = ({ item }: { item: Hospital }) => { const isSelected = selectedHospitalId === item.hospital_id; return ( handleHospitalSelect(item.hospital_id || '')} disabled={isLoading} > {item.hospital_name || 'Unknown Hospital'} {isSelected && ( )} ); }; /** * Render Search Input * * Purpose: Render search input field */ const renderSearchInput = () => ( {searchQuery.length > 0 && ( )} ); /** * Render Loading State * * Purpose: Show loading indicator while fetching hospitals */ const renderLoadingState = () => ( Loading hospitals... ); /** * Render Empty State * * Purpose: Show message when no hospitals are available */ const renderEmptyState = () => ( {searchQuery ? 'No Hospitals Found' : 'No Hospitals Available'} {searchQuery ? 'Try adjusting your search terms or browse all hospitals.' : 'There are no hospitals available at the moment. Please try again later.' } ); /** * Render Search Results Info * * Purpose: Show search results count */ const renderSearchResultsInfo = () => { if (!searchQuery.trim()) return null; return ( {filteredHospitals.length} hospital{filteredHospitals.length !== 1 ? 's' : ''} found ); }; // ============================================================================ // RENDER // ============================================================================ return ( {/* Header */} Create Account Step 5 of 5 {/* Content */} Select Your Hospital Choose the hospital where you work or will be practicing. {/* Search Input */} {renderSearchInput()} {/* Search Results Info */} {renderSearchResultsInfo()} {/* Hospital List */} {hospitalLoading ? ( renderLoadingState() ) : filteredHospitals.length > 0 ? ( item.hospital_id || ''} showsVerticalScrollIndicator={true} contentContainerStyle={styles.hospitalList} keyboardShouldPersistTaps="handled" /> ) : ( renderEmptyState() )} {/* Sticky Continue Button */} {isLoading ? 'Creating Account...' : 'Create Account'} ); }; // ============================================================================ // STYLES // ============================================================================ const styles = StyleSheet.create({ // Main container container: { flex: 1, backgroundColor: theme.colors.background, }, // Header section header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingTop: theme.spacing.xl, paddingBottom: theme.spacing.lg, paddingHorizontal: theme.spacing.lg, borderBottomWidth: 1, borderBottomColor: theme.colors.border, }, // Back button backButton: { padding: theme.spacing.sm, borderRadius: theme.borderRadius.medium, backgroundColor: theme.colors.backgroundAlt, }, // Header content headerContent: { flex: 1, alignItems: 'center', }, // Header spacer headerSpacer: { width: 40, }, // Title title: { fontSize: theme.typography.fontSize.displaySmall, fontFamily: theme.typography.fontFamily.bold, color: theme.colors.textPrimary, marginBottom: theme.spacing.xs, }, // Subtitle subtitle: { fontSize: theme.typography.fontSize.bodyMedium, fontFamily: theme.typography.fontFamily.regular, color: theme.colors.textSecondary, }, // Content section content: { flex: 1, paddingHorizontal: theme.spacing.lg, paddingTop: theme.spacing.lg, }, // Section title sectionTitle: { fontSize: theme.typography.fontSize.displaySmall, fontFamily: theme.typography.fontFamily.bold, color: theme.colors.textPrimary, marginBottom: theme.spacing.sm, }, // Description description: { fontSize: theme.typography.fontSize.bodyMedium, fontFamily: theme.typography.fontFamily.regular, color: theme.colors.textSecondary, marginBottom: theme.spacing.lg, }, // Search container searchContainer: { marginBottom: theme.spacing.lg, }, // Search input wrapper searchInputWrapper: { flexDirection: 'row', alignItems: 'center', backgroundColor: theme.colors.backgroundAlt, borderWidth: 1, borderColor: theme.colors.border, borderRadius: theme.borderRadius.medium, paddingHorizontal: theme.spacing.md, }, // Search icon searchIcon: { marginRight: theme.spacing.sm, }, // Search input searchInput: { flex: 1, paddingVertical: theme.spacing.md, fontSize: theme.typography.fontSize.bodyLarge, fontFamily: theme.typography.fontFamily.regular, color: theme.colors.textPrimary, }, // Clear button clearButton: { padding: theme.spacing.xs, marginLeft: theme.spacing.sm, }, // Search results info searchResultsInfo: { marginBottom: theme.spacing.md, }, // Search results text searchResultsText: { fontSize: theme.typography.fontSize.bodySmall, fontFamily: theme.typography.fontFamily.medium, color: theme.colors.textSecondary, }, // Hospital list container hospitalListContainer: { flex: 1, }, // Hospital list hospitalList: { paddingBottom: theme.spacing.lg, }, // Hospital item hospitalItem: { backgroundColor: theme.colors.background, borderWidth: 1, borderColor: theme.colors.border, borderRadius: theme.borderRadius.medium, padding: theme.spacing.md, marginBottom: theme.spacing.sm, }, // Hospital item selected hospitalItemSelected: { borderColor: theme.colors.primary, backgroundColor: theme.colors.tertiary, }, // Hospital content hospitalContent: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', }, // Hospital info hospitalInfo: { flex: 1, }, // Hospital name hospitalName: { fontSize: theme.typography.fontSize.bodyLarge, fontFamily: theme.typography.fontFamily.medium, color: theme.colors.textPrimary, }, // Hospital name selected hospitalNameSelected: { color: theme.colors.primary, fontFamily: theme.typography.fontFamily.bold, }, // Selected icon selectedIcon: { width: 24, height: 24, borderRadius: 12, backgroundColor: theme.colors.primary, alignItems: 'center', justifyContent: 'center', }, // Loading container loadingContainer: { flex: 1, alignItems: 'center', justifyContent: 'center', paddingVertical: theme.spacing.xxl, }, // Loading text loadingText: { fontSize: theme.typography.fontSize.bodyMedium, fontFamily: theme.typography.fontFamily.regular, color: theme.colors.textSecondary, marginTop: theme.spacing.md, }, // Empty container emptyContainer: { flex: 1, alignItems: 'center', justifyContent: 'center', paddingVertical: theme.spacing.xxl, }, // Empty title emptyTitle: { fontSize: theme.typography.fontSize.displaySmall, fontFamily: theme.typography.fontFamily.bold, color: theme.colors.textPrimary, marginTop: theme.spacing.md, marginBottom: theme.spacing.sm, }, // Empty text emptyText: { fontSize: theme.typography.fontSize.bodyMedium, fontFamily: theme.typography.fontFamily.regular, color: theme.colors.textSecondary, textAlign: 'center', paddingHorizontal: theme.spacing.lg, }, // Sticky button container stickyButtonContainer: { paddingHorizontal: theme.spacing.lg, paddingVertical: theme.spacing.lg, backgroundColor: theme.colors.background, borderTopWidth: 1, borderTopColor: theme.colors.border, }, // Continue button continueButton: { backgroundColor: theme.colors.primary, borderRadius: theme.borderRadius.medium, paddingVertical: theme.spacing.md, paddingHorizontal: theme.spacing.lg, alignItems: 'center', ...theme.shadows.primary, }, // Continue button disabled continueButtonDisabled: { backgroundColor: theme.colors.border, opacity: 0.6, }, // Continue button text continueButtonText: { fontSize: theme.typography.fontSize.bodyLarge, fontFamily: theme.typography.fontFamily.bold, color: theme.colors.background, }, // Continue button text disabled continueButtonTextDisabled: { color: theme.colors.textMuted, }, }); export default HospitalSelectionStep; /* * End of File: HospitalSelectionStep.tsx * Design & Developed by Tech4Biz Solutions * Copyright (c) Spurrin Innovations. All rights reserved. */