diff --git a/src/app/components/import/import.component.css b/src/app/components/import/import.component.css
new file mode 100644
index 0000000..8630c5b
--- /dev/null
+++ b/src/app/components/import/import.component.css
@@ -0,0 +1,82 @@
+.import-container {
+ padding: 20px;
+ max-width: 1200px;
+ margin: 0 auto;
+}
+
+.full-width {
+ width: 100%;
+}
+
+.button-container {
+ display: flex;
+ justify-content: flex-end;
+ margin: 20px 0;
+ gap: 10px;
+}
+
+.mapping-container {
+ margin-top: 30px;
+ padding: 20px;
+ background-color: #f5f5f5;
+ border-radius: 4px;
+}
+
+.mapping-description {
+ color: #666;
+ margin-bottom: 20px;
+}
+
+.mapping-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
+ gap: 20px;
+ margin-bottom: 30px;
+}
+
+.mapping-row {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+}
+
+.field-label {
+ font-size: 14px;
+ color: #333;
+}
+
+.preview-section {
+ margin-top: 30px;
+ padding: 20px;
+ background-color: #fff;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+}
+
+.preview-section h3 {
+ margin-top: 0;
+ margin-bottom: 15px;
+}
+
+.preview-section pre {
+ background-color: #f8f8f8;
+ padding: 15px;
+ border-radius: 4px;
+ overflow-x: auto;
+ font-size: 12px;
+}
+
+mat-spinner {
+ display: inline-block;
+ margin-right: 8px;
+}
+
+.error-snackbar {
+ background: #f44336;
+ color: white;
+}
+
+.success-snackbar {
+ background: #4caf50;
+ color: white;
+}
\ No newline at end of file
diff --git a/src/app/components/import/import.component.html b/src/app/components/import/import.component.html
new file mode 100644
index 0000000..0b85de3
--- /dev/null
+++ b/src/app/components/import/import.component.html
@@ -0,0 +1,84 @@
+
+
+
+
Import de données
+
Importez des données depuis une API Geoapify
+
+
+
+
+
+
+
Correspondance des champs
+
+ Sélectionnez les champs de l'API qui correspondent à vos champs système
+
+
+
+
+
+
+
+
+
+
+
0" class="bg-white rounded-lg border border-gray-200 p-6">
+
Aperçu des données
+
{{data.features[0] | json}}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/components/import/import.component.ts b/src/app/components/import/import.component.ts
new file mode 100644
index 0000000..351f9f7
--- /dev/null
+++ b/src/app/components/import/import.component.ts
@@ -0,0 +1,129 @@
+import { Component } from '@angular/core';
+import { FormBuilder, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
+import { ImportService, GeoapifyResponse, GeoapifyFeature } from '../../services/import.service';
+import { CommonModule } from '@angular/common';
+import { POIService } from '../../services/poi.service';
+import { POI } from '../../model/POI';
+
+@Component({
+ selector: 'app-import',
+ templateUrl: './import.component.html',
+ styleUrls: ['./import.component.css'],
+ imports: [CommonModule, ReactiveFormsModule]
+})
+export class ImportComponent {
+ importForm: FormGroup;
+ isLoading = false;
+ data: GeoapifyResponse | null = null;
+ fieldMappings: { [key: string]: string } = {};
+ availableFields: string[] = [];
+ targetFields = [
+ 'title',
+ 'description',
+ 'complete_address',
+ 'latitude',
+ 'longitude'
+ ];
+
+ constructor(
+ private fb: FormBuilder,
+ private importService: ImportService,
+ private poiService: POIService
+ ) {
+ this.importForm = this.fb.group({
+ apiUrl: ['', [Validators.required, Validators.pattern('^https?://.+')]]
+ });
+ }
+
+ onSubmit(): void {
+ if (this.importForm.valid) {
+ this.isLoading = true;
+ const url = this.importForm.get('apiUrl')?.value;
+
+ this.importService.fetchDataFromUrl(url).subscribe({
+ next: (response) => {
+ if (this.importService.validateGeoapifyData(response)) {
+ this.data = response;
+ this.extractAvailableFields(response.features[0]);
+ this.initializeFieldMappings();
+ } else {
+ this.showError('Format de données invalide');
+ }
+ this.isLoading = false;
+ },
+ error: (error) => {
+ this.showError(error.message);
+ this.isLoading = false;
+ }
+ });
+ }
+ }
+
+ private extractAvailableFields(feature: GeoapifyFeature): void {
+ this.availableFields = Object.keys(feature.properties);
+ }
+
+ private initializeFieldMappings(): void {
+ this.fieldMappings = {};
+ this.targetFields.forEach(field => {
+ this.fieldMappings[field] = '';
+ });
+ }
+
+ updateFieldMapping(targetField: string, sourceField: string): void {
+ this.fieldMappings[targetField] = sourceField;
+ }
+
+ processImport(): void {
+ if (!this.data) return;
+
+ this.isLoading = true;
+ let successCount = 0;
+ let errorCount = 0;
+
+ // Traiter chaque feature
+ this.data.features.forEach(feature => {
+ const poi = this.importService.convertToPOI(feature, this.fieldMappings);
+
+ this.poiService.addPOI(poi).subscribe({
+ next: () => {
+ successCount++;
+ if (successCount + errorCount === this.data!.features.length) {
+ this.showSuccess(`${successCount} POIs importés avec succès`);
+ this.isLoading = false;
+ }
+ },
+ error: (error) => {
+ console.error('Erreur lors de l\'import du POI:', error);
+ errorCount++;
+ if (successCount + errorCount === this.data!.features.length) {
+ this.showError(`${errorCount} erreurs lors de l'import`);
+ this.isLoading = false;
+ }
+ }
+ });
+ });
+ }
+
+ private showError(message: string): void {
+ const notification = document.createElement('div');
+ notification.className = 'fixed top-4 right-4 bg-red-500 text-white px-6 py-3 rounded-lg shadow-lg z-50';
+ notification.textContent = message;
+ document.body.appendChild(notification);
+
+ setTimeout(() => {
+ notification.remove();
+ }, 5000);
+ }
+
+ private showSuccess(message: string): void {
+ const notification = document.createElement('div');
+ notification.className = 'fixed top-4 right-4 bg-green-500 text-white px-6 py-3 rounded-lg shadow-lg z-50';
+ notification.textContent = message;
+ document.body.appendChild(notification);
+
+ setTimeout(() => {
+ notification.remove();
+ }, 5000);
+ }
+}
\ No newline at end of file