@naarni/design-system
Version:
Naarni React Native Design System for EV Fleet Apps
156 lines (147 loc) • 5.73 kB
JavaScript
import React, { useState, useRef } from 'react';
import { View, TouchableOpacity, StyleSheet } from 'react-native';
import { Icon } from '../Icon';
import { Text } from '../Text';
import { Card } from '../Card/Card';
import MapComponent from './Map';
import { styles as mapStyles } from './styles';
const EnhancedMap = ({ showControls = true, showVehicleInfo = true, selectedVehicle, onVehicleSelect, vehicles = [], onVehiclePress, ...mapProps }) => {
const mapRef = useRef(null);
const [isVehicleInfoVisible, setIsVehicleInfoVisible] = useState(false);
// Debug logging (reduced for stability)
console.log('🗺️ EnhancedMap: Vehicles:', vehicles.length);
const handleVehiclePress = (vehicle) => {
try {
onVehicleSelect?.(vehicle);
setIsVehicleInfoVisible(true);
onVehiclePress?.(vehicle);
}
catch (error) {
console.error('EnhancedMap vehicle press error:', error);
}
};
const handleFitToVehicles = () => {
try {
mapRef.current?.fitToVehicles();
}
catch (error) {
console.error('Fit to vehicles error:', error);
}
};
const handleFitToSelectedVehicle = () => {
try {
if (selectedVehicle) {
mapRef.current?.fitToVehicle(selectedVehicle);
}
}
catch (error) {
console.error('Fit to selected vehicle error:', error);
}
};
const handleClearSelection = () => {
try {
onVehicleSelect?.(null);
setIsVehicleInfoVisible(false);
}
catch (error) {
console.error('Clear selection error:', error);
}
};
const renderControls = () => {
if (!showControls)
return null;
return (<View style={mapStyles.controlsContainer}>
<TouchableOpacity style={mapStyles.controlButton} onPress={handleFitToVehicles} testID="fit-to-vehicles-button">
<Icon name="map-marker-multiple" size={20} color="#007AFF"/>
</TouchableOpacity>
{selectedVehicle && (<TouchableOpacity style={mapStyles.controlButton} onPress={handleFitToSelectedVehicle} testID="fit-to-selected-vehicle-button">
<Icon name="map-marker" size={20} color="#007AFF"/>
</TouchableOpacity>)}
{selectedVehicle && (<TouchableOpacity style={mapStyles.controlButton} onPress={handleClearSelection} testID="clear-selection-button">
<Icon name="close" size={20} color="#FF3B30"/>
</TouchableOpacity>)}
</View>);
};
const renderVehicleInfo = () => {
if (!showVehicleInfo || !selectedVehicle || !isVehicleInfoVisible)
return null;
return (<Card style={mapStyles.vehicleInfo}>
<View style={styles.vehicleHeader}>
<Text variant="h6" style={styles.vehicleName}>
{selectedVehicle.name || 'Vehicle'}
</Text>
<TouchableOpacity onPress={handleClearSelection}>
<Icon name="close" size={16} color="#666"/>
</TouchableOpacity>
</View>
{selectedVehicle.description && (<Text variant="body2" color="#666" style={styles.vehicleDescription}>
{selectedVehicle.description}
</Text>)}
<View style={styles.vehicleDetails}>
<View style={styles.detailRow}>
<Text variant="caption" color="#666">Location:</Text>
<Text variant="body2">
{selectedVehicle.latitude.toFixed(6)}, {selectedVehicle.longitude.toFixed(6)}
</Text>
</View>
{selectedVehicle.speed !== undefined && (<View style={styles.detailRow}>
<Text variant="caption" color="#666">Speed:</Text>
<Text variant="body2">{selectedVehicle.speed} km/h</Text>
</View>)}
{selectedVehicle.battery !== undefined && (<View style={styles.detailRow}>
<Text variant="caption" color="#666">Battery:</Text>
<Text variant="body2" color={selectedVehicle.battery < 20 ? '#FF3B30' : '#34C759'}>
{selectedVehicle.battery}%
</Text>
</View>)}
{selectedVehicle.status && (<View style={styles.detailRow}>
<Text variant="caption" color="#666">Status:</Text>
<Text variant="body2" style={styles.statusText}>
{selectedVehicle.status}
</Text>
</View>)}
{selectedVehicle.lastUpdate && (<View style={styles.detailRow}>
<Text variant="caption" color="#666">Last Update:</Text>
<Text variant="body2">
{selectedVehicle.lastUpdate.toLocaleTimeString()}
</Text>
</View>)}
</View>
</Card>);
};
return (<View style={styles.container}>
<MapComponent ref={mapRef} vehicles={vehicles} onVehiclePress={handleVehiclePress} {...mapProps}/>
{renderControls()}
{renderVehicleInfo()}
</View>);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
vehicleHeader: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 8,
},
vehicleName: {
flex: 1,
marginRight: 8,
},
vehicleDescription: {
marginBottom: 12,
},
vehicleDetails: {
gap: 4,
},
detailRow: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
statusText: {
textTransform: 'capitalize',
},
});
export default EnhancedMap;