import { Component, OnInit, ViewContainerRef, ViewEncapsulation } from '@angular/core'; import Map from 'ol/Map'; import View from 'ol/View'; import LayerGroup from 'ol/layer/Group'; import LayerTile from 'ol/layer/Tile'; import OSM from 'ol/source/OSM'; import LayerSwitcher, { BaseLayerOptions, GroupLayerOptions, } from 'ol-layerswitcher'; import MousePosition from 'ol/control/MousePosition'; import FullScreen from 'ol/control/FullScreen'; import ZoomToExtent from 'ol/control/ZoomToExtent'; import ImageLayer from 'ol/layer/Image'; import GeoJSON from 'ol/format/GeoJSON'; import Zoom from 'ol/control/Zoom'; import ZoomSlider from 'ol/control/ZoomSlider'; import { FormBuilder, FormGroup } from '@angular/forms'; import VectorSource from 'ol/source/Vector'; import VectorLayer from 'ol/layer/Vector'; import Feature from 'ol/Feature'; import Icon from 'ol/style/Icon'; import Point from 'ol/geom/Point'; import { Circle as CircleStyle, Fill, RegularShape, Stroke, Style, Text, } from 'ol/style'; import { Draw, Modify, MouseWheelZoom, defaults as defaultInteractions, DoubleClickZoom } from 'ol/interaction'; import LineString from 'ol/geom/LineString'; import { getArea, getLength } from 'ol/sphere'; import { fromLonLat, transform } from 'ol/proj'; import { Router } from '@angular/router'; import { circular } from 'ol/geom/Polygon'; import { take } from 'rxjs'; import { CrudService } from 'src/app/crud.service'; import { NzModalService } from 'ng-zorro-antd/modal'; import { NzMessageService } from 'ng-zorro-antd/message'; import { GlobalService } from 'src/app/global.service'; import { HttpErrorResponse } from '@angular/common/http'; import { NzTreeNodeOptions } from 'ng-zorro-antd/tree'; import { TokenStorage } from 'src/app/utilitaire/token-storage'; import { JwtHelperService } from '@auth0/angular-jwt'; declare var $: any; declare var NioApp: any; /* déclaration pour outils de mesure */ const style = new Style({ fill: new Fill({ color: 'rgba(255, 255, 255, 0.2)', }), stroke: new Stroke({ color: 'rgba(0, 0, 0, 0.5)', lineDash: [10, 10], width: 2, }), image: new CircleStyle({ radius: 5, stroke: new Stroke({ color: 'rgba(0, 0, 0, 0.7)', }), fill: new Fill({ color: 'rgba(255, 255, 255, 0.2)', }), }), }); const labelStyle = new Style({ text: new Text({ font: '14px Calibri,sans-serif', fill: new Fill({ color: 'rgba(255, 255, 255, 1)', }), backgroundFill: new Fill({ color: 'rgba(26, 88, 144, 1)', }), padding: [3, 3, 3, 3], textBaseline: 'bottom', offsetY: -15, }), image: new RegularShape({ radius: 8, points: 3, angle: Math.PI, displacement: [0, 10], fill: new Fill({ //color: 'rgba(0, 0, 0, 0.7)', color: 'rgba(26, 88, 144, 1)', }), }), }); const tipStyle = new Style({ text: new Text({ font: '12px Calibri,sans-serif', fill: new Fill({ color: 'rgba(255, 255, 255, 1)', }), backgroundFill: new Fill({ color: 'rgba(0, 0, 0, 0.4)', }), padding: [2, 2, 2, 2], textAlign: 'left', offsetX: 15, }), }); const modifyStyle = new Style({ image: new CircleStyle({ radius: 5, stroke: new Stroke({ color: 'rgba(0, 0, 0, 0.7)', }), fill: new Fill({ color: 'rgba(0, 0, 0, 0.4)', }), }), text: new Text({ text: 'Drag to modify', font: '12px Calibri,sans-serif', fill: new Fill({ color: 'rgba(255, 255, 255, 1)', }), backgroundFill: new Fill({ color: 'rgba(0, 0, 0, 0.7)', }), padding: [2, 2, 2, 2], textAlign: 'left', offsetX: 15, }), }); const segmentStyle = new Style({ text: new Text({ font: '12px Calibri,sans-serif', fill: new Fill({ color: 'rgba(255, 255, 255, 1)', }), backgroundFill: new Fill({ color: 'rgba(0, 0, 0, 0.4)', }), padding: [2, 2, 2, 2], textBaseline: 'bottom', offsetY: -12, }), image: new RegularShape({ radius: 6, points: 3, angle: Math.PI, displacement: [0, 8], fill: new Fill({ color: 'rgba(0, 0, 0, 0.4)', }), }), }); const segmentStyles = [segmentStyle]; const formatLength = function (line: any) { const length = getLength(line, { projection: 'EPSG:4326' }); let output; if (length > 100) { output = Math.round((length / 1000) * 100) / 100 + ' km'; } else { output = Math.round(length * 100) / 100 + ' m'; } return output; }; const formatArea = function (polygon: any) { const area = getArea(polygon, { projection: 'EPSG:4326' }); let output; if (area > 10000) { output = Math.round((area / 1000000) * 100) / 100 + ' km\xB2'; } else { output = Math.round(area * 100) / 100 + ' m\xB2'; } return output; }; const sourceDrawOutil = new VectorSource(); const modify = new Modify({ source: sourceDrawOutil, style: modifyStyle }); let tipPoint: any; function styleFunction(feature: any, segments: any, drawType: any, tip: any) { const styles = [style]; const geometry = feature.getGeometry(); const type = geometry.getType(); let point, label, line; if (!drawType || drawType === type) { if (type === 'Polygon') { point = geometry.getInteriorPoint(); label = formatArea(geometry); line = new LineString(geometry.getCoordinates()[0]); } else if (type === 'LineString') { point = new Point(geometry.getLastCoordinate()); label = formatLength(geometry); line = geometry; } } if (segments && line) { let count = 0; line.forEachSegment(function (a: any, b: any) { const segment = new LineString([a, b]); //transform('EPSG:4326', 'EPSG:3413') /*const aLbalel = transform(a, 'EPSG:4326', 'EPSG:3857'); const bLbalel = transform(b, 'EPSG:4326', 'EPSG:3857'); const segmentLabel = new LineString([aLbalel, bLbalel]);*/ const label = formatLength(segment); if (segmentStyles.length - 1 < count) { segmentStyles.push(segmentStyle.clone()); } const segmentPoint = new Point(segment.getCoordinateAt(0.5)); segmentStyles[count].setGeometry(segmentPoint); segmentStyles[count]?.getText()?.setText(label); styles.push(segmentStyles[count]); count++; }); } if (label) { labelStyle.setGeometry(point); labelStyle.getText()?.setText(label); styles.push(labelStyle); } if ( tip && type === 'Point' && !modify.getOverlay()?.getSource()?.getFeatures().length ) { tipPoint = geometry; tipStyle.getText()?.setText(tip); styles.push(tipStyle); } return styles; } @Component({ selector: 'app-cartographie-fiscale-tfu', templateUrl: './cartographie-fiscale-tfu.component.html', styleUrls: ['./cartographie-fiscale-tfu.component.css'], encapsulation: ViewEncapsulation.None // ← ajouter cette ligne }) export class CartographieFiscaleTfuComponent implements OnInit { iconImagePosition = new Style({ image: new Icon({ anchor: [0.5, 46], anchorXUnits: 'fraction', anchorYUnits: 'pixels', src: 'assets/static/images/marker-icon.png', size: [25, 45], // [25, 45], }), }); styleDelimiterLayer = new Style({ stroke: new Stroke({ color: 'black', width: 3, }), fill: new Fill({ color: 'transparent', }), }); baseOSM = new LayerTile({ title: 'OSM', type: 'base', visible: true, source: new OSM(), } as BaseLayerOptions); baseMaps = new LayerGroup({ title: 'Base maps', layers: [this.baseOSM], } as GroupLayerOptions); view = new View({ projection: 'EPSG:4326', center: [2.315834, 9.307690],//[2.237783, 8.993058], zoom: 7.2, minZoom: 7.2, /*extent: [ -1.3114703249183064, 5.3826768040185105, 8.825820324918308, 12.48591919598149, ],*/ }); map!: Map; mouse_position = new MousePosition(); full_sc = new FullScreen({ label: 'F' }); zoom = new Zoom({ zoomInLabel: '+', zoomOutLabel: '-' }); slider = new ZoomSlider(); zoom_ex = new ZoomToExtent({ extent: [ -1.3114703249183064, 5.3826768040185105, 8.825820324918308, 12.48591919598149, ], }); departementList: any[] = []; communeList: any[] = []; arrondissementList: any[] = []; villageQuartierList: any[] = []; parcelleList: any[] = []; parcelleFilteredList: any[] = []; parcelleSearchFilteredList: any[] = []; filterForm!: FormGroup; sourceDecoupage: VectorSource = new VectorSource(); vectorDecoupage: any; sourceParcelle: VectorSource = new VectorSource(); vectorParcelle: any; circleMarkerVector: any; iconVectorLayer: any; globalSearch = ''; coordinate1 = { longitude: null, latitude: null }; rayon = 0; /* outils de dessins */ isDrawing = false; sketch: any; typeSelect: string = 'LineString'; showSegments: boolean = true; clearPrevious: boolean = true; vectorDrawOutil = new VectorLayer({ source: sourceDrawOutil, style: (feature: any) => { return styleFunction( feature, this.showSegments, this.typeSelect, 'Click to start measuring' ); }, zIndex: 7, }); draw: any; /* fin outils de dessins */ mapDataInfo: any = null; batimentList: any[] = []; uniteLogementList: any[] = []; visibleMapData = false; keyFilter: any = null; activeTab: string = 'legende'; // ← ajouter ici // ── Cartes pliables ─────────────────────────────────────────────────── collapsedCards: { [key: string]: boolean } = { localisation: false, // false = déplié par défaut propriete: false, representant: false, fiscal: false }; activeInfoTab: string = 'batiment'; keyFliterList: any[] = [ { couleur: '#333', code: 'ALL', libelle: 'Toutes les parcelles' }, { couleur: '#94a3b8', code: 'NON_ENQUETE_NON_BATIE', libelle: 'Parcelles non enquêtées — Non bâties', batie: false, status: 'NON_ENQUETE' }, { couleur: '#8b5cf6', code: 'NON_ENQUETE_BATIE', libelle: 'Parcelles non enquêtées — Bâties', batie: true, status: 'NON_ENQUETE' }, { couleur: '#06b6d4', code: 'ENQUETE_NON_BATIE_AJOUR', libelle: 'Non bâties — À jour', batie: false, status: 'AJOUR' }, { couleur: '#22c55e', code: 'ENQUETE_BATIE_AJOUR', libelle: 'Bâties — À jour', batie: true, status: 'AJOUR' }, { couleur: '#f59e0b', code: 'ENQUETE_NON_BATIE_NON_AJOUR', libelle: 'Non bâties — Non à jour', batie: false, status: 'NON_AJOUR' }, { couleur: '#f97316', code: 'ENQUETE_BATIE_NON_AJOUR', libelle: 'Bâties — Non à jour', batie: true, status: 'NON_AJOUR' }, { couleur: '#ef4444', code: 'PARCELLE_NON_ENQUETER', libelle: 'Parcelles non enquêtées', status: 'NON_ENQUETE' }, { couleur: '#ef4444', code: 'PARCELLE_ENDETTE', libelle: 'Parcelles endettées', status: 'NON_AJOUR' }, { couleur: '#393542', code: 'PARCELLE_A_JOUR_DU_FISC', libelle: 'Parcelles à jour du fisc', status: 'AJOUR' }, ]; commune: any; nodes: NzTreeNodeOptions[] = []; quartierSelected: any = null; arbreUtilisateurCourant: any[] = []; user: any = null; // ── Filtre boîte flottante ──────────────────────────── filterBoxVisible = false; filterApplied = false; filterCritere = ''; filterValue = ''; filterQlotissement = ''; filterIlotLotissement = ''; filterPlotissement = ''; filterPersonneNom: string = ''; filterPersonnePrenom: string = ''; constructor( private router: Router, private fb: FormBuilder, private crudService: CrudService, private modal: NzModalService, private message: NzMessageService, private globalService: GlobalService, private tokenStorage: TokenStorage, ) { } ngOnInit(): void { this.globalService.setLodingSuccess(false); const token = this.tokenStorage.getToken() != null ? this.tokenStorage.getToken() : ''; const helper = new JwtHelperService(); const decodeToken = helper.decodeToken(token ? token : ''); this.user = decodeToken?.user; if (this.user) { this.crudService.getAll('secteur-decoupage/arbre/user-id/' + this.user?.id).subscribe( (data: any) => { this.arbreUtilisateurCourant = data.object ? data.object : []; if (this.arbreUtilisateurCourant && this.arbreUtilisateurCourant.length > 0) { this.constructionArbreUtilisateurs(); } this.message.success(`Chargement des découpages de l'utilisateur ${this.user?.nom} réussi`); }, (error: any) => { this.message.error(`Chargement des découpages de l'utilisateur ${this.user?.nom} échoué`); }); } this.map = new Map({ target: 'map', view: this.view, interactions: defaultInteractions().getArray().filter( (interaction: any) => !(interaction instanceof DoubleClickZoom) && !(interaction instanceof MouseWheelZoom) // ← ajouter cette ligne ), }); this.map.addLayer(this.baseMaps); this.map.addControl(this.mouse_position); //this.map.addControl(this.overview); this.map.addControl(this.full_sc); this.map.addControl(this.zoom); this.map.addControl(this.slider); this.map.addControl(this.zoom_ex); this.globalService.setLodingSuccess(false); } chargerParcelleListByQuartier(quartier: any): void { if (quartier) { console.log("data quartier ===> ", quartier); this.message.loading('Chargement des parcelles en cours ...'); this.globalService.setLodingSuccess(true); //this.crudService.getAll('parcelle-geom/by-quartier/' + quartier.code).subscribe( this.crudService.getAll('parcelle-geom/by-quartier-id/' + quartier.quartierId).subscribe( (data: any) => { console.log('data parcelle ==>', data); if (data.object) { //dessiner les parcelles this.parcelleList = data.object.filter((el: any) => el.ilot != null); this.parcelleFilteredList = data.object.filter((el: any) => el.ilot != null); this.parcelleSearchFilteredList = data.object.filter((el: any) => el.ilot != null);; if (this.parcelleList && this.parcelleList.length > 0) { if (this.parcelleList[0].longitude && this.parcelleList[0].latitude) { this.map.getView().setCenter([this.parcelleList[0].longitude, this.parcelleList[0].latitude]); this.map.getView().setZoom(17); } } this.doMapCPS(); //} } this.message.remove(); this.globalService.setLodingSuccess(false); }, (error: HttpErrorResponse) => { this.message.create('error', `Erreur de connexion internet ou du système`); this.globalService.setLodingSuccess(false); this.message.remove(); } ); } } doMapCPS(): void { this.map.removeLayer(this.vectorParcelle); if (this.parcelleFilteredList.length > 0 && this.map) { this.globalService.setLodingSuccess(true); this.sourceParcelle = new VectorSource({ features: new GeoJSON().readFeatures( { type: 'FeatureCollection', name: 'Parcelle', features: this.buildFeatureFormatData(this.parcelleFilteredList), }, { dataProjection: 'EPSG:32631', featureProjection: 'EPSG:4326' } ), }); console.log(this.sourceParcelle); this.vectorParcelle = new VectorLayer({ source: this.sourceParcelle, zIndex: 6, }); this.sourceParcelle .getFeatures() .forEach((feature: any, index: number) => { feature.setStyle(this.getDynamiqueStyleParcelle(this.parcelleFilteredList[index])); feature.setProperties({ parcelle: this.parcelleFilteredList[index], }); }); this.map.addLayer(this.vectorParcelle); this.message.remove(); this.globalService.setLodingSuccess(false); //console.log('map must draw layer ===> ', this.sourceParcelle); } } initMap(): void { this.map.removeLayer(this.vectorDecoupage); this.map.removeLayer(this.vectorParcelle); this.map.removeLayer(this.iconVectorLayer); this.map.removeLayer(this.circleMarkerVector); this.map.getView().setCenter([2.237783, 8.993058]); this.map.getView().setZoom(7.3); } onMouseEnter(): void { console.log(this.globalSearch); this.globalService.setLodingSuccess(true); if (this.globalSearch != '' && this.globalSearch != undefined && this.parcelleList.length > 0) { this.parcelleFilteredList = this.parcelleList.filter( (element: any) => (element.ilot && element.ilot.toLowerCase().indexOf(this.globalSearch.toLowerCase()) > -1) || (element.p && element.p.toLowerCase().indexOf(this.globalSearch.toLowerCase()) > -1) || (element.nomEtPrenoms && element.nomEtPrenoms.toLowerCase().indexOf(this.globalSearch.toLowerCase()) > -1) || (element.q && element.q.toLowerCase().indexOf(this.globalSearch.toLowerCase()) > -1) ); this.map.getView().setCenter([this.parcelleFilteredList[0].longitude, this.parcelleFilteredList[0].latitude]); this.map.getView().setZoom(19); this.doMapCPS(); } else { this.parcelleFilteredList = this.parcelleList; this.map.getView().setZoom(17); this.doMapCPS(); } this.globalService.setLodingSuccess(false); } compareFn = (o1: any, o2: any) => (o1 && o2 ? o1.code === o2.code : o1 === o2); keyFilterAction(value: any): void { console.log('keyFilterAction', value); this.filterCritere = ''; this.filterValue = ''; this.filterQlotissement = ''; this.filterIlotLotissement = ''; this.filterPlotissement = ''; this.filterPersonneNom = ''; // ← ajouter this.filterPersonnePrenom = ''; // ← ajouter this.filterApplied = false; this.globalService.setLodingSuccess(true); this.parcelleFilteredList = []; if (value && value?.code == 'ALL') { this.parcelleFilteredList = this.parcelleList; this.doMapCPS(); this.globalService.setLodingSuccess(false); return; } if (value && (value?.code == 'PARCELLE_ENDETTE' || value?.code == 'PARCELLE_NON_ENQUETER' || value?.code == 'PARCELLE_A_JOUR_DU_FISC')) { this.parcelleFilteredList = this.parcelleList.filter((element: any) => (element.statutParcelle == value.status)); this.doMapCPS(); this.globalService.setLodingSuccess(false); return; } if (value && value?.code != 'ALL' && value?.code != 'PARCELLE_A_JOUR_DU_FISC' && value?.code != 'PARCELLE_ENDETTE' && value?.code != 'PARCELLE_NON_ENQUETER') { this.parcelleFilteredList = this.parcelleList.filter((element: any) => (element.batie == value.batie && element.statutParcelle == value.status)); this.doMapCPS(); this.globalService.setLodingSuccess(false); return; } console.log(' this.parcelleFilteredList ==>', this.parcelleFilteredList); } buildFeatureFormatData(dataList: any[]): any[] { dataList.forEach((element) => { Object.defineProperty(element, 'type', { value: 'Feature', writable: false, }); //element.geometry.coordinates = element.geometry.coordinates = transform(element.geometry.coordinates, 'EPSG:3857', 'EPSG:4326'); }); console.log('dataList ==>', dataList); return dataList; } positionActuelle(): void { this.crudService.getPosition().then( (res: any) => { console.log('res', res); this.coordinate1.longitude = res.lng; this.coordinate1.latitude = res.lat; }, (failure: any) => { console.error(failure); //expected output: Oopsy... } ); } resetSimulation(): void { this.coordinate1.longitude = null; this.coordinate1.latitude = null; this.map.removeLayer(this.circleMarkerVector); this.map.removeLayer(this.iconVectorLayer); } lancerSimulation(): void { if ( this.coordinate1.longitude != null && this.coordinate1.latitude != null && this.rayon > 0 ) { this.map.removeLayer(this.circleMarkerVector); this.map.removeLayer(this.iconVectorLayer); const circleFeature = new Feature({ geometry: circular( [this.coordinate1.longitude, this.coordinate1.latitude], this.rayon ), }); this.circleMarkerVector = new VectorLayer({ source: new VectorSource({ features: [circleFeature], }), }); circleFeature.setStyle(this.styleDelimiterLayer); this.map.addLayer(this.circleMarkerVector); this.circleMarkerVector.setZIndex(8); this.makeIconeToLongLat(this.coordinate1.longitude, this.coordinate1.latitude); const circleGeometry: any = circleFeature.getGeometry(); //const size = this.map.getSize(); this.view.fit(circleGeometry, { padding: [170, 50, 30, 150] }); } else { this.message.create('error', 'Formulaire invalid !'); } } makeIconeToLongLat(long: any, lat: any): void { const iconFeature = new Feature({ geometry: new Point([long, lat]), }); iconFeature.setStyle(this.iconImagePosition); const iconVectorSource = new VectorSource({ features: [iconFeature], }); this.iconVectorLayer = new VectorLayer({ source: iconVectorSource, }); this.map.addLayer(this.iconVectorLayer); this.iconVectorLayer.setZIndex(1000); } getDynamiqueStyleParcelle(parcelle: any): Style { const element = this.keyFliterList.find((e: any) => e.status == parcelle.statutParcelle && e.batie == parcelle.batie); //console.log('element ===>', element); return new Style({ stroke: new Stroke({ color: 'black', width: 1 }), fill: new Fill({ color: element ? element.couleur : '#94a3b8', //color: '#94a3b8', }), }); } /* dessin de distance */ onChangeTypeSelectDrawing(): void { this.map.removeInteraction(this.draw); this.addInteraction(); } onChangeShowSegmentDrawing(valueEvent: any): void { this.showSegments = valueEvent; console.log('this.showSegments', this.showSegments); this.vectorDrawOutil.changed(); this.draw.getOverlay().changed(); } showOutilsMeasure(): void { this.isDrawing = true; //this.vectorDrawOutil.setZIndex(7); this.map.addLayer(this.vectorDrawOutil); this.map.addInteraction(modify); this.addInteraction(); } hideOutilsMeasure(): void { this.isDrawing = false; //this.vectorDrawOutil.setZIndex(0); sourceDrawOutil.clear(); this.draw.dispose(); //this.map.removeLayer(this.vectorDrawOutil); this.map.removeInteraction(this.draw); } addInteraction(): void { const drawType: any = this.typeSelect; const activeTip = 'Click to continue drawing the ' + (drawType === 'Polygon' ? 'polygon' : 'line'); const idleTip = 'Click to start measuring'; let tip = idleTip; this.draw = new Draw({ source: sourceDrawOutil, type: drawType, style: (feature: any) => { //console.log("this.showSegments", this.showSegments); return styleFunction(feature, this.showSegments, drawType, tip); }, }); this.draw.on('drawstart', () => { console.log('this.clearPrevious ==>', this.clearPrevious); if (this.clearPrevious == true) { sourceDrawOutil.clear(); } modify.setActive(false); tip = activeTip; }); this.draw.on('drawend', () => { modifyStyle.setGeometry(tipPoint); modify.setActive(true); if (this.map != undefined) { this.map.once('pointermove', () => { modifyStyle.setGeometry(''); }); } tip = idleTip; }); modify.setActive(true); this.map.addInteraction(this.draw); } /* fin dessin de distance */ getInformationFromCoord(event: any) { if (this.isDrawing == false) { //this.parcelle = null; this.batimentList = []; this.uniteLogementList = []; const coordinate: any = this.map.getEventCoordinate(event); const pixels = this.map.getEventPixel(event); var features = this.map.getFeaturesAtPixel(pixels); if (features && features.length > 0) { features.forEach((element: any) => { console.log("element['values_']", element['values_']); const result: any = element ? element?.values_ : null; console.log('result.values_', result.values_); if (result != null) { this.mapDataInfo = result?.parcelle; if (this.mapDataInfo != null) { this.visibleMapData = true; this.crudService.getAll('batiment/all/by-parcelle-id/' + this.mapDataInfo?.parcelleId).subscribe( (data: any) => { this.batimentList = data.object ? data.object : []; console.log(' this.batimentList ==> ', this.batimentList); } ); this.crudService.getAll('unite-logement/by-parcelle-id/' + this.mapDataInfo?.parcelleId).subscribe( (data: any) => { this.uniteLogementList = data.object ? data.object : []; console.log(' this.uniteLogementList ==> ', this.uniteLogementList); } ); } /*console.log('this.parcelle', this.parcelle); if(this.parcelle != null) { this.parcelleService .getListProprietaire(this.parcelle?.id) .pipe(take(1)) .subscribe((dataAppartenir: any) => { console.log('dataAppartenir ==> ', dataAppartenir); this.appartenirList = dataAppartenir.object ? dataAppartenir.object : []; }); this.parcelleService .getBatiementListOfParcelle(this.parcelle.id) .subscribe((data: any) => { this.batimentList = data.object; }); this.parcelleService .getUniteLogementListOfParcelle(this.parcelle.id) .subscribe((data: any) => { this.uniteLogementList = data.object; }); }*/ } }); } } } formatMontant(val: number): string { if (!val && val !== 0) return '—'; return new Intl.NumberFormat('fr-FR').format(val) + ' FCFA'; } close(): void { this.visibleMapData = false; } detailByNup(): void { if (this.mapDataInfo && this.mapDataInfo.parcelleId) { //const urlBase = this.router.url const baseUrl = window.location.origin; console.log('baseUrl ==>', baseUrl); window.open(baseUrl+'/core/cartographie/data/detail-parcelle/' + this.mapDataInfo.parcelleId) //this.router.navigate(['/core/cartographie/data/detail-information-parcelle/' + this.mapDataInfo.parcelleId]); } else { this.modal.error({ nzTitle: 'Erreur', nzContent: "Cette parcelle ne comporte pas de données fiscale d'enquête" }); } } openGoogleMap(mode: 'driving' | 'walking' | 'bicycling' | 'transit'): void { if (this.mapDataInfo && this.mapDataInfo.longitude && this.mapDataInfo.latitude) { const destinationLat = this.mapDataInfo.latitude; const destinationLng = this.mapDataInfo.longitude; navigator.geolocation.getCurrentPosition( (position) => { const originLat = position.coords.latitude; const originLng = position.coords.longitude; const url = `https://www.google.com/maps/dir/?api=1&origin=${originLat},${originLng}&destination=${destinationLat},${destinationLng}&travelmode=${mode}`; window.open(url, '_blank'); }, (error) => { console.error("Erreur de géolocalisation", error); alert("Impossible d'obtenir votre position."); } ); } else { this.modal.error({ nzTitle: 'Erreur', nzContent: 'Les coordonnées géographique de la parcelle ne sont pas disponibles.' }); } } constructionArbreUtilisateurs() { const data: any[] = this.arbreUtilisateurCourant; // Grouper par département — objet indexé par id const deptObj: { [id: number]: any } = {}; data.forEach(item => { // Niveau département if (!deptObj[item.departementId]) { deptObj[item.departementId] = { ...item, communes: {} as { [id: number]: any } }; } const dept = deptObj[item.departementId]; // Niveau commune if (!dept.communes[item.communeId]) { dept.communes[item.communeId] = { ...item, arrondissements: {} as { [id: number]: any } }; } const commune = dept.communes[item.communeId]; // Niveau arrondissement if (!commune.arrondissements[item.arrondissementId]) { commune.arrondissements[item.arrondissementId] = { ...item, quartiers: [] as any[] }; } const arr = commune.arrondissements[item.arrondissementId]; // Niveau quartier arr.quartiers.push(item); }); // Construire les nœuds nz-tree this.nodes = Object.values(deptObj).map((dept: any) => ({ title: `${dept.departementCode} — ${dept.departementNom}`, key: `dept-${dept.departementId}`, icon: 'bank', isLeaf: false, expanded: false, nbParcelles: dept.nbParcellesDepartement, children: Object.values(dept.communes).map((comm: any) => ({ title: `${comm.communeCode} — ${comm.communeNom}`, key: `comm-${comm.communeId}`, icon: 'home', isLeaf: false, expanded: false, nbParcelles: comm.nbParcellesCommune, children: Object.values(comm.arrondissements).map((arr: any) => ({ title: arr.arrondissementNom, key: `arr-${arr.arrondissementId}`, icon: 'apartment', isLeaf: false, expanded: false, nbParcelles: arr.nbParcellesArrondissement, children: arr.quartiers.map((quart: any) => ({ title: quart.quartierNom, key: `quart-${quart.quartierId}`, icon: 'environment', isLeaf: true, nbParcelles: quart.nbParcellesQuartier, quartier: quart })) })) })) })); } onNodeClick(event: any) { const node = event.node; if (node.isLeaf && node.key.startsWith('quart-')) { this.quartierSelected = node.origin.quartier; console.log(' this.quartierSelected ==>', this.quartierSelected); this.message.create('success', `Quartier ${this.quartierSelected.quartierNom} sélectionné.`); // votre logique de sélection... if (this.quartierSelected) { this.chargerParcelleListByQuartier(this.quartierSelected); } } } getBadgeColor(niveau: string): string { const colors: any = { 'dept': '#204e10', 'comm': '#10b981', 'arr': '#f59e0b', 'quart': '#ef6972' }; return colors[niveau] ?? '#6b7280'; } getNiveau(key: string): string { if (key.startsWith('dept')) return 'dept'; if (key.startsWith('comm')) return 'comm'; if (key.startsWith('arr')) return 'arr'; if (key.startsWith('quart')) return 'quart'; return ''; } toggleCard(key: string): void { this.collapsedCards[key] = !this.collapsedCards[key]; } toggleFilterBox(): void { this.filterBoxVisible = !this.filterBoxVisible; } getFilterPlaceholder(critere: string): string { const map: { [key: string]: string } = { nup: 'ex: NUP-COT-001', numeroTitreFoncier: 'ex: TF-2023-412', telephone: 'ex: +229 97...', ifu: 'ex: IFU-000...', npi: 'ex: NPI-...', raisonSociale: 'ex: SARL BÉNIN...', }; return map[critere] ?? 'Entrer une valeur…'; } appliquerFiltre(): void { if (!this.filterCritere) return; this.globalService.setLodingSuccess(true); if (this.filterCritere === 'qip_lotissement') { this.parcelleFilteredList = this.parcelleList.filter(item => { const ilotItem = (item.ilotLotissement || item.ilot || '').trim().toLowerCase(); const plotItem = (item.plotissement || item.p || '').trim().toLowerCase(); const filterIlot = this.filterIlotLotissement?.trim().toLowerCase() || ''; const filterPlot = this.filterPlotissement?.trim().toLowerCase() || ''; // Si filtre îlot → champ doit exister et matcher if (filterIlot && (!ilotItem || ilotItem !== filterIlot)) { return false; } // Si filtre plot → champ doit exister et matcher if (filterPlot && (!plotItem || plotItem !== filterPlot)) { return false; } // Si on arrive ici → ok return true; }); } else if (this.filterCritere === 'personne_nom_prenom') { // ── Nom & Prénom : correspondance exacte sur chaque champ renseigné ────── const nom = this.filterPersonneNom.trim().toLowerCase(); const prenom = this.filterPersonnePrenom.trim().toLowerCase(); this.parcelleFilteredList = this.parcelleList.filter(item => { const itemNom = (item.nomEtPrenoms || item.nom || '').toLowerCase(); const itemPrenom = (item.nomEtPrenoms || item.prenom || '').toLowerCase(); const nomOk = !nom || itemNom === nom || itemNom.startsWith(nom); const prenomOk = !prenom || itemPrenom === prenom || itemPrenom.indexOf(prenom) > -1; return nomOk && prenomOk; }); } else { // ── Champ unique : correspondance exacte ────────────────────────────────── const val = this.filterValue.trim().toLowerCase(); if (!val) { this.globalService.setLodingSuccess(false); return; } this.parcelleFilteredList = this.parcelleList.filter(item => { const champ = (item[this.filterCritere] || '').toString().toLowerCase(); return champ === val || champ.startsWith(val); }); } if (this.parcelleFilteredList && this.parcelleFilteredList.length != this.parcelleList.length) { if (this.parcelleFilteredList[0].longitude && this.parcelleFilteredList[0].latitude) { this.map.getView().setCenter([this.parcelleFilteredList[0].longitude, this.parcelleFilteredList[0].latitude]); this.map.getView().setZoom(18); } } this.doMapCPS(); this.globalService.setLodingSuccess(false); this.filterApplied = true; } reinitialiserFiltre(): void { this.filterCritere = ''; this.filterValue = ''; this.filterQlotissement = ''; this.filterIlotLotissement = ''; this.filterPlotissement = ''; this.filterPersonneNom = ''; // ← ajouter this.filterPersonnePrenom = ''; // ← ajouter this.keyFilter = ''; this.filterApplied = false; this.globalService.setLodingSuccess(true); this.parcelleFilteredList = [...this.parcelleList]; this.doMapCPS(); this.globalService.setLodingSuccess(false); } }