price optional, better labeling, impr. filter
This commit is contained in:
parent
03d075b7d9
commit
fbca2ddab5
|
|
@ -268,7 +268,7 @@ export const BusinessListingSchema = z
|
||||||
title: z.string().min(10),
|
title: z.string().min(10),
|
||||||
description: z.string().min(10),
|
description: z.string().min(10),
|
||||||
location: GeoSchema,
|
location: GeoSchema,
|
||||||
price: z.number().positive(),
|
price: z.number().positive().optional().nullable(),
|
||||||
favoritesForUser: z.array(z.string()),
|
favoritesForUser: z.array(z.string()),
|
||||||
draft: z.boolean(),
|
draft: z.boolean(),
|
||||||
listingsCategory: ListingsCategoryEnum,
|
listingsCategory: ListingsCategoryEnum,
|
||||||
|
|
@ -326,7 +326,7 @@ export const CommercialPropertyListingSchema = z
|
||||||
title: z.string().min(10),
|
title: z.string().min(10),
|
||||||
description: z.string().min(10),
|
description: z.string().min(10),
|
||||||
location: GeoSchema,
|
location: GeoSchema,
|
||||||
price: z.number().positive(),
|
price: z.number().positive().optional().nullable(),
|
||||||
favoritesForUser: z.array(z.string()),
|
favoritesForUser: z.array(z.string()),
|
||||||
listingsCategory: ListingsCategoryEnum,
|
listingsCategory: ListingsCategoryEnum,
|
||||||
internalListingNumber: z.number().int().positive().optional().nullable(),
|
internalListingNumber: z.number().int().positive().optional().nullable(),
|
||||||
|
|
|
||||||
|
|
@ -54,11 +54,11 @@
|
||||||
<label class="block mb-2 text-sm font-medium text-gray-900">Search Type</label>
|
<label class="block mb-2 text-sm font-medium text-gray-900">Search Type</label>
|
||||||
<div class="flex items-center space-x-4">
|
<div class="flex items-center space-x-4">
|
||||||
<label class="inline-flex items-center">
|
<label class="inline-flex items-center">
|
||||||
<input type="radio" class="form-radio" name="searchType" [(ngModel)]="criteria.searchType" (ngModelChange)="onCriteriaChange()" value="exact" />
|
<input type="radio" class="form-radio" name="searchType" [ngModel]="criteria.searchType" (ngModelChange)="updateCriteria({ searchType: $event })" value="exact" />
|
||||||
<span class="ml-2">Exact City</span>
|
<span class="ml-2">Exact City</span>
|
||||||
</label>
|
</label>
|
||||||
<label class="inline-flex items-center">
|
<label class="inline-flex items-center">
|
||||||
<input type="radio" class="form-radio" name="searchType" [(ngModel)]="criteria.searchType" (ngModelChange)="onCriteriaChange()" value="radius" />
|
<input type="radio" class="form-radio" name="searchType" [ngModel]="criteria.searchType" (ngModelChange)="updateCriteria({ searchType: $event })" value="radius" />
|
||||||
<span class="ml-2">Radius Search</span>
|
<span class="ml-2">Radius Search</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -71,7 +71,7 @@
|
||||||
type="button"
|
type="button"
|
||||||
class="px-3 py-2 text-xs font-medium text-center border border-gray-200 hover:bg-gray-500 hover:text-white"
|
class="px-3 py-2 text-xs font-medium text-center border border-gray-200 hover:bg-gray-500 hover:text-white"
|
||||||
[ngClass]="criteria.radius === radius ? 'text-white bg-gray-500' : 'text-gray-900 bg-white'"
|
[ngClass]="criteria.radius === radius ? 'text-white bg-gray-500' : 'text-gray-900 bg-white'"
|
||||||
(click)="criteria.radius = radius"
|
(click)="setRadius(radius)"
|
||||||
>
|
>
|
||||||
{{ radius }}
|
{{ radius }}
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -81,9 +81,11 @@
|
||||||
<div>
|
<div>
|
||||||
<label for="price" class="block mb-2 text-sm font-medium text-gray-900">Price</label>
|
<label for="price" class="block mb-2 text-sm font-medium text-gray-900">Price</label>
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
<app-validated-price name="price-from" (ngModelChange)="debouncedSearch()" [(ngModel)]="criteria.minPrice" placeholder="From" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5"></app-validated-price>
|
<app-validated-price name="price-from" [ngModel]="criteria.minPrice" (ngModelChange)="updateCriteria({ minPrice: $event })" placeholder="From" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5">
|
||||||
|
</app-validated-price>
|
||||||
<span>-</span>
|
<span>-</span>
|
||||||
<app-validated-price name="price-to" (ngModelChange)="debouncedSearch()" [(ngModel)]="criteria.maxPrice" placeholder="To" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5"></app-validated-price>
|
<app-validated-price name="price-to" [ngModel]="criteria.maxPrice" (ngModelChange)="updateCriteria({ maxPrice: $event })" placeholder="To" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5">
|
||||||
|
</app-validated-price>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -91,9 +93,9 @@
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
id="title"
|
id="title"
|
||||||
[(ngModel)]="criteria.title"
|
[ngModel]="criteria.title"
|
||||||
(ngModelChange)="debouncedSearch()"
|
(ngModelChange)="updateCriteria({ title: $event })"
|
||||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
class="bg-gray-50 border border-gray-300 text-sm rounded-lg block w-full p-2.5"
|
||||||
placeholder="e.g. Office Space"
|
placeholder="e.g. Office Space"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -158,11 +160,11 @@
|
||||||
<label class="block mb-2 text-sm font-medium text-gray-900">Search Type</label>
|
<label class="block mb-2 text-sm font-medium text-gray-900">Search Type</label>
|
||||||
<div class="flex items-center space-x-4">
|
<div class="flex items-center space-x-4">
|
||||||
<label class="inline-flex items-center">
|
<label class="inline-flex items-center">
|
||||||
<input type="radio" class="form-radio" name="searchType" [(ngModel)]="criteria.searchType" (ngModelChange)="onCriteriaChange()" value="exact" />
|
<input type="radio" class="form-radio" name="searchType" [ngModel]="criteria.searchType" (ngModelChange)="updateCriteria({ searchType: $event })" value="exact" />
|
||||||
<span class="ml-2">Exact City</span>
|
<span class="ml-2">Exact City</span>
|
||||||
</label>
|
</label>
|
||||||
<label class="inline-flex items-center">
|
<label class="inline-flex items-center">
|
||||||
<input type="radio" class="form-radio" name="searchType" [(ngModel)]="criteria.searchType" (ngModelChange)="onCriteriaChange()" value="radius" />
|
<input type="radio" class="form-radio" name="searchType" [ngModel]="criteria.searchType" (ngModelChange)="updateCriteria({ searchType: $event })" value="radius" />
|
||||||
<span class="ml-2">Radius Search</span>
|
<span class="ml-2">Radius Search</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -199,9 +201,9 @@
|
||||||
<div>
|
<div>
|
||||||
<label for="price" class="block mb-2 text-sm font-medium text-gray-900">Price</label>
|
<label for="price" class="block mb-2 text-sm font-medium text-gray-900">Price</label>
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
<app-validated-price name="price-from" (ngModelChange)="debouncedSearch()" [(ngModel)]="criteria.minPrice" placeholder="From" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5"></app-validated-price>
|
<app-validated-price name="price-from" [ngModel]="criteria.minPrice" (ngModelChange)="updateCriteria({ minPrice: $event })" placeholder="From" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5"> </app-validated-price>
|
||||||
<span>-</span>
|
<span>-</span>
|
||||||
<app-validated-price name="price-to" (ngModelChange)="debouncedSearch()" [(ngModel)]="criteria.maxPrice" placeholder="To" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5"></app-validated-price>
|
<app-validated-price name="price-to" [ngModel]="criteria.maxPrice" (ngModelChange)="updateCriteria({ maxPrice: $event })" placeholder="To" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5"> </app-validated-price>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -209,9 +211,9 @@
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
id="title"
|
id="title"
|
||||||
[(ngModel)]="criteria.title"
|
[ngModel]="criteria.title"
|
||||||
(ngModelChange)="debouncedSearch()"
|
(ngModelChange)="updateCriteria({ title: $event })"
|
||||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
class="bg-gray-50 border border-gray-300 text-sm rounded-lg block w-full p-2.5"
|
||||||
placeholder="e.g. Office Space"
|
placeholder="e.g. Office Space"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ export class SearchModalCommercialComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup debounced search
|
// Setup debounced search
|
||||||
this.searchDebounce$.pipe(debounceTime(400), distinctUntilChanged(), takeUntil(this.destroy$)).subscribe(() => {
|
this.searchDebounce$.pipe(debounceTime(400), takeUntil(this.destroy$)).subscribe(() => {
|
||||||
this.triggerSearch();
|
this.triggerSearch();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -236,7 +236,7 @@ export class SearchModalCommercialComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper methods
|
// Helper methods
|
||||||
private updateCriteria(updates: any): void {
|
public updateCriteria(updates: any): void {
|
||||||
if (this.isModal) {
|
if (this.isModal) {
|
||||||
// In modal: Update locally only
|
// In modal: Update locally only
|
||||||
this.criteria = { ...this.criteria, ...updates };
|
this.criteria = { ...this.criteria, ...updates };
|
||||||
|
|
@ -262,7 +262,7 @@ export class SearchModalCommercialComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
private setTotalNumberOfResults(): void {
|
private setTotalNumberOfResults(): void {
|
||||||
this.numberOfResults$ = this.listingService.getNumberOfListings('commercialProperty');
|
this.numberOfResults$ = this.listingService.getNumberOfListings('commercialProperty', this.criteria);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getDefaultCriteria(): CommercialPropertyListingCriteria {
|
private getDefaultCriteria(): CommercialPropertyListingCriteria {
|
||||||
|
|
|
||||||
|
|
@ -71,11 +71,11 @@
|
||||||
<label class="block mb-2 text-sm font-medium text-gray-900">Search Type</label>
|
<label class="block mb-2 text-sm font-medium text-gray-900">Search Type</label>
|
||||||
<div class="flex items-center space-x-4">
|
<div class="flex items-center space-x-4">
|
||||||
<label class="inline-flex items-center">
|
<label class="inline-flex items-center">
|
||||||
<input type="radio" class="form-radio" name="searchType" [(ngModel)]="criteria.searchType" (ngModelChange)="onCriteriaChange()" value="exact" />
|
<input type="radio" class="form-radio" name="searchType" [ngModel]="criteria.searchType" (ngModelChange)="updateCriteria({ searchType: $event })" value="exact" />
|
||||||
<span class="ml-2">Exact City</span>
|
<span class="ml-2">Exact City</span>
|
||||||
</label>
|
</label>
|
||||||
<label class="inline-flex items-center">
|
<label class="inline-flex items-center">
|
||||||
<input type="radio" class="form-radio" name="searchType" [(ngModel)]="criteria.searchType" (ngModelChange)="onCriteriaChange()" value="radius" />
|
<input type="radio" class="form-radio" name="searchType" [ngModel]="criteria.searchType" (ngModelChange)="updateCriteria({ searchType: $event })" value="radius" />
|
||||||
<span class="ml-2">Radius Search</span>
|
<span class="ml-2">Radius Search</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -88,7 +88,7 @@
|
||||||
type="button"
|
type="button"
|
||||||
class="px-3 py-2 text-xs font-medium text-center border border-gray-200 hover:bg-gray-500 hover:text-white"
|
class="px-3 py-2 text-xs font-medium text-center border border-gray-200 hover:bg-gray-500 hover:text-white"
|
||||||
[ngClass]="criteria.radius === radius ? 'text-white bg-gray-500' : 'text-gray-900 bg-white'"
|
[ngClass]="criteria.radius === radius ? 'text-white bg-gray-500' : 'text-gray-900 bg-white'"
|
||||||
(click)="criteria.radius = radius"
|
(click)="setRadius(radius)"
|
||||||
>
|
>
|
||||||
{{ radius }}
|
{{ radius }}
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -98,25 +98,31 @@
|
||||||
<div>
|
<div>
|
||||||
<label for="price" class="block mb-2 text-sm font-medium text-gray-900">Price</label>
|
<label for="price" class="block mb-2 text-sm font-medium text-gray-900">Price</label>
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
<app-validated-price name="price-from" (ngModelChange)="debouncedSearch()" [(ngModel)]="criteria.minPrice" placeholder="From" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5"></app-validated-price>
|
<app-validated-price name="price-from" [ngModel]="criteria.minPrice" (ngModelChange)="updateCriteria({ minPrice: $event })" placeholder="From" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5">
|
||||||
|
</app-validated-price>
|
||||||
<span>-</span>
|
<span>-</span>
|
||||||
<app-validated-price name="price-to" (ngModelChange)="debouncedSearch()" [(ngModel)]="criteria.maxPrice" placeholder="To" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5"></app-validated-price>
|
<app-validated-price name="price-to" [ngModel]="criteria.maxPrice" (ngModelChange)="updateCriteria({ maxPrice: $event })" placeholder="To" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5">
|
||||||
|
</app-validated-price>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="salesRevenue" class="block mb-2 text-sm font-medium text-gray-900">Sales Revenue</label>
|
<label for="salesRevenue" class="block mb-2 text-sm font-medium text-gray-900">Sales Revenue</label>
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
<app-validated-price name="salesRevenue-from" (ngModelChange)="debouncedSearch()" [(ngModel)]="criteria.minRevenue" placeholder="From" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5"></app-validated-price>
|
<app-validated-price name="salesRevenue-from" [ngModel]="criteria.minRevenue" (ngModelChange)="updateCriteria({ minRevenue: $event })" placeholder="From" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5">
|
||||||
|
</app-validated-price>
|
||||||
<span>-</span>
|
<span>-</span>
|
||||||
<app-validated-price name="salesRevenue-to" (ngModelChange)="debouncedSearch()" [(ngModel)]="criteria.maxRevenue" placeholder="To" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5"></app-validated-price>
|
<app-validated-price name="salesRevenue-to" [ngModel]="criteria.maxRevenue" (ngModelChange)="updateCriteria({ maxRevenue: $event })" placeholder="To" inputClasses="bg-gray-50 text-sm !mt-0 p.2.5">
|
||||||
|
</app-validated-price>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="cashflow" class="block mb-2 text-sm font-medium text-gray-900">Cashflow</label>
|
<label for="cashflow" class="block mb-2 text-sm font-medium text-gray-900">Cashflow</label>
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
<app-validated-price name="cashflow-from" (ngModelChange)="debouncedSearch()" [(ngModel)]="criteria.minCashFlow" placeholder="From" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5"></app-validated-price>
|
<app-validated-price name="cashflow-from" [ngModel]="criteria.minCashFlow" (ngModelChange)="updateCriteria({ minCashFlow: $event })" placeholder="From" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5">
|
||||||
|
</app-validated-price>
|
||||||
<span>-</span>
|
<span>-</span>
|
||||||
<app-validated-price name="cashflow-to" (ngModelChange)="debouncedSearch()" [(ngModel)]="criteria.maxCashFlow" placeholder="To" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5"></app-validated-price>
|
<app-validated-price name="cashflow-to" [ngModel]="criteria.maxCashFlow" (ngModelChange)="updateCriteria({ maxCashFlow: $event })" placeholder="To" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5">
|
||||||
|
</app-validated-price>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -124,9 +130,9 @@
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
id="title"
|
id="title"
|
||||||
[(ngModel)]="criteria.title"
|
[ngModel]="criteria.title"
|
||||||
(ngModelChange)="debouncedSearch()"
|
(ngModelChange)="updateCriteria({ title: $event })"
|
||||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
class="bg-gray-50 border border-gray-300 text-sm rounded-lg block w-full p-2.5"
|
||||||
placeholder="e.g. Restaurant"
|
placeholder="e.g. Restaurant"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -162,18 +168,18 @@
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
id="numberEmployees-from"
|
id="numberEmployees-from"
|
||||||
[(ngModel)]="criteria.minNumberEmployees"
|
[ngModel]="criteria.minNumberEmployees"
|
||||||
(ngModelChange)="debouncedSearch()"
|
(ngModelChange)="updateCriteria({ minNumberEmployees: $event })"
|
||||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-1/2 p-2.5"
|
class="bg-gray-50 border border-gray-300 text-sm rounded-lg block w-1/2 p-2.5"
|
||||||
placeholder="From"
|
placeholder="From"
|
||||||
/>
|
/>
|
||||||
<span>-</span>
|
<span>-</span>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
id="numberEmployees-to"
|
id="numberEmployees-to"
|
||||||
[(ngModel)]="criteria.maxNumberEmployees"
|
[ngModel]="criteria.maxNumberEmployees"
|
||||||
(ngModelChange)="debouncedSearch()"
|
(ngModelChange)="updateCriteria({ maxNumberEmployees: $event })"
|
||||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-1/2 p-2.5"
|
class="bg-gray-50 border border-gray-300 text-sm rounded-lg block w-1/2 p-2.5"
|
||||||
placeholder="To"
|
placeholder="To"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -184,9 +190,9 @@
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
id="establishedMin"
|
id="establishedMin"
|
||||||
[(ngModel)]="criteria.establishedMin"
|
[ngModel]="criteria.establishedMin"
|
||||||
(ngModelChange)="debouncedSearch()"
|
(ngModelChange)="updateCriteria({ establishedMin: $event })"
|
||||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-1/2 p-2.5"
|
class="bg-gray-50 border border-gray-300 text-sm rounded-lg block w-1/2 p-2.5"
|
||||||
placeholder="YY"
|
placeholder="YY"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -196,9 +202,9 @@
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
id="brokername"
|
id="brokername"
|
||||||
[(ngModel)]="criteria.brokerName"
|
[ngModel]="criteria.brokerName"
|
||||||
(ngModelChange)="debouncedSearch()"
|
(ngModelChange)="updateCriteria({ brokerName: $event })"
|
||||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
class="bg-gray-50 border border-gray-300 text-sm rounded-lg block w-full p-2.5"
|
||||||
placeholder="e.g. Brokers Invest"
|
placeholder="e.g. Brokers Invest"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -269,11 +275,11 @@
|
||||||
<label class="block mb-2 text-sm font-medium text-gray-900">Search Type</label>
|
<label class="block mb-2 text-sm font-medium text-gray-900">Search Type</label>
|
||||||
<div class="flex items-center space-x-4">
|
<div class="flex items-center space-x-4">
|
||||||
<label class="inline-flex items-center">
|
<label class="inline-flex items-center">
|
||||||
<input type="radio" class="form-radio" name="searchType" (ngModelChange)="onCriteriaChange()" [(ngModel)]="criteria.searchType" value="exact" />
|
<input type="radio" class="form-radio" name="searchType" [ngModel]="criteria.searchType" (ngModelChange)="updateCriteria({ searchType: $event })" value="exact" />
|
||||||
<span class="ml-2">Exact City</span>
|
<span class="ml-2">Exact City</span>
|
||||||
</label>
|
</label>
|
||||||
<label class="inline-flex items-center">
|
<label class="inline-flex items-center">
|
||||||
<input type="radio" class="form-radio" name="searchType" (ngModelChange)="onCriteriaChange()" [(ngModel)]="criteria.searchType" value="radius" />
|
<input type="radio" class="form-radio" name="searchType" [ngModel]="criteria.searchType" (ngModelChange)="updateCriteria({ searchType: $event })" value="radius" />
|
||||||
<span class="ml-2">Radius Search</span>
|
<span class="ml-2">Radius Search</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -296,25 +302,29 @@
|
||||||
<div>
|
<div>
|
||||||
<label for="price" class="block mb-2 text-sm font-medium text-gray-900">Price</label>
|
<label for="price" class="block mb-2 text-sm font-medium text-gray-900">Price</label>
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
<app-validated-price name="price-from" (ngModelChange)="debouncedSearch()" [(ngModel)]="criteria.minPrice" placeholder="From" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5"></app-validated-price>
|
<app-validated-price name="price-from" [ngModel]="criteria.minPrice" (ngModelChange)="updateCriteria({ minPrice: $event })" placeholder="From" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5"> </app-validated-price>
|
||||||
<span>-</span>
|
<span>-</span>
|
||||||
<app-validated-price name="price-to" (ngModelChange)="debouncedSearch()" [(ngModel)]="criteria.maxPrice" placeholder="To" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5"></app-validated-price>
|
<app-validated-price name="price-to" [ngModel]="criteria.maxPrice" (ngModelChange)="updateCriteria({ maxPrice: $event })" placeholder="To" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5"> </app-validated-price>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="salesRevenue" class="block mb-2 text-sm font-medium text-gray-900">Sales Revenue</label>
|
<label for="salesRevenue" class="block mb-2 text-sm font-medium text-gray-900">Sales Revenue</label>
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
<app-validated-price name="salesRevenue-from" (ngModelChange)="debouncedSearch()" [(ngModel)]="criteria.minRevenue" placeholder="From" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5"></app-validated-price>
|
<app-validated-price name="salesRevenue-from" [ngModel]="criteria.minRevenue" (ngModelChange)="updateCriteria({ minRevenue: $event })" placeholder="From" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5">
|
||||||
|
</app-validated-price>
|
||||||
<span>-</span>
|
<span>-</span>
|
||||||
<app-validated-price name="salesRevenue-to" (ngModelChange)="debouncedSearch()" [(ngModel)]="criteria.maxRevenue" placeholder="To" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5"></app-validated-price>
|
<app-validated-price name="salesRevenue-to" [ngModel]="criteria.maxRevenue" (ngModelChange)="updateCriteria({ maxRevenue: $event })" placeholder="To" inputClasses="bg-gray-50 text-sm !mt-0 p.2.5">
|
||||||
|
</app-validated-price>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="cashflow" class="block mb-2 text-sm font-medium text-gray-900">Cashflow</label>
|
<label for="cashflow" class="block mb-2 text-sm font-medium text-gray-900">Cashflow</label>
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
<app-validated-price name="cashflow-from" (ngModelChange)="debouncedSearch()" [(ngModel)]="criteria.minCashFlow" placeholder="From" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5"></app-validated-price>
|
<app-validated-price name="cashflow-from" [ngModel]="criteria.minCashFlow" (ngModelChange)="updateCriteria({ minCashFlow: $event })" placeholder="From" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5">
|
||||||
|
</app-validated-price>
|
||||||
<span>-</span>
|
<span>-</span>
|
||||||
<app-validated-price name="cashflow-to" (ngModelChange)="debouncedSearch()" [(ngModel)]="criteria.maxCashFlow" placeholder="To" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5"></app-validated-price>
|
<app-validated-price name="cashflow-to" [ngModel]="criteria.maxCashFlow" (ngModelChange)="updateCriteria({ maxCashFlow: $event })" placeholder="To" inputClasses="bg-gray-50 text-sm !mt-0 p-2.5">
|
||||||
|
</app-validated-price>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -322,9 +332,9 @@
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
id="title"
|
id="title"
|
||||||
[(ngModel)]="criteria.title"
|
[ngModel]="criteria.title"
|
||||||
(ngModelChange)="debouncedSearch()"
|
(ngModelChange)="updateCriteria({ title: $event })"
|
||||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
class="bg-gray-50 border border-gray-300 text-sm rounded-lg block w-full p-2.5"
|
||||||
placeholder="e.g. Restaurant"
|
placeholder="e.g. Restaurant"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -360,18 +370,18 @@
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
id="numberEmployees-from"
|
id="numberEmployees-from"
|
||||||
[(ngModel)]="criteria.minNumberEmployees"
|
[ngModel]="criteria.minNumberEmployees"
|
||||||
(ngModelChange)="debouncedSearch()"
|
(ngModelChange)="updateCriteria({ minNumberEmployees: $event })"
|
||||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-1/2 p-2.5"
|
class="bg-gray-50 border border-gray-300 text-sm rounded-lg block w-1/2 p-2.5"
|
||||||
placeholder="From"
|
placeholder="From"
|
||||||
/>
|
/>
|
||||||
<span>-</span>
|
<span>-</span>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
id="numberEmployees-to"
|
id="numberEmployees-to"
|
||||||
[(ngModel)]="criteria.maxNumberEmployees"
|
[ngModel]="criteria.maxNumberEmployees"
|
||||||
(ngModelChange)="debouncedSearch()"
|
(ngModelChange)="updateCriteria({ maxNumberEmployees: $event })"
|
||||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-1/2 p-2.5"
|
class="bg-gray-50 border border-gray-300 text-sm rounded-lg block w-1/2 p-2.5"
|
||||||
placeholder="To"
|
placeholder="To"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -382,9 +392,9 @@
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
id="establishedMin"
|
id="establishedMin"
|
||||||
[(ngModel)]="criteria.establishedMin"
|
[ngModel]="criteria.establishedMin"
|
||||||
(ngModelChange)="debouncedSearch()"
|
(ngModelChange)="updateCriteria({ establishedMin: $event })"
|
||||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-1/2 p-2.5"
|
class="bg-gray-50 border border-gray-300 text-sm rounded-lg block w-1/2 p-2.5"
|
||||||
placeholder="YY"
|
placeholder="YY"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -394,9 +404,9 @@
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
id="brokername"
|
id="brokername"
|
||||||
[(ngModel)]="criteria.brokerName"
|
[ngModel]="criteria.brokerName"
|
||||||
(ngModelChange)="debouncedSearch()"
|
(ngModelChange)="updateCriteria({ brokerName: $event })"
|
||||||
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
class="bg-gray-50 border border-gray-300 text-sm rounded-lg block w-full p-2.5"
|
||||||
placeholder="e.g. Brokers Invest"
|
placeholder="e.g. Brokers Invest"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -86,14 +86,12 @@ export class SearchModalComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup debounced search
|
// Setup debounced search
|
||||||
this.searchDebounce$.pipe(debounceTime(400), distinctUntilChanged(), takeUntil(this.destroy$)).subscribe(() => {
|
this.searchDebounce$.pipe(debounceTime(400), takeUntil(this.destroy$)).subscribe(() => this.triggerSearch());
|
||||||
this.triggerSearch();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeWithCriteria(criteria: any): void {
|
private initializeWithCriteria(criteria: any): void {
|
||||||
this.criteria = criteria;
|
this.criteria = criteria;
|
||||||
this.currentListingType = criteria.criteriaType;
|
this.currentListingType = criteria?.criteriaType;
|
||||||
this.backupCriteria = JSON.parse(JSON.stringify(criteria));
|
this.backupCriteria = JSON.parse(JSON.stringify(criteria));
|
||||||
this.updateSelectedPropertyType();
|
this.updateSelectedPropertyType();
|
||||||
this.setTotalNumberOfResults();
|
this.setTotalNumberOfResults();
|
||||||
|
|
@ -312,7 +310,7 @@ export class SearchModalComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper methods
|
// Helper methods
|
||||||
private updateCriteria(updates: any): void {
|
public updateCriteria(updates: any): void {
|
||||||
if (this.isModal) {
|
if (this.isModal) {
|
||||||
// In modal: Update locally only
|
// In modal: Update locally only
|
||||||
this.criteria = { ...this.criteria, ...updates };
|
this.criteria = { ...this.criteria, ...updates };
|
||||||
|
|
@ -356,10 +354,10 @@ export class SearchModalComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
switch (this.currentListingType) {
|
switch (this.currentListingType) {
|
||||||
case 'businessListings':
|
case 'businessListings':
|
||||||
this.numberOfResults$ = this.listingService.getNumberOfListings('business');
|
this.numberOfResults$ = this.listingService.getNumberOfListings('business', this.criteria);
|
||||||
break;
|
break;
|
||||||
case 'commercialPropertyListings':
|
case 'commercialPropertyListings':
|
||||||
this.numberOfResults$ = this.listingService.getNumberOfListings('commercialProperty');
|
this.numberOfResults$ = this.listingService.getNumberOfListings('commercialProperty', this.criteria);
|
||||||
break;
|
break;
|
||||||
case 'brokerListings':
|
case 'brokerListings':
|
||||||
this.numberOfResults$ = this.userService.getNumberOfBroker();
|
this.numberOfResults$ = this.userService.getNumberOfBroker();
|
||||||
|
|
|
||||||
|
|
@ -41,10 +41,19 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="text-base font-bold text-gray-800 mb-2">
|
<p class="text-base font-bold text-gray-800 mb-2">
|
||||||
<strong>Asking price:</strong> <span class="text-green-600"> {{ listing.price | currency : 'USD' : 'symbol' : '1.0-0' }}</span>
|
<strong>Asking price:</strong>
|
||||||
|
<span class="text-green-600">
|
||||||
|
{{ listing?.price != null ? (listing.price | currency : 'USD' : 'symbol' : '1.0-0') : 'undisclosed' }}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<p class="text-sm text-gray-600 mb-2">
|
||||||
|
<strong>Sales revenue:</strong>
|
||||||
|
{{ listing?.salesRevenue != null ? (listing.salesRevenue | currency : 'USD' : 'symbol' : '1.0-0') : 'undisclosed' }}
|
||||||
|
</p>
|
||||||
|
<p class="text-sm text-gray-600 mb-2">
|
||||||
|
<strong>Net profit:</strong>
|
||||||
|
{{ listing?.cashFlow != null ? (listing.cashFlow | currency : 'USD' : 'symbol' : '1.0-0') : 'undisclosed' }}
|
||||||
</p>
|
</p>
|
||||||
<p class="text-sm text-gray-600 mb-2"><strong>Sales revenue:</strong> {{ listing.salesRevenue | currency : 'USD' : 'symbol' : '1.0-0' }}</p>
|
|
||||||
<p class="text-sm text-gray-600 mb-2"><strong>Net profit:</strong> {{ listing.cashFlow | currency : 'USD' : 'symbol' : '1.0-0' }}</p>
|
|
||||||
<p class="text-sm text-gray-600 mb-2">
|
<p class="text-sm text-gray-600 mb-2">
|
||||||
<strong>Location:</strong> {{ listing.location.name ? listing.location.name : listing.location.county ? listing.location.county : this.selectOptions.getState(listing.location.state) }}
|
<strong>Location:</strong> {{ listing.location.name ? listing.location.name : listing.location.county ? listing.location.county : this.selectOptions.getState(listing.location.state) }}
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,8 @@ export class ListingsService {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
getNumberOfListings(listingsCategory: 'business' | 'commercialProperty'): Observable<number> {
|
getNumberOfListings(listingsCategory: 'business' | 'commercialProperty', crit?: any): Observable<number> {
|
||||||
const criteria = getCriteriaByListingCategory(listingsCategory);
|
const criteria = crit ? crit : getCriteriaByListingCategory(listingsCategory);
|
||||||
const sortBy = getSortByListingCategory(listingsCategory);
|
const sortBy = getSortByListingCategory(listingsCategory);
|
||||||
const body = { ...criteria, sortBy }; // Merge, falls relevant (wenn Backend sortBy für Count braucht; sonst ignorieren)
|
const body = { ...criteria, sortBy }; // Merge, falls relevant (wenn Backend sortBy für Count braucht; sonst ignorieren)
|
||||||
return this.http.post<number>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/findTotal`, body);
|
return this.http.post<number>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/findTotal`, body);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue