diff --git a/assets/js/add-lieu.js b/assets/js/add-lieu.js index d0a6a9a..2188c13 100644 --- a/assets/js/add-lieu.js +++ b/assets/js/add-lieu.js @@ -4,100 +4,62 @@ document.addEventListener("DOMContentLoaded", () => { const saveLieuButton = document.getElementById("save-lieu"); const lieuNomInput = document.getElementById("lieu-nom"); const lieuNomError = document.getElementById("lieu-nom-error"); - const villeSelect = document.getElementById("sortie_ville"); const lieuSelect = document.getElementById("sortie_lieu"); - let map, marker, selectedAddress, selectedRue, cityPolygon, cityBounds; + let map, marker, selectedAddress, selectedRue, selectedVille, selectedCodePostal; // Ouvrir la modal - document.getElementById("add-lieu-button").addEventListener("click", async () => { - const villeId = villeSelect.value; + document.getElementById("add-lieu-button").addEventListener("click", () => { + addLieuModal.classList.remove("hidden"); - if (!villeId) { - alert("Veuillez sélectionner une ville avant d'ajouter un lieu."); - return; + // Détruire la carte si elle existe déjà + if (map) { + map.remove(); + map = null; + marker = null; } - try { - // Récupérer les limites et le centre de la ville depuis le serveur - const response = await fetch(`/get-bounds/${villeId}`); - if (!response.ok) { - throw new Error("Erreur lors de la récupération des informations de la ville."); - } - const data = await response.json(); + // Initialiser la carte + map = L.map("map").setView([48.8566, 2.3522], 13); // Coordonnées par défaut (Paris) + L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { + maxZoom: 19, + minZoom: 13, + }).addTo(map); - addLieuModal.classList.remove("hidden"); + // Gérer les clics sur la carte + map.on("click", async (e) => { + const { lat, lng } = e.latlng; + selectedAddress = { lat, lng }; - // Détruire la carte si elle existe déjà - if (map) { - map.remove(); - map = null; - marker = null; + if (marker) { + marker.setLatLng([lat, lng]); + } else { + marker = L.marker([lat, lng]).addTo(map); } - // Initialiser la carte - map = L.map("map").setView([data.centerLat, data.centerLng], 13); - L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { - maxZoom: 19, - minZoom: 13, - }).addTo(map); + try { + // Utiliser l'API Nominatim pour récupérer les informations d'adresse + const response = await fetch( + `https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=${lat}&lon=${lng}` + ); + if (!response.ok) { + throw new Error("Erreur lors de la récupération des informations de l'adresse."); + } - cityBounds = L.latLngBounds( - [data.south, data.west], - [data.north, data.east] - ); + const data = await response.json(); + selectedRue = data.address.road || "Rue inconnue"; + selectedVille = data.address.city || data.address.town || data.address.village || "Ville inconnue"; + selectedCodePostal = data.address.postcode || "Code postal inconnu"; - map.fitBounds(cityBounds); - map.setMaxBounds(cityBounds); - - // Ajouter le polygone de la ville si disponible - if (data.polygon_geojson) { - cityPolygon = L.geoJSON(data.polygon_geojson, { - style: { - color: "blue", - weight: 2, - fillOpacity: 0.3, - }, - }).addTo(map); + console.log(`Rue: ${selectedRue}, Ville: ${selectedVille}, Code postal: ${selectedCodePostal}`); + } catch (error) { + console.error("Erreur lors de la recherche inversée :", error); + selectedRue = null; + selectedVille = null; + selectedCodePostal = null; + alert("Impossible de récupérer l'adresse à partir de ces coordonnées."); } - - // Gérer les clics sur la carte - map.on("click", async (e) => { - const { lat, lng } = e.latlng; - - if (!cityBounds.contains([lat, lng])) { - alert("Vous ne pouvez pas sélectionner un emplacement en dehors de la ville."); - return; - } - - selectedAddress = { lat, lng }; - - if (marker) { - marker.setLatLng([lat, lng]); - } else { - marker = L.marker([lat, lng]).addTo(map); - } - - try { - const response = await fetch( - `https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=${lat}&lon=${lng}` - ); - if (!response.ok) { - throw new Error("Erreur lors de la récupération des informations de l'adresse."); - } - - const data = await response.json(); - selectedRue = data.address.road || "Rue inconnue"; - } catch (error) { - console.error("Erreur lors de la recherche inversée :", error); - selectedRue = null; - alert("Impossible de récupérer l'adresse à partir de ces coordonnées."); - } - }); - } catch (error) { - console.error("Erreur :", error); - alert("Impossible de récupérer les données de la ville."); - } + }); }); // Fermer la modal @@ -118,17 +80,11 @@ document.addEventListener("DOMContentLoaded", () => { return; } - if (!selectedAddress || !selectedRue) { + if (!selectedAddress || !selectedRue || !selectedVille || !selectedCodePostal) { alert("Veuillez sélectionner un emplacement valide sur la carte."); return; } - const villeId = villeSelect.value; - if (!villeId) { - alert("Veuillez sélectionner une ville."); - return; - } - // Réinitialiser les erreurs lieuNomError.textContent = ""; lieuNomError.classList.add("hidden"); @@ -142,9 +98,10 @@ document.addEventListener("DOMContentLoaded", () => { body: JSON.stringify({ nom, rue: selectedRue, + ville: selectedVille, + codePostal: selectedCodePostal, latitude: selectedAddress.lat, longitude: selectedAddress.lng, - villeId, }), }) .then((response) => response.json().then((data) => ({ status: response.status, data }))) @@ -166,4 +123,4 @@ document.addEventListener("DOMContentLoaded", () => { alert("Une erreur inattendue s'est produite."); }); }); -}); +}); \ No newline at end of file diff --git a/assets/js/lieu.js b/assets/js/lieu.js deleted file mode 100644 index 70d6729..0000000 --- a/assets/js/lieu.js +++ /dev/null @@ -1,87 +0,0 @@ -document.addEventListener('DOMContentLoaded', function () { - const villeSelect = document.getElementById('sortie_ville'); - const lieuSelect = document.getElementById('sortie_lieu'); - - const rueLabel = document.getElementById('rue-value'); - const codePostalLabel = document.getElementById('codePostal-value'); - const latitudeLabel = document.getElementById('latitude-value'); - const longitudeLabel = document.getElementById('longitude-value'); - - if (villeSelect && lieuSelect) { - // Désactiver le menu déroulant des lieux au départ - lieuSelect.disabled = true; - - // Listener pour le changement de ville - villeSelect.addEventListener('change', function () { - const villeId = villeSelect.value; - - // Réinitialisation des options de lieu - lieuSelect.innerHTML = ''; - lieuSelect.disabled = true; // Toujours désactiver avant de récupérer les données - - if (villeId) { - fetch(`/get-lieux/${villeId}`) - .then(response => { - if (!response.ok) { - throw new Error('Erreur lors de la récupération des lieux'); - } - return response.json(); - }) - .then(data => { - // Ajouter les options si des lieux sont disponibles - if (data.length > 0) { - data.forEach(lieu => { - const option = document.createElement('option'); - option.value = lieu.id; // Utiliser l'ID pour la soumission - option.textContent = lieu.nom; // Texte visible dans le menu - - option.dataset.details = JSON.stringify({ - rue: lieu.rue, - codePostal: lieu.codePostal, - latitude: lieu.latitude, - longitude: lieu.longitude - }); - - lieuSelect.appendChild(option); - }); - lieuSelect.disabled = false; // Activer le menu des lieux - } else { - lieuSelect.innerHTML = ''; - lieuSelect.disabled = true; // Toujours désactivé si aucun lieu n'est trouvé - } - }) - .catch(error => { - console.error('Erreur lors de la récupération des lieux :', error); - }); - } - }); - - // Listener pour le changement de lieu - lieuSelect.addEventListener('change', function () { - const selectedOption = lieuSelect.options[lieuSelect.selectedIndex]; - if (selectedOption) { - const lieuDetails = selectedOption.dataset.details - ? JSON.parse(selectedOption.dataset.details) - : null; - - // Mise à jour des labels avec les détails du lieu sélectionné - rueLabel.textContent = lieuDetails?.rue || 'Non renseignée'; - codePostalLabel.textContent = lieuDetails?.codePostal || 'Non renseigné'; - latitudeLabel.textContent = lieuDetails?.latitude || 'Non renseignée'; - longitudeLabel.textContent = lieuDetails?.longitude || 'Non renseignée'; - - console.log('Lieu sélectionné:', lieuDetails); - } else { - // Réinitialiser les labels si aucun lieu n'est sélectionné - rueLabel.textContent = 'Renseigner avec le lieu'; - codePostalLabel.textContent = 'Renseigner avec le lieu'; - latitudeLabel.textContent = 'Renseigner avec le lieu'; - longitudeLabel.textContent = 'Renseigner avec le lieu'; - - console.log('Aucun lieu sélectionné.'); - } - }); - } else { - console.error('Les champs ville-select ou lieu-select sont introuvables.'); - } -}); diff --git a/assets/js/show-lieu.js b/assets/js/show-lieu.js new file mode 100644 index 0000000..e385f23 --- /dev/null +++ b/assets/js/show-lieu.js @@ -0,0 +1,59 @@ +document.addEventListener("DOMContentLoaded", () => { + console.log("DOMContentLoaded"); + const lieuSelect = document.getElementById("sortie_lieu"); + const rueValue = document.getElementById("rue-value"); + const codePostalValue = document.getElementById("codePostal-value"); + const latitudeValue = document.getElementById("latitude-value"); + const longitudeValue = document.getElementById("longitude-value"); + const villeValue = document.getElementById("ville-value"); + + // Vérifier que le champ "lieu" existe + if (!lieuSelect) { + console.error("Le champ 'lieu-select' est introuvable."); + return; + } + + console.log("Script chargé. En attente de la sélection d'un lieu."); + + // Écouter les changements sur le champ "lieu" + lieuSelect.addEventListener("change", async () => { + const lieuId = lieuSelect.value; + + console.log(`Lieu sélectionné : ${lieuId}`); + + // Si aucun lieu sélectionné, réinitialiser les champs + if (!lieuId) { + console.warn("Aucun lieu sélectionné. Réinitialisation des champs."); + rueValue.textContent = "Renseigner avec le lieu"; + codePostalValue.textContent = "Renseigner avec le lieu"; + latitudeValue.textContent = "Renseigner avec le lieu"; + longitudeValue.textContent = "Renseigner avec le lieu"; + villeValue.textContent = "Renseigner avec le lieu"; + return; + } + + try { + // Requête vers l'API pour récupérer les données du lieu + console.log(`Envoi de la requête à l'API pour le lieu ID : ${lieuId}`); + const response = await fetch(`/lieux/${lieuId}`); + if (!response.ok) { + throw new Error(`Erreur lors de la récupération des informations (statut ${response.status})`); + } + + const data = await response.json(); + console.log("Données reçues depuis l'API :", data); + + // Mise à jour des champs avec les données récupérées + rueValue.textContent = data.rue || "Non renseigné"; + codePostalValue.textContent = data.codePostal || "Non renseigné"; + latitudeValue.textContent = data.latitude || "Non renseigné"; + longitudeValue.textContent = data.longitude || "Non renseigné"; + villeValue.textContent = data.ville || "Non renseigné"; + + console.log("Champs mis à jour avec succès."); + } catch (error) { + console.error("Erreur lors de la récupération des données :", error); + alert("Une erreur s'est produite lors de la récupération des informations du lieu."); + } + }); +}); diff --git a/src/Controller/LieuController.php b/src/Controller/LieuController.php index 05922d0..f347a78 100644 --- a/src/Controller/LieuController.php +++ b/src/Controller/LieuController.php @@ -3,7 +3,7 @@ namespace App\Controller; use App\Entity\Lieu; -use App\Entity\Ville; +use App\Repository\LieuRepository; use App\Repository\VilleRepository; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; @@ -30,18 +30,12 @@ class LieuController extends AbstractController ): JsonResponse { $data = json_decode($request->getContent(), true); - if (!isset($data['nom'], $data['latitude'], $data['longitude'], $data['villeId'])) { + if (!isset($data['nom'], $data['latitude'], $data['longitude'], $data['ville'], $data['codePostal'])) { return new JsonResponse(['error' => 'Données manquantes.'], Response::HTTP_BAD_REQUEST); } - $ville = $villeRepository->find($data['villeId']); - if (!$ville) { - return new JsonResponse(['error' => 'Ville non trouvée.'], Response::HTTP_NOT_FOUND); - } - $existingLieuByName = $entityManager->getRepository(Lieu::class)->findOneBy([ 'nom' => $data['nom'], - 'ville' => $ville, ]); if ($existingLieuByName) { return new JsonResponse(['error' => "Un lieu avec le nom '{$data['nom']}' existe déjà."], Response::HTTP_CONFLICT); @@ -52,7 +46,8 @@ class LieuController extends AbstractController $lieu->setRue($data['rue']); $lieu->setLatitude($data['latitude']); $lieu->setLongitude($data['longitude']); - $lieu->setVille($ville); + $lieu->setVille($data['ville']); + $lieu->setCodePostal($data['codePostal']); $entityManager->persist($lieu); $entityManager->flush(); @@ -63,51 +58,21 @@ class LieuController extends AbstractController ], Response::HTTP_CREATED); } - - #[Route('/get-bounds/{villeId}', name: 'get_bounds', methods: ['GET'])] - public function getBounds(VilleRepository $villeRepository, string $villeId): JsonResponse + #[Route('/lieux/{id}', name: 'lieu_details', methods: ['GET'])] + public function getLieuDetails(string $id, LieuRepository $lieuRepository): JsonResponse { - $ville = $villeRepository->find($villeId); + $lieu = $lieuRepository->find($id); - if (!$ville) { - return new JsonResponse(['error' => 'Ville non trouvée'], Response::HTTP_NOT_FOUND); + if (!$lieu) { + return new JsonResponse(['error' => 'Lieu introuvable'], 404); } - $params = [ - 'q' => $ville->getNom(), - 'format' => 'json', - 'polygon_geojson' => 1, - ]; - $url = 'https://nominatim.openstreetmap.org/search?' . http_build_query($params); - - try { - $context = stream_context_create([ - 'http' => [ - 'header' => "User-Agent: MyApp/1.0 (contact@myapp.com)\r\n", - ], - ]); - - $response = file_get_contents($url, false, $context); - $data = json_decode($response, true); - - if (!empty($data[0]['boundingbox'])) { - $boundingBox = $data[0]['boundingbox']; - $centerLat = ($boundingBox[0] + $boundingBox[1]) / 2; - $centerLng = ($boundingBox[2] + $boundingBox[3]) / 2; - - return new JsonResponse([ - 'south' => $boundingBox[0], - 'north' => $boundingBox[1], - 'west' => $boundingBox[2], - 'east' => $boundingBox[3], - 'centerLat' => $centerLat, - 'centerLng' => $centerLng, - ]); - } - - return new JsonResponse(['error' => 'Bounding box non trouvée'], Response::HTTP_NOT_FOUND); - } catch (\Exception $e) { - return new JsonResponse(['error' => $e->getMessage()], Response::HTTP_INTERNAL_SERVER_ERROR); - } + return new JsonResponse([ + 'rue' => $lieu->getRue(), + 'codePostal' => $lieu->getCodePostal(), + 'latitude' => $lieu->getLatitude(), + 'longitude' => $lieu->getLongitude(), + 'ville' => $lieu->getVille(), + ]); } } diff --git a/src/Controller/SortieController.php b/src/Controller/SortieController.php index 567e22f..cc1fb5b 100644 --- a/src/Controller/SortieController.php +++ b/src/Controller/SortieController.php @@ -26,54 +26,48 @@ class SortieController extends AbstractController ParticipantRepository $participantRepository, EtatRepository $etatRepository ): Response { - $sortie = new Sortie(); - - $token = $tokenStorage->getToken(); - $userConnect = $token?->getUser(); - + // Vérifier si l'utilisateur est connecté + $userConnect = $tokenStorage->getToken()?->getUser(); if (!$userConnect) { $this->addFlash('error', 'Vous devez être connecté pour créer une sortie.'); return $this->redirectToRoute('app_login'); } + $sortie = new Sortie(); $form = $this->createForm(SortieType::class, $sortie); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $lieuId = $form->get('lieu')->getData(); - $lieu = $lieuRepository->find($lieuId); - + // Vérifier le lieu + $lieu = $form->get('lieu')->getData(); if (!$lieu) { - $this->addFlash('error', 'Le lieu sélectionné est invalide.'); + $this->addFlash('error', 'Veuillez sélectionner un lieu valide.'); return $this->redirectToRoute('sortie_create'); } - $sortie->setLieu($lieu); - + // Vérifier le participant (organisateur) $participant = $participantRepository->find($userConnect->getIdParticipant()); - if (!$participant) { - $this->addFlash('error', 'Impossible de déterminer le site de l\'utilisateur.'); + $this->addFlash('error', 'Impossible de trouver votre profil.'); return $this->redirectToRoute('sortie_create'); } - $sortie->setSite($participant->getSite()); - - $etat = $etatRepository->find('019349ba-38ca-7a39-93c3-62f046671525'); + // Définir les relations et l'état initial + $etat = $etatRepository->findOneBy(['libelle' => 'Créée']); if (!$etat) { - $this->addFlash('error', 'État non trouvé.'); + $this->addFlash('error', 'Erreur interne : état introuvable.'); return $this->redirectToRoute('sortie_create'); } - $sortie->setEtat($etat); - - $sortie->setOrganisateur($participant); + $sortie->setLieu($lieu) + ->setSite($participant->getSite()) + ->setEtat($etat) + ->setOrganisateur($participant); $entityManager->persist($sortie); $entityManager->flush(); $this->addFlash('success', 'La sortie a été créée avec succès.'); - return $this->redirectToRoute('home'); } @@ -84,64 +78,54 @@ class SortieController extends AbstractController } #[Route('/view/{id}', name: 'view', methods: ['GET'])] - public function view(string $id, EntityManagerInterface $entityManager, TokenStorageInterface $tokenStorage): Response - { - $token = $tokenStorage->getToken(); - $userConnect = $token?->getUser(); - + public function view( + string $id, + EntityManagerInterface $entityManager, + TokenStorageInterface $tokenStorage + ): Response { $sortie = $entityManager->getRepository(Sortie::class)->find($id); - if (!$sortie) { - $this->addFlash('error', 'La sortie demandée n\'existe pas.'); + $this->addFlash('error', 'Cette sortie n\'existe pas.'); return $this->redirectToRoute('home'); } - $profile = $this->getUser(); - return $this->render('sortie/view.html.twig', [ 'sortie' => $sortie, - 'profile' => $userConnect, + 'profile' => $tokenStorage->getToken()?->getUser(), ]); } #[Route('/inscription/{id}', name: 'inscription', methods: ['POST'])] - public function inscription(string $id, EntityManagerInterface $entityManager, TokenStorageInterface $tokenStorage): Response - { - $token = $tokenStorage->getToken(); - $userConnect = $token?->getUser(); - + public function inscription( + string $id, + EntityManagerInterface $entityManager, + TokenStorageInterface $tokenStorage + ): Response { + $userConnect = $tokenStorage->getToken()?->getUser(); if (!$userConnect) { $this->addFlash('error', 'Vous devez être connecté pour vous inscrire.'); return $this->redirectToRoute('app_login'); } $sortie = $entityManager->getRepository(Sortie::class)->find($id); - if (!$sortie) { - $this->addFlash('error', 'La sortie demandée n\'existe pas.'); + $this->addFlash('error', 'Cette sortie n\'existe pas.'); return $this->redirectToRoute('home'); } + // Conditions supplémentaires pour l'inscription if ($sortie->getEtat()->getLibelle() !== 'Ouverte') { - $this->addFlash('error', 'Vous ne pouvez pas vous inscrire à cette sortie car elle n\'est pas ouverte.'); - return $this->redirectToRoute('sortie_view', ['id' => $id]); - } - - if ($sortie->getParticipants()->contains($userConnect)) { + $this->addFlash('error', 'Cette sortie n\'est pas ouverte aux inscriptions.'); + } elseif ($sortie->getParticipants()->contains($userConnect)) { $this->addFlash('error', 'Vous êtes déjà inscrit à cette sortie.'); - return $this->redirectToRoute('sortie_view', ['id' => $id]); + } elseif ($sortie->getParticipants()->count() >= $sortie->getNbInscriptionsMax()) { + $this->addFlash('error', 'Cette sortie est complète.'); + } else { + $sortie->addParticipant($userConnect); + $entityManager->flush(); + $this->addFlash('success', 'Votre inscription a été validée.'); } - if ($sortie->getParticipants()->count() >= $sortie->getNbInscriptionsMax()) { - $this->addFlash('error', 'Le nombre maximum d\'inscriptions a été atteint pour cette sortie.'); - return $this->redirectToRoute('sortie_view', ['id' => $id]); - } - - $sortie->addParticipant($userConnect); - $entityManager->flush(); - - $this->addFlash('success', 'Vous êtes inscrit à la sortie avec succès !'); - return $this->redirectToRoute('sortie_view', ['id' => $id]); } @@ -154,17 +138,14 @@ class SortieController extends AbstractController LieuRepository $lieuRepository ): Response { $sortie = $entityManager->getRepository(Sortie::class)->find($id); - if (!$sortie) { - $this->addFlash('error', 'La sortie demandée n\'existe pas.'); + $this->addFlash('error', 'Cette sortie n\'existe pas.'); return $this->redirectToRoute('home'); } - $token = $tokenStorage->getToken(); - $userConnect = $token?->getUser(); - + $userConnect = $tokenStorage->getToken()?->getUser(); if ($userConnect->getIdParticipant() !== $sortie->getOrganisateur()->getIdParticipant()) { - $this->addFlash('error', 'Vous n\'avez pas l\'autorisation de modifier cette sortie.'); + $this->addFlash('error', 'Vous ne pouvez pas modifier cette sortie.'); return $this->redirectToRoute('home'); } @@ -172,17 +153,13 @@ class SortieController extends AbstractController $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $lieuId = $form->get('lieu')->getData(); - $lieu = $lieuRepository->find($lieuId); - + $lieu = $form->get('lieu')->getData(); if ($lieu) { $sortie->setLieu($lieu); } - $entityManager->flush(); - $this->addFlash('success', 'La sortie a été mise à jour avec succès.'); - + $this->addFlash('success', 'Les modifications ont été enregistrées.'); return $this->redirectToRoute('sortie_view', ['id' => $sortie->getIdSortie()]); } @@ -192,5 +169,4 @@ class SortieController extends AbstractController 'profile' => $userConnect, ]); } - } diff --git a/src/Form/SortieType.php b/src/Form/SortieType.php index 0ff4429..0f54912 100644 --- a/src/Form/SortieType.php +++ b/src/Form/SortieType.php @@ -7,7 +7,6 @@ use App\Entity\Lieu; use App\Entity\Participant; use App\Entity\Site; use App\Entity\Sortie; -use App\Entity\Ville; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\IntegerType; diff --git a/templates/sortie/create.html.twig b/templates/sortie/create.html.twig index 155a30c..b09b2e6 100644 --- a/templates/sortie/create.html.twig +++ b/templates/sortie/create.html.twig @@ -97,10 +97,6 @@