💄 Handle multiple GMaps API results

This commit is contained in:
itskovacs 2025-11-02 00:18:32 +01:00
parent 65865f2e2d
commit 4b2a784189
5 changed files with 85 additions and 4 deletions

View File

@ -0,0 +1,24 @@
<div class="divide-y divide-gray-200 dark:divide-gray-700">
@for (r of results; track r.name) {
<div class="flex items-center justify-between gap-4 p-4 cursor-pointer hover:bg-gray-50" (click)="closeDialog(r)">
<div class="flex flex-1 min-w-0 items-center gap-2">
<div class="shrink-0">
<img class="size-12 rounded-full" src="favicon.png">
</div>
<div>
<p class="font-medium text-gray-900 truncate dark:text-white">
{{ r.name }}
</p>
<p class="text-sm text-gray-500 truncate dark:text-gray-400">
{{ r.description.split('\n')[0] }}
</p>
</div>
</div>
<div class="text-gray-900 dark:text-white">
-
</div>
</div>
}
</div>

View File

@ -0,0 +1,26 @@
import { Component } from '@angular/core';
import { ButtonModule } from 'primeng/button';
import { DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog';
import { GooglePlaceResult } from '../../types/poi';
@Component({
selector: 'app-place-create-gmaps-modal',
imports: [ButtonModule],
standalone: true,
templateUrl: './place-create-gmaps-modal.component.html',
styleUrl: './place-create-gmaps-modal.component.scss',
})
export class PlaceCreateGmapsModalComponent {
results: GooglePlaceResult[];
constructor(
private ref: DynamicDialogRef,
private config: DynamicDialogConfig,
) {
this.results = this.config.data;
}
closeDialog(data: GooglePlaceResult) {
this.ref.close(data);
}
}

View File

@ -6,7 +6,8 @@
<label for="name">Name</label>
</p-floatlabel>
<p-button icon="pi pi-sparkles" variant="text" [disabled]="!placeForm.get('name')!.value"
class="absolute right-2 top-1/2 -translate-y-1/2" pTooltip="Query GMaps API" (click)="gmapsSearchText()" />
class="absolute right-2 top-1/2 -translate-y-1/2" pTooltip="Complete using GMaps API"
(click)="gmapsSearchText()" />
</div>
<p-floatlabel variant="in">

View File

@ -2,23 +2,24 @@ import { Component } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import { ButtonModule } from 'primeng/button';
import { DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog';
import { DialogService, DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog';
import { FloatLabelModule } from 'primeng/floatlabel';
import { InputTextModule } from 'primeng/inputtext';
import { SelectModule } from 'primeng/select';
import { TextareaModule } from 'primeng/textarea';
import { Observable } from 'rxjs';
import { Observable, take } from 'rxjs';
import { AsyncPipe } from '@angular/common';
import { InputGroupModule } from 'primeng/inputgroup';
import { InputGroupAddonModule } from 'primeng/inputgroupaddon';
import { ApiService } from '../../services/api.service';
import { UtilsService } from '../../services/utils.service';
import { FocusTrapModule } from 'primeng/focustrap';
import { Category, Place } from '../../types/poi';
import { Category, GooglePlaceResult, Place } from '../../types/poi';
import { CheckboxModule } from 'primeng/checkbox';
import { TooltipModule } from 'primeng/tooltip';
import { checkAndParseLatLng, formatLatLng } from '../../shared/latlng-parser';
import { InputNumberModule } from 'primeng/inputnumber';
import { PlaceCreateGmapsModalComponent } from '../place-create-gmaps-modal/place-create-gmaps-modal.component';
@Component({
selector: 'app-place-create-modal',
@ -54,6 +55,7 @@ export class PlaceCreateModalComponent {
private ref: DynamicDialogRef,
private apiService: ApiService,
private utilsService: UtilsService,
private dialogService: DialogService,
private fb: FormBuilder,
private config: DynamicDialogConfig,
) {
@ -215,6 +217,34 @@ export class PlaceCreateModalComponent {
this.placeForm.get('category')?.markAsDirty();
return;
}
const modal: DynamicDialogRef = this.dialogService.open(PlaceCreateGmapsModalComponent, {
header: 'Select GMaps Place',
modal: true,
appendTo: 'body',
closable: true,
dismissableMask: true,
data: results,
width: '40vw',
breakpoints: {
'960px': '70vw',
'640px': '90vw',
},
})!;
modal.onClose.pipe(take(1)).subscribe({
next: (result: GooglePlaceResult | null) => {
if (!result) return;
const r = result;
this.placeForm.patchValue({
...r,
lat: formatLatLng(r.lat),
lng: formatLatLng(r.lng),
place: r.name || '',
});
this.placeForm.get('category')?.markAsDirty();
},
});
},
});
}