const handleCancel = () => {
setAddHouseModalVisible(false);
setIsFullForm(false); // Réinitialiser l'état pour afficher le petit formulaire par défaut
};
const resetFormFields = () => {
setNewAddress('');
setFloor(undefined);
setSurface(undefined);
setHouseType('');
setSide(undefined);
setMainStreet('');
setRating(0);
setComment('');
setNewPhotos([]);
setSuggestions([]);
setExistingApartmentSelected(false);
setHousingType(undefined);
};
// Fonction pour mettre à jour l'adresse et obtenir des suggestions
const handleAddressChange = (address: string) => {
setNewAddress(address);
// Clear previous timeout to reset the debounce delay
if (debounceTimeoutRef.current) {
clearTimeout(debounceTimeoutRef.current);
}
// If the input is too short, clear the suggestions and return
if (address.length < 3) {
setSuggestions([]);
return;
}
// Set the debounce timeout to trigger API after 5 seconds of inactivity
debounceTimeoutRef.current = setTimeout(async () => {
setLoadingSuggestions(true);
try {
const response = await axios.get('https://us1.locationiq.com/v1/search.php', {
params: {
key: 'pk.d479d2963139d82080bb400f75d95123',
q: address,
format: 'json',
addressdetails: 1,
limit: 5,
},
});
const filteredSuggestions = response.data.slice(0, 2); // Display only top 2 suggestions
setSuggestions(filteredSuggestions);
} catch (error) {
console.error('Error retrieving address suggestions:', error);
Alert.alert('Error', 'Unable to retrieve address suggestions.');
} finally {
setLoadingSuggestions(false);
}
}, 1500); // The debounce delay starts after typing stops
// Obtenir le nom de fichier à partir de l'URI de l'image
const fileName = imageUri.substring(imageUri.lastIndexOf('/') + 1);
// Référence de l'image dans Firebase Storage
const reference = ref(storage, images/${fileName});
// Adapter l'URI pour iOS si nécessaire
const uploadUri = Platform.OS === 'ios' ? imageUri.replace('file://', '') : imageUri;
try {
// Lire le fichier comme un blob (car uploadBytesResumable ne prend pas directement des URI)
const response = await fetch(uploadUri);
const blob = await response.blob();
// Commencer le téléchargement avec Firebase Storage
const task = uploadBytesResumable(reference, blob);
// Suivre la progression du téléchargement
task.on('state_changed', (snapshot) => {
console.log(`${snapshot.bytesTransferred} bytes transferred out of ${snapshot.totalBytes}`);
});
// Attendre la fin du téléchargement
await task;
// Obtenir l'URL de téléchargement de l'image
const downloadUrl = await getDownloadURL(reference);
console.log('Image successfully uploaded: ', downloadUrl);
return downloadUrl;
// Fonction pour ajouter ou mettre à jour un logement avec la note et le commentaire
const normalizeCoordinate = (coord: number, precision: number = 6) => {
return parseFloat(coord.toFixed(precision));
};
const data = response.data[0];
if (data) {
const latitude = normalizeCoordinate(parseFloat(data.lat));
const longitude = normalizeCoordinate(parseFloat(data.lon));
console.log('Address found:', { latitude, longitude });
const existingHouse = await findExistingHouse(latitude, longitude);
let filteredApartments: any[] = [];
if (existingHouse && !existingApartmentSelected) {
console.log('Existing house found:', existingHouse);
let existingApartments = existingHouse.apartments;
if (housingType === 'appartement') {
existingApartments = existingApartments.filter(apartment =>
apartment.ratings.some(rating => rating.floor === floor)
);
}
filteredApartments = existingApartments.filter(apartment =>
apartment.ratings.some(rating => rating.floor === floor)
);
console.log('Filtered apartments:', filteredApartments);
}
Alert.alert(
'Votre logement est-il présent parmi ces résultats?',
'Veuillez choisir un appartement existant ou ajouter un nouveau logement.',
[
...filteredApartments.map(apartment => ({
text: `${apartment.surface} m², ${apartment.houseType}, côté ${apartment.side}, rue ${apartment.mainStreet}`,
onPress: () => {
console.log('User selected existing apartment:', apartment);
setSurface(apartment.surface);
setHouseType(apartment.houseType);
setSide(apartment.side);
setMainStreet(apartment.mainStreet || '');
setFloor(apartment.ratings.find((rating: { floor: any; }) => rating.floor)?.floor);
setExistingApartmentSelected(true);
setIsFullForm(true);
setAddHouseModalVisible(true);
console.log('Full form state set for existing apartment:', { isFullForm: true, addHouseModalVisible: true });
},
})),
{
text: 'Ajouter un nouveau logement',
onPress: () => {
console.log('User chose to add a new apartment.');
resetFormFields();
setNewAddress(newAddress);
setFloor(floor);
setHousingType('appartement');
setIsFullForm(true);
setExistingApartmentSelected(false);
setAddHouseModalVisible(true);
console.log('Full form state set for new apartment:', { isFullForm: true, addHouseModalVisible: true });
},
style: 'cancel',
},
],
{ cancelable: false }
);
setLoading(false);
} else {
Alert.alert('Erreur', 'Adresse non trouvée.');
setLoading(false);
}
} catch (error) {
console.error('Erreur lors de la vérification des logements existants:', error);
Alert.alert('Erreur', 'Erreur lors de la vérification des logements existants.');
setLoading(false);
}
};
const proceedWithNoteValidation = async (badgeLevel: number) => {
try {
setLoading(true);
console.log('Loading state:', loading); // Ajoutez cette ligne pour vérifier l'état loading
// Request and update geolocation
const location = await requestAndUpdateGeolocation();
const response = await axios.get('https://us1.locationiq.com/v1/search.php', {
params: {
key: 'pk.d479d2963139d82080bb400f75d95123',
q: newAddress,
format: 'json',
addressdetails: 1,
limit: 1,
},
});
const data = response.data[0];
if (data) {
const latitude = normalizeCoordinate(parseFloat(data.lat));
const longitude = normalizeCoordinate(parseFloat(data.lon));
const areaType = await getAreaType(latitude, longitude);
const tolerance = areaType === 'urban' ? 30 : 100;
let updatedBadgeLevel = badgeLevel;
if (location) {
const distance = getDistance(
{ latitude, longitude },
{ latitude: location.coords.latitude, longitude: location.coords.longitude }
);
if (distance <= tolerance) {
updatedBadgeLevel = 1; // Update badge level to 1 if within tolerance
} else {
Alert.alert('Erreur', `La position géolocalisée est trop éloignée de l'adresse saisie. Tolérance: ${tolerance} mètres.`);
setLoading(false);
return;
}
} else {
// Geolocation is not available, prompt the user
Alert.alert(
'Géolocalisation désactivée',
'La géolocalisation est désactivée. Voulez-vous quand même déposer la note ? La crédibilité de votre note sera faible voire nulle.',
[
{
text: 'Non',
onPress: () => {
setLoading(false); // Stop loading if the user chooses not to proceed
},
style: 'cancel',
},
{
text: 'Oui',
onPress: () => {
setLoading(true);
// Proceed with submission despite low credibility
submitNoteWithoutGeolocation(latitude, longitude, badgeLevel);
},
},
],
{ cancelable: false }
);
return;
}
const existingHouse = await findExistingHouse(latitude, longitude);
const uploadedPhotoUrls = await Promise.all(newPhotos.map(photoUri => uploadImage(photoUri)));
const validUploadedPhotoUrls = uploadedPhotoUrls.filter(url => url !== null);
if (existingHouse) {
if (!user) {
throw new Error('User must be logged in to add a rating.');
}
let apartment;
if (housingType === 'appartement') {
if (!surface || !side || !floor) {
throw new Error('Surface, side, and floor must be defined to create a new apartment.');
}
apartment = existingHouse.apartments.find(apartment =>
apartment.surface === surface &&
apartment.side === side &&
apartment.houseType === houseType &&
apartment.mainStreet === mainStreet &&
apartment.ratings.some(rating => rating.floor === floor)
);
if (!apartment) {
apartment = {
surface: surface ?? 0,
side,
houseType,
mainStreet,
ratings: []
};
existingHouse.apartments.push(apartment);
}
} else {
apartment = existingHouse.apartments[0] || {
surface: surface ?? 0,
side: 'n/a',
houseType: 'maison',
mainStreet,
ratings: []
};
if (!existingHouse.apartments.length) {
existingHouse.apartments.push(apartment);
}
}
apartment.ratings.push({
userId: user.uid,
rating,
comment,
floor: housingType === 'appartement' ? (floor ?? 0) : 0,
photos: validUploadedPhotoUrls,
badgeLevel: updatedBadgeLevel
});
const averageRating = calculateAverageRating(
existingHouse.apartments.flatMap(apartment => apartment.ratings)
);
const updatedHouse: Partial<House> = {
apartments: existingHouse.apartments,
title: `${averageRating.toFixed(1)}`,
};
await setDoc(doc(db, 'houses', existingHouse.id), updatedHouse, { merge: true });
Alert.alert('Succès', 'Logement mis à jour avec succès.');
} else {
if (!user) {
throw new Error('User must be logged in to add a rating.');
}
let newApartment: Apartment;
if (housingType === 'appartement') {
if (!surface || !side || !floor) {
throw new Error('Surface, side, and floor must be defined to create a new apartment.');
}
newApartment =import React, { useState, useEffect, useRef } from 'react';
import { View, Text, Button, StyleSheet, Modal, TextInput, TouchableOpacity, Alert, ScrollView, FlatList, Image, ActivityIndicator, Switch } from 'react-native';
import MapView, { Marker } from 'react-native-maps';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { collection, onSnapshot, doc, getDoc, setDoc, addDoc, query, where, getDocs } from 'firebase/firestore';
import { onAuthStateChanged, createUserWithEmailAndPassword, signInWithEmailAndPassword, UserCredential } from 'firebase/auth';
import { ref, uploadBytesResumable, getDownloadURL } from 'firebase/storage';
import axios from 'axios';
import as Location from 'expo-location';
import as ImagePicker from 'expo-image-picker';
import WelcomeScreen from './WelcomeScreen'; // Import the WelcomeScreen component
const handleCancel = () => {
setAddHouseModalVisible(false);
setIsFullForm(false); // Réinitialiser l'état pour afficher le petit formulaire par défaut
};
const resetFormFields = () => {
setNewAddress('');
setFloor(undefined);
setSurface(undefined);
setHouseType('');
setSide(undefined);
setMainStreet('');
setRating(0);
setComment('');
setNewPhotos([]);
setSuggestions([]);
setExistingApartmentSelected(false);
setHousingType(undefined);
};
// Fonction pour mettre à jour l'adresse et obtenir des suggestions
const handleAddressChange = (address: string) => {
setNewAddress(address);
// Clear previous timeout to reset the debounce delay
if (debounceTimeoutRef.current) {
clearTimeout(debounceTimeoutRef.current);
}
// If the input is too short, clear the suggestions and return
if (address.length < 3) {
setSuggestions([]);
return;
}
// Set the debounce timeout to trigger API after 5 seconds of inactivity
debounceTimeoutRef.current = setTimeout(async () => {
setLoadingSuggestions(true);
try {
const response = await axios.get('https://us1.locationiq.com/v1/search.php', {
params: {
key: 'pk.d479d2963139d82080bb400f75d95123',
q: address,
format: 'json',
addressdetails: 1,
limit: 5,
},
});
const filteredSuggestions = response.data.slice(0, 2); // Display only top 2 suggestions
setSuggestions(filteredSuggestions);
} catch (error) {
console.error('Error retrieving address suggestions:', error);
Alert.alert('Error', 'Unable to retrieve address suggestions.');
} finally {
setLoadingSuggestions(false);
}
}, 1500); // The debounce delay starts after typing stops
// Obtenir le nom de fichier à partir de l'URI de l'image
const fileName = imageUri.substring(imageUri.lastIndexOf('/') + 1);
// Référence de l'image dans Firebase Storage
const reference = ref(storage, images/${fileName});
// Adapter l'URI pour iOS si nécessaire
const uploadUri = Platform.OS === 'ios' ? imageUri.replace('file://', '') : imageUri;
try {
// Lire le fichier comme un blob (car uploadBytesResumable ne prend pas directement des URI)
const response = await fetch(uploadUri);
const blob = await response.blob();
// Commencer le téléchargement avec Firebase Storage
const task = uploadBytesResumable(reference, blob);
// Suivre la progression du téléchargement
task.on('state_changed', (snapshot) => {
console.log(`${snapshot.bytesTransferred} bytes transferred out of ${snapshot.totalBytes}`);
});
// Attendre la fin du téléchargement
await task;
// Obtenir l'URL de téléchargement de l'image
const downloadUrl = await getDownloadURL(reference);
console.log('Image successfully uploaded: ', downloadUrl);
return downloadUrl;
// Fonction pour ajouter ou mettre à jour un logement avec la note et le commentaire
const normalizeCoordinate = (coord: number, precision: number = 6) => {
return parseFloat(coord.toFixed(precision));
};
const data = response.data[0];
if (data) {
const latitude = normalizeCoordinate(parseFloat(data.lat));
const longitude = normalizeCoordinate(parseFloat(data.lon));
console.log('Address found:', { latitude, longitude });
const existingHouse = await findExistingHouse(latitude, longitude);
let filteredApartments: any[] = [];
if (existingHouse && !existingApartmentSelected) {
console.log('Existing house found:', existingHouse);
let existingApartments = existingHouse.apartments;
if (housingType === 'appartement') {
existingApartments = existingApartments.filter(apartment =>
apartment.ratings.some(rating => rating.floor === floor)
);
}
filteredApartments = existingApartments.filter(apartment =>
apartment.ratings.some(rating => rating.floor === floor)
);
console.log('Filtered apartments:', filteredApartments);
}
Alert.alert(
'Votre logement est-il présent parmi ces résultats?',
'Veuillez choisir un appartement existant ou ajouter un nouveau logement.',
[
...filteredApartments.map(apartment => ({
text: `${apartment.surface} m², ${apartment.houseType}, côté ${apartment.side}, rue ${apartment.mainStreet}`,
onPress: () => {
console.log('User selected existing apartment:', apartment);
setSurface(apartment.surface);
setHouseType(apartment.houseType);
setSide(apartment.side);
setMainStreet(apartment.mainStreet || '');
setFloor(apartment.ratings.find((rating: { floor: any; }) => rating.floor)?.floor);
setExistingApartmentSelected(true);
setIsFullForm(true);
setAddHouseModalVisible(true);
console.log('Full form state set for existing apartment:', { isFullForm: true, addHouseModalVisible: true });
},
})),
{
text: 'Ajouter un nouveau logement',
onPress: () => {
console.log('User chose to add a new apartment.');
resetFormFields();
setNewAddress(newAddress);
setFloor(floor);
setHousingType('appartement');
setIsFullForm(true);
setExistingApartmentSelected(false);
setAddHouseModalVisible(true);
console.log('Full form state set for new apartment:', { isFullForm: true, addHouseModalVisible: true });
},
style: 'cancel',
},
],
{ cancelable: false }
);
setLoading(false);
} else {
Alert.alert('Erreur', 'Adresse non trouvée.');
setLoading(false);
}
} catch (error) {
console.error('Erreur lors de la vérification des logements existants:', error);
Alert.alert('Erreur', 'Erreur lors de la vérification des logements existants.');
setLoading(false);
}
};
const proceedWithNoteValidation = async (badgeLevel: number) => {
try {
setLoading(true);
console.log('Loading state:', loading); // Ajoutez cette ligne pour vérifier l'état loading
// Request and update geolocation
const location = await requestAndUpdateGeolocation();
const response = await axios.get('https://us1.locationiq.com/v1/search.php', {
params: {
key: 'pk.d479d2963139d82080bb400f75d95123',
q: newAddress,
format: 'json',
addressdetails: 1,
limit: 1,
},
});
const data = response.data[0];
if (data) {
const latitude = normalizeCoordinate(parseFloat(data.lat));
const longitude = normalizeCoordinate(parseFloat(data.lon));
const areaType = await getAreaType(latitude, longitude);
const tolerance = areaType === 'urban' ? 30 : 100;
let updatedBadgeLevel = badgeLevel;
if (location) {
const distance = getDistance(
{ latitude, longitude },
{ latitude: location.coords.latitude, longitude: location.coords.longitude }
);
if (distance <= tolerance) {
updatedBadgeLevel = 1; // Update badge level to 1 if within tolerance
} else {
Alert.alert('Erreur', `La position géolocalisée est trop éloignée de l'adresse saisie. Tolérance: ${tolerance} mètres.`);
setLoading(false);
return;
}
} else {
// Geolocation is not available, prompt the user
Alert.alert(
'Géolocalisation désactivée',
'La géolocalisation est désactivée. Voulez-vous quand même déposer la note ? La crédibilité de votre note sera faible voire nulle.',
[
{
text: 'Non',
onPress: () => {
setLoading(false); // Stop loading if the user chooses not to proceed
},
style: 'cancel',
},
{
text: 'Oui',
onPress: () => {
setLoading(true);
// Proceed with submission despite low credibility
submitNoteWithoutGeolocation(latitude, longitude, badgeLevel);
},
},
],
{ cancelable: false }
);
return;
}
const existingHouse = await findExistingHouse(latitude, longitude);
const uploadedPhotoUrls = await Promise.all(newPhotos.map(photoUri => uploadImage(photoUri)));
const validUploadedPhotoUrls = uploadedPhotoUrls.filter(url => url !== null);
if (existingHouse) {
if (!user) {
throw new Error('User must be logged in to add a rating.');
}
let apartment;
if (housingType === 'appartement') {
if (!surface || !side || !floor) {
throw new Error('Surface, side, and floor must be defined to create a new apartment.');
}
apartment = existingHouse.apartments.find(apartment =>
apartment.surface === surface &&
apartment.side === side &&
apartment.houseType === houseType &&
apartment.mainStreet === mainStreet &&
apartment.ratings.some(rating => rating.floor === floor)
);
if (!apartment) {
apartment = {
surface: surface ?? 0,
side,
houseType,
mainStreet,
ratings: []
};
existingHouse.apartments.push(apartment);
}
} else {
apartment = existingHouse.apartments[0] || {
surface: surface ?? 0,
side: 'n/a',
houseType: 'maison',
mainStreet,
ratings: []
};
if (!existingHouse.apartments.length) {
existingHouse.apartments.push(apartment);
}
}
apartment.ratings.push({
userId: user.uid,
rating,
comment,
floor: housingType === 'appartement' ? (floor ?? 0) : 0,
photos: validUploadedPhotoUrls,
badgeLevel: updatedBadgeLevel
});
const averageRating = calculateAverageRating(
existingHouse.apartments.flatMap(apartment => apartment.ratings)
);
const updatedHouse: Partial<House> = {
apartments: existingHouse.apartments,
title: `${averageRating.toFixed(1)}`,
};
await setDoc(doc(db, 'houses', existingHouse.id), updatedHouse, { merge: true });
Alert.alert('Succès', 'Logement mis à jour avec succès.');
} else {
if (!user) {
throw new Error('User must be logged in to add a rating.');
}
let newApartment: Apartment;
if (housingType === 'appartement') {
if (!surface || !side || !floor) {
throw new Error('Surface, side, and floor must be defined to create a new apartment.');
}
newApartment =/// it repeat the import phase, then it never end
Extension version: 0.22.2
VS Code version: Code 1.95.2 (e8653663e8840adaf45af01eab5c627a5af81807, 2024-11-07T11:07:22.054Z)
OS version: Windows_NT x64 10.0.19045
Modes:
Type: Bug
import React, { useState, useEffect, useRef } from 'react'; import { View, Text, Button, StyleSheet, Modal, TextInput, TouchableOpacity, Alert, ScrollView, FlatList, Image, ActivityIndicator, Switch } from 'react-native'; import MapView, { Marker } from 'react-native-maps'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; import { collection, onSnapshot, doc, getDoc, setDoc, addDoc, query, where, getDocs } from 'firebase/firestore'; import { onAuthStateChanged, createUserWithEmailAndPassword, signInWithEmailAndPassword, UserCredential } from 'firebase/auth'; import { ref, uploadBytesResumable, getDownloadURL } from 'firebase/storage'; import axios from 'axios'; import as Location from 'expo-location'; import as ImagePicker from 'expo-image-picker'; import WelcomeScreen from './WelcomeScreen'; // Import the WelcomeScreen component
export default function HomeScreen() { const [showWelcomeScreen, setShowWelcomeScreen] = useState(true); // State to manage the welcome screen const [selectedHouse, setSelectedHouse] = useState<House | null>(null); const [rating, setRating] = useState(0);
const [comment, setComment] = useState('');
const [addHouseModalVisible, setAddHouseModalVisible] = useState(false);
const [newAddress, setNewAddress] = useState('');
const [floor, setFloor] = useState<number | undefined>(undefined);
const [newPhotos, setNewPhotos] = useState<string[]>([]);
const [houses, setHouses] = useState<House[]>([]);
const [suggestions, setSuggestions] = useState<any[]>([]);
const [user, setUser] = useState<User | null>(null);
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [showLogin, setShowLogin] = useState(false);
const [loadingSuggestions, setLoadingSuggestions] = useState(false);
const [streetName, setStreetName] = useState('');
const [doorNumber, setDoorNumber] = useState('');
const [surface, setSurface] = useState<number | undefined>(undefined);
const [houseType, setHouseType] = useState('');
const [side, setSide] = useState<'rue' | 'cour' | 'rue+cour' | undefined>(undefined);
const [mainStreet, setMainStreet] = useState('');
const [isMultipleStreets, setIsMultipleStreets] = useState(false);
const [isChecked, setIsChecked] = useState(false);
const [loading, setLoading] = useState(false);
const [housingType, setHousingType] = useState<'maison' | 'appartement' | undefined>(undefined);
const [existingApartmentSelected, setExistingApartmentSelected] = useState(false);
const debounceTimeoutRef = useRef<NodeJS.Timeout | null>(null); // Updated typing
const [translateY] = useState(new Animated.Value(0));
const [modalVisible, setModalVisible] = useState(false);
const [isFullForm, setIsFullForm] = useState(false);
const [showVerificationMessage, setShowVerificationMessage] = useState(true); // New state variable
// Charger les logements depuis Firestore en temps réel useEffect(() => { const housesCollection = collection(db, 'houses');
}, []);
// Surveiller l'état d'authentification et récupérer les données utilisateur useEffect(() => { const unsubscribeAuth = onAuthStateChanged(auth, async (authUser) => { if (authUser) { const uid = authUser.uid; const userDoc = await getDoc(doc(db, 'users', uid)); if (userDoc.exists()) { const userData = userDoc.data(); const currentUser: User = { uid: uid, email: userData.email || '', proofOfResidence: userData.proofOfResidence, }; setUser(currentUser); } else { // Si le document utilisateur n'existe pas, créez-le const newUser: User = { uid: uid, email: authUser.email || '', }; setUser(newUser); await setDoc(doc(db, 'users', uid), { email: newUser.email, }); } } else { setUser(null); } });
}, []);
const handleCancel = () => { setAddHouseModalVisible(false); setIsFullForm(false); // Réinitialiser l'état pour afficher le petit formulaire par défaut };
const resetFormFields = () => { setNewAddress(''); setFloor(undefined); setSurface(undefined); setHouseType(''); setSide(undefined); setMainStreet(''); setRating(0); setComment(''); setNewPhotos([]); setSuggestions([]); setExistingApartmentSelected(false); setHousingType(undefined); }; // Fonction pour mettre à jour l'adresse et obtenir des suggestions const handleAddressChange = (address: string) => { setNewAddress(address);
};
const uploadImage = async (imageUri: string) => { if (!imageUri) return null;
// Obtenir le nom de fichier à partir de l'URI de l'image const fileName = imageUri.substring(imageUri.lastIndexOf('/') + 1);
// Référence de l'image dans Firebase Storage const reference = ref(storage,
images/${fileName}
);// Adapter l'URI pour iOS si nécessaire const uploadUri = Platform.OS === 'ios' ? imageUri.replace('file://', '') : imageUri;
try { // Lire le fichier comme un blob (car
uploadBytesResumable
ne prend pas directement des URI) const response = await fetch(uploadUri); const blob = await response.blob();} catch (error) { console.error('Error uploading image: ', error); return null; } };
// Fonction pour ajouter ou mettre à jour un logement avec la note et le commentaire const normalizeCoordinate = (coord: number, precision: number = 6) => { return parseFloat(coord.toFixed(precision)); };
const findExistingHouse = async (latitude: number, longitude: number) => { const normalizedLatitude = normalizeCoordinate(latitude); const normalizedLongitude = normalizeCoordinate(longitude);
const q = query( collection(db, 'houses'), where('latitude', '==', normalizedLatitude), where('longitude', '==', normalizedLongitude) ); const querySnapshot = await getDocs(q); if (!querySnapshot.empty) { const doc = querySnapshot.docs[0]; return { id: doc.id, ...doc.data() } as House; } return null; };
const addOrUpdateMarker = async () => { if (!newAddress || !user || (housingType === 'appartement' && !floor)) { Alert.alert('Veuillez remplir tous les champs et être connecté.'); return; }
try { setLoading(true); console.log('Fetching address details...'); const response = await axios.get('https://us1.locationiq.com/v1/search.php', { params: { key: 'pk.d479d2963139d82080bb400f75d95123', q: newAddress, format: 'json', addressdetails: 1, limit: 1, }, });
} catch (error) { console.error('Erreur lors de la vérification des logements existants:', error); Alert.alert('Erreur', 'Erreur lors de la vérification des logements existants.'); setLoading(false); } };
const proceedWithNoteValidation = async (badgeLevel: number) => { try { setLoading(true); console.log('Loading state:', loading); // Ajoutez cette ligne pour vérifier l'état loading // Request and update geolocation const location = await requestAndUpdateGeolocation();
import { View, Text, Button, StyleSheet, Modal, TextInput, TouchableOpacity, Alert, ScrollView, FlatList, Image, ActivityIndicator, Switch } from 'react-native'; import MapView, { Marker } from 'react-native-maps'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; import { collection, onSnapshot, doc, getDoc, setDoc, addDoc, query, where, getDocs } from 'firebase/firestore'; import { onAuthStateChanged, createUserWithEmailAndPassword, signInWithEmailAndPassword, UserCredential } from 'firebase/auth'; import { ref, uploadBytesResumable, getDownloadURL } from 'firebase/storage'; import axios from 'axios'; import as Location from 'expo-location'; import as ImagePicker from 'expo-image-picker'; import WelcomeScreen from './WelcomeScreen'; // Import the WelcomeScreen component
export default function HomeScreen() { const [showWelcomeScreen, setShowWelcomeScreen] = useState(true); // State to manage the welcome screen const [selectedHouse, setSelectedHouse] = useState<House | null>(null); const [rating, setRating] = useState(0);
const [comment, setComment] = useState('');
const [addHouseModalVisible, setAddHouseModalVisible] = useState(false);
const [newAddress, setNewAddress] = useState('');
const [floor, setFloor] = useState<number | undefined>(undefined);
const [newPhotos, setNewPhotos] = useState<string[]>([]);
const [houses, setHouses] = useState<House[]>([]);
const [suggestions, setSuggestions] = useState<any[]>([]);
const [user, setUser] = useState<User | null>(null);
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [showLogin, setShowLogin] = useState(false);
const [loadingSuggestions, setLoadingSuggestions] = useState(false);
const [streetName, setStreetName] = useState('');
const [doorNumber, setDoorNumber] = useState('');
const [surface, setSurface] = useState<number | undefined>(undefined);
const [houseType, setHouseType] = useState('');
const [side, setSide] = useState<'rue' | 'cour' | 'rue+cour' | undefined>(undefined);
const [mainStreet, setMainStreet] = useState('');
const [isMultipleStreets, setIsMultipleStreets] = useState(false);
const [isChecked, setIsChecked] = useState(false);
const [loading, setLoading] = useState(false);
const [housingType, setHousingType] = useState<'maison' | 'appartement' | undefined>(undefined);
const [existingApartmentSelected, setExistingApartmentSelected] = useState(false);
const debounceTimeoutRef = useRef<NodeJS.Timeout | null>(null); // Updated typing
const [translateY] = useState(new Animated.Value(0));
const [modalVisible, setModalVisible] = useState(false);
const [isFullForm, setIsFullForm] = useState(false);
const [showVerificationMessage, setShowVerificationMessage] = useState(true); // New state variable
// Charger les logements depuis Firestore en temps réel useEffect(() => { const housesCollection = collection(db, 'houses');
}, []);
// Surveiller l'état d'authentification et récupérer les données utilisateur useEffect(() => { const unsubscribeAuth = onAuthStateChanged(auth, async (authUser) => { if (authUser) { const uid = authUser.uid; const userDoc = await getDoc(doc(db, 'users', uid)); if (userDoc.exists()) { const userData = userDoc.data(); const currentUser: User = { uid: uid, email: userData.email || '', proofOfResidence: userData.proofOfResidence, }; setUser(currentUser); } else { // Si le document utilisateur n'existe pas, créez-le const newUser: User = { uid: uid, email: authUser.email || '', }; setUser(newUser); await setDoc(doc(db, 'users', uid), { email: newUser.email, }); } } else { setUser(null); } });
}, []);
const handleCancel = () => { setAddHouseModalVisible(false); setIsFullForm(false); // Réinitialiser l'état pour afficher le petit formulaire par défaut };
const resetFormFields = () => { setNewAddress(''); setFloor(undefined); setSurface(undefined); setHouseType(''); setSide(undefined); setMainStreet(''); setRating(0); setComment(''); setNewPhotos([]); setSuggestions([]); setExistingApartmentSelected(false); setHousingType(undefined); }; // Fonction pour mettre à jour l'adresse et obtenir des suggestions const handleAddressChange = (address: string) => { setNewAddress(address);
};
const uploadImage = async (imageUri: string) => { if (!imageUri) return null;
// Obtenir le nom de fichier à partir de l'URI de l'image const fileName = imageUri.substring(imageUri.lastIndexOf('/') + 1);
// Référence de l'image dans Firebase Storage const reference = ref(storage,
images/${fileName}
);// Adapter l'URI pour iOS si nécessaire const uploadUri = Platform.OS === 'ios' ? imageUri.replace('file://', '') : imageUri;
try { // Lire le fichier comme un blob (car
uploadBytesResumable
ne prend pas directement des URI) const response = await fetch(uploadUri); const blob = await response.blob();} catch (error) { console.error('Error uploading image: ', error); return null; } };
// Fonction pour ajouter ou mettre à jour un logement avec la note et le commentaire const normalizeCoordinate = (coord: number, precision: number = 6) => { return parseFloat(coord.toFixed(precision)); };
const findExistingHouse = async (latitude: number, longitude: number) => { const normalizedLatitude = normalizeCoordinate(latitude); const normalizedLongitude = normalizeCoordinate(longitude);
const q = query( collection(db, 'houses'), where('latitude', '==', normalizedLatitude), where('longitude', '==', normalizedLongitude) ); const querySnapshot = await getDocs(q); if (!querySnapshot.empty) { const doc = querySnapshot.docs[0]; return { id: doc.id, ...doc.data() } as House; } return null; };
const addOrUpdateMarker = async () => { if (!newAddress || !user || (housingType === 'appartement' && !floor)) { Alert.alert('Veuillez remplir tous les champs et être connecté.'); return; }
try { setLoading(true); console.log('Fetching address details...'); const response = await axios.get('https://us1.locationiq.com/v1/search.php', { params: { key: 'pk.d479d2963139d82080bb400f75d95123', q: newAddress, format: 'json', addressdetails: 1, limit: 1, }, });
} catch (error) { console.error('Erreur lors de la vérification des logements existants:', error); Alert.alert('Erreur', 'Erreur lors de la vérification des logements existants.'); setLoading(false); } };
const proceedWithNoteValidation = async (badgeLevel: number) => { try { setLoading(true); console.log('Loading state:', loading); // Ajoutez cette ligne pour vérifier l'état loading // Request and update geolocation const location = await requestAndUpdateGeolocation();
Extension version: 0.22.2 VS Code version: Code 1.95.2 (e8653663e8840adaf45af01eab5c627a5af81807, 2024-11-07T11:07:22.054Z) OS version: Windows_NT x64 10.0.19045 Modes:
System Info
|Item|Value| |---|---| |CPUs|Intel(R) Core(TM) i5-4310U CPU @ 2.00GHz (4 x 2594)| |GPU Status|2d_canvas: enabledcanvas_oop_rasterization: enabled_on
direct_rendering_display_compositor: disabled_off_ok
gpu_compositing: enabled
multiple_raster_threads: enabled_on
opengl: enabled_on
rasterization: enabled
raw_draw: disabled_off_ok
skia_graphite: disabled_off
video_decode: enabled
video_encode: enabled
vulkan: disabled_off
webgl: enabled
webgl2: enabled
webgpu: enabled
webnn: disabled_off| |Load (avg)|undefined| |Memory (System)|7.91GB (1.08GB free)| |Process Argv|--crash-reporter-id b311a59f-9ff9-42ed-9c6a-2f202d0ce574| |Screen Reader|no| |VM|0%|
A/B Experiments
``` vsliv368cf:30146710 vspor879:30202332 vspor708:30202333 vspor363:30204092 vscod805:30301674 binariesv615:30325510 vsaa593cf:30376535 py29gd2263:31024239 c4g48928:30535728 azure-dev_surveyone:30548225 962ge761:30959799 pythongtdpath:30769146 pythonnoceb:30805159 asynctok:30898717 pythonmypyd1:30879173 2e7ec940:31000449 pythontbext0:30879054 cppperfnew:31000557 dsvsc020:30976470 pythonait:31006305 dsvsc021:30996838 f3je6385:31013174 dvdeprecation:31068756 dwnewjupytercf:31046870 newcmakeconfigv2:31071590 impr_priority:31102340 nativerepl2:31139839 refactort:31108082 pythonrstrctxt:31112756 cf971741:31144450 iacca1:31171482 notype1:31157159 5fd0e150:31155592 dwcopilot:31170013 ```