price optional, better labeling, impr. filter

This commit is contained in:
2025-09-29 14:44:47 -05:00
parent 03d075b7d9
commit fbca2ddab5
7 changed files with 98 additions and 79 deletions

View File

@@ -54,11 +54,11 @@
<label class="block mb-2 text-sm font-medium text-gray-900">Search Type</label>
<div class="flex items-center space-x-4">
<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>
</label>
<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>
</label>
</div>
@@ -71,7 +71,7 @@
type="button"
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'"
(click)="criteria.radius = radius"
(click)="setRadius(radius)"
>
{{ radius }}
</button>
@@ -81,9 +81,11 @@
<div>
<label for="price" class="block mb-2 text-sm font-medium text-gray-900">Price</label>
<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>
<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>
@@ -91,9 +93,9 @@
<input
type="text"
id="title"
[(ngModel)]="criteria.title"
(ngModelChange)="debouncedSearch()"
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"
[ngModel]="criteria.title"
(ngModelChange)="updateCriteria({ title: $event })"
class="bg-gray-50 border border-gray-300 text-sm rounded-lg block w-full p-2.5"
placeholder="e.g. Office Space"
/>
</div>
@@ -158,11 +160,11 @@
<label class="block mb-2 text-sm font-medium text-gray-900">Search Type</label>
<div class="flex items-center space-x-4">
<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>
</label>
<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>
</label>
</div>
@@ -199,9 +201,9 @@
<div>
<label for="price" class="block mb-2 text-sm font-medium text-gray-900">Price</label>
<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>
<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>
@@ -209,9 +211,9 @@
<input
type="text"
id="title"
[(ngModel)]="criteria.title"
(ngModelChange)="debouncedSearch()"
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"
[ngModel]="criteria.title"
(ngModelChange)="updateCriteria({ title: $event })"
class="bg-gray-50 border border-gray-300 text-sm rounded-lg block w-full p-2.5"
placeholder="e.g. Office Space"
/>
</div>

View File

@@ -77,7 +77,7 @@ export class SearchModalCommercialComponent implements OnInit, OnDestroy {
}
// Setup debounced search
this.searchDebounce$.pipe(debounceTime(400), distinctUntilChanged(), takeUntil(this.destroy$)).subscribe(() => {
this.searchDebounce$.pipe(debounceTime(400), takeUntil(this.destroy$)).subscribe(() => {
this.triggerSearch();
});
}
@@ -236,7 +236,7 @@ export class SearchModalCommercialComponent implements OnInit, OnDestroy {
}
// Helper methods
private updateCriteria(updates: any): void {
public updateCriteria(updates: any): void {
if (this.isModal) {
// In modal: Update locally only
this.criteria = { ...this.criteria, ...updates };
@@ -262,7 +262,7 @@ export class SearchModalCommercialComponent implements OnInit, OnDestroy {
}
private setTotalNumberOfResults(): void {
this.numberOfResults$ = this.listingService.getNumberOfListings('commercialProperty');
this.numberOfResults$ = this.listingService.getNumberOfListings('commercialProperty', this.criteria);
}
private getDefaultCriteria(): CommercialPropertyListingCriteria {

View File

@@ -71,11 +71,11 @@
<label class="block mb-2 text-sm font-medium text-gray-900">Search Type</label>
<div class="flex items-center space-x-4">
<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>
</label>
<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>
</label>
</div>
@@ -88,7 +88,7 @@
type="button"
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'"
(click)="criteria.radius = radius"
(click)="setRadius(radius)"
>
{{ radius }}
</button>
@@ -98,25 +98,31 @@
<div>
<label for="price" class="block mb-2 text-sm font-medium text-gray-900">Price</label>
<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>
<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>
<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">
<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>
<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>
<label for="cashflow" class="block mb-2 text-sm font-medium text-gray-900">Cashflow</label>
<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>
<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>
@@ -124,9 +130,9 @@
<input
type="text"
id="title"
[(ngModel)]="criteria.title"
(ngModelChange)="debouncedSearch()"
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"
[ngModel]="criteria.title"
(ngModelChange)="updateCriteria({ title: $event })"
class="bg-gray-50 border border-gray-300 text-sm rounded-lg block w-full p-2.5"
placeholder="e.g. Restaurant"
/>
</div>
@@ -162,18 +168,18 @@
<input
type="number"
id="numberEmployees-from"
[(ngModel)]="criteria.minNumberEmployees"
(ngModelChange)="debouncedSearch()"
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"
[ngModel]="criteria.minNumberEmployees"
(ngModelChange)="updateCriteria({ minNumberEmployees: $event })"
class="bg-gray-50 border border-gray-300 text-sm rounded-lg block w-1/2 p-2.5"
placeholder="From"
/>
<span>-</span>
<input
type="number"
id="numberEmployees-to"
[(ngModel)]="criteria.maxNumberEmployees"
(ngModelChange)="debouncedSearch()"
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"
[ngModel]="criteria.maxNumberEmployees"
(ngModelChange)="updateCriteria({ maxNumberEmployees: $event })"
class="bg-gray-50 border border-gray-300 text-sm rounded-lg block w-1/2 p-2.5"
placeholder="To"
/>
</div>
@@ -184,9 +190,9 @@
<input
type="number"
id="establishedMin"
[(ngModel)]="criteria.establishedMin"
(ngModelChange)="debouncedSearch()"
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"
[ngModel]="criteria.establishedMin"
(ngModelChange)="updateCriteria({ establishedMin: $event })"
class="bg-gray-50 border border-gray-300 text-sm rounded-lg block w-1/2 p-2.5"
placeholder="YY"
/>
</div>
@@ -196,9 +202,9 @@
<input
type="text"
id="brokername"
[(ngModel)]="criteria.brokerName"
(ngModelChange)="debouncedSearch()"
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"
[ngModel]="criteria.brokerName"
(ngModelChange)="updateCriteria({ brokerName: $event })"
class="bg-gray-50 border border-gray-300 text-sm rounded-lg block w-full p-2.5"
placeholder="e.g. Brokers Invest"
/>
</div>
@@ -269,11 +275,11 @@
<label class="block mb-2 text-sm font-medium text-gray-900">Search Type</label>
<div class="flex items-center space-x-4">
<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>
</label>
<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>
</label>
</div>
@@ -296,25 +302,29 @@
<div>
<label for="price" class="block mb-2 text-sm font-medium text-gray-900">Price</label>
<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>
<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>
<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">
<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>
<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>
<label for="cashflow" class="block mb-2 text-sm font-medium text-gray-900">Cashflow</label>
<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>
<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>
@@ -322,9 +332,9 @@
<input
type="text"
id="title"
[(ngModel)]="criteria.title"
(ngModelChange)="debouncedSearch()"
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"
[ngModel]="criteria.title"
(ngModelChange)="updateCriteria({ title: $event })"
class="bg-gray-50 border border-gray-300 text-sm rounded-lg block w-full p-2.5"
placeholder="e.g. Restaurant"
/>
</div>
@@ -360,18 +370,18 @@
<input
type="number"
id="numberEmployees-from"
[(ngModel)]="criteria.minNumberEmployees"
(ngModelChange)="debouncedSearch()"
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"
[ngModel]="criteria.minNumberEmployees"
(ngModelChange)="updateCriteria({ minNumberEmployees: $event })"
class="bg-gray-50 border border-gray-300 text-sm rounded-lg block w-1/2 p-2.5"
placeholder="From"
/>
<span>-</span>
<input
type="number"
id="numberEmployees-to"
[(ngModel)]="criteria.maxNumberEmployees"
(ngModelChange)="debouncedSearch()"
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"
[ngModel]="criteria.maxNumberEmployees"
(ngModelChange)="updateCriteria({ maxNumberEmployees: $event })"
class="bg-gray-50 border border-gray-300 text-sm rounded-lg block w-1/2 p-2.5"
placeholder="To"
/>
</div>
@@ -382,9 +392,9 @@
<input
type="number"
id="establishedMin"
[(ngModel)]="criteria.establishedMin"
(ngModelChange)="debouncedSearch()"
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"
[ngModel]="criteria.establishedMin"
(ngModelChange)="updateCriteria({ establishedMin: $event })"
class="bg-gray-50 border border-gray-300 text-sm rounded-lg block w-1/2 p-2.5"
placeholder="YY"
/>
</div>
@@ -394,9 +404,9 @@
<input
type="text"
id="brokername"
[(ngModel)]="criteria.brokerName"
(ngModelChange)="debouncedSearch()"
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"
[ngModel]="criteria.brokerName"
(ngModelChange)="updateCriteria({ brokerName: $event })"
class="bg-gray-50 border border-gray-300 text-sm rounded-lg block w-full p-2.5"
placeholder="e.g. Brokers Invest"
/>
</div>

View File

@@ -86,14 +86,12 @@ export class SearchModalComponent implements OnInit, OnDestroy {
}
// Setup debounced search
this.searchDebounce$.pipe(debounceTime(400), distinctUntilChanged(), takeUntil(this.destroy$)).subscribe(() => {
this.triggerSearch();
});
this.searchDebounce$.pipe(debounceTime(400), takeUntil(this.destroy$)).subscribe(() => this.triggerSearch());
}
private initializeWithCriteria(criteria: any): void {
this.criteria = criteria;
this.currentListingType = criteria.criteriaType;
this.currentListingType = criteria?.criteriaType;
this.backupCriteria = JSON.parse(JSON.stringify(criteria));
this.updateSelectedPropertyType();
this.setTotalNumberOfResults();
@@ -312,7 +310,7 @@ export class SearchModalComponent implements OnInit, OnDestroy {
}
// Helper methods
private updateCriteria(updates: any): void {
public updateCriteria(updates: any): void {
if (this.isModal) {
// In modal: Update locally only
this.criteria = { ...this.criteria, ...updates };
@@ -356,10 +354,10 @@ export class SearchModalComponent implements OnInit, OnDestroy {
switch (this.currentListingType) {
case 'businessListings':
this.numberOfResults$ = this.listingService.getNumberOfListings('business');
this.numberOfResults$ = this.listingService.getNumberOfListings('business', this.criteria);
break;
case 'commercialPropertyListings':
this.numberOfResults$ = this.listingService.getNumberOfListings('commercialProperty');
this.numberOfResults$ = this.listingService.getNumberOfListings('commercialProperty', this.criteria);
break;
case 'brokerListings':
this.numberOfResults$ = this.userService.getNumberOfBroker();