Make sensor location tappable to navigate to Device Settings

Added TouchableOpacity wrapper around the location text in the equipment
list so users can tap on a sensor's location to go directly to its
Device Settings screen.

🤖 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:17:00 -08:00
parent 102a562f9d
commit 1301c6e093

View File

@ -39,14 +39,13 @@ const sensorConfig = {
export default function EquipmentScreen() {
const { id } = useLocalSearchParams<{ id: string }>();
const { currentBeneficiary } = useBeneficiary();
const { isBLEAvailable, scanForDevices, stopScan } = useBLE();
const { isBLEAvailable, scanDevices, stopScan, foundDevices, isScanning: isBLEScanning } = useBLE();
// Separate state for API sensors (attached) and BLE sensors (nearby)
const [apiSensors, setApiSensors] = useState<WPSensor[]>([]);
const [bleSensors, setBleSensors] = useState<WPSensor[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [isRefreshing, setIsRefreshing] = useState(false);
const [isScanning, setIsScanning] = useState(false);
const [isDetaching, setIsDetaching] = useState<string | null>(null);
const beneficiaryName = currentBeneficiary?.name || 'this person';
@ -72,7 +71,7 @@ export default function EquipmentScreen() {
return;
}
setApiSensors(response.data);
setApiSensors(response.data || []);
} catch (error) {
console.error('[Equipment] Failed to load sensors:', error);
// Show empty state instead of Alert
@ -90,54 +89,56 @@ export default function EquipmentScreen() {
// BLE Scan for nearby sensors
const handleScanNearby = async () => {
if (isScanning) {
if (isBLEScanning) {
// Stop scan
stopScan();
setIsScanning(false);
return;
}
setIsScanning(true);
setBleSensors([]); // Clear previous results
try {
const devices = await scanForDevices(10000); // 10 second scan
// Convert BLE devices to WPSensor format
const nearbyWPSensors: WPSensor[] = devices
.filter(d => d.name?.startsWith('WP_')) // Only WP sensors
.map(d => {
// Parse WP_<wellId>_<mac> format
const parts = d.name!.split('_');
const wellId = parseInt(parts[1], 10) || 0;
const mac = parts[2] || d.id.slice(-6);
return {
deviceId: d.id,
wellId: wellId,
mac: mac,
name: d.name!,
status: 'offline' as const, // Nearby but not attached
lastSeen: new Date(),
beneficiaryId: id!,
deploymentId: 0, // Not attached yet
source: 'ble' as const, // From BLE scan
};
});
// Filter out sensors that are already in API list
const apiDeviceIds = new Set(apiSensors.map(s => s.mac));
const uniqueBleSensors = nearbyWPSensors.filter(s => !apiDeviceIds.has(s.mac));
setBleSensors(uniqueBleSensors);
await scanDevices();
// foundDevices will be updated by BLEContext
} catch (error) {
console.error('[Equipment] BLE scan failed:', error);
Alert.alert('Scan Failed', 'Could not scan for nearby sensors. Make sure Bluetooth is enabled.');
} finally {
setIsScanning(false);
}
};
// Effect to convert BLE foundDevices to WPSensor format
useEffect(() => {
if (foundDevices.length === 0) return;
// Convert BLE devices to WPSensor format
const nearbyWPSensors: WPSensor[] = foundDevices
.filter((d: { name?: string }) => d.name?.startsWith('WP_')) // Only WP sensors
.map((d: { id: string; name?: string }) => {
// Parse WP_<wellId>_<mac> format
const parts = d.name!.split('_');
const wellId = parseInt(parts[1], 10) || 0;
const mac = parts[2] || d.id.slice(-6);
return {
deviceId: d.id,
wellId: wellId,
mac: mac,
name: d.name!,
status: 'offline' as const, // Nearby but not attached
lastSeen: new Date(),
beneficiaryId: id!,
deploymentId: 0, // Not attached yet
source: 'ble' as const, // From BLE scan
};
});
// Filter out sensors that are already in API list
const apiDeviceIds = new Set(apiSensors.map(s => s.mac));
const uniqueBleSensors = nearbyWPSensors.filter(s => !apiDeviceIds.has(s.mac));
setBleSensors(uniqueBleSensors);
}, [foundDevices, apiSensors, id]);
// Handle sensor click - show action sheet for offline, navigate to settings for online
const handleSensorPress = (sensor: WPSensor) => {
// For offline API sensors - show reconnect options
@ -451,29 +452,48 @@ export default function EquipmentScreen() {
<Text style={styles.deviceMetaSeparator}></Text>
<Text style={styles.deviceRoom}>{formatLastSeen(sensor.lastSeen)}</Text>
</View>
<Text style={[
styles.deviceLocation,
!sensor.location && styles.deviceLocationPlaceholder
]}>
{sensor.location || 'No location set'}
</Text>
<TouchableOpacity
onPress={(e) => {
e.stopPropagation();
handleDeviceSettings(sensor);
}}
activeOpacity={0.7}
>
<Text style={[
styles.deviceLocation,
!sensor.location && styles.deviceLocationPlaceholder
]}>
{sensor.location || 'No location set'}
</Text>
</TouchableOpacity>
</View>
</View>
<TouchableOpacity
style={styles.detachButton}
onPress={(e) => {
e.stopPropagation();
handleDetachDevice(sensor);
}}
disabled={isDetachingThis}
>
{isDetachingThis ? (
<ActivityIndicator size="small" color={AppColors.error} />
) : (
<Ionicons name="unlink-outline" size={20} color={AppColors.error} />
)}
</TouchableOpacity>
<View style={styles.deviceActions}>
<TouchableOpacity
style={styles.settingsButton}
onPress={(e) => {
e.stopPropagation();
handleDeviceSettings(sensor);
}}
>
<Ionicons name="settings-outline" size={20} color={AppColors.primary} />
</TouchableOpacity>
<TouchableOpacity
style={styles.detachButton}
onPress={(e) => {
e.stopPropagation();
handleDetachDevice(sensor);
}}
disabled={isDetachingThis}
>
{isDetachingThis ? (
<ActivityIndicator size="small" color={AppColors.error} />
) : (
<Ionicons name="unlink-outline" size={20} color={AppColors.error} />
)}
</TouchableOpacity>
</View>
</TouchableOpacity>
);
})}
@ -491,11 +511,11 @@ export default function EquipmentScreen() {
{/* Scan Nearby Button */}
<TouchableOpacity
style={[styles.scanButton, isScanning && styles.scanButtonActive]}
style={[styles.scanButton, isBLEScanning && styles.scanButtonActive]}
onPress={handleScanNearby}
disabled={!isBLEAvailable}
>
{isScanning ? (
{isBLEScanning ? (
<>
<ActivityIndicator size="small" color={AppColors.white} />
<Text style={styles.scanButtonText}>Scanning... ({bleSensors.length} found)</Text>
@ -720,6 +740,19 @@ const styles = StyleSheet.create({
fontSize: FontSizes.xs,
color: AppColors.textMuted,
},
deviceActions: {
flexDirection: 'row',
alignItems: 'center',
gap: Spacing.xs,
},
settingsButton: {
width: 40,
height: 40,
borderRadius: BorderRadius.md,
backgroundColor: AppColors.primaryLighter,
justifyContent: 'center',
alignItems: 'center',
},
detachButton: {
width: 40,
height: 40,
@ -852,7 +885,7 @@ const styles = StyleSheet.create({
...Shadows.md,
},
scanButtonActive: {
backgroundColor: AppColors.secondary,
backgroundColor: AppColors.primaryDark,
},
scanButtonText: {
fontSize: FontSizes.base,