import React from 'react'; import { View, Text, StyleSheet, ScrollView, TouchableOpacity, } from 'react-native'; import { Ionicons } from '@expo/vector-icons'; import { SafeAreaView } from 'react-native-safe-area-context'; import type { SensorSetupState } from '@/types'; import { AppColors, BorderRadius, FontSizes, FontWeights, Spacing, Shadows, } from '@/constants/theme'; interface SetupResultsScreenProps { sensors: SensorSetupState[]; onRetry: (deviceId: string) => void; onDone: () => void; } // Format elapsed time as readable string function formatElapsedTime(startTime?: number, endTime?: number): string { if (!startTime || !endTime) return ''; const elapsed = Math.floor((endTime - startTime) / 1000); if (elapsed < 60) return `${elapsed}s`; const minutes = Math.floor(elapsed / 60); const seconds = elapsed % 60; return `${minutes}m ${seconds}s`; } // Get user-friendly error message function getErrorMessage(error: string | undefined): string { if (!error) return 'Unknown error'; const lowerError = error.toLowerCase(); if (lowerError.includes('connect') || lowerError.includes('connection')) { return 'Could not connect via Bluetooth'; } if (lowerError.includes('wifi') || lowerError.includes('network')) { return 'WiFi configuration failed'; } if (lowerError.includes('register') || lowerError.includes('attach') || lowerError.includes('api')) { return 'Could not register sensor'; } if (lowerError.includes('timeout') || lowerError.includes('respond')) { return 'Sensor not responding'; } if (lowerError.includes('unlock') || lowerError.includes('pin')) { return 'Could not unlock sensor'; } return error; } export default function SetupResultsScreen({ sensors, onRetry, onDone, }: SetupResultsScreenProps) { const successSensors = sensors.filter(s => s.status === 'success'); const failedSensors = sensors.filter(s => s.status === 'error'); const skippedSensors = sensors.filter(s => s.status === 'skipped'); const allSuccess = successSensors.length === sensors.length; const allFailed = failedSensors.length + skippedSensors.length === sensors.length; const partialSuccess = !allSuccess && !allFailed && successSensors.length > 0; // Calculate total setup time const totalTime = sensors.reduce((acc, sensor) => { if (sensor.startTime && sensor.endTime) { return acc + (sensor.endTime - sensor.startTime); } return acc; }, 0); const totalTimeStr = totalTime > 0 ? formatElapsedTime(0, totalTime) : null; return ( {/* Header */} Setup Complete {/* Summary Card */} {allSuccess ? 'All Sensors Connected!' : allFailed ? 'Setup Failed' : 'Partial Success'} {successSensors.length} of {sensors.length} sensors configured successfully {/* Stats Row */} {successSensors.length > 0 && ( {successSensors.length} Success )} {failedSensors.length > 0 && ( {failedSensors.length} Failed )} {skippedSensors.length > 0 && ( {skippedSensors.length} Skipped )} {totalTimeStr && ( Total time: {totalTimeStr} )} {/* Success List */} {successSensors.length > 0 && ( Successfully Connected {successSensors.map(sensor => ( {sensor.deviceName} {sensor.wellId && ( Well ID: {sensor.wellId} )} {sensor.startTime && sensor.endTime && ( {formatElapsedTime(sensor.startTime, sensor.endTime)} )} ))} )} {/* Failed List */} {failedSensors.length > 0 && ( Failed {failedSensors.map(sensor => ( {sensor.deviceName} {getErrorMessage(sensor.error)} onRetry(sensor.deviceId)} > Retry ))} )} {/* Skipped List */} {skippedSensors.length > 0 && ( Skipped {skippedSensors.map(sensor => ( {sensor.deviceName} Skipped by user onRetry(sensor.deviceId)} > Retry ))} )} {/* Help Info */} What's Next {successSensors.length > 0 ? ( '• Successfully connected sensors will appear in Equipment\n' + '• It may take up to 1 minute for sensors to come online\n' + '• You can configure sensor locations in Device Settings' ) : ( '• Return to Equipment and try adding sensors again\n' + '• Make sure sensors are powered on and nearby\n' + '• Check that WiFi password is correct' )} {/* Bottom Actions */} {(failedSensors.length > 0 || skippedSensors.length > 0) && ( { [...failedSensors, ...skippedSensors].forEach(s => onRetry(s.deviceId)); }} > Retry All Failed ({failedSensors.length + skippedSensors.length}) )} Done ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: AppColors.background, }, header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: Spacing.md, paddingVertical: Spacing.sm, borderBottomWidth: 1, borderBottomColor: AppColors.border, backgroundColor: AppColors.surface, }, headerTitle: { fontSize: FontSizes.lg, fontWeight: FontWeights.semibold, color: AppColors.textPrimary, }, placeholder: { width: 32, }, content: { flex: 1, }, scrollContent: { padding: Spacing.lg, paddingBottom: Spacing.xxl, }, // Summary Card summaryCard: { backgroundColor: AppColors.surface, borderRadius: BorderRadius.xl, padding: Spacing.xl, alignItems: 'center', marginBottom: Spacing.lg, ...Shadows.sm, }, summaryIcon: { width: 100, height: 100, borderRadius: 50, justifyContent: 'center', alignItems: 'center', marginBottom: Spacing.md, }, summaryTitle: { fontSize: FontSizes['2xl'], fontWeight: FontWeights.bold, color: AppColors.textPrimary, marginBottom: Spacing.xs, textAlign: 'center', }, summarySubtitle: { fontSize: FontSizes.base, color: AppColors.textSecondary, marginBottom: Spacing.md, textAlign: 'center', }, statsRow: { flexDirection: 'row', gap: Spacing.lg, marginBottom: Spacing.sm, }, statItem: { flexDirection: 'row', alignItems: 'center', gap: Spacing.xs, }, statDot: { width: 8, height: 8, borderRadius: 4, }, statText: { fontSize: FontSizes.sm, color: AppColors.textSecondary, fontWeight: FontWeights.medium, }, totalTime: { fontSize: FontSizes.sm, color: AppColors.textMuted, marginTop: Spacing.xs, }, // Sections section: { backgroundColor: AppColors.surface, borderRadius: BorderRadius.lg, padding: Spacing.md, marginBottom: Spacing.md, ...Shadows.xs, }, sectionHeader: { flexDirection: 'row', alignItems: 'center', gap: Spacing.sm, marginBottom: Spacing.md, paddingBottom: Spacing.sm, borderBottomWidth: 1, borderBottomColor: AppColors.border, }, sectionTitle: { fontSize: FontSizes.sm, fontWeight: FontWeights.semibold, color: AppColors.textSecondary, textTransform: 'uppercase', letterSpacing: 0.5, }, // Sensor Items sensorItem: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingVertical: Spacing.sm, borderBottomWidth: 1, borderBottomColor: AppColors.borderLight, }, sensorItemWithAction: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingVertical: Spacing.sm, borderBottomWidth: 1, borderBottomColor: AppColors.borderLight, }, sensorInfo: { flexDirection: 'row', alignItems: 'center', flex: 1, }, sensorIcon: { width: 36, height: 36, borderRadius: BorderRadius.md, justifyContent: 'center', alignItems: 'center', marginRight: Spacing.sm, }, sensorDetails: { flex: 1, }, sensorName: { fontSize: FontSizes.base, fontWeight: FontWeights.medium, color: AppColors.textPrimary, marginBottom: 2, }, sensorMeta: { flexDirection: 'row', gap: Spacing.sm, }, sensorMetaText: { fontSize: FontSizes.xs, color: AppColors.textMuted, }, errorText: { fontSize: FontSizes.xs, color: AppColors.error, }, skippedText: { fontSize: FontSizes.xs, color: AppColors.warning, }, // Buttons retryButton: { flexDirection: 'row', alignItems: 'center', gap: Spacing.xs, paddingVertical: Spacing.xs, paddingHorizontal: Spacing.sm, backgroundColor: AppColors.primaryLighter, borderRadius: BorderRadius.md, }, retryButtonText: { fontSize: FontSizes.sm, fontWeight: FontWeights.semibold, color: AppColors.primary, }, // Help Card helpCard: { backgroundColor: AppColors.infoLight, borderRadius: BorderRadius.lg, padding: Spacing.md, marginTop: Spacing.sm, }, helpHeader: { flexDirection: 'row', alignItems: 'center', gap: Spacing.sm, marginBottom: Spacing.xs, }, helpTitle: { fontSize: FontSizes.sm, fontWeight: FontWeights.semibold, color: AppColors.info, }, helpText: { fontSize: FontSizes.sm, color: AppColors.info, lineHeight: 20, }, // Bottom Actions bottomActions: { padding: Spacing.lg, borderTopWidth: 1, borderTopColor: AppColors.border, backgroundColor: AppColors.surface, gap: Spacing.sm, }, retryAllButton: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', gap: Spacing.sm, paddingVertical: Spacing.md, borderRadius: BorderRadius.lg, borderWidth: 1, borderColor: AppColors.primary, backgroundColor: AppColors.primaryLighter, }, retryAllButtonText: { fontSize: FontSizes.base, fontWeight: FontWeights.semibold, color: AppColors.primary, }, doneButton: { backgroundColor: AppColors.primary, paddingVertical: Spacing.md, borderRadius: BorderRadius.lg, alignItems: 'center', ...Shadows.md, }, doneButtonText: { fontSize: FontSizes.base, fontWeight: FontWeights.semibold, color: AppColors.white, }, });