diff --git a/README.md b/README.md index b88f3c3..552565d 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ npx expo install react-native-maps@1.9.0 npm install react-native-maps @react-navigation/native @react-navigation/bottom-tabs react-native-safe-area-context react-native-screens firebase npm install @react-native-community/datetimepicker -npx expo install expo-image-picker +npx expo install expo-image-picker +npx expo install expo-location npx expo start \ No newline at end of file diff --git a/app/(tabs)/mapScreen.tsx b/app/(tabs)/mapScreen.tsx index a9a8f54..98bc626 100644 --- a/app/(tabs)/mapScreen.tsx +++ b/app/(tabs)/mapScreen.tsx @@ -1,11 +1,15 @@ // MapScreen.tsx import { ThemedMapView } from '@/components/theme/themed-mapview'; +import { ThemedText } from '@/components/theme/themed-text'; +import { ThemedButton } from '@/components/theme/themed-button'; import React, { useEffect, useState } from 'react'; import { StyleSheet, View, Dimensions, Image, Text } from 'react-native'; import MapView, { Marker, Callout, CalloutSubview, PROVIDER_DEFAULT } from 'react-native-maps'; import { db } from '../../firebase_config'; import { Chantier } from '@/class/class'; import { getChantiers } from '@/services/ressourcesService'; +import { useLocation } from '@/hooks/useLocation'; + const MapScreen = () => { @@ -20,21 +24,30 @@ const region = { const [chantiers, setMarkers] = useState([]); const [loading, setLoading] = useState(true); + const [refreshing, setRefreshing] = useState(false); - useEffect(() => { - async function loadData() { + + async function loadData() { try { + setRefreshing(true) const data = await getChantiers(); + console.log("Chantiers chargés:", data.length); + console.log("📍 Premier chantier:", data[-1]); + console.log("🗺️ Coordonnées:", data[-1]?.latitude, data[-1]?.longitude); setMarkers(data); } catch (error) { console.error("Erreur lors du chargement :", error); } finally { setLoading(false); + setRefreshing(false); } } + useEffect(() => { loadData(); }, []); + console.log("🔄 Render - Nombre de chantiers:", chantiers.length); + return ( {Array.isArray(chantiers) && chantiers.map(chantier => ( + ))} + loadData()} + disabled={refreshing} + > + Actualiser + ); }; @@ -64,6 +87,13 @@ const styles = StyleSheet.create({ width: Dimensions.get('window').width, height: Dimensions.get('window').height, }, + refreshButton: { + position: 'absolute', + top: 50, + right: 20, + padding: 15, + borderRadius: 8, + }, }); export default MapScreen; diff --git a/components/add/addChantier.tsx b/components/add/addChantier.tsx index 918e04c..24cafb8 100644 --- a/components/add/addChantier.tsx +++ b/components/add/addChantier.tsx @@ -20,6 +20,8 @@ import SelectRessource from '@/components/add/select/selectRessource'; import { db } from '@/firebase_config'; import { doc } from 'firebase/firestore'; +import { useLocation } from '@/hooks/useLocation'; + type RessourcesQte = [Ressources, number]; //Uniquement accessible par le RESPONSSABLE du chantier @@ -28,6 +30,7 @@ export default function AddChantier() { const { chantier, setChantier } = useChantier(); const { user, setUser } = useUser(); const { ressources, setRessources } = useRessources(); + const { geocodeAddress} = useLocation(); const [editMode,setEditMode] = useState(false); @@ -62,6 +65,16 @@ export default function AddChantier() { }; async function onConfirm(): Promise { if (!isValidChantier() || !chefChantier) return; + try { + setLoading(true); + const coords = await geocodeAddress(adresse); + + if (!coords) { + console.error("Impossible de géocoder l'adresse"); + alert("Adresse introuvable. Veuillez vérifier l'adresse."); + setLoading(false); + return; + } const chantierDate = new Date(date); chantierDate.setHours(morning ? 0 : 12, 0, 0, 0); //CREATE NEW TYPE CHANTIER FOR FIRESTORE @@ -80,8 +93,8 @@ export default function AddChantier() { anomalies: [], dateDep: chantierDate, tempsEst: parseInt(duree) || 1, - latitude: 0, //TODO - longitude: 0, //TODO + latitude: coords.latitude, //TODO + longitude: coords.longitude, //TODO }; const id = await addChantier(chantierFirestore as any); if (id) { @@ -95,7 +108,13 @@ export default function AddChantier() { } as Chantier); setOpenConfirmation(false); } - } + } catch (error) { + console.error("Erreur lors de la création du chantier:", error); + alert("Erreur lors de la création du chantier"); + } finally { + setLoading(false); + } +} function onCancel(): void { setOpenConfirmation(false); diff --git a/hooks/useLocation.tsx b/hooks/useLocation.tsx new file mode 100644 index 0000000..bbb288b --- /dev/null +++ b/hooks/useLocation.tsx @@ -0,0 +1,50 @@ +import { useState } from 'react'; +import * as Location from 'expo-location'; + + +export const useLocation = () => { + const [errorMsg, setErrorMsg] = useState(null); + const [latitude, setLatitude] = useState(null); + const [longitude, setLongitude] = useState(null); + const [loading, setLoading] = useState(false); + + + const geocodeAddress = async (address: string) => { + try { + setLoading(true); + setErrorMsg(null); + + const { status } = await Location.requestForegroundPermissionsAsync(); + + if (status !== 'granted') { + throw new Error('Permission localisation refusée'); + } + const result = await Location.geocodeAsync(address); + + if (!result || result.length === 0) { + throw new Error("Adresse introuvable"); + } + + const { latitude, longitude } = result[0]; + + setLatitude(latitude); + setLongitude(longitude); + + return { latitude, longitude }; + } catch (error: any) { + console.error(error); + setErrorMsg("Impossible de localiser cette adresse"); + return null; + } finally { + setLoading(false); + } + }; + + return { + latitude, + longitude, + errorMsg, + loading, + geocodeAddress, + }; +};