chore: update map
This commit is contained in:
+41
-43
@@ -1,45 +1,43 @@
|
|||||||
{
|
{
|
||||||
"expo": {
|
"expo": {
|
||||||
"name": "Admin Panel",
|
"name": "Admin Panel",
|
||||||
"slug": "frontend-admin",
|
"slug": "frontend-admin",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"orientation": "portrait",
|
"orientation": "portrait",
|
||||||
"icon": "./assets/icon.png",
|
"icon": "./assets/icon.png",
|
||||||
"userInterfaceStyle": "dark",
|
"userInterfaceStyle": "dark",
|
||||||
"newArchEnabled": true,
|
"newArchEnabled": false,
|
||||||
"splash": {
|
"splash": {
|
||||||
"image": "./assets/splash-icon.png",
|
"image": "./assets/splash-icon.png",
|
||||||
"resizeMode": "contain",
|
"resizeMode": "contain",
|
||||||
"backgroundColor": "#0a0a0a"
|
"backgroundColor": "#0a0a0a"
|
||||||
},
|
},
|
||||||
"ios": {
|
"ios": {
|
||||||
"supportsTablet": true,
|
"supportsTablet": true,
|
||||||
"bundleIdentifier": "com.uberstup.adminpanel"
|
"bundleIdentifier": "com.uberstup.adminpanel"
|
||||||
},
|
},
|
||||||
"android": {
|
"android": {
|
||||||
"package": "com.uberstup.adminpanel",
|
"package": "com.uberstup.adminpanel",
|
||||||
"adaptiveIcon": {
|
"adaptiveIcon": {
|
||||||
"foregroundImage": "./assets/adaptive-icon.png",
|
"foregroundImage": "./assets/adaptive-icon.png",
|
||||||
"backgroundColor": "#0a0a0a"
|
"backgroundColor": "#0a0a0a"
|
||||||
},
|
},
|
||||||
"edgeToEdgeEnabled": true,
|
"edgeToEdgeEnabled": true,
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"android.permission.ACCESS_COARSE_LOCATION",
|
"android.permission.ACCESS_BACKGROUND_LOCATION",
|
||||||
"android.permission.ACCESS_FINE_LOCATION"
|
"android.permission.ACCESS_COARSE_LOCATION",
|
||||||
]
|
"android.permission.ACCESS_FINE_LOCATION"
|
||||||
},
|
]
|
||||||
"web": {
|
},
|
||||||
"favicon": "./assets/favicon.png"
|
"web": {
|
||||||
},
|
"favicon": "./assets/favicon.png"
|
||||||
"plugins": [
|
},
|
||||||
"expo-font",
|
"plugins": ["expo-font", "expo-location"],
|
||||||
"expo-location"
|
"extra": {
|
||||||
],
|
"eas": {
|
||||||
"extra": {
|
"projectId": "fcb7a0bc-5b2f-453d-ba16-9f97d9f0e440"
|
||||||
"eas": {
|
}
|
||||||
"projectId": "fcb7a0bc-5b2f-453d-ba16-9f97d9f0e440"
|
},
|
||||||
}
|
"owner": "xor290"
|
||||||
},
|
}
|
||||||
"owner": "xor290"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import {
|
|||||||
} from "react-native";
|
} from "react-native";
|
||||||
import { Ionicons } from "@expo/vector-icons";
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
import * as Location from "expo-location";
|
import * as Location from "expo-location";
|
||||||
import MapView, { Marker, Polyline, PROVIDER_DEFAULT } from "react-native-maps";
|
|
||||||
import { spacing, fontSize, borderRadius } from "../../theme";
|
import { spacing, fontSize, borderRadius } from "../../theme";
|
||||||
import { useTheme } from "../../context/ThemeContext";
|
import { useTheme } from "../../context/ThemeContext";
|
||||||
import {
|
import {
|
||||||
@@ -52,6 +51,12 @@ import Badge from "../../components/ui/Badge";
|
|||||||
import Button from "../../components/ui/Button";
|
import Button from "../../components/ui/Button";
|
||||||
import AlertModal from "../../components/ui/AlertModal";
|
import AlertModal from "../../components/ui/AlertModal";
|
||||||
import { useAlert } from "../../hooks/useAlert";
|
import { useAlert } from "../../hooks/useAlert";
|
||||||
|
import TomTomMap, {
|
||||||
|
TomTomMapRef,
|
||||||
|
TomTomMarker,
|
||||||
|
TomTomRoute,
|
||||||
|
TomTomDestination,
|
||||||
|
} from "../../components/TomTomMap";
|
||||||
|
|
||||||
const { width: SCREEN_WIDTH } = Dimensions.get("window");
|
const { width: SCREEN_WIDTH } = Dimensions.get("window");
|
||||||
const MAP_HEIGHT = 260;
|
const MAP_HEIGHT = 260;
|
||||||
@@ -91,8 +96,10 @@ export default function DashboardScreen() {
|
|||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
const appState = useRef(AppState.currentState);
|
const appState = useRef(AppState.currentState);
|
||||||
const mapRef = useRef<MapView | null>(null);
|
|
||||||
const fullscreenMapRef = useRef<MapView | null>(null);
|
// TomTom map refs
|
||||||
|
const mapRef = useRef<TomTomMapRef>(null);
|
||||||
|
const fullscreenMapRef = useRef<TomTomMapRef>(null);
|
||||||
const [mapFullscreen, setMapFullscreen] = useState(false);
|
const [mapFullscreen, setMapFullscreen] = useState(false);
|
||||||
|
|
||||||
// TomTom routing
|
// TomTom routing
|
||||||
@@ -117,6 +124,46 @@ export default function DashboardScreen() {
|
|||||||
[colors],
|
[colors],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// --------------------------------------------------
|
||||||
|
// Construire les props pour TomTomMap
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
// Marker du livreur (position courante)
|
||||||
|
const driverMarkers: TomTomMarker[] = useMemo(() => {
|
||||||
|
if (!lastCoords) return [];
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
id: "driver",
|
||||||
|
latitude: lastCoords.lat,
|
||||||
|
longitude: lastCoords.lng,
|
||||||
|
color: colors.success,
|
||||||
|
label: "Ma position",
|
||||||
|
description: lastUpdate
|
||||||
|
? lastUpdate.toLocaleTimeString("fr-FR", {
|
||||||
|
hour: "2-digit",
|
||||||
|
minute: "2-digit",
|
||||||
|
})
|
||||||
|
: undefined,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}, [lastCoords, lastUpdate, colors.success]);
|
||||||
|
|
||||||
|
// 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]);
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// Data
|
// Data
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
@@ -137,7 +184,6 @@ export default function DashboardScreen() {
|
|||||||
? deliveriesRes.deliveries
|
? deliveriesRes.deliveries
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
// Include queue commands
|
|
||||||
const queueCommands: DeliveryItem[] = [];
|
const queueCommands: DeliveryItem[] = [];
|
||||||
if (queueRes.success && queueRes.queue_info?.commands) {
|
if (queueRes.success && queueRes.queue_info?.commands) {
|
||||||
for (const cmd of queueRes.queue_info.commands) {
|
for (const cmd of queueRes.queue_info.commands) {
|
||||||
@@ -194,7 +240,6 @@ export default function DashboardScreen() {
|
|||||||
|
|
||||||
setDeliveries(enriched);
|
setDeliveries(enriched);
|
||||||
|
|
||||||
// Auto-calculate route for first in_progress / assigned delivery
|
|
||||||
const activeDelivery =
|
const activeDelivery =
|
||||||
enriched.find(
|
enriched.find(
|
||||||
(d) =>
|
(d) =>
|
||||||
@@ -227,7 +272,6 @@ export default function DashboardScreen() {
|
|||||||
if (!lastCoords) return;
|
if (!lastCoords) return;
|
||||||
setRouteLoading(true);
|
setRouteLoading(true);
|
||||||
try {
|
try {
|
||||||
// Geocode destination
|
|
||||||
const dest = await geocodeAddress(address);
|
const dest = await geocodeAddress(address);
|
||||||
if (!dest) {
|
if (!dest) {
|
||||||
setRouteLoading(false);
|
setRouteLoading(false);
|
||||||
@@ -235,7 +279,6 @@ export default function DashboardScreen() {
|
|||||||
}
|
}
|
||||||
setDestinationCoords(dest);
|
setDestinationCoords(dest);
|
||||||
|
|
||||||
// Calculate route
|
|
||||||
const result = await calculateRoute(
|
const result = await calculateRoute(
|
||||||
{ latitude: lastCoords.lat, longitude: lastCoords.lng },
|
{ latitude: lastCoords.lat, longitude: lastCoords.lng },
|
||||||
dest,
|
dest,
|
||||||
@@ -245,30 +288,12 @@ export default function DashboardScreen() {
|
|||||||
setInstructions(result.instructions);
|
setInstructions(result.instructions);
|
||||||
setCurrentInstructionIdx(0);
|
setCurrentInstructionIdx(0);
|
||||||
|
|
||||||
// Fit map to show both points
|
// Fit la map pour afficher driver + destination
|
||||||
if (mapRef.current) {
|
const coords = [
|
||||||
mapRef.current.fitToCoordinates(
|
{ latitude: lastCoords.lat, longitude: lastCoords.lng },
|
||||||
[
|
{ latitude: dest.latitude, longitude: dest.longitude },
|
||||||
{
|
];
|
||||||
latitude: lastCoords.lat,
|
mapRef.current?.fitToCoordinates(coords);
|
||||||
longitude: lastCoords.lng,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
latitude: dest.latitude,
|
|
||||||
longitude: dest.longitude,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
{
|
|
||||||
edgePadding: {
|
|
||||||
top: 80,
|
|
||||||
right: 60,
|
|
||||||
bottom: 80,
|
|
||||||
left: 60,
|
|
||||||
},
|
|
||||||
animated: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
/* silent */
|
/* silent */
|
||||||
@@ -286,7 +311,6 @@ export default function DashboardScreen() {
|
|||||||
const sendCurrentLocation = useCallback(async () => {
|
const sendCurrentLocation = useCallback(async () => {
|
||||||
if (sendingRef.current) return;
|
if (sendingRef.current) return;
|
||||||
sendingRef.current = true;
|
sendingRef.current = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const loc = await Promise.race([
|
const loc = await Promise.race([
|
||||||
Location.getCurrentPositionAsync({
|
Location.getCurrentPositionAsync({
|
||||||
@@ -297,7 +321,6 @@ export default function DashboardScreen() {
|
|||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// validation runtime + typage TS
|
|
||||||
if (
|
if (
|
||||||
!loc ||
|
!loc ||
|
||||||
typeof loc !== "object" ||
|
typeof loc !== "object" ||
|
||||||
@@ -313,7 +336,6 @@ export default function DashboardScreen() {
|
|||||||
|
|
||||||
setLastCoords({ lat: latitude, lng: longitude });
|
setLastCoords({ lat: latitude, lng: longitude });
|
||||||
setLastUpdate(new Date());
|
setLastUpdate(new Date());
|
||||||
|
|
||||||
await updateMyLocation(latitude, longitude);
|
await updateMyLocation(latitude, longitude);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("GPS error:", err);
|
console.log("GPS error:", err);
|
||||||
@@ -440,7 +462,6 @@ export default function DashboardScreen() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.instructionBar}>
|
<View style={styles.instructionBar}>
|
||||||
{/* Current instruction */}
|
|
||||||
<View style={styles.currentInstruction}>
|
<View style={styles.currentInstruction}>
|
||||||
<View style={styles.instructionIconBox}>
|
<View style={styles.instructionIconBox}>
|
||||||
<Ionicons
|
<Ionicons
|
||||||
@@ -464,7 +485,6 @@ export default function DashboardScreen() {
|
|||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Next instruction preview */}
|
|
||||||
{next && (
|
{next && (
|
||||||
<View style={styles.nextInstruction}>
|
<View style={styles.nextInstruction}>
|
||||||
<Text style={styles.nextLabel}>Puis</Text>
|
<Text style={styles.nextLabel}>Puis</Text>
|
||||||
@@ -482,7 +502,6 @@ export default function DashboardScreen() {
|
|||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Route summary + toggle all instructions */}
|
|
||||||
<View style={styles.routeSummary}>
|
<View style={styles.routeSummary}>
|
||||||
<View style={styles.routeInfoChip}>
|
<View style={styles.routeInfoChip}>
|
||||||
<Ionicons
|
<Ionicons
|
||||||
@@ -534,7 +553,6 @@ export default function DashboardScreen() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Card style={{ marginBottom: spacing.m }}>
|
<Card style={{ marginBottom: spacing.m }}>
|
||||||
{/* Header */}
|
|
||||||
<View style={styles.cardHeader}>
|
<View style={styles.cardHeader}>
|
||||||
<View style={{ flex: 1 }}>
|
<View style={{ flex: 1 }}>
|
||||||
<Text style={styles.deliveryId}>
|
<Text style={styles.deliveryId}>
|
||||||
@@ -568,7 +586,6 @@ export default function DashboardScreen() {
|
|||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Address + navigation */}
|
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={styles.addressRow}
|
style={styles.addressRow}
|
||||||
onPress={() => openNavigation(item.adresse)}
|
onPress={() => openNavigation(item.adresse)}
|
||||||
@@ -589,7 +606,6 @@ export default function DashboardScreen() {
|
|||||||
/>
|
/>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
{/* Calculate route button for active delivery */}
|
|
||||||
{isActive && lastCoords && (
|
{isActive && lastCoords && (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={styles.calcRouteBtn}
|
style={styles.calcRouteBtn}
|
||||||
@@ -609,7 +625,6 @@ export default function DashboardScreen() {
|
|||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Items / Products */}
|
|
||||||
{item.items && item.items.length > 0 && (
|
{item.items && item.items.length > 0 && (
|
||||||
<View style={styles.itemsSection}>
|
<View style={styles.itemsSection}>
|
||||||
<View style={styles.itemsHeader}>
|
<View style={styles.itemsHeader}>
|
||||||
@@ -652,7 +667,6 @@ export default function DashboardScreen() {
|
|||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Client phone */}
|
|
||||||
{item.clientPhone && (
|
{item.clientPhone && (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={styles.phoneRow}
|
style={styles.phoneRow}
|
||||||
@@ -669,7 +683,6 @@ export default function DashboardScreen() {
|
|||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Action buttons */}
|
|
||||||
{(item.status === "pending" || item.status === "assigned") && (
|
{(item.status === "pending" || item.status === "assigned") && (
|
||||||
<Button
|
<Button
|
||||||
title="Démarrer la livraison"
|
title="Démarrer la livraison"
|
||||||
@@ -696,76 +709,25 @@ export default function DashboardScreen() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// Header with map + route + status + GPS
|
// Header avec TomTomMap
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
const renderHeader = () => (
|
const renderHeader = () => (
|
||||||
<View>
|
<View>
|
||||||
{/* Map with route */}
|
{/* Carte TomTom */}
|
||||||
{lastCoords && (
|
{lastCoords ? (
|
||||||
<View style={styles.mapContainer}>
|
<View style={styles.mapContainer}>
|
||||||
<MapView
|
<TomTomMap
|
||||||
ref={mapRef}
|
ref={mapRef}
|
||||||
provider={PROVIDER_DEFAULT}
|
|
||||||
style={styles.map}
|
style={styles.map}
|
||||||
initialRegion={{
|
markers={driverMarkers}
|
||||||
|
route={tomtomRoute}
|
||||||
|
destination={tomtomDestination}
|
||||||
|
initialCenter={{
|
||||||
latitude: lastCoords.lat,
|
latitude: lastCoords.lat,
|
||||||
longitude: lastCoords.lng,
|
longitude: lastCoords.lng,
|
||||||
latitudeDelta: 0.02,
|
|
||||||
longitudeDelta: 0.02,
|
|
||||||
}}
|
}}
|
||||||
showsUserLocation={false}
|
initialZoom={14}
|
||||||
showsMyLocationButton={false}
|
/>
|
||||||
>
|
|
||||||
{/* Driver marker */}
|
|
||||||
<Marker
|
|
||||||
coordinate={{
|
|
||||||
latitude: lastCoords.lat,
|
|
||||||
longitude: lastCoords.lng,
|
|
||||||
}}
|
|
||||||
title="Ma position"
|
|
||||||
>
|
|
||||||
<View style={styles.driverMarkerOuter}>
|
|
||||||
<View style={styles.driverMarkerInner}>
|
|
||||||
<Ionicons
|
|
||||||
name="bicycle"
|
|
||||||
size={16}
|
|
||||||
color={colors.white}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</Marker>
|
|
||||||
|
|
||||||
{/* Destination marker */}
|
|
||||||
{destinationCoords && (
|
|
||||||
<Marker
|
|
||||||
coordinate={{
|
|
||||||
latitude: destinationCoords.latitude,
|
|
||||||
longitude: destinationCoords.longitude,
|
|
||||||
}}
|
|
||||||
title="Destination"
|
|
||||||
>
|
|
||||||
<View style={styles.destMarkerOuter}>
|
|
||||||
<View style={styles.destMarkerInner}>
|
|
||||||
<Ionicons
|
|
||||||
name="flag"
|
|
||||||
size={14}
|
|
||||||
color={colors.white}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</Marker>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Route polyline */}
|
|
||||||
{routeInfo && routeInfo.coordinates.length > 0 && (
|
|
||||||
<Polyline
|
|
||||||
coordinates={routeInfo.coordinates}
|
|
||||||
strokeColor="#4285F4"
|
|
||||||
strokeWidth={5}
|
|
||||||
lineDashPattern={[0]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</MapView>
|
|
||||||
|
|
||||||
{/* GPS overlay */}
|
{/* GPS overlay */}
|
||||||
<View style={styles.gpsOverlay}>
|
<View style={styles.gpsOverlay}>
|
||||||
@@ -793,7 +755,7 @@ export default function DashboardScreen() {
|
|||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Fullscreen button */}
|
{/* Bouton plein écran */}
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={styles.expandBtn}
|
style={styles.expandBtn}
|
||||||
onPress={() => setMapFullscreen(true)}
|
onPress={() => setMapFullscreen(true)}
|
||||||
@@ -806,7 +768,7 @@ export default function DashboardScreen() {
|
|||||||
/>
|
/>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
{/* Route loading indicator */}
|
{/* Indicateur calcul de route */}
|
||||||
{routeLoading && (
|
{routeLoading && (
|
||||||
<View style={styles.routeLoadingOverlay}>
|
<View style={styles.routeLoadingOverlay}>
|
||||||
<Text style={styles.routeLoadingText}>
|
<Text style={styles.routeLoadingText}>
|
||||||
@@ -815,10 +777,7 @@ export default function DashboardScreen() {
|
|||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
)}
|
) : (
|
||||||
|
|
||||||
{/* No location fallback */}
|
|
||||||
{!lastCoords && (
|
|
||||||
<View style={styles.noMapBox}>
|
<View style={styles.noMapBox}>
|
||||||
<Ionicons
|
<Ionicons
|
||||||
name="location-outline"
|
name="location-outline"
|
||||||
@@ -831,10 +790,10 @@ export default function DashboardScreen() {
|
|||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Navigation instructions */}
|
{/* Instructions navigation */}
|
||||||
{renderInstructionBar()}
|
{renderInstructionBar()}
|
||||||
|
|
||||||
{/* All instructions list */}
|
{/* Liste complète des étapes */}
|
||||||
{showInstructions && instructions.length > 0 && (
|
{showInstructions && instructions.length > 0 && (
|
||||||
<View style={styles.allInstructionsBox}>
|
<View style={styles.allInstructionsBox}>
|
||||||
<View style={styles.allInstructionsHeader}>
|
<View style={styles.allInstructionsHeader}>
|
||||||
@@ -937,12 +896,14 @@ export default function DashboardScreen() {
|
|||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// --------------------------------------------------
|
||||||
|
// Styles
|
||||||
|
// --------------------------------------------------
|
||||||
const styles = useMemo(
|
const styles = useMemo(
|
||||||
() =>
|
() =>
|
||||||
StyleSheet.create({
|
StyleSheet.create({
|
||||||
container: { flex: 1, backgroundColor: colors.bgPrimary },
|
container: { flex: 1, backgroundColor: colors.bgPrimary },
|
||||||
|
|
||||||
// Status
|
|
||||||
statusBar: {
|
statusBar: {
|
||||||
padding: spacing.l,
|
padding: spacing.l,
|
||||||
backgroundColor: colors.bgSecondary,
|
backgroundColor: colors.bgSecondary,
|
||||||
@@ -979,8 +940,9 @@ export default function DashboardScreen() {
|
|||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
marginBottom: spacing.m,
|
marginBottom: spacing.m,
|
||||||
position: "relative",
|
position: "relative",
|
||||||
|
height: MAP_HEIGHT,
|
||||||
},
|
},
|
||||||
map: { width: "100%", height: MAP_HEIGHT },
|
map: { flex: 1 },
|
||||||
gpsOverlay: {
|
gpsOverlay: {
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
bottom: spacing.s,
|
bottom: spacing.s,
|
||||||
@@ -1001,40 +963,6 @@ export default function DashboardScreen() {
|
|||||||
},
|
},
|
||||||
gpsOverlayTime: { color: colors.textMuted, fontSize: 10 },
|
gpsOverlayTime: { color: colors.textMuted, fontSize: 10 },
|
||||||
|
|
||||||
// Markers
|
|
||||||
driverMarkerOuter: {
|
|
||||||
width: 36,
|
|
||||||
height: 36,
|
|
||||||
borderRadius: 18,
|
|
||||||
backgroundColor: colors.success + "40",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
},
|
|
||||||
driverMarkerInner: {
|
|
||||||
width: 28,
|
|
||||||
height: 28,
|
|
||||||
borderRadius: 14,
|
|
||||||
backgroundColor: colors.success,
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
},
|
|
||||||
destMarkerOuter: {
|
|
||||||
width: 36,
|
|
||||||
height: 36,
|
|
||||||
borderRadius: 18,
|
|
||||||
backgroundColor: colors.danger + "40",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
},
|
|
||||||
destMarkerInner: {
|
|
||||||
width: 28,
|
|
||||||
height: 28,
|
|
||||||
borderRadius: 14,
|
|
||||||
backgroundColor: colors.danger,
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
},
|
|
||||||
|
|
||||||
noMapBox: {
|
noMapBox: {
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
paddingVertical: spacing.xl,
|
paddingVertical: spacing.xl,
|
||||||
@@ -1048,7 +976,6 @@ export default function DashboardScreen() {
|
|||||||
marginTop: spacing.s,
|
marginTop: spacing.s,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Route loading
|
|
||||||
routeLoadingOverlay: {
|
routeLoadingOverlay: {
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
top: 0,
|
top: 0,
|
||||||
@@ -1065,7 +992,19 @@ export default function DashboardScreen() {
|
|||||||
fontWeight: "600",
|
fontWeight: "600",
|
||||||
},
|
},
|
||||||
|
|
||||||
// Navigation instructions
|
expandBtn: {
|
||||||
|
position: "absolute",
|
||||||
|
top: spacing.s,
|
||||||
|
right: spacing.s,
|
||||||
|
width: 36,
|
||||||
|
height: 36,
|
||||||
|
borderRadius: 18,
|
||||||
|
backgroundColor: "rgba(0,0,0,0.6)",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
|
||||||
|
// Instructions
|
||||||
instructionBar: {
|
instructionBar: {
|
||||||
backgroundColor: colors.bgSecondary,
|
backgroundColor: colors.bgSecondary,
|
||||||
borderRadius: borderRadius.md,
|
borderRadius: borderRadius.md,
|
||||||
@@ -1202,10 +1141,7 @@ export default function DashboardScreen() {
|
|||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
},
|
},
|
||||||
stepText: {
|
stepText: { color: colors.textWhite, fontSize: fontSize.sm },
|
||||||
color: colors.textWhite,
|
|
||||||
fontSize: fontSize.sm,
|
|
||||||
},
|
|
||||||
stepStreet: {
|
stepStreet: {
|
||||||
color: colors.textMuted,
|
color: colors.textMuted,
|
||||||
fontSize: fontSize.xs,
|
fontSize: fontSize.xs,
|
||||||
@@ -1217,7 +1153,7 @@ export default function DashboardScreen() {
|
|||||||
fontWeight: "600",
|
fontWeight: "600",
|
||||||
},
|
},
|
||||||
|
|
||||||
// Calculate route button
|
// Calc route button
|
||||||
calcRouteBtn: {
|
calcRouteBtn: {
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
@@ -1252,7 +1188,6 @@ export default function DashboardScreen() {
|
|||||||
fontWeight: "600",
|
fontWeight: "600",
|
||||||
},
|
},
|
||||||
|
|
||||||
// Section
|
|
||||||
sectionTitle: {
|
sectionTitle: {
|
||||||
color: colors.textWhite,
|
color: colors.textWhite,
|
||||||
fontSize: fontSize.lg,
|
fontSize: fontSize.lg,
|
||||||
@@ -1277,7 +1212,6 @@ export default function DashboardScreen() {
|
|||||||
marginTop: 2,
|
marginTop: 2,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Address
|
|
||||||
addressRow: {
|
addressRow: {
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
@@ -1294,7 +1228,6 @@ export default function DashboardScreen() {
|
|||||||
fontSize: fontSize.sm,
|
fontSize: fontSize.sm,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Items
|
|
||||||
itemsSection: {
|
itemsSection: {
|
||||||
backgroundColor: colors.bgInput,
|
backgroundColor: colors.bgInput,
|
||||||
borderRadius: borderRadius.sm,
|
borderRadius: borderRadius.sm,
|
||||||
@@ -1361,7 +1294,6 @@ export default function DashboardScreen() {
|
|||||||
marginTop: spacing.xs,
|
marginTop: spacing.xs,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Phone
|
|
||||||
phoneRow: {
|
phoneRow: {
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
@@ -1377,27 +1309,12 @@ export default function DashboardScreen() {
|
|||||||
fontSize: fontSize.md,
|
fontSize: fontSize.md,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Expand button
|
// Fullscreen map modal
|
||||||
expandBtn: {
|
|
||||||
position: "absolute",
|
|
||||||
top: spacing.s,
|
|
||||||
right: spacing.s,
|
|
||||||
width: 36,
|
|
||||||
height: 36,
|
|
||||||
borderRadius: 18,
|
|
||||||
backgroundColor: "rgba(0,0,0,0.6)",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
},
|
|
||||||
|
|
||||||
// Fullscreen map
|
|
||||||
fullscreenContainer: {
|
fullscreenContainer: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: colors.bgPrimary,
|
backgroundColor: colors.bgPrimary,
|
||||||
},
|
},
|
||||||
fullscreenMap: {
|
fullscreenMap: { ...StyleSheet.absoluteFillObject },
|
||||||
...StyleSheet.absoluteFillObject,
|
|
||||||
},
|
|
||||||
fullscreenTopBar: {
|
fullscreenTopBar: {
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
top: 0,
|
top: 0,
|
||||||
@@ -1484,7 +1401,7 @@ export default function DashboardScreen() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
{/* Fullscreen map modal */}
|
{/* ── Modal plein écran avec TomTomMap ── */}
|
||||||
<Modal
|
<Modal
|
||||||
visible={mapFullscreen}
|
visible={mapFullscreen}
|
||||||
animationType="fade"
|
animationType="fade"
|
||||||
@@ -1494,70 +1411,18 @@ export default function DashboardScreen() {
|
|||||||
<StatusBar hidden={mapFullscreen} />
|
<StatusBar hidden={mapFullscreen} />
|
||||||
<View style={styles.fullscreenContainer}>
|
<View style={styles.fullscreenContainer}>
|
||||||
{lastCoords && (
|
{lastCoords && (
|
||||||
<MapView
|
<TomTomMap
|
||||||
ref={fullscreenMapRef}
|
ref={fullscreenMapRef}
|
||||||
provider={PROVIDER_DEFAULT}
|
|
||||||
style={styles.fullscreenMap}
|
style={styles.fullscreenMap}
|
||||||
initialRegion={{
|
markers={driverMarkers}
|
||||||
|
route={tomtomRoute}
|
||||||
|
destination={tomtomDestination}
|
||||||
|
initialCenter={{
|
||||||
latitude: lastCoords.lat,
|
latitude: lastCoords.lat,
|
||||||
longitude: lastCoords.lng,
|
longitude: lastCoords.lng,
|
||||||
latitudeDelta: 0.01,
|
|
||||||
longitudeDelta: 0.01,
|
|
||||||
}}
|
}}
|
||||||
showsUserLocation={false}
|
initialZoom={15}
|
||||||
showsMyLocationButton={false}
|
/>
|
||||||
showsCompass
|
|
||||||
showsScale
|
|
||||||
>
|
|
||||||
{/* Driver */}
|
|
||||||
<Marker
|
|
||||||
coordinate={{
|
|
||||||
latitude: lastCoords.lat,
|
|
||||||
longitude: lastCoords.lng,
|
|
||||||
}}
|
|
||||||
title="Ma position"
|
|
||||||
>
|
|
||||||
<View style={styles.driverMarkerOuter}>
|
|
||||||
<View style={styles.driverMarkerInner}>
|
|
||||||
<Ionicons
|
|
||||||
name="bicycle"
|
|
||||||
size={16}
|
|
||||||
color={colors.white}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</Marker>
|
|
||||||
|
|
||||||
{/* Destination */}
|
|
||||||
{destinationCoords && (
|
|
||||||
<Marker
|
|
||||||
coordinate={{
|
|
||||||
latitude: destinationCoords.latitude,
|
|
||||||
longitude: destinationCoords.longitude,
|
|
||||||
}}
|
|
||||||
title="Destination"
|
|
||||||
>
|
|
||||||
<View style={styles.destMarkerOuter}>
|
|
||||||
<View style={styles.destMarkerInner}>
|
|
||||||
<Ionicons
|
|
||||||
name="flag"
|
|
||||||
size={14}
|
|
||||||
color={colors.white}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</Marker>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Route */}
|
|
||||||
{routeInfo && routeInfo.coordinates.length > 0 && (
|
|
||||||
<Polyline
|
|
||||||
coordinates={routeInfo.coordinates}
|
|
||||||
strokeColor="#4285F4"
|
|
||||||
strokeWidth={5}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</MapView>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Top bar */}
|
{/* Top bar */}
|
||||||
@@ -1580,7 +1445,7 @@ export default function DashboardScreen() {
|
|||||||
<View style={{ width: 40 }} />
|
<View style={{ width: 40 }} />
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Fullscreen instruction bar */}
|
{/* Instruction bar en plein écran */}
|
||||||
{instructions.length > 0 && (
|
{instructions.length > 0 && (
|
||||||
<View style={styles.fullscreenInstructionBar}>
|
<View style={styles.fullscreenInstructionBar}>
|
||||||
<View style={styles.instructionIconBox}>
|
<View style={styles.instructionIconBox}>
|
||||||
@@ -1675,7 +1540,7 @@ export default function DashboardScreen() {
|
|||||||
</View>
|
</View>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
{/* Status bar */}
|
{/* ── Barre de statut ── */}
|
||||||
<View style={styles.statusBar}>
|
<View style={styles.statusBar}>
|
||||||
<Text style={styles.statusLabel}>Mon statut:</Text>
|
<Text style={styles.statusLabel}>Mon statut:</Text>
|
||||||
<View style={styles.statusBtns}>
|
<View style={styles.statusBtns}>
|
||||||
@@ -1712,6 +1577,7 @@ export default function DashboardScreen() {
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
{/* ── Liste des livraisons ── */}
|
||||||
<FlatList
|
<FlatList
|
||||||
data={deliveries}
|
data={deliveries}
|
||||||
keyExtractor={(item, index) => (item.id ?? index).toString()}
|
keyExtractor={(item, index) => (item.id ?? index).toString()}
|
||||||
@@ -1734,6 +1600,7 @@ export default function DashboardScreen() {
|
|||||||
}
|
}
|
||||||
ListHeaderComponent={renderHeader()}
|
ListHeaderComponent={renderHeader()}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<AlertModal
|
<AlertModal
|
||||||
visible={alert.visible}
|
visible={alert.visible}
|
||||||
type={alert.type}
|
type={alert.type}
|
||||||
|
|||||||
Reference in New Issue
Block a user