diff --git a/src/scenes/DAEItem/Infos.js b/src/scenes/DAEItem/Infos.js
index 7ef9ea5..6d6ae23 100644
--- a/src/scenes/DAEItem/Infos.js
+++ b/src/scenes/DAEItem/Infos.js
@@ -1,11 +1,18 @@
-import React, { useCallback } from "react";
-import { View, ScrollView, StyleSheet } from "react-native";
-import { Button } from "react-native-paper";
+import React, { useCallback, useEffect, useMemo, useState } from "react";
+import {
+ View,
+ ScrollView,
+ StyleSheet,
+ TouchableOpacity,
+ Platform,
+} from "react-native";
+import { Button, Modal, Portal } from "react-native-paper";
import { MaterialCommunityIcons } from "@expo/vector-icons";
import { useNavigation } from "@react-navigation/native";
+import { getApps, showLocation } from "react-native-map-link";
import Text from "~/components/Text";
-import { createStyles, useTheme } from "~/theme";
+import { useTheme } from "~/theme";
import { useDefibsState } from "~/stores";
import { getDefibAvailability } from "~/utils/dae/getDefibAvailability";
@@ -195,6 +202,15 @@ export default React.memo(function DAEItemInfos() {
const { colors } = useTheme();
const navigation = useNavigation();
const { selectedDefib: defib } = useDefibsState(["selectedDefib"]);
+ const [navModalVisible, setNavModalVisible] = useState(false);
+ const [availableApps, setAvailableApps] = useState([]);
+
+ useEffect(() => {
+ (async () => {
+ const result = await getApps({ alwaysIncludeGoogle: true });
+ setAvailableApps(result);
+ })();
+ }, []);
const { status, label: availabilityLabel } = getDefibAvailability(
defib?.horaires_std,
@@ -203,9 +219,82 @@ export default React.memo(function DAEItemInfos() {
const statusColor = STATUS_COLORS[status];
+ const openNavModal = useCallback(() => {
+ setNavModalVisible(true);
+ }, []);
+
+ const closeNavModal = useCallback(() => {
+ setNavModalVisible(false);
+ }, []);
+
const goToCarte = useCallback(() => {
+ closeNavModal();
navigation.navigate("DAEItemCarte");
- }, [navigation]);
+ }, [navigation, closeNavModal]);
+
+ const openExternalApp = useCallback(
+ (app) => {
+ closeNavModal();
+ if (defib?.latitude && defib?.longitude) {
+ showLocation({
+ latitude: defib.latitude,
+ longitude: defib.longitude,
+ app: app.id,
+ naverCallerName:
+ Platform.OS === "ios"
+ ? "com.alertesecours.alertesecours"
+ : "com.alertesecours",
+ });
+ }
+ },
+ [defib, closeNavModal],
+ );
+
+ const modalStyles = useMemo(
+ () => ({
+ container: {
+ backgroundColor: colors.surface,
+ marginHorizontal: 24,
+ borderRadius: 16,
+ paddingVertical: 16,
+ },
+ title: {
+ fontSize: 18,
+ fontWeight: "700",
+ textAlign: "center",
+ paddingHorizontal: 16,
+ paddingBottom: 12,
+ },
+ subtitle: {
+ fontSize: 14,
+ color: colors.onSurfaceVariant || colors.grey,
+ textAlign: "center",
+ paddingHorizontal: 16,
+ paddingBottom: 12,
+ },
+ option: {
+ flexDirection: "row",
+ alignItems: "center",
+ paddingVertical: 14,
+ paddingHorizontal: 20,
+ },
+ optionText: {
+ fontSize: 16,
+ marginLeft: 16,
+ flex: 1,
+ },
+ separator: {
+ height: StyleSheet.hairlineWidth,
+ backgroundColor: colors.outlineVariant || colors.grey,
+ marginHorizontal: 16,
+ },
+ cancelButton: {
+ marginTop: 8,
+ marginHorizontal: 16,
+ },
+ }),
+ [colors],
+ );
if (!defib) return null;
@@ -262,7 +351,7 @@ export default React.memo(function DAEItemInfos() {
+
+ {/* Navigation app chooser modal */}
+
+
+ Itinéraire
+
+ Quelle application souhaitez-vous utiliser ?
+
+
+ {/* In-app navigation option */}
+
+
+
+ Naviguer dans l'application
+
+
+
+ {/* External navigation apps */}
+ {availableApps.map((app) => (
+
+
+ openExternalApp(app)}
+ style={modalStyles.option}
+ activeOpacity={0.6}
+ >
+
+ {app.name}
+
+
+ ))}
+
+
+
+
);
});