213 lines
8.5 KiB
TypeScript
213 lines
8.5 KiB
TypeScript
import { CommonModule } from '@angular/common';
|
|
import { ChangeDetectorRef, Component } 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 onChange from 'on-change';
|
|
import { catchError, concat, debounceTime, distinctUntilChanged, 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 { 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, getCriteriaStateObject, map2User } from '../../utils/utils';
|
|
@UntilDestroy()
|
|
@Component({
|
|
selector: 'app-home',
|
|
standalone: true,
|
|
imports: [CommonModule, FormsModule, RouterModule, NgSelectModule],
|
|
templateUrl: './home.component.html',
|
|
styleUrl: './home.component.scss',
|
|
})
|
|
export class HomeComponent {
|
|
activeTabAction: 'business' | 'commercialProperty' | 'broker' = 'business';
|
|
type: string;
|
|
maxPrice: string;
|
|
minPrice: string;
|
|
criteria: BusinessListingCriteria | CommercialPropertyListingCriteria | UserListingCriteria;
|
|
states = [];
|
|
isMenuOpen = false;
|
|
user: KeycloakUser;
|
|
prompt: string;
|
|
cities$: Observable<CityAndStateResult[]>;
|
|
cityLoading = false;
|
|
cityInput$ = new Subject<string>();
|
|
cityOrState = undefined;
|
|
private criteriaChangeSubscription: Subscription;
|
|
numberOfResults$: Observable<number>;
|
|
public constructor(
|
|
private router: Router,
|
|
private modalService: ModalService,
|
|
private searchService: SearchService,
|
|
private activatedRoute: ActivatedRoute,
|
|
public selectOptions: SelectOptionsService,
|
|
public keycloakService: KeycloakService,
|
|
private criteriaChangeService: CriteriaChangeService,
|
|
private geoService: GeoService,
|
|
public cdRef: ChangeDetectorRef,
|
|
private listingService: ListingsService,
|
|
private userService: UserService,
|
|
) {}
|
|
async ngOnInit() {
|
|
const token = await this.keycloakService.getToken();
|
|
sessionStorage.removeItem('business_criteria');
|
|
sessionStorage.removeItem('commercialProperty_criteria');
|
|
sessionStorage.removeItem('broker_criteria');
|
|
this.criteria = this.createEnhancedProxy(getCriteriaStateObject('business'));
|
|
this.user = map2User(token);
|
|
this.loadCities();
|
|
this.setupCriteriaChangeListener();
|
|
}
|
|
async changeTab(tabname: 'business' | 'commercialProperty' | 'broker') {
|
|
this.activeTabAction = tabname;
|
|
if ('business' === tabname) {
|
|
this.criteria = this.createEnhancedProxy(getCriteriaStateObject('business'));
|
|
} else if ('commercialProperty' === tabname) {
|
|
this.criteria = this.createEnhancedProxy(getCriteriaStateObject('commercialProperty'));
|
|
} else if ('broker' === tabname) {
|
|
this.criteria = this.createEnhancedProxy(getCriteriaStateObject('broker'));
|
|
} else {
|
|
this.criteria = undefined;
|
|
}
|
|
}
|
|
private createEnhancedProxy(obj: any) {
|
|
const component = this;
|
|
|
|
const sessionStorageHandler = function (path, value, previous, applyData) {
|
|
let criteriaType = this.criteriaType;
|
|
sessionStorage.setItem(`${criteriaType}_criteria`, JSON.stringify(this));
|
|
};
|
|
|
|
return onChange(obj, function (path, value, previous, applyData) {
|
|
// Call the original sessionStorageHandler
|
|
sessionStorageHandler.call(this, path, value, previous, applyData);
|
|
|
|
// Notify about the criteria change using the component's context
|
|
component.criteriaChangeService.notifyCriteriaChange();
|
|
});
|
|
}
|
|
search() {
|
|
this.router.navigate([`${this.activeTabAction}Listings`]);
|
|
}
|
|
private setupCriteriaChangeListener() {
|
|
this.criteriaChangeSubscription = this.criteriaChangeService.criteriaChange$.pipe(untilDestroyed(this), debounceTime(400)).subscribe(() => this.setTotalNumberOfResults());
|
|
}
|
|
login() {
|
|
this.keycloakService.login({
|
|
redirectUri: window.location.href,
|
|
});
|
|
}
|
|
register() {
|
|
this.keycloakService.register({ redirectUri: `${window.location.origin}/account` });
|
|
}
|
|
toggleMenu() {
|
|
this.isMenuOpen = !this.isMenuOpen;
|
|
}
|
|
onTypesChange(value) {
|
|
if (value === '') {
|
|
// Wenn keine Option ausgewählt ist, setzen Sie types zurück auf ein leeres Array
|
|
this.criteria.types = [];
|
|
} else {
|
|
this.criteria.types = [value];
|
|
}
|
|
}
|
|
onRadiusChange(value) {
|
|
if (value === 'null') {
|
|
// Wenn keine Option ausgewählt ist, setzen Sie types zurück auf ein leeres Array
|
|
this.criteria.radius = null;
|
|
} else {
|
|
this.criteria.radius = parseInt(value);
|
|
}
|
|
}
|
|
async openModal() {
|
|
const accepted = await this.modalService.showModal(this.criteria);
|
|
if (accepted) {
|
|
//this.searchService.search(this.criteria);
|
|
this.router.navigate([`${this.activeTabAction}Listings`]);
|
|
}
|
|
}
|
|
private loadCities() {
|
|
this.cities$ = concat(
|
|
of([]), // default items
|
|
this.cityInput$.pipe(
|
|
distinctUntilChanged(),
|
|
tap(() => (this.cityLoading = true)),
|
|
switchMap(term =>
|
|
//this.geoService.findCitiesStartingWith(term).pipe(
|
|
this.geoService.findCitiesAndStatesStartingWith(term).pipe(
|
|
catchError(() => of([])), // empty list on error
|
|
// map(cities => cities.map(city => city.city)), // transform the list of objects to a list of city names
|
|
tap(() => (this.cityLoading = false)),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
trackByFn(item: GeoResult) {
|
|
return item.id;
|
|
}
|
|
setCityOrState(cityOrState: CityAndStateResult) {
|
|
if (cityOrState) {
|
|
if (cityOrState.type === 'state') {
|
|
this.criteria.state = cityOrState.state_code;
|
|
} else {
|
|
this.criteria.city = cityOrState.name;
|
|
this.criteria.state = cityOrState.state_code;
|
|
this.criteria.searchType = 'radius';
|
|
this.criteria.radius = 20;
|
|
}
|
|
} else {
|
|
this.criteria.state = null;
|
|
this.criteria.city = null;
|
|
this.criteria.radius = null;
|
|
this.criteria.searchType = 'exact';
|
|
}
|
|
}
|
|
getTypes() {
|
|
if (this.criteria.criteriaType === 'business') {
|
|
return this.selectOptions.typesOfBusiness;
|
|
} else if (this.criteria.criteriaType === 'commercialProperty') {
|
|
return this.selectOptions.typesOfCommercialProperty;
|
|
} else {
|
|
return this.selectOptions.customerSubTypes;
|
|
}
|
|
}
|
|
getPlaceholderLabel() {
|
|
if (this.criteria.criteriaType === 'business') {
|
|
return 'Business Type';
|
|
} else if (this.criteria.criteriaType === 'commercialProperty') {
|
|
return 'Property Type';
|
|
} else {
|
|
return 'Professional Type';
|
|
}
|
|
}
|
|
setTotalNumberOfResults() {
|
|
if (this.criteria) {
|
|
console.log(`Getting total number of results for ${this.criteria.criteriaType}`);
|
|
if (this.criteria.criteriaType === 'business' || this.criteria.criteriaType === 'commercialProperty') {
|
|
this.numberOfResults$ = this.listingService.getNumberOfListings(this.criteria, this.criteria.criteriaType);
|
|
} else if (this.criteria.criteriaType === 'broker') {
|
|
this.numberOfResults$ = this.userService.getNumberOfBroker(this.criteria);
|
|
} else {
|
|
this.numberOfResults$ = of();
|
|
}
|
|
}
|
|
}
|
|
getNumberOfFiltersSet() {
|
|
if (this.criteria?.criteriaType === 'broker') {
|
|
return compareObjects(createEmptyUserListingCriteria(), this.criteria, ['start', 'length', 'page', 'searchType', 'radius']);
|
|
} else if (this.criteria?.criteriaType === 'business') {
|
|
return compareObjects(createEmptyBusinessListingCriteria(), this.criteria, ['start', 'length', 'page', 'searchType', 'radius']);
|
|
} else if (this.criteria?.criteriaType === 'commercialProperty') {
|
|
return compareObjects(createEmptyCommercialPropertyListingCriteria(), this.criteria, ['start', 'length', 'page', 'searchType', 'radius']);
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
}
|