You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
front/src/app/components/add-pin-popup/add-pin-popup.component.ts

218 lines
6.5 KiB

import { CommonModule } from '@angular/common';
import {
AfterViewInit,
Component,
Input,
OnInit,
ViewChild,
} from '@angular/core';
import {
FormBuilder,
FormControl,
FormGroup,
ReactiveFormsModule,
} from '@angular/forms';
import { forkJoin, of, Subscription } from 'rxjs';
import {
catchError,
debounceTime,
distinctUntilChanged,
switchMap,
} from 'rxjs/operators';
import { AutocompleteService } from '../../services/auto-complete/auto-complete.service';
import { ExifService } from '../../services/exif/exif.service';
import { ImageService } from '../../services/image/image.service';
import { MapReloadService } from '../../services/map-reload/map-reload.service';
import { ModalService } from '../../services/modal/modal.service';
import { PinService } from '../../services/pin/pin.service';
import { DragDropComponent } from '../drag-drop/drag-drop.component';
@Component({
selector: 'app-add-pin-popup',
standalone: true,
imports: [ReactiveFormsModule, CommonModule, DragDropComponent],
templateUrl: './add-pin-popup.component.html',
})
export class AddPinPopupComponent implements OnInit {
@ViewChild(DragDropComponent) dragDropComponent!: DragDropComponent;
form: FormGroup;
suggestions: any[] = [];
inputFocused: boolean = false;
@Input() isHomePage: boolean = false;
files: File[] = [];
isPinModalOpen: boolean = false;
modalId: string = 'add-pin-modal';
private modalSub!: Subscription;
constructor(
private fb: FormBuilder,
private autocompleteService: AutocompleteService,
private pinService: PinService,
private exifService: ExifService,
private modalService: ModalService,
private mapReloadService: MapReloadService,
private imageService: ImageService
) {
this.form = this.fb.group({
title: new FormControl(''),
description: new FormControl(''),
location: new FormControl(''),
files: new FormControl(null),
date: new FormControl(''),
});
}
onFocus(): void {
this.inputFocused = true;
}
onBlur(): void {
setTimeout(() => {
this.inputFocused = false; // Désactiver le focus après un petit délai pour permettre un clic sur la liste
}, 200);
}
ngOnInit(): void {
this.modalSub = this.modalService
.getModalState(this.modalId)
.subscribe((open) => {
this.isPinModalOpen = open;
if (open) {
const images = this.modalService.getImageFiles().getValue();
if (images && images.length > 0) {
this.files = images;
this.form.patchValue({ files: images });
// Convertir les fichiers en FileList pour le composant drag-drop
const dataTransfer = new DataTransfer();
images.forEach((file) => dataTransfer.items.add(file));
const fileList = dataTransfer.files;
if (this.dragDropComponent) {
this.dragDropComponent.updateFileNamesFromFileList(fileList);
}
}
}
});
this.form
.get('location')
?.valueChanges.pipe(
debounceTime(200), // Attendre 200ms après la dernière frappe
distinctUntilChanged(), // Ignorer si la nouvelle valeur est la même que la précédente
switchMap((query) => {
const trimmedQuery = query.trim();
if (trimmedQuery.length > 2) {
return this.autocompleteService.getAddressSuggestions(trimmedQuery);
}
return of([]);
}),
catchError((error) => {
console.error('Error fetching suggestions:', error);
return of([]);
})
)
.subscribe((data) => {
this.suggestions = data;
});
}
selectSuggestion(suggestion: any): void {
const locationControl = this.form.get('location');
if (locationControl instanceof FormControl) {
locationControl.setValue(suggestion.display_name);
}
this.suggestions = [];
}
async onFilesReceived(files: FileList): Promise<void> {
this.files = Array.from(files);
if (this.dragDropComponent) {
this.dragDropComponent.updateFileNamesFromFileList(files);
} else {
console.warn('AddPinPopupComponent - dragDropComponent not available');
}
for (let i = 0; i < this.files.length; i++) {
try {
const data = await this.exifService.getLocation(this.files[i]);
if (data.latitude !== undefined && data.longitude !== undefined) {
const address = await this.autocompleteService
.getAddressFromCoordinates(data.latitude, data.longitude)
.toPromise();
if (address) {
this.form.get('location')?.setValue(address.display_name);
break;
}
}
} catch (error) {
console.error(
'AddPinPopupComponent - Error processing EXIF data:',
error
);
}
}
}
getFileNames(): string[] {
return this.files.map((file) => file.name);
}
ngOnDestroy() {
this.modalSub.unsubscribe();
}
submitForm(): void {
if (this.form.valid) {
const uploadObservables = this.files.map((file) =>
this.imageService.postImage(file)
);
forkJoin(uploadObservables).subscribe((responses) => {
// responses est un tableau de réponses API
this.files = responses.map((res: any) => res.id); // ou res.json().id si nécessaire
const pinData = {
...this.form.value,
files: this.files,
date: this.form.get('date')?.value || null,
};
this.pinService.addPin(pinData)?.subscribe(() => {
this.mapReloadService.requestReload(); // Demander le rechargement de la carte
this.closePinModal();
this.form.reset(); // Réinitialiser le formulaire après soumission
});
});
} else {
console.error('Le formulaire est invalide');
}
}
openPinModal() {
// this.isPinModalOpen = true;
this.modalService.openModal(this.modalId);
}
closePinModal() {
// this.isPinModalOpen = false;
this.modalService.closeModal(this.modalId);
}
getImagePreview(file: File): string {
return URL.createObjectURL(file);
}
removeFile(fileName: string): void {
const index = this.files.findIndex((file) => file.name === fileName);
if (index > -1) {
this.files.splice(index, 1);
// Mettre à jour le form control
const dataTransfer = new DataTransfer();
this.files.forEach((file) => dataTransfer.items.add(file));
this.form.patchValue({ files: dataTransfer.files });
}
}
}