@@ -1,20 +1,30 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ChangeDetectorRef, Component } from '@angular/core';
|
||||
import { ChangeDetectorRef, Component, ElementRef, ViewChild } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
||||
import { NgSelectModule } from '@ng-select/ng-select';
|
||||
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
import { catchError, concat, debounceTime, distinctUntilChanged, Observable, of, Subject, Subscription, switchMap, tap } from 'rxjs';
|
||||
import { catchError, concat, debounceTime, distinctUntilChanged, lastValueFrom, Observable, of, Subject, Subscription, switchMap, tap } from 'rxjs';
|
||||
import { BusinessListingCriteria, CityAndStateResult, CommercialPropertyListingCriteria, GeoResult, KeycloakUser, UserListingCriteria } from '../../../../../bizmatch-server/src/models/main.model';
|
||||
import { ModalService } from '../../components/search-modal/modal.service';
|
||||
import { AiService } from '../../services/ai.service';
|
||||
import { CriteriaChangeService } from '../../services/criteria-change.service';
|
||||
import { GeoService } from '../../services/geo.service';
|
||||
import { ListingsService } from '../../services/listings.service';
|
||||
import { SearchService } from '../../services/search.service';
|
||||
import { SelectOptionsService } from '../../services/select-options.service';
|
||||
import { UserService } from '../../services/user.service';
|
||||
import { compareObjects, createEmptyBusinessListingCriteria, createEmptyCommercialPropertyListingCriteria, createEmptyUserListingCriteria, createEnhancedProxy, getCriteriaStateObject, map2User } from '../../utils/utils';
|
||||
import {
|
||||
assignProperties,
|
||||
compareObjects,
|
||||
createEmptyBusinessListingCriteria,
|
||||
createEmptyCommercialPropertyListingCriteria,
|
||||
createEmptyUserListingCriteria,
|
||||
createEnhancedProxy,
|
||||
getCriteriaStateObject,
|
||||
map2User,
|
||||
} from '../../utils/utils';
|
||||
@UntilDestroy()
|
||||
@Component({
|
||||
selector: 'app-home',
|
||||
@@ -24,6 +34,7 @@ import { compareObjects, createEmptyBusinessListingCriteria, createEmptyCommerci
|
||||
styleUrl: './home.component.scss',
|
||||
})
|
||||
export class HomeComponent {
|
||||
placeholders: string[] = ['waterfront property close to Houston less than 1M', 'construction area with beach access close to San Diego'];
|
||||
activeTabAction: 'business' | 'commercialProperty' | 'broker' = 'business';
|
||||
type: string;
|
||||
maxPrice: string;
|
||||
@@ -39,6 +50,18 @@ export class HomeComponent {
|
||||
cityOrState = undefined;
|
||||
private criteriaChangeSubscription: Subscription;
|
||||
numberOfResults$: Observable<number>;
|
||||
|
||||
aiSearch = false;
|
||||
aiSearchText = '';
|
||||
loadingAi = false;
|
||||
@ViewChild('aiSearchInput', { static: false }) searchInput!: ElementRef;
|
||||
typingSpeed: number = 100; // Geschwindigkeit des Tippens (ms)
|
||||
pauseTime: number = 2000; // Pausezeit, bevor der Text verschwindet (ms)
|
||||
index: number = 0;
|
||||
charIndex: number = 0;
|
||||
typingInterval: any;
|
||||
showInput: boolean = true; // Steuerung der Anzeige des Eingabefelds
|
||||
|
||||
public constructor(
|
||||
private router: Router,
|
||||
private modalService: ModalService,
|
||||
@@ -51,6 +74,7 @@ export class HomeComponent {
|
||||
public cdRef: ChangeDetectorRef,
|
||||
private listingService: ListingsService,
|
||||
private userService: UserService,
|
||||
private aiService: AiService,
|
||||
) {}
|
||||
async ngOnInit() {
|
||||
const token = await this.keycloakService.getToken();
|
||||
@@ -193,4 +217,87 @@ export class HomeComponent {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
toggleAiSearch() {
|
||||
this.aiSearch = !this.aiSearch;
|
||||
if (!this.aiSearch) {
|
||||
this.aiSearchText = '';
|
||||
this.stopTypingEffect();
|
||||
} else {
|
||||
setTimeout(() => this.startTypingEffect(), 0);
|
||||
}
|
||||
}
|
||||
ngOnDestroy(): void {
|
||||
clearTimeout(this.typingInterval); // Stelle sicher, dass das Intervall gestoppt wird, wenn die Komponente zerstört wird
|
||||
}
|
||||
|
||||
startTypingEffect(): void {
|
||||
if (!this.aiSearchText) {
|
||||
this.typePlaceholder();
|
||||
}
|
||||
}
|
||||
|
||||
stopTypingEffect(): void {
|
||||
clearTimeout(this.typingInterval);
|
||||
}
|
||||
typePlaceholder(): void {
|
||||
if (!this.searchInput || !this.searchInput.nativeElement) {
|
||||
return; // Falls das Eingabefeld nicht verfügbar ist (z.B. durch ngIf)
|
||||
}
|
||||
|
||||
if (this.aiSearchText) {
|
||||
return; // Stoppe, wenn der Benutzer Text eingegeben hat
|
||||
}
|
||||
|
||||
const inputField = this.searchInput.nativeElement as HTMLInputElement;
|
||||
if (document.activeElement === inputField) {
|
||||
this.stopTypingEffect();
|
||||
return;
|
||||
}
|
||||
|
||||
inputField.placeholder = this.placeholders[this.index].substring(0, this.charIndex);
|
||||
|
||||
if (this.charIndex < this.placeholders[this.index].length) {
|
||||
this.charIndex++;
|
||||
this.typingInterval = setTimeout(() => this.typePlaceholder(), this.typingSpeed);
|
||||
} else {
|
||||
// Nach dem vollständigen Tippen eine Pause einlegen
|
||||
this.typingInterval = setTimeout(() => {
|
||||
inputField.placeholder = ''; // Schlagartiges Löschen des Platzhalters
|
||||
this.charIndex = 0;
|
||||
this.index = (this.index + 1) % this.placeholders.length;
|
||||
this.typingInterval = setTimeout(() => this.typePlaceholder(), this.typingSpeed);
|
||||
}, this.pauseTime);
|
||||
}
|
||||
}
|
||||
async generateAiResponse() {
|
||||
this.loadingAi = true;
|
||||
const result = await this.aiService.generateAiReponse(this.aiSearchText);
|
||||
console.log(result);
|
||||
let criteria: BusinessListingCriteria | CommercialPropertyListingCriteria | UserListingCriteria | any;
|
||||
if (result.criteriaType === 'businessListings') {
|
||||
this.changeTab('business');
|
||||
criteria = result as BusinessListingCriteria;
|
||||
} else if (result.criteriaType === 'commercialPropertyListings') {
|
||||
this.changeTab('commercialProperty');
|
||||
criteria = result as CommercialPropertyListingCriteria;
|
||||
} else {
|
||||
this.changeTab('broker');
|
||||
criteria = result as UserListingCriteria;
|
||||
}
|
||||
const city = criteria.city as string;
|
||||
if (city && city.length > 0) {
|
||||
let results = await lastValueFrom(this.geoService.findCitiesStartingWith(city, criteria.state));
|
||||
if (results.length > 0) {
|
||||
criteria.city = results[0];
|
||||
} else {
|
||||
criteria.city = null;
|
||||
}
|
||||
}
|
||||
if (criteria.radius && criteria.radius.length > 0) {
|
||||
criteria.radius = parseInt(criteria.radius);
|
||||
}
|
||||
this.loadingAi = false;
|
||||
this.criteria = assignProperties(this.criteria, criteria);
|
||||
this.search();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user