From f6e4e51a34b145b5b58b459f87132a5a5cc89b77 Mon Sep 17 00:00:00 2001 From: Xor290 Date: Thu, 19 Feb 2026 10:06:21 +0100 Subject: [PATCH] chore: fix map dashboard admin --- .../src/screens/admin/DeliveryScreen.tsx | 298 +++++++----------- 1 file changed, 114 insertions(+), 184 deletions(-) diff --git a/frontend-admin/src/screens/admin/DeliveryScreen.tsx b/frontend-admin/src/screens/admin/DeliveryScreen.tsx index f6b21357..8e5a9acb 100644 --- a/frontend-admin/src/screens/admin/DeliveryScreen.tsx +++ b/frontend-admin/src/screens/admin/DeliveryScreen.tsx @@ -14,10 +14,8 @@ import { TouchableOpacity, Modal, StatusBar, - Dimensions, } from "react-native"; import { Ionicons } from "@expo/vector-icons"; -import MapView, { Marker, Polyline, PROVIDER_DEFAULT } from "react-native-maps"; import { spacing, fontSize, borderRadius } from "../../theme"; import { useTheme } from "../../context/ThemeContext"; import { @@ -31,6 +29,12 @@ import { STATUS_LABELS, getStatusColors } from "../../utils/constants"; import LoadingSpinner from "../../components/ui/LoadingSpinner"; import Card from "../../components/ui/Card"; import Badge from "../../components/ui/Badge"; +import TomTomMap, { + TomTomMapRef, + TomTomMarker, + TomTomRoute, + TomTomDestination, +} from "../../components/TomTomMap"; const MAP_HEIGHT = 280; @@ -47,9 +51,9 @@ export default function DeliveryScreen() { const [loading, setLoading] = useState(true); const [refreshing, setRefreshing] = useState(false); - // Map - const mapRef = useRef(null); - const fullscreenMapRef = useRef(null); + // TomTomMap refs + const mapRef = useRef(null); + const fullscreenMapRef = useRef(null); const [mapFullscreen, setMapFullscreen] = useState(false); // Selected livreur route tracking @@ -88,6 +92,44 @@ export default function DeliveryScreen() { (l) => l.location.latitude !== 0 && l.location.longitude !== 0, ); + // -------------------------------------------------- + // Construire les markers TomTom pour tous les livreurs + // -------------------------------------------------- + const tomtomMarkers: TomTomMarker[] = useMemo(() => { + return livreursWithGPS.map((l) => ({ + id: l.username, + latitude: l.location.latitude, + longitude: l.location.longitude, + color: statusColors[l.status] || colors.textMuted, + label: l.username, + description: `${STATUS_LABELS[l.status] || l.status}${ + l.stats.current_command + ? ` · Cmd #${l.stats.current_command}` + : "" + }`, + isSelected: selectedLivreur?.username === l.username, + })); + }, [livreursWithGPS, selectedLivreur, statusColors, colors.textMuted]); + + // Route TomTom + const tomtomRoute: TomTomRoute | null = useMemo(() => { + if (!routeInfo || routeInfo.coordinates.length === 0) return null; + return { coordinates: routeInfo.coordinates, color: "#4285F4" }; + }, [routeInfo]); + + // Destination TomTom + const tomtomDestination: TomTomDestination | null = useMemo(() => { + if (!destinationCoords) return null; + return { + latitude: destinationCoords.latitude, + longitude: destinationCoords.longitude, + color: colors.danger, + }; + }, [destinationCoords, colors.danger]); + + // -------------------------------------------------- + // Track livreur — calcul de route + // -------------------------------------------------- const trackLivreur = useCallback( async (livreur: DeliveryPerson) => { setSelectedLivreur(livreur); @@ -121,30 +163,15 @@ export default function DeliveryScreen() { const result = await calculateRoute(origin, dest); if (result) { setRouteInfo(result.route); + // Fit la map sur les deux points const ref = mapFullscreen ? fullscreenMapRef : mapRef; - if (ref.current) { - ref.current.fitToCoordinates( - [ - { - latitude: origin.latitude, - longitude: origin.longitude, - }, - { - latitude: dest.latitude, - longitude: dest.longitude, - }, - ], - { - edgePadding: { - top: 80, - right: 60, - bottom: 80, - left: 60, - }, - animated: true, - }, - ); - } + ref.current?.fitToCoordinates([ + { + latitude: origin.latitude, + longitude: origin.longitude, + }, + { latitude: dest.latitude, longitude: dest.longitude }, + ]); } } catch { /* silent */ @@ -160,21 +187,28 @@ export default function DeliveryScreen() { setDestinationCoords(null); }; - const fitAllMarkers = (ref: React.RefObject) => { - if (ref.current && livreursWithGPS.length > 0) { - ref.current.fitToCoordinates( - livreursWithGPS.map((l) => ({ - latitude: l.location.latitude, - longitude: l.location.longitude, - })), - { - edgePadding: { top: 60, right: 60, bottom: 60, left: 60 }, - animated: true, - }, + // -------------------------------------------------- + // onMarkerPress depuis TomTomMap + // -------------------------------------------------- + const handleMarkerPress = useCallback( + (markerId: string) => { + const livreur = livreursWithGPS.find( + (l) => l.username === markerId, ); - } - }; + if (livreur) { + if (selectedLivreur?.username === markerId) { + clearRoute(); + } else { + trackLivreur(livreur); + } + } + }, + [livreursWithGPS, selectedLivreur, trackLivreur], + ); + // -------------------------------------------------- + // Styles + // -------------------------------------------------- const styles = useMemo( () => StyleSheet.create({ @@ -208,46 +242,9 @@ export default function DeliveryScreen() { overflow: "hidden", marginBottom: spacing.m, position: "relative", + height: MAP_HEIGHT, }, - map: { width: "100%", height: MAP_HEIGHT }, - - markerOuter: { - width: 34, - height: 34, - borderRadius: 17, - justifyContent: "center", - alignItems: "center", - }, - markerSelected: { - borderWidth: 2, - borderColor: colors.accent, - width: 40, - height: 40, - borderRadius: 20, - }, - markerInner: { - width: 26, - height: 26, - borderRadius: 13, - justifyContent: "center", - alignItems: "center", - }, - destMarkerOuter: { - width: 30, - height: 30, - borderRadius: 15, - backgroundColor: colors.danger + "40", - justifyContent: "center", - alignItems: "center", - }, - destMarkerInner: { - width: 22, - height: 22, - borderRadius: 11, - backgroundColor: colors.danger, - justifyContent: "center", - alignItems: "center", - }, + map: { flex: 1 }, routeOverlay: { position: "absolute", @@ -393,6 +390,7 @@ export default function DeliveryScreen() { marginTop: spacing.xxl, }, + // Fullscreen fullscreenContainer: { flex: 1, backgroundColor: colors.bgPrimary, @@ -472,77 +470,9 @@ export default function DeliveryScreen() { [colors], ); - const renderMapMarkers = () => - livreursWithGPS.map((l) => { - const isSelected = selectedLivreur?.username === l.username; - const markerColor = statusColors[l.status] || colors.textMuted; - return ( - trackLivreur(l)} - > - - - - - - - ); - }); - - const renderRouteOverlay = () => { - if (!destinationCoords) return null; - return ( - <> - - - - - - - - {routeInfo && routeInfo.coordinates.length > 0 && ( - - )} - - ); - }; - + // -------------------------------------------------- + // Render livreur card + // -------------------------------------------------- const renderLivreur = ({ item }: { item: DeliveryPerson }) => { const isSelected = selectedLivreur?.username === item.username; const hasGPS = item.location.latitude !== 0; @@ -658,27 +588,28 @@ export default function DeliveryScreen() { ); }; + // -------------------------------------------------- + // Header avec TomTomMap + // -------------------------------------------------- const renderHeader = () => ( - {livreursWithGPS.length > 0 && ( + {livreursWithGPS.length > 0 ? ( - fitAllMarkers(mapRef)} - showsUserLocation={false} - > - {renderMapMarkers()} - {renderRouteOverlay()} - + initialZoom={12} + onMarkerPress={handleMarkerPress} + /> + {/* Overlay info route sélectionnée */} {routeInfo && selectedLivreur && ( @@ -720,7 +651,7 @@ export default function DeliveryScreen() { fitAllMarkers(mapRef)} + onPress={() => mapRef.current?.fitAllMarkers()} > - )} - - {livreursWithGPS.length === 0 && !loading && ( + ) : !loading ? ( - )} + ) : null} Livreurs ({livreurs.length}) @@ -765,7 +694,7 @@ export default function DeliveryScreen() { return ( - {/* Fullscreen map modal */} + {/* ── Modal plein écran TomTomMap ── */} - {/* Summary */} + {/* ── Résumé stats ── */} + {/* ── Liste livreurs ── */} item.username}