Add retry button for individual failed sensors on results screen

- Added handleRetryFromResults function to retry setup for a single sensor
- Added Retry button next to each failed/skipped sensor in the results list
- When clicked, resets sensor state and returns to batch setup phase
- Added new styles: resultItemWithAction, resultItemLeft, retryItemButton

TASK-6.2: Add results screen after batch setup

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Sergei 2026-01-19 23:00:32 -08:00
parent ca820b25fb
commit 516dc37527

View File

@ -433,6 +433,23 @@ export default function SetupWiFiScreen() {
router.replace(`/(tabs)/beneficiaries/${id}/equipment` as any);
};
// Retry a single sensor from results screen
const handleRetryFromResults = (deviceId: string) => {
const index = sensors.findIndex(s => s.deviceId === deviceId);
if (index >= 0) {
// Reset the sensor state
setSensors(prev => prev.map(s =>
s.deviceId === deviceId
? { ...s, status: 'pending' as SensorSetupStatus, error: undefined, steps: createInitialSteps() }
: s
));
setCurrentIndex(index);
setIsPaused(false);
// Go back to batch setup phase
setPhase('batch_setup');
}
};
const getSignalStrength = (rssi: number): string => {
if (rssi >= -50) return 'Excellent';
if (rssi >= -60) return 'Good';
@ -507,21 +524,30 @@ export default function SetupWiFiScreen() {
<View style={styles.resultsSection}>
<Text style={styles.resultsSectionTitle}>Failed</Text>
{failedSensors.map(sensor => (
<View key={sensor.deviceId} style={styles.resultItem}>
<Ionicons
name={sensor.status === 'skipped' ? 'remove-circle' : 'close-circle'}
size={20}
color={sensor.status === 'skipped' ? AppColors.warning : AppColors.error}
/>
<View style={styles.resultItemContent}>
<Text style={styles.resultItemText}>{sensor.deviceName}</Text>
{sensor.error && (
<Text style={styles.resultItemError}>{sensor.error}</Text>
)}
{sensor.status === 'skipped' && (
<Text style={styles.resultItemError}>Skipped</Text>
)}
<View key={sensor.deviceId} style={styles.resultItemWithAction}>
<View style={styles.resultItemLeft}>
<Ionicons
name={sensor.status === 'skipped' ? 'remove-circle' : 'close-circle'}
size={20}
color={sensor.status === 'skipped' ? AppColors.warning : AppColors.error}
/>
<View style={styles.resultItemContent}>
<Text style={styles.resultItemText}>{sensor.deviceName}</Text>
{sensor.error && (
<Text style={styles.resultItemError}>{sensor.error}</Text>
)}
{sensor.status === 'skipped' && (
<Text style={styles.resultItemError}>Skipped</Text>
)}
</View>
</View>
<TouchableOpacity
style={styles.retryItemButton}
onPress={() => handleRetryFromResults(sensor.deviceId)}
>
<Ionicons name="refresh" size={16} color={AppColors.primary} />
<Text style={styles.retryItemButtonText}>Retry</Text>
</TouchableOpacity>
</View>
))}
</View>
@ -1039,6 +1065,20 @@ const styles = StyleSheet.create({
paddingVertical: Spacing.xs,
gap: Spacing.sm,
},
resultItemWithAction: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingVertical: Spacing.sm,
borderBottomWidth: 1,
borderBottomColor: AppColors.border,
},
resultItemLeft: {
flexDirection: 'row',
alignItems: 'flex-start',
flex: 1,
gap: Spacing.sm,
},
resultItemContent: {
flex: 1,
},
@ -1052,6 +1092,20 @@ const styles = StyleSheet.create({
color: AppColors.error,
marginTop: 2,
},
retryItemButton: {
flexDirection: 'row',
alignItems: 'center',
gap: Spacing.xs,
paddingVertical: Spacing.xs,
paddingHorizontal: Spacing.sm,
backgroundColor: AppColors.primaryLighter,
borderRadius: BorderRadius.md,
},
retryItemButtonText: {
fontSize: FontSizes.sm,
fontWeight: FontWeights.semibold,
color: AppColors.primary,
},
bottomActions: {
padding: Spacing.lg,
borderTopWidth: 1,