This commit is contained in:
parent
4efa6c9d77
commit
4dcff1d883
|
|
@ -69,11 +69,11 @@ export interface ListCriteria {
|
||||||
state: string;
|
state: string;
|
||||||
city: GeoResult;
|
city: GeoResult;
|
||||||
prompt: string;
|
prompt: string;
|
||||||
sortBy: SortByOptions;
|
|
||||||
searchType: 'exact' | 'radius';
|
searchType: 'exact' | 'radius';
|
||||||
// radius: '5' | '20' | '50' | '100' | '200' | '300' | '400' | '500';
|
// radius: '5' | '20' | '50' | '100' | '200' | '300' | '400' | '500';
|
||||||
radius: number;
|
radius: number;
|
||||||
criteriaType: 'businessListings' | 'commercialPropertyListings' | 'brokerListings';
|
criteriaType: 'businessListings' | 'commercialPropertyListings' | 'brokerListings';
|
||||||
|
sortBy?: SortByOptions;
|
||||||
}
|
}
|
||||||
export interface BusinessListingCriteria extends ListCriteria {
|
export interface BusinessListingCriteria extends ListCriteria {
|
||||||
minPrice: number;
|
minPrice: number;
|
||||||
|
|
|
||||||
|
|
@ -6,32 +6,23 @@
|
||||||
<div class="flex items-center md:order-2 space-x-3 rtl:space-x-reverse">
|
<div class="flex items-center md:order-2 space-x-3 rtl:space-x-reverse">
|
||||||
<!-- Filter button -->
|
<!-- Filter button -->
|
||||||
@if(isFilterUrl()){
|
@if(isFilterUrl()){
|
||||||
<!-- <button
|
|
||||||
type="button"
|
|
||||||
#triggerButton
|
|
||||||
(click)="openModal()"
|
|
||||||
id="filterDropdownButton"
|
|
||||||
class="max-sm:hidden px-4 py-2 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-lg hover:bg-gray-100 hover:text-blue-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
|
|
||||||
>
|
|
||||||
<i class="fas fa-filter mr-2"></i>Filter ({{ getNumberOfFiltersSet() }})
|
|
||||||
</button> -->
|
|
||||||
<!-- Sort button -->
|
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
id="sortDropdownButton"
|
id="sortDropdownButton"
|
||||||
class="max-sm:hidden px-4 py-2 text-sm font-medium bg-white border border-gray-200 rounded-lg hover:bg-gray-100 hover:text-blue-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
|
class="max-sm:hidden px-4 py-2 text-sm font-medium bg-white border border-gray-200 rounded-lg hover:bg-gray-100 hover:text-blue-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
|
||||||
(click)="toggleSortDropdown()"
|
(click)="toggleSortDropdown()"
|
||||||
[ngClass]="{ 'text-blue-500': selectOptions.getSortByOption(criteria?.sortBy) !== 'Sort', 'text-gray-900': selectOptions.getSortByOption(criteria?.sortBy) === 'Sort' }"
|
[ngClass]="{ 'text-blue-500': selectOptions.getSortByOption(sortBy) !== 'Sort', 'text-gray-900': selectOptions.getSortByOption(sortBy) === 'Sort' }"
|
||||||
>
|
>
|
||||||
<i class="fas fa-sort mr-2"></i>{{ selectOptions.getSortByOption(criteria?.sortBy) }}
|
<i class="fas fa-sort mr-2"></i>{{ selectOptions.getSortByOption(sortBy) }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- Sort options dropdown -->
|
<!-- Sort options dropdown -->
|
||||||
<div *ngIf="sortDropdownVisible" class="absolute right-0 z-50 w-48 md:mt-2 max-md:mt-20 max-md:mr-[-2.5rem] bg-white border border-gray-200 rounded-lg drop-shadow-custom-bg dark:bg-gray-800 dark:border-gray-600">
|
<div *ngIf="sortDropdownVisible" class="absolute right-0 z-50 w-48 md:mt-2 max-md:mt-20 max-md:mr-[-2.5rem] bg-white border border-gray-200 rounded-lg drop-shadow-custom-bg dark:bg-gray-800 dark:border-gray-600">
|
||||||
<ul class="py-1 text-sm text-gray-700 dark:text-gray-200">
|
<ul class="py-1 text-sm text-gray-700 dark:text-gray-200">
|
||||||
@for(item of sortByOptions; track item){
|
@for(item of sortByOptions; track item){
|
||||||
<li (click)="sortBy(item.value)" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-700 cursor-pointer">{{ item.selectName ? item.selectName : item.name }}</li>
|
<li (click)="sortByFct(item.value)" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-700 cursor-pointer">{{ item.selectName ? item.selectName : item.name }}</li>
|
||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -217,23 +208,14 @@
|
||||||
</div>
|
</div>
|
||||||
<!-- Mobile filter button -->
|
<!-- Mobile filter button -->
|
||||||
<div class="md:hidden flex justify-center pb-4">
|
<div class="md:hidden flex justify-center pb-4">
|
||||||
<!-- <button
|
|
||||||
(click)="openModal()"
|
|
||||||
type="button"
|
|
||||||
id="filterDropdownMobileButton"
|
|
||||||
class="w-full mx-4 px-4 py-2 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-lg hover:bg-gray-100 hover:text-blue-700 focus:ring-2 focus:ring-blue-700 focus:text-blue-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
|
|
||||||
>
|
|
||||||
<i class="fas fa-filter mr-2"></i>Filter ({{ getNumberOfFiltersSet() }})
|
|
||||||
</button> -->
|
|
||||||
<!-- Sorting -->
|
|
||||||
<button
|
<button
|
||||||
(click)="toggleSortDropdown()"
|
(click)="toggleSortDropdown()"
|
||||||
type="button"
|
type="button"
|
||||||
id="sortDropdownMobileButton"
|
id="sortDropdownMobileButton"
|
||||||
class="mx-4 w-1/2 px-4 py-2 text-sm font-medium bg-white border border-gray-200 rounded-lg hover:bg-gray-100 hover:text-blue-700 focus:ring-2 focus:ring-blue-700 focus:text-blue-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
|
class="mx-4 w-1/2 px-4 py-2 text-sm font-medium bg-white border border-gray-200 rounded-lg hover:bg-gray-100 hover:text-blue-700 focus:ring-2 focus:ring-blue-700 focus:text-blue-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
|
||||||
[ngClass]="{ 'text-blue-500': selectOptions.getSortByOption(criteria?.sortBy) !== 'Sort', 'text-gray-900': selectOptions.getSortByOption(criteria?.sortBy) === 'Sort' }"
|
[ngClass]="{ 'text-blue-500': selectOptions.getSortByOption(sortBy) !== 'Sort', 'text-gray-900': selectOptions.getSortByOption(sortBy) === 'Sort' }"
|
||||||
>
|
>
|
||||||
<i class="fas fa-sort mr-2"></i>{{ selectOptions.getSortByOption(criteria?.sortBy) }}
|
<i class="fas fa-sort mr-2"></i>{{ selectOptions.getSortByOption(sortBy) }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ import { SearchService } from '../../services/search.service';
|
||||||
import { SelectOptionsService } from '../../services/select-options.service';
|
import { SelectOptionsService } from '../../services/select-options.service';
|
||||||
import { SharedService } from '../../services/shared.service';
|
import { SharedService } from '../../services/shared.service';
|
||||||
import { UserService } from '../../services/user.service';
|
import { UserService } from '../../services/user.service';
|
||||||
import { assignProperties, compareObjects, createEmptyBusinessListingCriteria, createEmptyCommercialPropertyListingCriteria, createEmptyUserListingCriteria, getCriteriaProxy, map2User } from '../../utils/utils';
|
import { assignProperties, createEmptyUserListingCriteria, getCriteriaProxy, map2User } from '../../utils/utils';
|
||||||
import { DropdownComponent } from '../dropdown/dropdown.component';
|
import { DropdownComponent } from '../dropdown/dropdown.component';
|
||||||
import { ModalService } from '../search-modal/modal.service';
|
import { ModalService } from '../search-modal/modal.service';
|
||||||
@UntilDestroy()
|
@UntilDestroy()
|
||||||
|
|
@ -49,6 +49,7 @@ export class HeaderComponent {
|
||||||
sortByOptions: KeyValueAsSortBy[] = [];
|
sortByOptions: KeyValueAsSortBy[] = [];
|
||||||
numberOfBroker$: Observable<number>;
|
numberOfBroker$: Observable<number>;
|
||||||
numberOfCommercial$: Observable<number>;
|
numberOfCommercial$: Observable<number>;
|
||||||
|
sortBy: SortByOptions = null; // Neu: Separate Property
|
||||||
constructor(
|
constructor(
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private userService: UserService,
|
private userService: UserService,
|
||||||
|
|
@ -76,7 +77,7 @@ export class HeaderComponent {
|
||||||
this.profileUrl = this.user.hasProfile ? `${this.env.imageBaseUrl}/pictures/profile/${emailToDirName(this.user.email)}.avif?_ts=${new Date().getTime()}` : `/assets/images/placeholder.png`;
|
this.profileUrl = this.user.hasProfile ? `${this.env.imageBaseUrl}/pictures/profile/${emailToDirName(this.user.email)}.avif?_ts=${new Date().getTime()}` : `/assets/images/placeholder.png`;
|
||||||
}
|
}
|
||||||
this.numberOfBroker$ = this.userService.getNumberOfBroker(createEmptyUserListingCriteria());
|
this.numberOfBroker$ = this.userService.getNumberOfBroker(createEmptyUserListingCriteria());
|
||||||
this.numberOfCommercial$ = this.listingService.getNumberOfListings(createEmptyCommercialPropertyListingCriteria(), 'commercialProperty');
|
this.numberOfCommercial$ = this.listingService.getNumberOfListings('commercialProperty');
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
initFlowbite();
|
initFlowbite();
|
||||||
}, 10);
|
}, 10);
|
||||||
|
|
@ -87,7 +88,7 @@ export class HeaderComponent {
|
||||||
|
|
||||||
this.checkCurrentRoute(this.router.url);
|
this.checkCurrentRoute(this.router.url);
|
||||||
this.setupSortByOptions();
|
this.setupSortByOptions();
|
||||||
|
this.loadSortBy(); // Neu
|
||||||
this.routerSubscription = this.router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe((event: any) => {
|
this.routerSubscription = this.router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe((event: any) => {
|
||||||
this.checkCurrentRoute(event.urlAfterRedirects);
|
this.checkCurrentRoute(event.urlAfterRedirects);
|
||||||
this.setupSortByOptions();
|
this.setupSortByOptions();
|
||||||
|
|
@ -99,31 +100,56 @@ export class HeaderComponent {
|
||||||
this.user = u;
|
this.user = u;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
private loadSortBy() {
|
||||||
|
const storedSortBy = sessionStorage.getItem(this.getSortByKey());
|
||||||
|
this.sortBy = storedSortBy ? (storedSortBy as SortByOptions) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private saveSortBy() {
|
||||||
|
sessionStorage.setItem(this.getSortByKey(), this.sortBy);
|
||||||
|
}
|
||||||
|
private getSortByKey(): string {
|
||||||
|
// Basierend auf Route (für Business/Commercial unterscheiden)
|
||||||
|
if (this.isBusinessListing()) return 'businessSortBy';
|
||||||
|
if (this.isCommercialPropertyListing()) return 'commercialSortBy';
|
||||||
|
if (this.isProfessionalListing()) return 'professionalsSortBy';
|
||||||
|
return 'defaultSortBy'; // Fallback
|
||||||
|
}
|
||||||
|
sortByFct(selectedSortBy: SortByOptions) {
|
||||||
|
this.sortBy = selectedSortBy;
|
||||||
|
this.saveSortBy(); // Speichere separat
|
||||||
|
this.sortDropdownVisible = false;
|
||||||
|
this.searchService.search(this.criteria.criteriaType); // Neu: Übergebe sortBy separat
|
||||||
|
}
|
||||||
private checkCurrentRoute(url: string): void {
|
private checkCurrentRoute(url: string): void {
|
||||||
this.baseRoute = url.split('/')[1]; // Nimmt den ersten Teil der Route nach dem ersten '/'
|
this.baseRoute = url.split('/')[1]; // Nimmt den ersten Teil der Route nach dem ersten '/'
|
||||||
const specialRoutes = [, '', ''];
|
const specialRoutes = [, '', ''];
|
||||||
this.criteria = getCriteriaProxy(this.baseRoute, this);
|
this.criteria = getCriteriaProxy(this.baseRoute, this);
|
||||||
// this.searchService.search(this.criteria);
|
|
||||||
}
|
}
|
||||||
setupSortByOptions() {
|
setupSortByOptions() {
|
||||||
this.sortByOptions = [];
|
this.sortByOptions = [];
|
||||||
|
let storedSortBy = null;
|
||||||
if (this.isProfessionalListing()) {
|
if (this.isProfessionalListing()) {
|
||||||
this.sortByOptions = [...this.sortByOptions, ...this.selectOptions.sortByOptions.filter(s => s.type === 'professional')];
|
this.sortByOptions = [...this.sortByOptions, ...this.selectOptions.sortByOptions.filter(s => s.type === 'professional')];
|
||||||
|
storedSortBy = sessionStorage.getItem('professionalsSortBy');
|
||||||
}
|
}
|
||||||
if (this.isBusinessListing()) {
|
if (this.isBusinessListing()) {
|
||||||
this.sortByOptions = [...this.sortByOptions, ...this.selectOptions.sortByOptions.filter(s => s.type === 'business' || s.type === 'listing')];
|
this.sortByOptions = [...this.sortByOptions, ...this.selectOptions.sortByOptions.filter(s => s.type === 'business' || s.type === 'listing')];
|
||||||
|
storedSortBy = sessionStorage.getItem('businessSortBy');
|
||||||
}
|
}
|
||||||
if (this.isCommercialPropertyListing()) {
|
if (this.isCommercialPropertyListing()) {
|
||||||
this.sortByOptions = [...this.sortByOptions, ...this.selectOptions.sortByOptions.filter(s => s.type === 'commercial' || s.type === 'listing')];
|
this.sortByOptions = [...this.sortByOptions, ...this.selectOptions.sortByOptions.filter(s => s.type === 'commercial' || s.type === 'listing')];
|
||||||
|
storedSortBy = sessionStorage.getItem('commercialSortBy');
|
||||||
}
|
}
|
||||||
this.sortByOptions = [...this.sortByOptions, ...this.selectOptions.sortByOptions.filter(s => !s.type)];
|
this.sortByOptions = [...this.sortByOptions, ...this.selectOptions.sortByOptions.filter(s => !s.type)];
|
||||||
|
this.sortBy = storedSortBy && storedSortBy !== 'null' ? (storedSortBy as SortByOptions) : null;
|
||||||
}
|
}
|
||||||
ngAfterViewInit() {}
|
ngAfterViewInit() {}
|
||||||
|
|
||||||
async openModal() {
|
async openModal() {
|
||||||
const modalResult = await this.modalService.showModal(this.criteria);
|
const modalResult = await this.modalService.showModal(this.criteria);
|
||||||
if (modalResult.accepted) {
|
if (modalResult.accepted) {
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search(this.criteria.criteriaType);
|
||||||
} else {
|
} else {
|
||||||
this.criteria = assignProperties(this.criteria, modalResult.criteria);
|
this.criteria = assignProperties(this.criteria, modalResult.criteria);
|
||||||
}
|
}
|
||||||
|
|
@ -147,9 +173,7 @@ export class HeaderComponent {
|
||||||
isProfessionalListing(): boolean {
|
isProfessionalListing(): boolean {
|
||||||
return ['/brokerListings'].includes(this.router.url);
|
return ['/brokerListings'].includes(this.router.url);
|
||||||
}
|
}
|
||||||
// isSortingUrl(): boolean {
|
|
||||||
// return ['/businessListings', '/commercialPropertyListings'].includes(this.router.url);
|
|
||||||
// }
|
|
||||||
closeDropdown() {
|
closeDropdown() {
|
||||||
const dropdownButton = document.getElementById('user-menu-button');
|
const dropdownButton = document.getElementById('user-menu-button');
|
||||||
const dropdownMenu = this.user ? document.getElementById('user-login') : document.getElementById('user-unknown');
|
const dropdownMenu = this.user ? document.getElementById('user-login') : document.getElementById('user-unknown');
|
||||||
|
|
@ -180,23 +204,7 @@ export class HeaderComponent {
|
||||||
this.destroy$.next();
|
this.destroy$.next();
|
||||||
this.destroy$.complete();
|
this.destroy$.complete();
|
||||||
}
|
}
|
||||||
getNumberOfFiltersSet() {
|
|
||||||
if (this.criteria?.criteriaType === 'brokerListings') {
|
|
||||||
return compareObjects(createEmptyUserListingCriteria(), this.criteria, ['start', 'length', 'page', 'searchType', 'radius', 'sortBy']);
|
|
||||||
} else if (this.criteria?.criteriaType === 'businessListings') {
|
|
||||||
return compareObjects(createEmptyBusinessListingCriteria(), this.criteria, ['start', 'length', 'page', 'searchType', 'radius', 'sortBy']);
|
|
||||||
} else if (this.criteria?.criteriaType === 'commercialPropertyListings') {
|
|
||||||
return compareObjects(createEmptyCommercialPropertyListingCriteria(), this.criteria, ['start', 'length', 'page', 'searchType', 'radius', 'sortBy']);
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sortBy(sortBy: SortByOptions) {
|
|
||||||
this.criteria.sortBy = sortBy;
|
|
||||||
this.sortDropdownVisible = false;
|
|
||||||
this.searchService.search(this.criteria);
|
|
||||||
}
|
|
||||||
toggleSortDropdown() {
|
toggleSortDropdown() {
|
||||||
this.sortDropdownVisible = !this.sortDropdownVisible;
|
this.sortDropdownVisible = !this.sortDropdownVisible;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -95,11 +95,11 @@ export class SearchModalCommercialComponent {
|
||||||
this.criteria.title = null;
|
this.criteria.title = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search(this.criteria.criteriaType);
|
||||||
}
|
}
|
||||||
clearFilter() {
|
clearFilter() {
|
||||||
resetCommercialPropertyListingCriteria(this.criteria);
|
resetCommercialPropertyListingCriteria(this.criteria);
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search(this.criteria.criteriaType);
|
||||||
}
|
}
|
||||||
// Handle category change
|
// Handle category change
|
||||||
onCategoryChange(event: any[]) {
|
onCategoryChange(event: any[]) {
|
||||||
|
|
@ -116,7 +116,7 @@ export class SearchModalCommercialComponent {
|
||||||
this.criteria.types.splice(index, 1);
|
this.criteria.types.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search(this.criteria.criteriaType);
|
||||||
}
|
}
|
||||||
private loadCounties() {
|
private loadCounties() {
|
||||||
this.counties$ = concat(
|
this.counties$ = concat(
|
||||||
|
|
@ -135,7 +135,7 @@ export class SearchModalCommercialComponent {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
onCriteriaChange() {
|
onCriteriaChange() {
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search(this.criteria.criteriaType);
|
||||||
}
|
}
|
||||||
setCity(city) {
|
setCity(city) {
|
||||||
if (city) {
|
if (city) {
|
||||||
|
|
@ -146,7 +146,7 @@ export class SearchModalCommercialComponent {
|
||||||
this.criteria.radius = null;
|
this.criteria.radius = null;
|
||||||
this.criteria.searchType = 'exact';
|
this.criteria.searchType = 'exact';
|
||||||
}
|
}
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search(this.criteria.criteriaType);
|
||||||
}
|
}
|
||||||
setState(state: string) {
|
setState(state: string) {
|
||||||
if (state) {
|
if (state) {
|
||||||
|
|
@ -155,11 +155,11 @@ export class SearchModalCommercialComponent {
|
||||||
this.criteria.state = null;
|
this.criteria.state = null;
|
||||||
this.setCity(null);
|
this.setCity(null);
|
||||||
}
|
}
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search(this.criteria.criteriaType);
|
||||||
}
|
}
|
||||||
setRadius(radius: number) {
|
setRadius(radius: number) {
|
||||||
this.criteria.radius = radius;
|
this.criteria.radius = radius;
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search(this.criteria.criteriaType);
|
||||||
}
|
}
|
||||||
private setupCriteriaChangeListener() {
|
private setupCriteriaChangeListener() {
|
||||||
this.criteriaChangeSubscription = this.criteriaChangeService.criteriaChange$.pipe(debounceTime(400)).subscribe(() => {
|
this.criteriaChangeSubscription = this.criteriaChangeService.criteriaChange$.pipe(debounceTime(400)).subscribe(() => {
|
||||||
|
|
@ -181,14 +181,14 @@ export class SearchModalCommercialComponent {
|
||||||
}
|
}
|
||||||
closeAndSearch() {
|
closeAndSearch() {
|
||||||
this.modalService.accept();
|
this.modalService.accept();
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search(this.criteria.criteriaType);
|
||||||
this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
setTotalNumberOfResults() {
|
setTotalNumberOfResults() {
|
||||||
if (this.criteria) {
|
if (this.criteria) {
|
||||||
console.log(`Getting total number of results for ${this.criteria.criteriaType}`);
|
console.log(`Getting total number of results for ${this.criteria.criteriaType}`);
|
||||||
if (this.criteria.criteriaType === 'commercialPropertyListings') {
|
if (this.criteria.criteriaType === 'commercialPropertyListings') {
|
||||||
this.numberOfResults$ = this.listingService.getNumberOfListings(this.criteria, 'commercialProperty');
|
this.numberOfResults$ = this.listingService.getNumberOfListings('commercialProperty');
|
||||||
} else {
|
} else {
|
||||||
this.numberOfResults$ = of();
|
this.numberOfResults$ = of();
|
||||||
}
|
}
|
||||||
|
|
@ -202,7 +202,7 @@ export class SearchModalCommercialComponent {
|
||||||
debouncedSearch() {
|
debouncedSearch() {
|
||||||
clearTimeout(this.debounceTimeout);
|
clearTimeout(this.debounceTimeout);
|
||||||
this.debounceTimeout = setTimeout(() => {
|
this.debounceTimeout = setTimeout(() => {
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search(this.criteria.criteriaType);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -140,12 +140,12 @@ export class SearchModalComponent {
|
||||||
this.criteria.title = null;
|
this.criteria.title = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search(this.criteria.criteriaType);
|
||||||
}
|
}
|
||||||
// Handle category change
|
// Handle category change
|
||||||
onCategoryChange(selectedCategories: string[]) {
|
onCategoryChange(selectedCategories: string[]) {
|
||||||
this.criteria.types = selectedCategories;
|
this.criteria.types = selectedCategories;
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search(this.criteria.criteriaType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle property type change
|
// Handle property type change
|
||||||
|
|
@ -159,7 +159,7 @@ export class SearchModalComponent {
|
||||||
this.criteria[value] = true;
|
this.criteria[value] = true;
|
||||||
}
|
}
|
||||||
this.selectedPropertyType = value;
|
this.selectedPropertyType = value;
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search(this.criteria.criteriaType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update selected property type based on current criteria
|
// Update selected property type based on current criteria
|
||||||
|
|
@ -181,7 +181,7 @@ export class SearchModalComponent {
|
||||||
this.criteria.types.splice(index, 1);
|
this.criteria.types.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search(this.criteria.criteriaType);
|
||||||
}
|
}
|
||||||
private loadCounties() {
|
private loadCounties() {
|
||||||
this.counties$ = concat(
|
this.counties$ = concat(
|
||||||
|
|
@ -200,7 +200,7 @@ export class SearchModalComponent {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
onCriteriaChange() {
|
onCriteriaChange() {
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search(this.criteria.criteriaType);
|
||||||
}
|
}
|
||||||
setCity(city) {
|
setCity(city) {
|
||||||
if (city) {
|
if (city) {
|
||||||
|
|
@ -211,7 +211,7 @@ export class SearchModalComponent {
|
||||||
this.criteria.radius = null;
|
this.criteria.radius = null;
|
||||||
this.criteria.searchType = 'exact';
|
this.criteria.searchType = 'exact';
|
||||||
}
|
}
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search(this.criteria.criteriaType);
|
||||||
}
|
}
|
||||||
setState(state: string) {
|
setState(state: string) {
|
||||||
if (state) {
|
if (state) {
|
||||||
|
|
@ -220,11 +220,11 @@ export class SearchModalComponent {
|
||||||
this.criteria.state = null;
|
this.criteria.state = null;
|
||||||
this.setCity(null);
|
this.setCity(null);
|
||||||
}
|
}
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search(this.criteria.criteriaType);
|
||||||
}
|
}
|
||||||
setRadius(radius: number) {
|
setRadius(radius: number) {
|
||||||
this.criteria.radius = radius;
|
this.criteria.radius = radius;
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search(this.criteria.criteriaType);
|
||||||
}
|
}
|
||||||
private setupCriteriaChangeListener() {
|
private setupCriteriaChangeListener() {
|
||||||
this.criteriaChangeSubscription = this.criteriaChangeService.criteriaChange$.pipe(debounceTime(400)).subscribe(() => {
|
this.criteriaChangeSubscription = this.criteriaChangeService.criteriaChange$.pipe(debounceTime(400)).subscribe(() => {
|
||||||
|
|
@ -246,7 +246,7 @@ export class SearchModalComponent {
|
||||||
}
|
}
|
||||||
closeAndSearch() {
|
closeAndSearch() {
|
||||||
this.modalService.accept();
|
this.modalService.accept();
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search(this.criteria.criteriaType);
|
||||||
this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
isTypeOfBusinessClicked(v: KeyValueStyle) {
|
isTypeOfBusinessClicked(v: KeyValueStyle) {
|
||||||
|
|
@ -259,7 +259,7 @@ export class SearchModalComponent {
|
||||||
if (this.criteria) {
|
if (this.criteria) {
|
||||||
console.log(`Getting total number of results for ${this.criteria.criteriaType}`);
|
console.log(`Getting total number of results for ${this.criteria.criteriaType}`);
|
||||||
if (this.criteria.criteriaType === 'businessListings' || this.criteria.criteriaType === 'commercialPropertyListings') {
|
if (this.criteria.criteriaType === 'businessListings' || this.criteria.criteriaType === 'commercialPropertyListings') {
|
||||||
this.numberOfResults$ = this.listingService.getNumberOfListings(this.criteria, this.criteria.criteriaType === 'businessListings' ? 'business' : 'commercialProperty');
|
this.numberOfResults$ = this.listingService.getNumberOfListings(this.criteria.criteriaType === 'businessListings' ? 'business' : 'commercialProperty');
|
||||||
} else if (this.criteria.criteriaType === 'brokerListings') {
|
} else if (this.criteria.criteriaType === 'brokerListings') {
|
||||||
//this.numberOfResults$ = this.userService.getNumberOfBroker(this.criteria);
|
//this.numberOfResults$ = this.userService.getNumberOfBroker(this.criteria);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -270,7 +270,7 @@ export class SearchModalComponent {
|
||||||
clearFilter() {
|
clearFilter() {
|
||||||
resetBusinessListingCriteria(this.criteria);
|
resetBusinessListingCriteria(this.criteria);
|
||||||
|
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search(this.criteria.criteriaType);
|
||||||
}
|
}
|
||||||
close() {
|
close() {
|
||||||
this.modalService.reject(this.backupCriteria);
|
this.modalService.reject(this.backupCriteria);
|
||||||
|
|
@ -282,12 +282,12 @@ export class SearchModalComponent {
|
||||||
|
|
||||||
// Aktivieren Sie nur die aktuell ausgewählte Checkbox
|
// Aktivieren Sie nur die aktuell ausgewählte Checkbox
|
||||||
this.criteria[checkbox] = value;
|
this.criteria[checkbox] = value;
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search(this.criteria.criteriaType);
|
||||||
}
|
}
|
||||||
debouncedSearch() {
|
debouncedSearch() {
|
||||||
clearTimeout(this.debounceTimeout);
|
clearTimeout(this.debounceTimeout);
|
||||||
this.debounceTimeout = setTimeout(() => {
|
this.debounceTimeout = setTimeout(() => {
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search(this.criteria.criteriaType);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
||||||
import { NgSelectModule } from '@ng-select/ng-select';
|
import { NgSelectModule } from '@ng-select/ng-select';
|
||||||
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
|
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
|
||||||
import { initFlowbite } from 'flowbite';
|
import { initFlowbite } from 'flowbite';
|
||||||
import { catchError, concat, debounceTime, distinctUntilChanged, lastValueFrom, Observable, of, Subject, Subscription, switchMap, tap } from 'rxjs';
|
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 { BusinessListingCriteria, CityAndStateResult, CommercialPropertyListingCriteria, GeoResult, KeycloakUser, UserListingCriteria } from '../../../../../bizmatch-server/src/models/main.model';
|
||||||
import { ModalService } from '../../components/search-modal/modal.service';
|
import { ModalService } from '../../components/search-modal/modal.service';
|
||||||
import { TooltipComponent } from '../../components/tooltip/tooltip.component';
|
import { TooltipComponent } from '../../components/tooltip/tooltip.component';
|
||||||
|
|
@ -18,7 +18,6 @@ import { SearchService } from '../../services/search.service';
|
||||||
import { SelectOptionsService } from '../../services/select-options.service';
|
import { SelectOptionsService } from '../../services/select-options.service';
|
||||||
import { UserService } from '../../services/user.service';
|
import { UserService } from '../../services/user.service';
|
||||||
import {
|
import {
|
||||||
assignProperties,
|
|
||||||
compareObjects,
|
compareObjects,
|
||||||
createEmptyBusinessListingCriteria,
|
createEmptyBusinessListingCriteria,
|
||||||
createEmptyCommercialPropertyListingCriteria,
|
createEmptyCommercialPropertyListingCriteria,
|
||||||
|
|
@ -26,6 +25,7 @@ import {
|
||||||
createEnhancedProxy,
|
createEnhancedProxy,
|
||||||
getCriteriaStateObject,
|
getCriteriaStateObject,
|
||||||
map2User,
|
map2User,
|
||||||
|
removeSortByStorage,
|
||||||
} from '../../utils/utils';
|
} from '../../utils/utils';
|
||||||
@UntilDestroy()
|
@UntilDestroy()
|
||||||
@Component({
|
@Component({
|
||||||
|
|
@ -86,12 +86,13 @@ export class HomeComponent {
|
||||||
initFlowbite();
|
initFlowbite();
|
||||||
}, 0);
|
}, 0);
|
||||||
this.numberOfBroker$ = this.userService.getNumberOfBroker(createEmptyUserListingCriteria());
|
this.numberOfBroker$ = this.userService.getNumberOfBroker(createEmptyUserListingCriteria());
|
||||||
this.numberOfCommercial$ = this.listingService.getNumberOfListings(createEmptyCommercialPropertyListingCriteria(), 'commercialProperty');
|
this.numberOfCommercial$ = this.listingService.getNumberOfListings('commercialProperty');
|
||||||
const token = await this.authService.getToken();
|
const token = await this.authService.getToken();
|
||||||
sessionStorage.removeItem('businessListings');
|
sessionStorage.removeItem('businessListings');
|
||||||
sessionStorage.removeItem('commercialPropertyListings');
|
sessionStorage.removeItem('commercialPropertyListings');
|
||||||
sessionStorage.removeItem('brokerListings');
|
sessionStorage.removeItem('brokerListings');
|
||||||
this.criteria = createEnhancedProxy(getCriteriaStateObject('businessListings'), this);
|
this.criteria = createEnhancedProxy(getCriteriaStateObject('businessListings'), this);
|
||||||
|
removeSortByStorage();
|
||||||
this.user = map2User(token);
|
this.user = map2User(token);
|
||||||
this.loadCities();
|
this.loadCities();
|
||||||
this.setupCriteriaChangeListener();
|
this.setupCriteriaChangeListener();
|
||||||
|
|
@ -201,7 +202,7 @@ export class HomeComponent {
|
||||||
if (this.criteria) {
|
if (this.criteria) {
|
||||||
console.log(`Getting total number of results for ${this.criteria.criteriaType}`);
|
console.log(`Getting total number of results for ${this.criteria.criteriaType}`);
|
||||||
if (this.criteria.criteriaType === 'businessListings' || this.criteria.criteriaType === 'commercialPropertyListings') {
|
if (this.criteria.criteriaType === 'businessListings' || this.criteria.criteriaType === 'commercialPropertyListings') {
|
||||||
this.numberOfResults$ = this.listingService.getNumberOfListings(this.criteria, this.criteria.criteriaType === 'businessListings' ? 'business' : 'commercialProperty');
|
this.numberOfResults$ = this.listingService.getNumberOfListings(this.criteria.criteriaType === 'businessListings' ? 'business' : 'commercialProperty');
|
||||||
} else if (this.criteria.criteriaType === 'brokerListings') {
|
} else if (this.criteria.criteriaType === 'brokerListings') {
|
||||||
this.numberOfResults$ = this.userService.getNumberOfBroker(this.criteria);
|
this.numberOfResults$ = this.userService.getNumberOfBroker(this.criteria);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -273,41 +274,4 @@ export class HomeComponent {
|
||||||
}, this.pauseTime);
|
}, this.pauseTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async generateAiResponse() {
|
|
||||||
this.loadingAi = true;
|
|
||||||
this.aiSearchFailed = false;
|
|
||||||
try {
|
|
||||||
const result = await this.aiService.generateAiReponse(this.aiSearchText);
|
|
||||||
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();
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
this.aiSearchFailed = true;
|
|
||||||
this.loadingAi = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { ChangeDetectorRef, Component } from '@angular/core';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
||||||
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
|
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
|
||||||
import { BusinessListing, User } from '../../../../../../bizmatch-server/src/models/db.model';
|
import { BusinessListing, SortByOptions, User } from '../../../../../../bizmatch-server/src/models/db.model';
|
||||||
import { LISTINGS_PER_PAGE, ListingType, UserListingCriteria, emailToDirName } from '../../../../../../bizmatch-server/src/models/main.model';
|
import { LISTINGS_PER_PAGE, ListingType, UserListingCriteria, emailToDirName } from '../../../../../../bizmatch-server/src/models/main.model';
|
||||||
import { environment } from '../../../../environments/environment';
|
import { environment } from '../../../../environments/environment';
|
||||||
import { CustomerSubTypeComponent } from '../../../components/customer-sub-type/customer-sub-type.component';
|
import { CustomerSubTypeComponent } from '../../../components/customer-sub-type/customer-sub-type.component';
|
||||||
|
|
@ -45,6 +45,7 @@ export class BrokerListingsComponent {
|
||||||
emailToDirName = emailToDirName;
|
emailToDirName = emailToDirName;
|
||||||
page = 1;
|
page = 1;
|
||||||
pageCount = 1;
|
pageCount = 1;
|
||||||
|
sortBy: SortByOptions = null; // Neu: Separate Property
|
||||||
constructor(
|
constructor(
|
||||||
public selectOptions: SelectOptionsService,
|
public selectOptions: SelectOptionsService,
|
||||||
private listingsService: ListingsService,
|
private listingsService: ListingsService,
|
||||||
|
|
@ -60,13 +61,19 @@ export class BrokerListingsComponent {
|
||||||
) {
|
) {
|
||||||
this.criteria = getCriteriaProxy('brokerListings', this) as UserListingCriteria;
|
this.criteria = getCriteriaProxy('brokerListings', this) as UserListingCriteria;
|
||||||
this.init();
|
this.init();
|
||||||
this.searchService.currentCriteria.pipe(untilDestroyed(this)).subscribe(criteria => {
|
this.loadSortBy();
|
||||||
if (criteria && criteria.criteriaType === 'brokerListings') {
|
this.searchService.currentCriteria.pipe(untilDestroyed(this)).subscribe(({ criteria, sortBy }) => {
|
||||||
|
if (criteria.criteriaType === 'brokerListings') {
|
||||||
this.criteria = criteria as UserListingCriteria;
|
this.criteria = criteria as UserListingCriteria;
|
||||||
|
this.sortBy = sortBy || this.sortBy || null;
|
||||||
this.search();
|
this.search();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
private loadSortBy() {
|
||||||
|
const storedSortBy = sessionStorage.getItem('professionalsSortBy');
|
||||||
|
this.sortBy = storedSortBy && storedSortBy !== 'null' ? (storedSortBy as SortByOptions) : null;
|
||||||
|
}
|
||||||
async ngOnInit() {}
|
async ngOnInit() {}
|
||||||
async init() {
|
async init() {
|
||||||
this.search();
|
this.search();
|
||||||
|
|
@ -101,14 +108,14 @@ export class BrokerListingsComponent {
|
||||||
this.criteriaChangeService.notifyCriteriaChange();
|
this.criteriaChangeService.notifyCriteriaChange();
|
||||||
|
|
||||||
// Search with cleared filters
|
// Search with cleared filters
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search('brokerListings');
|
||||||
}
|
}
|
||||||
|
|
||||||
async openFilterModal() {
|
async openFilterModal() {
|
||||||
// Open the search modal with current criteria
|
// Open the search modal with current criteria
|
||||||
const modalResult = await this.modalService.showModal(this.criteria);
|
const modalResult = await this.modalService.showModal(this.criteria);
|
||||||
if (modalResult.accepted) {
|
if (modalResult.accepted) {
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search('brokerListings');
|
||||||
} else {
|
} else {
|
||||||
this.criteria = assignProperties(this.criteria, modalResult.criteria);
|
this.criteria = assignProperties(this.criteria, modalResult.criteria);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { FormsModule } from '@angular/forms';
|
||||||
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
||||||
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
|
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { BusinessListing } from '../../../../../../bizmatch-server/src/models/db.model';
|
import { BusinessListing, SortByOptions } from '../../../../../../bizmatch-server/src/models/db.model';
|
||||||
import { BusinessListingCriteria, LISTINGS_PER_PAGE, ListingType, emailToDirName } from '../../../../../../bizmatch-server/src/models/main.model';
|
import { BusinessListingCriteria, LISTINGS_PER_PAGE, ListingType, emailToDirName } from '../../../../../../bizmatch-server/src/models/main.model';
|
||||||
import { environment } from '../../../../environments/environment';
|
import { environment } from '../../../../environments/environment';
|
||||||
import { PaginatorComponent } from '../../../components/paginator/paginator.component';
|
import { PaginatorComponent } from '../../../components/paginator/paginator.component';
|
||||||
|
|
@ -43,6 +43,7 @@ export class BusinessListingsComponent {
|
||||||
page = 1;
|
page = 1;
|
||||||
pageCount = 1;
|
pageCount = 1;
|
||||||
emailToDirName = emailToDirName;
|
emailToDirName = emailToDirName;
|
||||||
|
sortBy: SortByOptions = null; // Neu: Separate Property
|
||||||
constructor(
|
constructor(
|
||||||
public selectOptions: SelectOptionsService,
|
public selectOptions: SelectOptionsService,
|
||||||
private listingsService: ListingsService,
|
private listingsService: ListingsService,
|
||||||
|
|
@ -58,13 +59,19 @@ export class BusinessListingsComponent {
|
||||||
this.criteria = getCriteriaProxy('businessListings', this) as BusinessListingCriteria;
|
this.criteria = getCriteriaProxy('businessListings', this) as BusinessListingCriteria;
|
||||||
this.modalService.sendCriteria(this.criteria);
|
this.modalService.sendCriteria(this.criteria);
|
||||||
this.init();
|
this.init();
|
||||||
this.searchService.currentCriteria.pipe(untilDestroyed(this)).subscribe(criteria => {
|
this.loadSortBy();
|
||||||
if (criteria && criteria.criteriaType === 'businessListings') {
|
this.searchService.currentCriteria.pipe(untilDestroyed(this)).subscribe(({ criteria, sortBy }) => {
|
||||||
|
if (criteria.criteriaType === 'businessListings') {
|
||||||
this.criteria = criteria as BusinessListingCriteria;
|
this.criteria = criteria as BusinessListingCriteria;
|
||||||
|
this.sortBy = sortBy || this.sortBy || null;
|
||||||
this.search();
|
this.search();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
private loadSortBy() {
|
||||||
|
const storedSortBy = sessionStorage.getItem('businessSortBy');
|
||||||
|
this.sortBy = storedSortBy && storedSortBy !== 'null' ? (storedSortBy as SortByOptions) : null;
|
||||||
|
}
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
this.search();
|
this.search();
|
||||||
}
|
}
|
||||||
|
|
@ -73,7 +80,7 @@ export class BusinessListingsComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
async search() {
|
async search() {
|
||||||
const listingReponse = await this.listingsService.getListings(this.criteria, 'business');
|
const listingReponse = await this.listingsService.getListings('business');
|
||||||
this.listings = listingReponse.results;
|
this.listings = listingReponse.results;
|
||||||
this.totalRecords = listingReponse.totalCount;
|
this.totalRecords = listingReponse.totalCount;
|
||||||
this.pageCount = this.totalRecords % LISTINGS_PER_PAGE === 0 ? this.totalRecords / LISTINGS_PER_PAGE : Math.floor(this.totalRecords / LISTINGS_PER_PAGE) + 1;
|
this.pageCount = this.totalRecords % LISTINGS_PER_PAGE === 0 ? this.totalRecords / LISTINGS_PER_PAGE : Math.floor(this.totalRecords / LISTINGS_PER_PAGE) + 1;
|
||||||
|
|
@ -106,7 +113,7 @@ export class BusinessListingsComponent {
|
||||||
this.criteriaChangeService.notifyCriteriaChange();
|
this.criteriaChangeService.notifyCriteriaChange();
|
||||||
|
|
||||||
// Search with cleared filters
|
// Search with cleared filters
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search('businessListings');
|
||||||
}
|
}
|
||||||
|
|
||||||
async openFilterModal() {
|
async openFilterModal() {
|
||||||
|
|
@ -114,7 +121,7 @@ export class BusinessListingsComponent {
|
||||||
const modalResult = await this.modalService.showModal(this.criteria);
|
const modalResult = await this.modalService.showModal(this.criteria);
|
||||||
if (modalResult.accepted) {
|
if (modalResult.accepted) {
|
||||||
this.criteria = assignProperties(this.criteria, modalResult.criteria); // Update criteria with modal result
|
this.criteria = assignProperties(this.criteria, modalResult.criteria); // Update criteria with modal result
|
||||||
this.searchService.search(this.criteria); // Trigger search with updated criteria
|
this.searchService.search('businessListings'); // Trigger search with updated criteria
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { FormsModule } from '@angular/forms';
|
||||||
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
||||||
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
|
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { CommercialPropertyListing } from '../../../../../../bizmatch-server/src/models/db.model';
|
import { CommercialPropertyListing, SortByOptions } from '../../../../../../bizmatch-server/src/models/db.model';
|
||||||
import { CommercialPropertyListingCriteria, LISTINGS_PER_PAGE, ResponseCommercialPropertyListingArray } from '../../../../../../bizmatch-server/src/models/main.model';
|
import { CommercialPropertyListingCriteria, LISTINGS_PER_PAGE, ResponseCommercialPropertyListingArray } from '../../../../../../bizmatch-server/src/models/main.model';
|
||||||
import { environment } from '../../../../environments/environment';
|
import { environment } from '../../../../environments/environment';
|
||||||
import { PaginatorComponent } from '../../../components/paginator/paginator.component';
|
import { PaginatorComponent } from '../../../components/paginator/paginator.component';
|
||||||
|
|
@ -43,7 +43,7 @@ export class CommercialPropertyListingsComponent {
|
||||||
page = 1;
|
page = 1;
|
||||||
pageCount = 1;
|
pageCount = 1;
|
||||||
ts = new Date().getTime();
|
ts = new Date().getTime();
|
||||||
|
sortBy: SortByOptions = null; // Neu: Separate Property
|
||||||
constructor(
|
constructor(
|
||||||
public selectOptions: SelectOptionsService,
|
public selectOptions: SelectOptionsService,
|
||||||
private listingsService: ListingsService,
|
private listingsService: ListingsService,
|
||||||
|
|
@ -58,23 +58,25 @@ export class CommercialPropertyListingsComponent {
|
||||||
) {
|
) {
|
||||||
this.criteria = getCriteriaProxy('commercialPropertyListings', this) as CommercialPropertyListingCriteria;
|
this.criteria = getCriteriaProxy('commercialPropertyListings', this) as CommercialPropertyListingCriteria;
|
||||||
this.modalService.sendCriteria(this.criteria);
|
this.modalService.sendCriteria(this.criteria);
|
||||||
this.init();
|
this.loadSortBy();
|
||||||
this.searchService.currentCriteria.pipe(untilDestroyed(this)).subscribe(criteria => {
|
this.searchService.currentCriteria.pipe(untilDestroyed(this)).subscribe(({ criteria, sortBy }) => {
|
||||||
if (criteria && criteria.criteriaType === 'commercialPropertyListings') {
|
if (criteria.criteriaType === 'commercialPropertyListings') {
|
||||||
this.criteria = criteria as CommercialPropertyListingCriteria;
|
this.criteria = criteria as CommercialPropertyListingCriteria;
|
||||||
|
this.sortBy = sortBy || this.sortBy || null;
|
||||||
this.search();
|
this.search();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
private loadSortBy() {
|
||||||
async ngOnInit() {}
|
const storedSortBy = sessionStorage.getItem('commercialSortBy');
|
||||||
|
this.sortBy = storedSortBy && storedSortBy !== 'null' ? (storedSortBy as SortByOptions) : null;
|
||||||
async init() {
|
}
|
||||||
|
async ngOnInit() {
|
||||||
this.search();
|
this.search();
|
||||||
}
|
}
|
||||||
|
|
||||||
async search() {
|
async search() {
|
||||||
const listingReponse = await this.listingsService.getListings(this.criteria, 'commercialProperty');
|
const listingReponse = await this.listingsService.getListings('commercialProperty');
|
||||||
this.listings = (<ResponseCommercialPropertyListingArray>listingReponse).results;
|
this.listings = (<ResponseCommercialPropertyListingArray>listingReponse).results;
|
||||||
this.totalRecords = (<ResponseCommercialPropertyListingArray>listingReponse).totalCount;
|
this.totalRecords = (<ResponseCommercialPropertyListingArray>listingReponse).totalCount;
|
||||||
this.pageCount = this.totalRecords % LISTINGS_PER_PAGE === 0 ? this.totalRecords / LISTINGS_PER_PAGE : Math.floor(this.totalRecords / LISTINGS_PER_PAGE) + 1;
|
this.pageCount = this.totalRecords % LISTINGS_PER_PAGE === 0 ? this.totalRecords / LISTINGS_PER_PAGE : Math.floor(this.totalRecords / LISTINGS_PER_PAGE) + 1;
|
||||||
|
|
@ -114,14 +116,14 @@ export class CommercialPropertyListingsComponent {
|
||||||
this.criteriaChangeService.notifyCriteriaChange();
|
this.criteriaChangeService.notifyCriteriaChange();
|
||||||
|
|
||||||
// Search with cleared filters
|
// Search with cleared filters
|
||||||
this.searchService.search(this.criteria);
|
this.searchService.search('commercialPropertyListings');
|
||||||
}
|
}
|
||||||
|
|
||||||
async openFilterModal() {
|
async openFilterModal() {
|
||||||
const modalResult = await this.modalService.showModal(this.criteria);
|
const modalResult = await this.modalService.showModal(this.criteria);
|
||||||
if (modalResult.accepted) {
|
if (modalResult.accepted) {
|
||||||
this.criteria = assignProperties(this.criteria, modalResult.criteria); // Update criteria with modal result
|
this.criteria = assignProperties(this.criteria, modalResult.criteria); // Update criteria with modal result
|
||||||
this.searchService.search(this.criteria); // Trigger search with updated criteria
|
this.searchService.search('commercialPropertyListings'); // Trigger search with updated criteria
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,9 @@ import { HttpClient } from '@angular/common/http';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Observable, lastValueFrom } from 'rxjs';
|
import { Observable, lastValueFrom } from 'rxjs';
|
||||||
import { BusinessListing, CommercialPropertyListing } from '../../../../bizmatch-server/src/models/db.model';
|
import { BusinessListing, CommercialPropertyListing } from '../../../../bizmatch-server/src/models/db.model';
|
||||||
import { BusinessListingCriteria, CommercialPropertyListingCriteria, ListingType, ResponseBusinessListingArray, ResponseCommercialPropertyListingArray } from '../../../../bizmatch-server/src/models/main.model';
|
import { ListingType, ResponseBusinessListingArray, ResponseCommercialPropertyListingArray } from '../../../../bizmatch-server/src/models/main.model';
|
||||||
import { environment } from '../../environments/environment';
|
import { environment } from '../../environments/environment';
|
||||||
|
import { getCriteriaByListingCategory, getSortByListingCategory } from '../utils/utils';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
|
|
@ -12,20 +13,21 @@ export class ListingsService {
|
||||||
private apiBaseUrl = environment.apiBaseUrl;
|
private apiBaseUrl = environment.apiBaseUrl;
|
||||||
constructor(private http: HttpClient) {}
|
constructor(private http: HttpClient) {}
|
||||||
|
|
||||||
async getListings(
|
async getListings(listingsCategory: 'business' | 'professionals_brokers' | 'commercialProperty'): Promise<ResponseBusinessListingArray | ResponseCommercialPropertyListingArray> {
|
||||||
criteria: BusinessListingCriteria | CommercialPropertyListingCriteria,
|
const criteria = getCriteriaByListingCategory(listingsCategory);
|
||||||
listingsCategory: 'business' | 'professionals_brokers' | 'commercialProperty',
|
const sortBy = getSortByListingCategory(listingsCategory);
|
||||||
): Promise<ResponseBusinessListingArray | ResponseCommercialPropertyListingArray> {
|
const body = { ...criteria, sortBy }; // Merge sortBy in Body
|
||||||
const result = await lastValueFrom(this.http.post<ResponseBusinessListingArray | ResponseCommercialPropertyListingArray>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/find`, criteria));
|
const result = await lastValueFrom(this.http.post<ResponseBusinessListingArray | ResponseCommercialPropertyListingArray>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/find`, body));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
getNumberOfListings(criteria: BusinessListingCriteria | CommercialPropertyListingCriteria, listingsCategory: 'business' | 'commercialProperty'): Observable<number> {
|
|
||||||
return this.http.post<number>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/findTotal`, criteria);
|
getNumberOfListings(listingsCategory: 'business' | 'commercialProperty'): Observable<number> {
|
||||||
}
|
const criteria = getCriteriaByListingCategory(listingsCategory);
|
||||||
async getListingsByPrompt(criteria: BusinessListingCriteria | CommercialPropertyListingCriteria): Promise<BusinessListing[]> {
|
const sortBy = getSortByListingCategory(listingsCategory);
|
||||||
const result = await lastValueFrom(this.http.post<BusinessListing[]>(`${this.apiBaseUrl}/bizmatch/listings/business/search`, criteria));
|
const body = { ...criteria, sortBy }; // Merge, falls relevant (wenn Backend sortBy für Count braucht; sonst ignorieren)
|
||||||
return result;
|
return this.http.post<number>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/findTotal`, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
getListingById(id: string, listingsCategory?: 'business' | 'commercialProperty'): Observable<ListingType> {
|
getListingById(id: string, listingsCategory?: 'business' | 'commercialProperty'): Observable<ListingType> {
|
||||||
const result = this.http.get<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/${id}`);
|
const result = this.http.get<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/${id}`);
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,30 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
|
import { SortByOptions } from '../../../../bizmatch-server/src/models/db.model';
|
||||||
import { BusinessListingCriteria, CommercialPropertyListingCriteria, UserListingCriteria } from '../../../../bizmatch-server/src/models/main.model';
|
import { BusinessListingCriteria, CommercialPropertyListingCriteria, UserListingCriteria } from '../../../../bizmatch-server/src/models/main.model';
|
||||||
|
import { getCriteriaProxy } from '../utils/utils';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
})
|
})
|
||||||
export class SearchService {
|
export class SearchService {
|
||||||
private criteriaSource = new Subject<BusinessListingCriteria | CommercialPropertyListingCriteria | UserListingCriteria>();
|
private criteriaSource = new Subject<{
|
||||||
|
criteria: BusinessListingCriteria | CommercialPropertyListingCriteria | UserListingCriteria;
|
||||||
|
sortBy?: SortByOptions;
|
||||||
|
}>();
|
||||||
currentCriteria = this.criteriaSource.asObservable();
|
currentCriteria = this.criteriaSource.asObservable();
|
||||||
|
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
search(criteria: BusinessListingCriteria | CommercialPropertyListingCriteria | UserListingCriteria): void {
|
search(criteriaType: 'businessListings' | 'commercialPropertyListings' | 'brokerListings'): void {
|
||||||
this.criteriaSource.next(criteria);
|
const criteria = getCriteriaProxy(criteriaType, this);
|
||||||
|
const storedSortBy =
|
||||||
|
criteriaType === 'businessListings'
|
||||||
|
? sessionStorage.getItem('businessSortBy')
|
||||||
|
: criteriaType === 'commercialPropertyListings'
|
||||||
|
? sessionStorage.getItem('commercialSortBy')
|
||||||
|
: sessionStorage.getItem('professionalsSortBy');
|
||||||
|
const sortBy = storedSortBy && storedSortBy !== 'null' ? (storedSortBy as SortByOptions) : null;
|
||||||
|
this.criteriaSource.next({ criteria, sortBy });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { Router } from '@angular/router';
|
||||||
import { ConsoleFormattedStream, INFO, createLogger as _createLogger, stdSerializers } from 'browser-bunyan';
|
import { ConsoleFormattedStream, INFO, createLogger as _createLogger, stdSerializers } from 'browser-bunyan';
|
||||||
import { jwtDecode } from 'jwt-decode';
|
import { jwtDecode } from 'jwt-decode';
|
||||||
import onChange from 'on-change';
|
import onChange from 'on-change';
|
||||||
import { User } from '../../../../bizmatch-server/src/models/db.model';
|
import { SortByOptions, User } from '../../../../bizmatch-server/src/models/db.model';
|
||||||
import { BusinessListingCriteria, CommercialPropertyListingCriteria, JwtToken, KeycloakUser, MailInfo, UserListingCriteria } from '../../../../bizmatch-server/src/models/main.model';
|
import { BusinessListingCriteria, CommercialPropertyListingCriteria, JwtToken, KeycloakUser, MailInfo, UserListingCriteria } from '../../../../bizmatch-server/src/models/main.model';
|
||||||
import { environment } from '../../environments/environment';
|
import { environment } from '../../environments/environment';
|
||||||
|
|
||||||
|
|
@ -15,7 +15,6 @@ export function createEmptyBusinessListingCriteria(): BusinessListingCriteria {
|
||||||
city: null,
|
city: null,
|
||||||
types: [],
|
types: [],
|
||||||
prompt: '',
|
prompt: '',
|
||||||
sortBy: null,
|
|
||||||
criteriaType: 'businessListings',
|
criteriaType: 'businessListings',
|
||||||
minPrice: null,
|
minPrice: null,
|
||||||
maxPrice: null,
|
maxPrice: null,
|
||||||
|
|
@ -46,7 +45,6 @@ export function createEmptyCommercialPropertyListingCriteria(): CommercialProper
|
||||||
city: null,
|
city: null,
|
||||||
types: [],
|
types: [],
|
||||||
prompt: '',
|
prompt: '',
|
||||||
sortBy: null,
|
|
||||||
criteriaType: 'commercialPropertyListings',
|
criteriaType: 'commercialPropertyListings',
|
||||||
minPrice: null,
|
minPrice: null,
|
||||||
maxPrice: null,
|
maxPrice: null,
|
||||||
|
|
@ -64,7 +62,6 @@ export function createEmptyUserListingCriteria(): UserListingCriteria {
|
||||||
city: null,
|
city: null,
|
||||||
types: [],
|
types: [],
|
||||||
prompt: '',
|
prompt: '',
|
||||||
sortBy: null,
|
|
||||||
criteriaType: 'brokerListings',
|
criteriaType: 'brokerListings',
|
||||||
brokerName: '',
|
brokerName: '',
|
||||||
companyName: '',
|
companyName: '',
|
||||||
|
|
@ -82,7 +79,6 @@ export function resetBusinessListingCriteria(criteria: BusinessListingCriteria)
|
||||||
criteria.city = null;
|
criteria.city = null;
|
||||||
criteria.types = [];
|
criteria.types = [];
|
||||||
criteria.prompt = '';
|
criteria.prompt = '';
|
||||||
criteria.sortBy = null;
|
|
||||||
criteria.criteriaType = 'businessListings';
|
criteria.criteriaType = 'businessListings';
|
||||||
criteria.minPrice = null;
|
criteria.minPrice = null;
|
||||||
criteria.maxPrice = null;
|
criteria.maxPrice = null;
|
||||||
|
|
@ -110,7 +106,6 @@ export function resetCommercialPropertyListingCriteria(criteria: CommercialPrope
|
||||||
criteria.city = null;
|
criteria.city = null;
|
||||||
criteria.types = [];
|
criteria.types = [];
|
||||||
criteria.prompt = '';
|
criteria.prompt = '';
|
||||||
criteria.sortBy = null;
|
|
||||||
criteria.criteriaType = 'commercialPropertyListings';
|
criteria.criteriaType = 'commercialPropertyListings';
|
||||||
criteria.minPrice = null;
|
criteria.minPrice = null;
|
||||||
criteria.maxPrice = null;
|
criteria.maxPrice = null;
|
||||||
|
|
@ -126,7 +121,6 @@ export function resetUserListingCriteria(criteria: UserListingCriteria) {
|
||||||
criteria.city = null;
|
criteria.city = null;
|
||||||
criteria.types = [];
|
criteria.types = [];
|
||||||
criteria.prompt = '';
|
criteria.prompt = '';
|
||||||
criteria.sortBy = null;
|
|
||||||
criteria.criteriaType = 'brokerListings';
|
criteria.criteriaType = 'brokerListings';
|
||||||
criteria.brokerName = '';
|
criteria.brokerName = '';
|
||||||
criteria.companyName = '';
|
criteria.companyName = '';
|
||||||
|
|
@ -300,6 +294,11 @@ export function checkAndUpdate(changed: boolean, condition: boolean, assignment:
|
||||||
}
|
}
|
||||||
return changed || condition;
|
return changed || condition;
|
||||||
}
|
}
|
||||||
|
export function removeSortByStorage() {
|
||||||
|
sessionStorage.removeItem('businessSortBy');
|
||||||
|
sessionStorage.removeItem('commercialSortBy');
|
||||||
|
sessionStorage.removeItem('professionalsSortBy');
|
||||||
|
}
|
||||||
// -----------------------------
|
// -----------------------------
|
||||||
// Criteria Proxy
|
// Criteria Proxy
|
||||||
// -----------------------------
|
// -----------------------------
|
||||||
|
|
@ -341,6 +340,19 @@ export function createEnhancedProxy(obj: BusinessListingCriteria | CommercialPro
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// export function isAdmin(email: string) {
|
export function getCriteriaByListingCategory(listingsCategory: 'business' | 'professionals_brokers' | 'commercialProperty') {
|
||||||
// return 'andreas.knuth@gmail.com' === email;
|
const storedState =
|
||||||
// }
|
listingsCategory === 'business'
|
||||||
|
? sessionStorage.getItem('businessListings')
|
||||||
|
: listingsCategory === 'commercialProperty'
|
||||||
|
? sessionStorage.getItem('commercialPropertyListings')
|
||||||
|
: sessionStorage.getItem('brokerListings');
|
||||||
|
return JSON.parse(storedState);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSortByListingCategory(listingsCategory: 'business' | 'professionals_brokers' | 'commercialProperty') {
|
||||||
|
const storedSortBy =
|
||||||
|
listingsCategory === 'business' ? sessionStorage.getItem('businessSortBy') : listingsCategory === 'commercialProperty' ? sessionStorage.getItem('commercialSortBy') : sessionStorage.getItem('professionalsSortBy');
|
||||||
|
const sortBy = storedSortBy && storedSortBy !== 'null' ? (storedSortBy as SortByOptions) : null;
|
||||||
|
return sortBy;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue