Recherche de pin par titre + Click sur la suggestion : Modification de l'url + Recentrage de la map

search-pin
Mathis FRAMIT 3 months ago
parent 5d92f57481
commit b349bba725

@ -1,9 +1,11 @@
import { Component, OnInit, ViewContainerRef } from '@angular/core';
import * as L from 'leaflet';
import 'leaflet/dist/leaflet.css';
import { Monument } from '../../model/Monument';
import { Pin } from '../../model/Pin';
import { PinService } from '../../services/pin.service';
import { MonumentMarkerComponent } from '../monument-marker/monument-marker.component';
import { PinMarkerComponent } from '../pin-marker/pin-marker.component';
import { ActivatedRoute } from '@angular/router';
import { Router } from '@angular/router';
@Component({
selector: 'app-leaflet-map',
@ -11,10 +13,13 @@ import { MonumentMarkerComponent } from '../monument-marker/monument-marker.comp
})
export class LeafletMapComponent implements OnInit {
private map!: L.Map;
private markersMap: { [key: string]: L.Marker } = {};
constructor(
private viewContainerRef: ViewContainerRef,
private pinsService: PinService
private pinsService: PinService,
private route: ActivatedRoute,
private router: Router
) {}
ngOnInit(): void {
@ -51,27 +56,47 @@ export class LeafletMapComponent implements OnInit {
</svg>
`);
this.pinsService.getPins().subscribe((monuments: Monument[]) => {
console.log(monuments);
this.pinsService.getPins().subscribe((pins: Pin[]) => {
console.log(pins);
// Add markers
monuments.forEach((monument: Monument) => {
//const icon = monument.visited ? visitedIcon : notVisitedIcon;
pins.forEach((pin: Pin) => {
//const icon = pin.visited ? visitedIcon : notVisitedIcon;
const icon = visitedIcon;
const marker = L.marker(monument.location as [number, number], {
const marker = L.marker(pin.location as [number, number], {
icon,
}).addTo(this.map);
marker.on('popupclose', () => {
this.router.navigate(['/map']);
});
marker.on('popupopen', () => {
this.router.navigate(['/map'], { queryParams: { pin: pin.id } });
});
// Dynamically create Angular component and attach it to popup
const popupDiv = document.createElement('div');
const componentRef = this.viewContainerRef.createComponent(
MonumentMarkerComponent
);
const componentRef =
this.viewContainerRef.createComponent(PinMarkerComponent);
componentRef.instance.monument = monument;
componentRef.instance.pin = pin;
popupDiv.appendChild(componentRef.location.nativeElement);
marker.bindPopup(popupDiv);
// Stocker les marqueurs par ID
this.markersMap[pin.id] = marker;
});
// Ouvrir automatiquement la pop-up si un ID est passé dans l'URL
this.route.queryParams.subscribe((params) => {
const pinId = params['pin']; // Récupérer l'ID du Pin depuis les paramètres de requête
if (pinId && this.markersMap[pinId]) {
this.markersMap[pinId].openPopup(); // Ouvrir la pop-up du marqueur correspondant
console.log('Coords du pin : ', this.markersMap[pinId].getLatLng());
this.map.setView(this.markersMap[pinId].getLatLng(), 6); // Centrer la carte sur le marqueur
}
});
});
}

@ -55,12 +55,30 @@
</svg>
<span class="sr-only">Search icon</span>
</div>
<input
type="text"
id="search-navbar"
class="block w-full p-2 ps-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="Search..."
/>
<form [formGroup]="searchForm">
<input
type="text"
id="search-navbar"
class="block w-full p-2 ps-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="Search..."
formControlName="searchControl"
(focus)="onFocus()"
(blur)="onBlur()"
/>
</form>
<ul
*ngIf="pinsFiltered.length > 0 && inputFocus"
class="bg-white dark:bg-gray-700 border border-gray-300 mt-2 rounded shadow absolute z-10 max-h-60 overflow-auto w-full"
>
<li
*ngFor="let suggestion of pinsFiltered"
(click)="clickSuggestion(suggestion)"
class="p-2 block text-sm font-medium text-gray-900 dark:text-white hover:bg-gray-500 cursor-pointer"
>
{{ suggestion.title }}
</li>
</ul>
</div>
<button
data-collapse-toggle="navbar-search"
@ -145,7 +163,7 @@
/>
</div>
<ul
class="flex flex-col p-4 lg:p-0 mt-4 font-medium border border-gray-100 rounded-lg bg-gray-50 lg:space-x-8 rtl:space-x-reverse lg:flex-row lg:mt-0 lg:border-0 lg:bg-white dark:bg-gray-800 lg:dark:bg-gray-900 dark:border-gray-700"
class="flex flex-col p-0 lg:p-0 mt-4 font-medium border border-gray-100 rounded-lg bg-gray-50 lg:space-x-8 rtl:space-x-reverse lg:flex-row lg:mt-0 lg:border-0 lg:bg-white dark:bg-gray-800 lg:dark:bg-gray-900 dark:border-gray-700"
>
<li class="flex items-center space-x-2">
<a

@ -1,30 +1,144 @@
import { NgIf } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { NavigationEnd, Router, RouterLink } from '@angular/router';
import { Component, input, OnInit } from '@angular/core';
import {
NavigationEnd,
ActivatedRoute,
Router,
RouterLink,
} from '@angular/router';
import { AddPinPopupComponent } from '../add-pin-popup/add-pin-popup.component';
import { LocalStorageService } from '../../services/localstorage.service';
import { Pin } from '../../model/Pin';
import { PinService } from '../../services/pin.service';
import { CommonModule } from '@angular/common';
import { FormControl } from '@angular/forms';
import { FormGroup } from '@angular/forms';
import { FormBuilder } from '@angular/forms';
import { ReactiveFormsModule } from '@angular/forms';
import {
debounceTime,
distinctUntilChanged,
switchMap,
of,
catchError,
} from 'rxjs';
@Component({
selector: 'app-navbar',
imports: [AddPinPopupComponent, NgIf, RouterLink],
imports: [
AddPinPopupComponent,
NgIf,
RouterLink,
CommonModule,
ReactiveFormsModule,
],
templateUrl: './navbar.component.html',
})
export class NavbarComponent implements OnInit {
isHome: boolean = false;
isModalOpen: boolean = false;
pins: Pin[] = [];
pinsFiltered: Pin[] = [];
inputFocus: Boolean = false;
searchForm: FormGroup;
constructor(
private router: Router,
private localStorageService: LocalStorageService
) {}
private route: ActivatedRoute,
private localStorageService: LocalStorageService,
private pinService: PinService,
private fb: FormBuilder
) {
this.searchForm = this.fb.group({
searchControl: new FormControl(''),
});
}
ngOnInit(): void {
this.pins = this.pinService.getPins().subscribe((pins: Pin[]) => {
this.pins = pins;
});
this.isHome = this.router.url === '/';
this.router.events.subscribe((event) => {
if (event instanceof NavigationEnd) {
this.isHome = event.url === '/';
}
});
// Initialise la barre de recherche avec debounce et distinctUntilChanged
this.searchForm
.get('searchControl')
?.valueChanges.pipe(
debounceTime(300), // Attendre 300ms après la dernière frappe
distinctUntilChanged(), // Ignorer si la nouvelle valeur est la même que la précédente
switchMap((searchTerm) => {
console.log(
'Value change : ',
this.searchForm.get('searchControl')?.valueChanges
);
const trimmedQuery = searchTerm?.trim();
if (trimmedQuery && trimmedQuery.length > 1) {
return of(this.filterPins(trimmedQuery));
}
return of([]);
}),
catchError((error) => {
console.error(
'Erreur lors de la récupération des suggestions :',
error
);
return of([]);
})
)
.subscribe((filteredPins) => {
this.pinsFiltered = filteredPins;
console.log('Pins filtrés : ', this.pinsFiltered);
});
}
filterPins(searchTerm: string): Pin[] {
const filteredPins: Pin[] = [];
console.log('Pins : ', this.pins);
if (this.pins.length === 0) {
this.pins = this.pinService.getPins();
}
this.pins.forEach((pin: Pin) => {
if (
pin.title &&
pin.title.toLowerCase().includes(searchTerm.toLowerCase())
) {
console.log('Search term : ', searchTerm, ' / Pin trouvé : ', pin);
filteredPins.push(pin);
}
});
return filteredPins;
}
clickSuggestion(pin: Pin): void {
this.searchForm.reset();
const queryParams = { pin: pin.id }; // Remplacer "id" par la bonne propriété si nécessaire
this.router.navigate([], {
relativeTo: this.route,
queryParams: queryParams,
queryParamsHandling: 'merge', // Conserve les autres paramètres de requête
});
console.log('Redirection avec ID :', pin.id);
}
onFocus(): void {
this.inputFocus = true;
}
onBlur(): void {
setTimeout(() => {
this.inputFocus = false;
}, 200); // Petit délai pour laisser l'utilisateur cliquer
}
public logout() {

@ -3,11 +3,15 @@ import { Injectable } from '@angular/core';
import { switchMap } from 'rxjs';
import { environment } from '../../environments/environment';
import { AutocompleteService } from './auto-complete.service';
import { Pin } from '../model/Pin';
@Injectable({
providedIn: 'root',
})
export class PinService {
allPins: Pin[] = [];
filteredPins: Pin[] = [];
private apiURL = environment.apiURL;
private token = localStorage.getItem('auth_token');
constructor(

Loading…
Cancel
Save