@rolatech/angular-property 20.0.2-beta.3 → 20.0.4-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (17) hide show
  1. package/fesm2022/rolatech-angular-property-property-filter-icon.component-_P3G8E-x.mjs +126 -0
  2. package/fesm2022/rolatech-angular-property-property-filter-icon.component-_P3G8E-x.mjs.map +1 -0
  3. package/fesm2022/rolatech-angular-property-property-index.component-DGFoqfbV.mjs +92 -0
  4. package/fesm2022/rolatech-angular-property-property-index.component-DGFoqfbV.mjs.map +1 -0
  5. package/fesm2022/{rolatech-angular-property-property-manage-viewings-index.component-UsM6RfhW.mjs → rolatech-angular-property-property-manage-viewings-index.component-Dsk7BMQF.mjs} +2 -2
  6. package/fesm2022/{rolatech-angular-property-property-manage-viewings-index.component-UsM6RfhW.mjs.map → rolatech-angular-property-property-manage-viewings-index.component-Dsk7BMQF.mjs.map} +1 -1
  7. package/fesm2022/{rolatech-angular-property-rolatech-angular-property-CQG71H-d.mjs → rolatech-angular-property-rolatech-angular-property-D6LNKZBf.mjs} +367 -131
  8. package/fesm2022/rolatech-angular-property-rolatech-angular-property-D6LNKZBf.mjs.map +1 -0
  9. package/fesm2022/rolatech-angular-property.mjs +1 -1
  10. package/index.d.ts +6 -6
  11. package/package.json +5 -5
  12. package/themes/_default.scss +1 -1
  13. package/fesm2022/rolatech-angular-property-property-filter-icon.component-CO2B-Na5.mjs +0 -93
  14. package/fesm2022/rolatech-angular-property-property-filter-icon.component-CO2B-Na5.mjs.map +0 -1
  15. package/fesm2022/rolatech-angular-property-property-index.component-Bg9L4p2Z.mjs +0 -44
  16. package/fesm2022/rolatech-angular-property-property-index.component-Bg9L4p2Z.mjs.map +0 -1
  17. package/fesm2022/rolatech-angular-property-rolatech-angular-property-CQG71H-d.mjs.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, ElementRef, input, booleanAttribute, effect, HostBinding, ViewEncapsulation, Component, viewChild, PLATFORM_ID, output, computed, model, signal, Pipe, ViewChild } from '@angular/core';
2
+ import { inject, ElementRef, input, booleanAttribute, effect, HostBinding, ViewEncapsulation, Component, viewChild, PLATFORM_ID, output, computed, EventEmitter, Injectable, signal, Pipe, DestroyRef, model, ViewChild } from '@angular/core';
3
3
  import * as i1$4 from '@angular/material/button';
4
4
  import { MatButtonModule } from '@angular/material/button';
5
5
  import * as i4 from '@angular/material/menu';
@@ -10,8 +10,8 @@ import { MatSnackBar } from '@angular/material/snack-bar';
10
10
  import { MatTableModule } from '@angular/material/table';
11
11
  import * as i1$1 from '@angular/router';
12
12
  import { RouterLink, RouterModule, Router, ActivatedRoute, RouterLinkActive, RouterOutlet } from '@angular/router';
13
- import { ThumbnailComponent, ImagePlaceholderComponent, ToolbarComponent, SpinnerComponent, ImagePreviewDialogComponent, BaseComponent, AcceptDialogComponent, RejectDialogComponent, RichLabelComponent, AngularComponentsModule, ConfirmationDialogComponent, TabsComponent, TabComponent, EmptyComponent, ContainerComponent, ListComponent, MediaListComponent, MediaListItemComponent, InputComponent } from '@rolatech/angular-components';
14
- import { PropertyService, FeatureService, PropertySearchService, DialogService } from '@rolatech/angular-services';
13
+ import { ThumbnailComponent, ImagePlaceholderComponent, ToolbarComponent, SpinnerComponent, ImagePreviewDialogComponent, BaseComponent, AcceptDialogComponent, RejectDialogComponent, RichLabelComponent, AngularComponentsModule, ConfirmationDialogComponent, TabsComponent, TabComponent, EmptyComponent, ContainerComponent, SearchBar, ListComponent, MediaListComponent, MediaListItemComponent, InputComponent } from '@rolatech/angular-components';
14
+ import { PropertyService, FeatureService, TimeZoneService, PropertySearchService, DialogService } from '@rolatech/angular-services';
15
15
  import * as i1 from '@angular/common';
16
16
  import { CommonModule, NgClass, isPlatformBrowser, ViewportScroller, KeyValuePipe, Location } from '@angular/common';
17
17
  import { FixedPipe, AngularCommonModule, OptionsFormatPipe, APP_CONFIG, DecimalDirective, DurationPipe } from '@rolatech/angular-common';
@@ -30,7 +30,7 @@ import * as i5 from '@angular/material/select';
30
30
  import { MatSelectModule } from '@angular/material/select';
31
31
  import * as i1$5 from '@angular/material/chips';
32
32
  import { MatChipsModule } from '@angular/material/chips';
33
- import { startWith, map, defer, forkJoin, from, concatMap, take, Observable } from 'rxjs';
33
+ import { startWith, map, defer, distinctUntilChanged, switchMap, finalize, forkJoin, from, concatMap, take, Observable } from 'rxjs';
34
34
  import { ENTER, COMMA } from '@angular/cdk/keycodes';
35
35
  import * as i4$2 from '@angular/material/autocomplete';
36
36
  import { MatAutocompleteModule } from '@angular/material/autocomplete';
@@ -38,9 +38,6 @@ import { MatOptionModule, MAT_DATE_LOCALE, DateAdapter, MAT_DATE_FORMATS } from
38
38
  import _, { findIndex, findLastIndex, first, remove } from 'lodash';
39
39
  import * as i2$1 from '@angular/material/divider';
40
40
  import { MatDividerModule, MatDivider } from '@angular/material/divider';
41
- import * as i7 from '@angular/material/datepicker';
42
- import { MatDatepickerModule } from '@angular/material/datepicker';
43
- import { trigger, state, transition, style, animate } from '@angular/animations';
44
41
  import { CommentsComponent } from '@rolatech/angular-comment';
45
42
  import { DomSanitizer } from '@angular/platform-browser';
46
43
  import * as i4$1 from '@angular/cdk/text-field';
@@ -48,8 +45,11 @@ import { TextFieldModule } from '@angular/cdk/text-field';
48
45
  import * as i7$1 from '@angular/material/radio';
49
46
  import { MatRadioModule } from '@angular/material/radio';
50
47
  import { MomentDateAdapter } from '@angular/material-moment-adapter';
48
+ import * as i7 from '@angular/material/datepicker';
49
+ import { MatDatepickerModule } from '@angular/material/datepicker';
51
50
  import * as i3$1 from '@angular/material/progress-spinner';
52
51
  import { MatProgressSpinner, MatProgressSpinnerModule } from '@angular/material/progress-spinner';
52
+ import { trigger, state, transition, style, animate } from '@angular/animations';
53
53
  import * as i8 from '@angular/material/progress-bar';
54
54
  import { MatProgressBarModule } from '@angular/material/progress-bar';
55
55
  import * as i1$6 from '@angular/material/checkbox';
@@ -300,11 +300,11 @@ class PropertyManageItemComponent {
300
300
  archived() { }
301
301
  delete() { }
302
302
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyManageItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
303
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.0", type: PropertyManageItemComponent, isStandalone: true, selector: "rolatech-property-manage-item", inputs: { property: { classPropertyName: "property", publicName: "property", isSignal: true, isRequired: true, transformFunction: null }, thumbnail: { classPropertyName: "thumbnail", publicName: "thumbnail", isSignal: true, isRequired: false, transformFunction: null }, list: { classPropertyName: "list", publicName: "list", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.rolatech-property-manage-item": "this.hasClass" } }, ngImport: i0, template: "<div\n class=\"flex p-3 bg-[--rt-raised-background] hover:bg-[--rt-raised-background] cursor-pointer rounded-md\"\n [ngClass]=\"list() ? 'w-full flex-row' : 'flex-col h-full'\"\n>\n <div>\n @if (property().media) {\n <div class=\"object-cover aspect-video rounded-lg\" [ngClass]=\"list() ? 'w-32 mr-3' : ''\">\n @defer {\n <rolatech-thumbnail [src]=\"property().media ? property().media[0].url : ''\" size=\"medium\" mode=\"full\">\n </rolatech-thumbnail>\n } @placeholder {\n <div class=\"bg-[--rt-raised-background] h-full w-full object-cover aspect-video rounded-lg\"></div>\n }\n </div>\n } @else {\n <div class=\"object-cover aspect-video rounded-lg\" [ngClass]=\"list() ? 'w-32 mr-3' : ''\">\n <rolatech-image-placeholder></rolatech-image-placeholder>\n </div>\n }\n </div>\n\n <div class=\"py-2\">\n <div class=\"text-lg font-bold\">\n {{ property().title }}\n </div>\n </div>\n <div class=\"flex-1\"></div>\n <div class=\"\">\u00A3{{ property().price | fixed }}</div>\n</div>\n", styles: ["rolatech-property-manage-item{--rt-property-view-item-margin: 16px;width:calc(100% / var(--rt-property-view-items-per-row) - var(--rt-property-view-item-margin) - .01px)}rolatech-property-manage-item[list]{--rt-property-view-items-per-row: 1}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ImagePlaceholderComponent, selector: "rolatech-image-placeholder", inputs: ["ratio"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatMenuModule }, { kind: "pipe", type: FixedPipe, name: "fixed" }], encapsulation: i0.ViewEncapsulation.None, deferBlockDependencies: [() => [ThumbnailComponent]] });
303
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.0", type: PropertyManageItemComponent, isStandalone: true, selector: "rolatech-property-manage-item", inputs: { property: { classPropertyName: "property", publicName: "property", isSignal: true, isRequired: true, transformFunction: null }, thumbnail: { classPropertyName: "thumbnail", publicName: "thumbnail", isSignal: true, isRequired: false, transformFunction: null }, list: { classPropertyName: "list", publicName: "list", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.rolatech-property-manage-item": "this.hasClass" } }, ngImport: i0, template: "<div\n class=\"flex p-3 bg-[--rt-raised-background] hover:bg-[--rt-raised-background] cursor-pointer rounded-md\"\n [ngClass]=\"list() ? 'w-full flex-row' : 'flex-col h-full'\"\n>\n <div>\n @if (property().media) {\n <div class=\"object-cover aspect-video rounded-lg\" [ngClass]=\"list() ? 'w-32 mr-3' : ''\">\n @defer {\n <rolatech-thumbnail\n [src]=\"property().media ? property().media[0].url : property().mediaUrl\"\n size=\"medium\"\n mode=\"full\"\n >\n </rolatech-thumbnail>\n } @placeholder {\n <div class=\"bg-[--rt-raised-background] h-full w-full object-cover aspect-video rounded-lg\"></div>\n }\n </div>\n } @else {\n <div class=\"object-cover aspect-video rounded-lg\" [ngClass]=\"list() ? 'w-32 mr-3' : ''\">\n <rolatech-image-placeholder></rolatech-image-placeholder>\n </div>\n }\n </div>\n\n <div class=\"py-2\">\n <div class=\"text-lg font-bold\">\n {{ property().title }}\n </div>\n </div>\n <div class=\"flex-1\"></div>\n <div class=\"\">\u00A3{{ property().price | fixed }}</div>\n</div>\n", styles: ["rolatech-property-manage-item{--rt-property-view-item-margin: 16px;width:calc(100% / var(--rt-property-view-items-per-row) - var(--rt-property-view-item-margin) - .01px)}rolatech-property-manage-item[list]{--rt-property-view-items-per-row: 1}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ImagePlaceholderComponent, selector: "rolatech-image-placeholder", inputs: ["ratio"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatMenuModule }, { kind: "pipe", type: FixedPipe, name: "fixed" }], encapsulation: i0.ViewEncapsulation.None, deferBlockDependencies: [() => [ThumbnailComponent]] });
304
304
  }
305
305
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyManageItemComponent, decorators: [{
306
306
  type: Component,
307
- args: [{ selector: 'rolatech-property-manage-item', imports: [CommonModule, ThumbnailComponent, ImagePlaceholderComponent, MatButtonModule, MatMenuModule, FixedPipe], encapsulation: ViewEncapsulation.None, template: "<div\n class=\"flex p-3 bg-[--rt-raised-background] hover:bg-[--rt-raised-background] cursor-pointer rounded-md\"\n [ngClass]=\"list() ? 'w-full flex-row' : 'flex-col h-full'\"\n>\n <div>\n @if (property().media) {\n <div class=\"object-cover aspect-video rounded-lg\" [ngClass]=\"list() ? 'w-32 mr-3' : ''\">\n @defer {\n <rolatech-thumbnail [src]=\"property().media ? property().media[0].url : ''\" size=\"medium\" mode=\"full\">\n </rolatech-thumbnail>\n } @placeholder {\n <div class=\"bg-[--rt-raised-background] h-full w-full object-cover aspect-video rounded-lg\"></div>\n }\n </div>\n } @else {\n <div class=\"object-cover aspect-video rounded-lg\" [ngClass]=\"list() ? 'w-32 mr-3' : ''\">\n <rolatech-image-placeholder></rolatech-image-placeholder>\n </div>\n }\n </div>\n\n <div class=\"py-2\">\n <div class=\"text-lg font-bold\">\n {{ property().title }}\n </div>\n </div>\n <div class=\"flex-1\"></div>\n <div class=\"\">\u00A3{{ property().price | fixed }}</div>\n</div>\n", styles: ["rolatech-property-manage-item{--rt-property-view-item-margin: 16px;width:calc(100% / var(--rt-property-view-items-per-row) - var(--rt-property-view-item-margin) - .01px)}rolatech-property-manage-item[list]{--rt-property-view-items-per-row: 1}\n"] }]
307
+ args: [{ selector: 'rolatech-property-manage-item', imports: [CommonModule, ThumbnailComponent, ImagePlaceholderComponent, MatButtonModule, MatMenuModule, FixedPipe], encapsulation: ViewEncapsulation.None, template: "<div\n class=\"flex p-3 bg-[--rt-raised-background] hover:bg-[--rt-raised-background] cursor-pointer rounded-md\"\n [ngClass]=\"list() ? 'w-full flex-row' : 'flex-col h-full'\"\n>\n <div>\n @if (property().media) {\n <div class=\"object-cover aspect-video rounded-lg\" [ngClass]=\"list() ? 'w-32 mr-3' : ''\">\n @defer {\n <rolatech-thumbnail\n [src]=\"property().media ? property().media[0].url : property().mediaUrl\"\n size=\"medium\"\n mode=\"full\"\n >\n </rolatech-thumbnail>\n } @placeholder {\n <div class=\"bg-[--rt-raised-background] h-full w-full object-cover aspect-video rounded-lg\"></div>\n }\n </div>\n } @else {\n <div class=\"object-cover aspect-video rounded-lg\" [ngClass]=\"list() ? 'w-32 mr-3' : ''\">\n <rolatech-image-placeholder></rolatech-image-placeholder>\n </div>\n }\n </div>\n\n <div class=\"py-2\">\n <div class=\"text-lg font-bold\">\n {{ property().title }}\n </div>\n </div>\n <div class=\"flex-1\"></div>\n <div class=\"\">\u00A3{{ property().price | fixed }}</div>\n</div>\n", styles: ["rolatech-property-manage-item{--rt-property-view-item-margin: 16px;width:calc(100% / var(--rt-property-view-items-per-row) - var(--rt-property-view-item-margin) - .01px)}rolatech-property-manage-item[list]{--rt-property-view-items-per-row: 1}\n"] }]
308
308
  }], ctorParameters: () => [], propDecorators: { hasClass: [{
309
309
  type: HostBinding,
310
310
  args: ['class.rolatech-property-manage-item']
@@ -1067,83 +1067,78 @@ const propertyManageOffersRoutes = [
1067
1067
  },
1068
1068
  ];
1069
1069
 
1070
- class PropertyFilterComponent {
1071
- towns = ['London'];
1072
- filter = model(false, ...(ngDevMode ? [{ debugName: "filter" }] : []));
1073
- minDate = new Date();
1074
- propertyFilterIconComponent = defer(() => import('./rolatech-angular-property-property-filter-icon.component-CO2B-Na5.mjs').then((m) => m.PropertyFilterIconComponent));
1075
- searchOptions = {
1076
- town: '',
1077
- startDate: '',
1078
- endDate: '',
1079
- };
1080
- reset() { }
1081
- search() { }
1082
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1083
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.0", type: PropertyFilterComponent, isStandalone: true, selector: "rolatech-property-filter", inputs: { filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filter: "filterChange" }, ngImport: i0, template: "<!-- <div class=\"p-3\">\n <div class=\"bg-white p-3 flex items-center justify-between rounded-md\">\n <div class=\"flex items-center\">\n <mat-form-field subscriptSizing=\"dynamic\">\n <mat-select #select=\"matSelect\" placeholder=\"Town\" i18n-placeholder [(ngModel)]=\"searchOptions.town\">\n @for (Town of towns; track Town) {\n <mat-option [value]=\"Town\">\n {{ Town }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n <div class=\"flex gap-3\">\n <a mat-stroked-button class=\"w-[128px]\" (click)=\"reset()\" i18n>Reset</a>\n <ng-container *ngComponentOutlet=\"propertyFilterIconComponent | async\"></ng-container>\n <a mat-flat-button class=\"w-full\" (click)=\"search()\" i18n>Search</a>\n </div>\n </div>\n</div> -->\n<div\n [ngClass]=\"filter() ? 'transition-height duration-500 ease-in-out' : 'md:h-14 h-0 transition-height duration-500 ease-in-out'\"\n>\n <div\n class=\"min-w-[256px] md:min-w-[320px] h-full m-3 flex flex-row md:flex-col md:h-full items-center md:items-start shadow-inner shadow-light-400 md:shadow-none overflow-x-scroll overflow-y-hidden scrollbar-hide whitespace-pre\"\n >\n <div class=\"w-full h-full\">\n <div class=\"flex flex-col md:flex-row h-in justify-center items-center gap-3\">\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-select #select=\"matSelect\" placeholder=\"Town\" [(ngModel)]=\"searchOptions.city\">\n @for (town of towns; track town) {\n <mat-option [value]=\"town\">\n {{ town }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <input\n matInput\n placeholder=\"Available\"\n [matDatepicker]=\"startDatePicker\"\n [min]=\"minDate\"\n (focus)=\"startDatePicker.open()\"\n name=\"available\"\n [(ngModel)]=\"searchOptions.available\"\n (dateInput)=\"searchOptions.available = $event.value.format('YYYY-MM-DD')\"\n readonly\n />\n <mat-datepicker-toggle matIconPrefix [for]=\"startDatePicker\"></mat-datepicker-toggle>\n <mat-datepicker #startDatePicker></mat-datepicker>\n </mat-form-field>\n <div class=\"flex w-full gap-3\">\n <a mat-stroked-button class=\"w-[128px]\" (click)=\"reset()\">Reset</a>\n <ng-container *ngComponentOutlet=\"propertyFilterIconComponent | async\"></ng-container>\n <a mat-flat-button class=\"w-full\" (click)=\"search()\">Search</a>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: ["mat-form-field{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1$2.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i5.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i5.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i7.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i7.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i7.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }], animations: [
1084
- trigger('filter', [
1085
- state('collapsed', style({ height: '0px', minHeight: '0' })),
1086
- state('expanded', style({ height: '*' })),
1087
- transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
1088
- ]),
1089
- ] });
1070
+ var PropertyViewType;
1071
+ (function (PropertyViewType) {
1072
+ PropertyViewType[PropertyViewType["GRID"] = 0] = "GRID";
1073
+ PropertyViewType[PropertyViewType["LIST"] = 1] = "LIST";
1074
+ })(PropertyViewType || (PropertyViewType = {}));
1075
+ class PropertyUtil {
1076
+ viewEvent = new EventEmitter();
1077
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyUtil, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1078
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyUtil, providedIn: 'root' });
1090
1079
  }
1091
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyFilterComponent, decorators: [{
1092
- type: Component,
1093
- args: [{ selector: 'rolatech-property-filter', imports: [
1094
- CommonModule,
1095
- MatButtonModule,
1096
- MatFormFieldModule,
1097
- MatInputModule,
1098
- MatSelectModule,
1099
- MatOptionModule,
1100
- FormsModule,
1101
- MatDatepickerModule,
1102
- ], animations: [
1103
- trigger('filter', [
1104
- state('collapsed', style({ height: '0px', minHeight: '0' })),
1105
- state('expanded', style({ height: '*' })),
1106
- transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
1107
- ]),
1108
- ], template: "<!-- <div class=\"p-3\">\n <div class=\"bg-white p-3 flex items-center justify-between rounded-md\">\n <div class=\"flex items-center\">\n <mat-form-field subscriptSizing=\"dynamic\">\n <mat-select #select=\"matSelect\" placeholder=\"Town\" i18n-placeholder [(ngModel)]=\"searchOptions.town\">\n @for (Town of towns; track Town) {\n <mat-option [value]=\"Town\">\n {{ Town }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n <div class=\"flex gap-3\">\n <a mat-stroked-button class=\"w-[128px]\" (click)=\"reset()\" i18n>Reset</a>\n <ng-container *ngComponentOutlet=\"propertyFilterIconComponent | async\"></ng-container>\n <a mat-flat-button class=\"w-full\" (click)=\"search()\" i18n>Search</a>\n </div>\n </div>\n</div> -->\n<div\n [ngClass]=\"filter() ? 'transition-height duration-500 ease-in-out' : 'md:h-14 h-0 transition-height duration-500 ease-in-out'\"\n>\n <div\n class=\"min-w-[256px] md:min-w-[320px] h-full m-3 flex flex-row md:flex-col md:h-full items-center md:items-start shadow-inner shadow-light-400 md:shadow-none overflow-x-scroll overflow-y-hidden scrollbar-hide whitespace-pre\"\n >\n <div class=\"w-full h-full\">\n <div class=\"flex flex-col md:flex-row h-in justify-center items-center gap-3\">\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-select #select=\"matSelect\" placeholder=\"Town\" [(ngModel)]=\"searchOptions.city\">\n @for (town of towns; track town) {\n <mat-option [value]=\"town\">\n {{ town }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <input\n matInput\n placeholder=\"Available\"\n [matDatepicker]=\"startDatePicker\"\n [min]=\"minDate\"\n (focus)=\"startDatePicker.open()\"\n name=\"available\"\n [(ngModel)]=\"searchOptions.available\"\n (dateInput)=\"searchOptions.available = $event.value.format('YYYY-MM-DD')\"\n readonly\n />\n <mat-datepicker-toggle matIconPrefix [for]=\"startDatePicker\"></mat-datepicker-toggle>\n <mat-datepicker #startDatePicker></mat-datepicker>\n </mat-form-field>\n <div class=\"flex w-full gap-3\">\n <a mat-stroked-button class=\"w-[128px]\" (click)=\"reset()\">Reset</a>\n <ng-container *ngComponentOutlet=\"propertyFilterIconComponent | async\"></ng-container>\n <a mat-flat-button class=\"w-full\" (click)=\"search()\">Search</a>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: ["mat-form-field{width:100%}\n"] }]
1080
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyUtil, decorators: [{
1081
+ type: Injectable,
1082
+ args: [{
1083
+ providedIn: 'root',
1084
+ }]
1109
1085
  }] });
1110
1086
 
1111
1087
  class PropertyLayoutComponent extends BaseComponent {
1112
1088
  propertyService = inject(PropertyService);
1089
+ util = inject(PropertyUtil);
1090
+ open = signal(false, ...(ngDevMode ? [{ debugName: "open" }] : []));
1091
+ model = {};
1092
+ gridView = true;
1093
+ searchBar = viewChild('searchBar', ...(ngDevMode ? [{ debugName: "searchBar" }] : []));
1113
1094
  selectIndex = 0;
1114
1095
  filter = false;
1096
+ propertyFilterIconComponent = defer(() => import('./rolatech-angular-property-property-filter-icon.component-_P3G8E-x.mjs').then((m) => m.PropertyFilterIconComponent));
1115
1097
  ngOnInit() {
1116
- this.findCategories();
1117
- }
1118
- findCategories() {
1119
- // this.categoryService.find({}, false).subscribe({
1120
- // next: (res: any) => {
1121
- // this.categories = res.data;
1122
- // },
1123
- // });
1124
- }
1125
- loadPropertyByCategoryIndex(index) {
1126
- // this.selectIndex = index;
1127
- // const id = this.categories[index].id;
1128
- // if (index === 0) {
1129
- // this.router.navigate([`./`]);
1130
- // // this.propertyService.find({}).subscribe({
1131
- // // next: res => {
1132
- // // }
1133
- // // })
1134
- // } else {
1135
- // this.router.navigate([`../categories/${id}`], {
1136
- // relativeTo: this.route,
1137
- // });
1138
- // }
1139
1098
  }
1140
- nextCategory() { }
1099
+ toggleSearch() {
1100
+ this.open.update(v => !v);
1101
+ }
1102
+ onCloseSearch() {
1103
+ // this.open.set(false);
1104
+ // this.router.navigate([], { queryParams: {}, queryParamsHandling: 'merge' });
1105
+ this.router.navigate(["/properties"]);
1106
+ }
1107
+ toggleView() {
1108
+ if (this.gridView) {
1109
+ this.gridView = false;
1110
+ this.util.viewEvent.emit(PropertyViewType.LIST);
1111
+ }
1112
+ else {
1113
+ this.gridView = true;
1114
+ this.util.viewEvent.emit(PropertyViewType.GRID);
1115
+ }
1116
+ }
1117
+ onSearch(event) {
1118
+ const qp = Object.fromEntries(Object.entries(event).filter(([_, v]) => v !== undefined && v !== null && !(Array.isArray(v) && v.length === 0) && v !== ''));
1119
+ this.router.navigate([], {
1120
+ queryParams: qp,
1121
+ queryParamsHandling: 'merge', // keep other params like sort, etc.
1122
+ });
1123
+ }
1124
+ searchByText(event) {
1125
+ this.router.navigate([], {
1126
+ queryParams: { q: event, page: 1, limit: 15 },
1127
+ queryParamsHandling: 'merge', // keep other params like sort, etc.
1128
+ });
1129
+ }
1130
+ onReset(event) {
1131
+ this.router.navigate([], {
1132
+ queryParams: {}, // empty
1133
+ // omit queryParamsHandling so it REPLACES (not merges) → clears everything
1134
+ });
1135
+ }
1141
1136
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyLayoutComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1142
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.2.0", type: PropertyLayoutComponent, isStandalone: true, selector: "rolatech-property-layout", usesInheritance: true, ngImport: i0, template: "<rolatech-container>\n <div class=\"flex flex-col min-w-[320px] max-w-[1280px] m-auto\">\n <rolatech-property-filter [(filter)]=\"filter\"></rolatech-property-filter>\n <div class=\"flex justify-between items-center\">\n <div class=\"p-3 text-2xl font-medium\" i18n>Properties</div>\n <button mat-button class=\"md:invisible\" (click)=\"filter = !filter\">\n <mat-icon>tune</mat-icon>\n <span>Filter</span>\n </button>\n </div>\n <div class=\"w-full\">\n <router-outlet></router-outlet>\n </div>\n </div>\n</rolatech-container>\n", styles: [".property-layout-active{border-radius:var(--rt-rounded-base, 8px);background-color:var(-rt-base-background, #fff);color:var(--rt-brand-color, #000)}@media (max-width: 768px){.property-layout-active{background-color:var(--rt-text-primary, #000);color:var(--rt-text-primary-inverse, #000)}}.scrollbar-hide::-webkit-scrollbar{display:none}.scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}\n"], dependencies: [{ kind: "ngmodule", type: AngularCommonModule }, { kind: "directive", type: i1$1.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "ngmodule", type: AngularComponentsModule }, { kind: "component", type: i1$4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "component", type: PropertyFilterComponent, selector: "rolatech-property-filter", inputs: ["filter"], outputs: ["filterChange"] }] });
1137
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.2.0", type: PropertyLayoutComponent, isStandalone: true, selector: "rolatech-property-layout", viewQueries: [{ propertyName: "searchBar", first: true, predicate: ["searchBar"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<rolatech-container>\n <div class=\"flex flex-col min-w-[320px] max-w-[1280px] m-auto\">\n <div class=\"flex justify-between items-center h-16\">\n <div class=\"flex justify-between items-center w-full\">\n <div class=\"p-3 text-2xl font-medium\" i18n>Properties</div>\n <div class=\"flex flex-row\">\n <button mat-icon-button (click)=\"toggleSearch()\">\n <mat-icon>search</mat-icon>\n </button>\n <button mat-icon-button (click)=\"toggleView()\">\n <mat-icon>{{ gridView ? 'view_list' : 'grid_on' }}</mat-icon>\n </button>\n <ng-container *ngComponentOutlet=\"propertyFilterIconComponent | async\"></ng-container>\n </div>\n </div>\n </div>\n <rolatech-search-bar\n [(show)]=\"open\"\n #searchBar\n (search)=\"searchByText($event)\"\n (close)=\"onCloseSearch()\"\n ></rolatech-search-bar>\n <div class=\"w-full\">\n <router-outlet></router-outlet>\n </div>\n </div>\n</rolatech-container>\n", styles: [".property-layout-active{border-radius:var(--rt-rounded-base, 8px);background-color:var(-rt-base-background, #fff);color:var(--rt-brand-color, #000)}@media (max-width: 768px){.property-layout-active{background-color:var(--rt-text-primary, #000);color:var(--rt-text-primary-inverse, #000)}}.scrollbar-hide::-webkit-scrollbar{display:none}.scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}\n"], dependencies: [{ kind: "ngmodule", type: AngularCommonModule }, { kind: "directive", type: i1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: i1$1.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "ngmodule", type: AngularComponentsModule }, { kind: "component", type: i1$4.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "component", type: SearchBar, selector: "rolatech-search-bar", inputs: ["show"], outputs: ["showChange", "search", "close"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }] });
1143
1138
  }
1144
1139
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyLayoutComponent, decorators: [{
1145
1140
  type: Component,
1146
- args: [{ selector: 'rolatech-property-layout', imports: [AngularCommonModule, AngularComponentsModule, ContainerComponent, PropertyFilterComponent], template: "<rolatech-container>\n <div class=\"flex flex-col min-w-[320px] max-w-[1280px] m-auto\">\n <rolatech-property-filter [(filter)]=\"filter\"></rolatech-property-filter>\n <div class=\"flex justify-between items-center\">\n <div class=\"p-3 text-2xl font-medium\" i18n>Properties</div>\n <button mat-button class=\"md:invisible\" (click)=\"filter = !filter\">\n <mat-icon>tune</mat-icon>\n <span>Filter</span>\n </button>\n </div>\n <div class=\"w-full\">\n <router-outlet></router-outlet>\n </div>\n </div>\n</rolatech-container>\n", styles: [".property-layout-active{border-radius:var(--rt-rounded-base, 8px);background-color:var(-rt-base-background, #fff);color:var(--rt-brand-color, #000)}@media (max-width: 768px){.property-layout-active{background-color:var(--rt-text-primary, #000);color:var(--rt-text-primary-inverse, #000)}}.scrollbar-hide::-webkit-scrollbar{display:none}.scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}\n"] }]
1141
+ args: [{ selector: 'rolatech-property-layout', imports: [AngularCommonModule, AngularComponentsModule, ContainerComponent, SearchBar], template: "<rolatech-container>\n <div class=\"flex flex-col min-w-[320px] max-w-[1280px] m-auto\">\n <div class=\"flex justify-between items-center h-16\">\n <div class=\"flex justify-between items-center w-full\">\n <div class=\"p-3 text-2xl font-medium\" i18n>Properties</div>\n <div class=\"flex flex-row\">\n <button mat-icon-button (click)=\"toggleSearch()\">\n <mat-icon>search</mat-icon>\n </button>\n <button mat-icon-button (click)=\"toggleView()\">\n <mat-icon>{{ gridView ? 'view_list' : 'grid_on' }}</mat-icon>\n </button>\n <ng-container *ngComponentOutlet=\"propertyFilterIconComponent | async\"></ng-container>\n </div>\n </div>\n </div>\n <rolatech-search-bar\n [(show)]=\"open\"\n #searchBar\n (search)=\"searchByText($event)\"\n (close)=\"onCloseSearch()\"\n ></rolatech-search-bar>\n <div class=\"w-full\">\n <router-outlet></router-outlet>\n </div>\n </div>\n</rolatech-container>\n", styles: [".property-layout-active{border-radius:var(--rt-rounded-base, 8px);background-color:var(-rt-base-background, #fff);color:var(--rt-brand-color, #000)}@media (max-width: 768px){.property-layout-active{background-color:var(--rt-text-primary, #000);color:var(--rt-text-primary-inverse, #000)}}.scrollbar-hide::-webkit-scrollbar{display:none}.scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}\n"] }]
1147
1142
  }] });
1148
1143
 
1149
1144
  class PropertyActionsComponent {
@@ -1244,18 +1239,23 @@ class PropertyVideoComponent {
1244
1239
  sanitizer = inject(DomSanitizer);
1245
1240
  video = input.required(...(ngDevMode ? [{ debugName: "video" }] : []));
1246
1241
  videoUrl = computed(() => {
1242
+ if (this.video().provider !== PropertyVideoProvider.YOUTUBE)
1243
+ return;
1247
1244
  const match = this.video().url.match(/(?:youtu\.be\/|youtube\.com\/watch\?v=)([\w-]+)/);
1248
1245
  if (match && match[1]) {
1249
1246
  return this.sanitizer.bypassSecurityTrustResourceUrl(`https://www.youtube.com/embed/${match[1]}`);
1250
1247
  }
1251
1248
  return null; // Not a valid YouTube URL
1252
1249
  }, ...(ngDevMode ? [{ debugName: "videoUrl" }] : []));
1250
+ youtube = computed(() => {
1251
+ return this.video().provider === PropertyVideoProvider.YOUTUBE;
1252
+ }, ...(ngDevMode ? [{ debugName: "youtube" }] : []));
1253
1253
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyVideoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1254
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.2.0", type: PropertyVideoComponent, isStandalone: true, selector: "rolatech-property-video", inputs: { video: { classPropertyName: "video", publicName: "video", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"\">\n <div class=\"text-2xl font-bold py-4\" i18n>Videos</div>\n <iframe [src]=\"videoUrl()\" frameborder=\"0\" allowfullscreen class=\"w-full aspect-video\"></iframe>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
1254
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.0", type: PropertyVideoComponent, isStandalone: true, selector: "rolatech-property-video", inputs: { video: { classPropertyName: "video", publicName: "video", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"\">\n <div class=\"text-2xl font-bold py-4\" i18n>Videos</div>\n {{ youtube() }}\n @if (youtube()) {\n <iframe [src]=\"videoUrl()\" frameborder=\"0\" allowfullscreen class=\"w-full aspect-video\"></iframe>\n } @else {\n <video controls #videoContainer [src]=\"video().url\" class=\"w-full aspect-video\" [poster]=\"video().thumbnail\">\n <!-- <source [src]=\"video().url\" type=\"video/mp4\" /> -->\n </video>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
1255
1255
  }
1256
1256
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyVideoComponent, decorators: [{
1257
1257
  type: Component,
1258
- args: [{ selector: 'rolatech-property-video', imports: [CommonModule], template: "<div class=\"\">\n <div class=\"text-2xl font-bold py-4\" i18n>Videos</div>\n <iframe [src]=\"videoUrl()\" frameborder=\"0\" allowfullscreen class=\"w-full aspect-video\"></iframe>\n</div>\n" }]
1258
+ args: [{ selector: 'rolatech-property-video', imports: [CommonModule], template: "<div class=\"\">\n <div class=\"text-2xl font-bold py-4\" i18n>Videos</div>\n {{ youtube() }}\n @if (youtube()) {\n <iframe [src]=\"videoUrl()\" frameborder=\"0\" allowfullscreen class=\"w-full aspect-video\"></iframe>\n } @else {\n <video controls #videoContainer [src]=\"video().url\" class=\"w-full aspect-video\" [poster]=\"video().thumbnail\">\n <!-- <source [src]=\"video().url\" type=\"video/mp4\" /> -->\n </video>\n }\n</div>\n" }]
1259
1259
  }] });
1260
1260
 
1261
1261
  class PropertyActionContactComponent {
@@ -1292,27 +1292,155 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImpor
1292
1292
  class PropertyHighlights {
1293
1293
  highlights = input.required(...(ngDevMode ? [{ debugName: "highlights" }] : []));
1294
1294
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyHighlights, deps: [], target: i0.ɵɵFactoryTarget.Component });
1295
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.0", type: PropertyHighlights, isStandalone: true, selector: "rolatech-property-highlights", inputs: { highlights: { classPropertyName: "highlights", publicName: "highlights", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"\">\n <div class=\"text-2xl font-bold py-3\" i18n>Highlights</div>\n <div class=\"flex flex-col flex-wrap items-center text-sm\">\n @for (item of highlights(); track item) {\n <div class=\"flex items-center mr-2\">\n <mat-icon>check</mat-icon>\n <span>{{ item.text }}</span>\n </div>\n }\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
1295
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.0", type: PropertyHighlights, isStandalone: true, selector: "rolatech-property-highlights", inputs: { highlights: { classPropertyName: "highlights", publicName: "highlights", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"\">\n <div class=\"text-2xl font-bold py-3\" i18n>Highlights</div>\n <div class=\"flex flex-col flex-wrap\">\n @for (item of highlights(); track $index) {\n <div class=\"flex items-center py-1\">\n <!-- <mat-icon>check</mat-icon> -->\n <span>{{ item }}</span>\n </div>\n }\n </div>\n</div>\n", styles: [""] });
1296
1296
  }
1297
1297
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyHighlights, decorators: [{
1298
1298
  type: Component,
1299
- args: [{ selector: 'rolatech-property-highlights', imports: [MatIcon], template: "<div class=\"\">\n <div class=\"text-2xl font-bold py-3\" i18n>Highlights</div>\n <div class=\"flex flex-col flex-wrap items-center text-sm\">\n @for (item of highlights(); track item) {\n <div class=\"flex items-center mr-2\">\n <mat-icon>check</mat-icon>\n <span>{{ item.text }}</span>\n </div>\n }\n </div>\n</div>\n" }]
1299
+ args: [{ selector: 'rolatech-property-highlights', template: "<div class=\"\">\n <div class=\"text-2xl font-bold py-3\" i18n>Highlights</div>\n <div class=\"flex flex-col flex-wrap\">\n @for (item of highlights(); track $index) {\n <div class=\"flex items-center py-1\">\n <!-- <mat-icon>check</mat-icon> -->\n <span>{{ item }}</span>\n </div>\n }\n </div>\n</div>\n" }]
1300
+ }] });
1301
+
1302
+ const BANDS = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
1303
+ const RANGES = {
1304
+ A: '(92+)', B: '(81-91)', C: '(69-80)', D: '(55-68)',
1305
+ E: '(39-54)', F: '(21-38)', G: '(1-20)',
1306
+ };
1307
+ const COLORS = {
1308
+ A: '#0E9F6E', // green
1309
+ B: '#10B981',
1310
+ C: '#84CC16',
1311
+ D: '#F59E0B',
1312
+ E: '#F97316',
1313
+ F: '#FB7185',
1314
+ G: '#DC2626'
1315
+ };
1316
+ function bandFromScore(s) {
1317
+ const v = s ?? 0;
1318
+ if (v >= 92)
1319
+ return 'A';
1320
+ if (v >= 81)
1321
+ return 'B';
1322
+ if (v >= 69)
1323
+ return 'C';
1324
+ if (v >= 55)
1325
+ return 'D';
1326
+ if (v >= 39)
1327
+ return 'E';
1328
+ if (v >= 21)
1329
+ return 'F';
1330
+ return 'G';
1331
+ }
1332
+ class EpcChart {
1333
+ // --- inputs (signals) ---
1334
+ currentScore = input(null, ...(ngDevMode ? [{ debugName: "currentScore" }] : [])); // 1..100
1335
+ potentialScore = input(null, ...(ngDevMode ? [{ debugName: "potentialScore" }] : [])); // 1..100
1336
+ showCaptions = input(true, ...(ngDevMode ? [{ debugName: "showCaptions" }] : []));
1337
+ // --- layout ---
1338
+ width = 920;
1339
+ leftPadding = 24;
1340
+ headerY = 40;
1341
+ rangeColW = 90;
1342
+ gapY = 10;
1343
+ topY = 110; // top of first row area
1344
+ rowH = 48; // height of each wedge row
1345
+ rows = 7;
1346
+ // wedge geometry
1347
+ wedgeMaxW = 420; // width of 'A' row
1348
+ wedgeMinW = 220;
1349
+ wedgeDelta = 44; // decrement per row
1350
+ cut = 24; // right slant depth
1351
+ // arrow columns
1352
+ arrowW = 104;
1353
+ arrowH = 44;
1354
+ colGap = 130;
1355
+ wedgeAreaRight = this.leftPadding + this.rangeColW + 12 + this.wedgeMaxW + 20;
1356
+ currentColX = this.wedgeAreaRight + 80;
1357
+ potentialColX = this.currentColX + this.colGap;
1358
+ // captions
1359
+ topCaptionY = this.topY - 22;
1360
+ get bottomCaptionY() { return this.topY + this.rows * (this.rowH + this.gapY) + 22; }
1361
+ // overall height
1362
+ get height() {
1363
+ return this.bottomCaptionY + 56;
1364
+ }
1365
+ // expose constants to template
1366
+ bands = BANDS;
1367
+ RANGES = RANGES;
1368
+ COLORS = COLORS;
1369
+ get rangeX() { return this.leftPadding; }
1370
+ get maxW() { return this.wedgeMinW + 6 * this.wedgeDelta; } // width of G (widest)
1371
+ // helpers
1372
+ wedgeX(i) { return this.leftPadding + this.rangeColW + 12; }
1373
+ // private wedgeW(i: number) { return this.wedgeMaxW - (i * this.wedgeDelta); }
1374
+ wedgeW(i) {
1375
+ // A..G => 0..6 → widths increase downward
1376
+ return this.wedgeMinW + i * this.wedgeDelta;
1377
+ }
1378
+ rowY(i) { return this.topY + i * (this.rowH + this.gapY); }
1379
+ wedgePoints1(i) {
1380
+ const x = this.wedgeX(i), y = this.rowY(i), w = this.wedgeW(i), h = this.rowH, c = this.cut;
1381
+ // rectangle with right chevron tip
1382
+ // (x,y) → (x+w-c,y) → (x+w,y+h/2) → (x+w-c,y+h) → (x,y+h)
1383
+ return `${x},${y} ${x + w - c},${y} ${x + w},${y + h / 2} ${x + w - c},${y + h} ${x},${y + h}`;
1384
+ }
1385
+ wedgePoints(i) {
1386
+ const x = this.wedgeX(i), y = this.rowY(i), w = this.wedgeW(i), h = this.rowH;
1387
+ // rectangle: (x,y) → (x+w,y) → (x+w,y+h) → (x,y+h)
1388
+ return `${x},${y} ${x + w},${y} ${x + w},${y + h} ${x},${y + h}`;
1389
+ }
1390
+ wedgeLetterX(i) {
1391
+ // place on the trailing (right) end of wedge, just before chevron tip
1392
+ return this.wedgeX(i) + this.wedgeW(i) - this.cut - 10;
1393
+ }
1394
+ // arrow badge (left-pointing)
1395
+ arrowPoints() {
1396
+ const w = this.arrowW, h = this.arrowH, tip = 18; // tip depth
1397
+ // (w,0) → (tip,0) → (0,h/2) → (tip,h) → (w,h) → close
1398
+ return `${w},0 ${tip},0 0,${h / 2} ${tip},${h} ${w},${h}`;
1399
+ }
1400
+ // vertical placement: center the arrow in the band row for the given score
1401
+ arrowY(score) {
1402
+ const b = bandFromScore(score);
1403
+ const rowIndex = this.bands.indexOf(b);
1404
+ const y = this.rowY(rowIndex) + (this.rowH - this.arrowH) / 2;
1405
+ return Math.max(y, this.topY); // safety
1406
+ }
1407
+ clampScore(s) { return Math.max(1, Math.min(100, Math.round(s))); }
1408
+ // add below COLORS, bandFromScore...
1409
+ colorForBand(b) { return COLORS[b]; }
1410
+ colorForScore(s) { return this.colorForBand(bandFromScore(s)); }
1411
+ // simple contrast so numbers stay readable
1412
+ textColorForBand(b) {
1413
+ const hex = this.colorForBand(b).replace('#', '');
1414
+ const r = parseInt(hex.slice(0, 2), 16);
1415
+ const g = parseInt(hex.slice(2, 4), 16);
1416
+ const bl = parseInt(hex.slice(4, 6), 16);
1417
+ const yiq = (r * 299 + g * 587 + bl * 114) / 1000;
1418
+ return yiq >= 170 ? '#111' : '#fff'; // light bg → dark text, else white
1419
+ }
1420
+ textColorForScore(s) { return this.textColorForBand(bandFromScore(s)); }
1421
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: EpcChart, deps: [], target: i0.ɵɵFactoryTarget.Component });
1422
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.0", type: EpcChart, isStandalone: true, selector: "rolatech-epc-chart", inputs: { currentScore: { classPropertyName: "currentScore", publicName: "currentScore", isSignal: true, isRequired: false, transformFunction: null }, potentialScore: { classPropertyName: "potentialScore", publicName: "potentialScore", isSignal: true, isRequired: false, transformFunction: null }, showCaptions: { classPropertyName: "showCaptions", publicName: "showCaptions", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "w-full" }, ngImport: i0, template: "<svg [attr.viewBox]=\"'0 0 ' + width + ' ' + height\" class=\"w-full h-auto\">\n <!-- outer border -->\n <rect x=\"8\" y=\"8\" [attr.width]=\"width-16\" [attr.height]=\"height-16\" fill=\"none\" stroke=\"#111\" stroke-width=\"2\" />\n\n <!-- header row -->\n <text [attr.x]=\"leftPadding\" [attr.y]=\"headerY\" font-weight=\"700\" font-size=\"16\">Energy Rating</text>\n <text [attr.x]=\"currentColX + arrowW/2\" [attr.y]=\"headerY\" text-anchor=\"middle\" font-weight=\"700\" font-size=\"16\">\n Current\n </text>\n <text [attr.x]=\"potentialColX + arrowW/2\" [attr.y]=\"headerY\" text-anchor=\"middle\" font-weight=\"700\" font-size=\"16\">\n Potential\n </text>\n <line x1=\"8\" [attr.y1]=\"headerY+10\" [attr.x2]=\"width-8\" [attr.y2]=\"headerY+10\" stroke=\"#111\" stroke-width=\"2\" />\n\n <!-- top/bottom captions -->\n @if (showCaptions()) {\n <text [attr.x]=\"leftPadding\" [attr.y]=\"topCaptionY\" fill=\"#9CA3AF\" font-size=\"20\">\n very energy efficient - lower running costs\n </text>\n <text [attr.x]=\"leftPadding\" [attr.y]=\"bottomCaptionY\" fill=\"#9CA3AF\" font-size=\"20\">\n not energy efficient - higher running costs\n </text>\n }\n\n <!-- Wedges (A..G) -->\n @for (b of bands; track b; let i = $index) {\n <!-- range text column -->\n <text [attr.x]=\"rangeX\" [attr.y]=\"rowY(i) + rowH/2 + 5\" fill=\"#6B7280\" font-size=\"16\">{{ RANGES[b] }}</text>\n\n <!-- colored wedge -->\n <polygon [attr.points]=\"wedgePoints(i)\" [attr.fill]=\"COLORS[b]\" stroke=\"none\" />\n\n <!-- band letter -->\n <text\n [attr.x]=\"wedgeLetterX(i)\"\n [attr.y]=\"rowY(i) + rowH/2 + 8\"\n fill=\"white\"\n font-size=\"28\"\n font-weight=\"700\"\n text-anchor=\"end\"\n >\n {{ b }}\n </text>\n }\n\n <!-- Current arrow badge -->\n @if (currentScore() !== null) {\n <g [attr.transform]=\"'translate(' + currentColX + ',' + arrowY(currentScore()!) + ')'\">\n <polygon [attr.points]=\"arrowPoints()\" [attr.fill]=\"colorForScore(currentScore()!)\"></polygon>\n <text\n [attr.x]=\"arrowW/2 + 6\"\n [attr.y]=\"arrowH/2 + 9\"\n text-anchor=\"middle\"\n font-size=\"24\"\n font-weight=\"800\"\n [attr.fill]=\"textColorForScore(currentScore()!)\"\n >\n {{ clampScore(currentScore()!) }}\n </text>\n <!-- underline (optional) -->\n <rect\n [attr.x]=\"arrowW/2 - 12\"\n [attr.y]=\"arrowH/2 + 12\"\n width=\"36\"\n height=\"3\"\n [attr.fill]=\"textColorForScore(currentScore()!)\"\n opacity=\"0.8\"\n />\n </g>\n }\n\n <!-- Potential arrow badge -->\n @if (potentialScore() !== null) {\n <g [attr.transform]=\"'translate(' + potentialColX + ',' + arrowY(potentialScore()!) + ')'\">\n <polygon [attr.points]=\"arrowPoints()\" [attr.fill]=\"colorForScore(potentialScore()!)\"></polygon>\n <text\n [attr.x]=\"arrowW/2 + 6\"\n [attr.y]=\"arrowH/2 + 9\"\n text-anchor=\"middle\"\n font-size=\"24\"\n font-weight=\"800\"\n [attr.fill]=\"textColorForScore(potentialScore()!)\"\n >\n {{ clampScore(potentialScore()!) }}\n </text>\n </g>\n }\n</svg>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
1423
+ }
1424
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: EpcChart, decorators: [{
1425
+ type: Component,
1426
+ args: [{ selector: 'rolatech-epc-chart', imports: [CommonModule], host: { class: 'w-full' }, template: "<svg [attr.viewBox]=\"'0 0 ' + width + ' ' + height\" class=\"w-full h-auto\">\n <!-- outer border -->\n <rect x=\"8\" y=\"8\" [attr.width]=\"width-16\" [attr.height]=\"height-16\" fill=\"none\" stroke=\"#111\" stroke-width=\"2\" />\n\n <!-- header row -->\n <text [attr.x]=\"leftPadding\" [attr.y]=\"headerY\" font-weight=\"700\" font-size=\"16\">Energy Rating</text>\n <text [attr.x]=\"currentColX + arrowW/2\" [attr.y]=\"headerY\" text-anchor=\"middle\" font-weight=\"700\" font-size=\"16\">\n Current\n </text>\n <text [attr.x]=\"potentialColX + arrowW/2\" [attr.y]=\"headerY\" text-anchor=\"middle\" font-weight=\"700\" font-size=\"16\">\n Potential\n </text>\n <line x1=\"8\" [attr.y1]=\"headerY+10\" [attr.x2]=\"width-8\" [attr.y2]=\"headerY+10\" stroke=\"#111\" stroke-width=\"2\" />\n\n <!-- top/bottom captions -->\n @if (showCaptions()) {\n <text [attr.x]=\"leftPadding\" [attr.y]=\"topCaptionY\" fill=\"#9CA3AF\" font-size=\"20\">\n very energy efficient - lower running costs\n </text>\n <text [attr.x]=\"leftPadding\" [attr.y]=\"bottomCaptionY\" fill=\"#9CA3AF\" font-size=\"20\">\n not energy efficient - higher running costs\n </text>\n }\n\n <!-- Wedges (A..G) -->\n @for (b of bands; track b; let i = $index) {\n <!-- range text column -->\n <text [attr.x]=\"rangeX\" [attr.y]=\"rowY(i) + rowH/2 + 5\" fill=\"#6B7280\" font-size=\"16\">{{ RANGES[b] }}</text>\n\n <!-- colored wedge -->\n <polygon [attr.points]=\"wedgePoints(i)\" [attr.fill]=\"COLORS[b]\" stroke=\"none\" />\n\n <!-- band letter -->\n <text\n [attr.x]=\"wedgeLetterX(i)\"\n [attr.y]=\"rowY(i) + rowH/2 + 8\"\n fill=\"white\"\n font-size=\"28\"\n font-weight=\"700\"\n text-anchor=\"end\"\n >\n {{ b }}\n </text>\n }\n\n <!-- Current arrow badge -->\n @if (currentScore() !== null) {\n <g [attr.transform]=\"'translate(' + currentColX + ',' + arrowY(currentScore()!) + ')'\">\n <polygon [attr.points]=\"arrowPoints()\" [attr.fill]=\"colorForScore(currentScore()!)\"></polygon>\n <text\n [attr.x]=\"arrowW/2 + 6\"\n [attr.y]=\"arrowH/2 + 9\"\n text-anchor=\"middle\"\n font-size=\"24\"\n font-weight=\"800\"\n [attr.fill]=\"textColorForScore(currentScore()!)\"\n >\n {{ clampScore(currentScore()!) }}\n </text>\n <!-- underline (optional) -->\n <rect\n [attr.x]=\"arrowW/2 - 12\"\n [attr.y]=\"arrowH/2 + 12\"\n width=\"36\"\n height=\"3\"\n [attr.fill]=\"textColorForScore(currentScore()!)\"\n opacity=\"0.8\"\n />\n </g>\n }\n\n <!-- Potential arrow badge -->\n @if (potentialScore() !== null) {\n <g [attr.transform]=\"'translate(' + potentialColX + ',' + arrowY(potentialScore()!) + ')'\">\n <polygon [attr.points]=\"arrowPoints()\" [attr.fill]=\"colorForScore(potentialScore()!)\"></polygon>\n <text\n [attr.x]=\"arrowW/2 + 6\"\n [attr.y]=\"arrowH/2 + 9\"\n text-anchor=\"middle\"\n font-size=\"24\"\n font-weight=\"800\"\n [attr.fill]=\"textColorForScore(potentialScore()!)\"\n >\n {{ clampScore(potentialScore()!) }}\n </text>\n </g>\n }\n</svg>\n" }]
1300
1427
  }] });
1301
1428
 
1302
1429
  class PropertyEpc {
1303
1430
  epc = input.required(...(ngDevMode ? [{ debugName: "epc" }] : []));
1304
1431
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyEpc, deps: [], target: i0.ɵɵFactoryTarget.Component });
1305
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.2.0", type: PropertyEpc, isStandalone: true, selector: "rolatech-property-epc", inputs: { epc: { classPropertyName: "epc", publicName: "epc", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"\">\n <div class=\"text-2xl font-bold py-3\" i18n>EPC</div>\n <div class=\"flex flex-col flex-wrap items-center text-sm\">\n <div>{{epc().name}}</div>\n <div>{{epc().score}}</div>\n </div>\n</div>\n", styles: [""] });
1432
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.2.0", type: PropertyEpc, isStandalone: true, selector: "rolatech-property-epc", inputs: { epc: { classPropertyName: "epc", publicName: "epc", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"w-full\">\n <div class=\"text-2xl font-bold py-3\" i18n>EPC</div>\n <div class=\"flex flex-row items-center font-thin text-sm\">\n <rolatech-epc-chart\n [currentScore]=\"epc().currentScore\"\n [potentialScore]=\"epc().potentialScore\"\n [showCaptions]=\"true\"\n ></rolatech-epc-chart>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: EpcChart, selector: "rolatech-epc-chart", inputs: ["currentScore", "potentialScore", "showCaptions"] }] });
1306
1433
  }
1307
1434
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyEpc, decorators: [{
1308
1435
  type: Component,
1309
- args: [{ selector: 'rolatech-property-epc', imports: [], template: "<div class=\"\">\n <div class=\"text-2xl font-bold py-3\" i18n>EPC</div>\n <div class=\"flex flex-col flex-wrap items-center text-sm\">\n <div>{{epc().name}}</div>\n <div>{{epc().score}}</div>\n </div>\n</div>\n" }]
1436
+ args: [{ selector: 'rolatech-property-epc', imports: [EpcChart], template: "<div class=\"w-full\">\n <div class=\"text-2xl font-bold py-3\" i18n>EPC</div>\n <div class=\"flex flex-row items-center font-thin text-sm\">\n <rolatech-epc-chart\n [currentScore]=\"epc().currentScore\"\n [potentialScore]=\"epc().potentialScore\"\n [showCaptions]=\"true\"\n ></rolatech-epc-chart>\n </div>\n</div>\n" }]
1310
1437
  }] });
1311
1438
 
1312
1439
  class PropertyDetailsComponent extends BaseComponent {
1313
1440
  authService = inject(AuthService);
1314
1441
  authUserService = inject(AuthUserService);
1315
1442
  propertyService = inject(PropertyService);
1443
+ timezoneService = inject(TimeZoneService);
1316
1444
  authenticated = this.authService.authenticated;
1317
1445
  property;
1318
1446
  fullname = '';
@@ -1325,11 +1453,20 @@ class PropertyDetailsComponent extends BaseComponent {
1325
1453
  features = [];
1326
1454
  highlights = [];
1327
1455
  epc;
1456
+ timezone = signal('', ...(ngDevMode ? [{ debugName: "timezone" }] : []));
1328
1457
  selectedVariant;
1329
1458
  variantOption = signal(undefined, ...(ngDevMode ? [{ debugName: "variantOption" }] : []));
1330
1459
  variantOptionChanged = computed(() => {
1331
1460
  return this.variantOption();
1332
1461
  }, ...(ngDevMode ? [{ debugName: "variantOptionChanged" }] : []));
1462
+ get videos() {
1463
+ if (this.timezone() === 'Asia/Shanghai') {
1464
+ return this.property.videos.filter(v => v.provider === PropertyVideoProvider.COS);
1465
+ }
1466
+ else {
1467
+ return this.property.videos.filter(v => v.provider === PropertyVideoProvider.YOUTUBE);
1468
+ }
1469
+ }
1333
1470
  // results: any[] = [];
1334
1471
  constructor() {
1335
1472
  super();
@@ -1344,6 +1481,12 @@ class PropertyDetailsComponent extends BaseComponent {
1344
1481
  this.findFeatures();
1345
1482
  this.findHighlights();
1346
1483
  this.getEpc();
1484
+ this.timezoneService.getTimeZoneFromApi().subscribe({
1485
+ next: res => {
1486
+ this.timezone.set(res);
1487
+ }
1488
+ });
1489
+ // this.timezone = this.timezoneService.getBrowserTimeZone() ?? ''
1347
1490
  }
1348
1491
  getProperty() {
1349
1492
  this.propertyService.get(this.id).subscribe({
@@ -1356,7 +1499,9 @@ class PropertyDetailsComponent extends BaseComponent {
1356
1499
  // this.results.push([item.option.id, item.value.id]);
1357
1500
  // });
1358
1501
  }
1359
- this.findUserBaseInfo(this.property.agentId);
1502
+ if (this.property.agentId) {
1503
+ this.findUserBaseInfo(this.property.agentId);
1504
+ }
1360
1505
  this.titleService.setTitle(`${this.property.title}`);
1361
1506
  },
1362
1507
  });
@@ -1382,14 +1527,14 @@ class PropertyDetailsComponent extends BaseComponent {
1382
1527
  findFeatures() {
1383
1528
  this.propertyService.findFeatures(this.id).subscribe({
1384
1529
  next: (res) => {
1385
- this.features = res.data;
1530
+ this.features = res.data || [];
1386
1531
  }
1387
1532
  });
1388
1533
  }
1389
1534
  findHighlights() {
1390
1535
  this.propertyService.getHighlights(this.id).subscribe({
1391
1536
  next: (res) => {
1392
- this.highlights = res.data;
1537
+ this.highlights = res.data || [];
1393
1538
  }
1394
1539
  });
1395
1540
  }
@@ -1478,7 +1623,7 @@ class PropertyDetailsComponent extends BaseComponent {
1478
1623
  // const updatedCriteria = matchingVariant ? updateCriteriaFromVariant(matchingVariant) : [];
1479
1624
  }
1480
1625
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyDetailsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1481
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.0", type: PropertyDetailsComponent, isStandalone: true, selector: "rolatech-property-details", usesInheritance: true, ngImport: i0, template: "@if (property) {\n <rolatech-container>\n <div class=\"flex flex-col w-full\">\n <div class=\"py-3\">\n <rolatech-property-media [media]=\"property.media\"></rolatech-property-media>\n </div>\n <div class=\"flex flex-col md:flex-row gap-3 w-full\">\n <div class=\"w-full md:w-2/3\">\n <rolatech-property-info [property]=\"property\" (wish)=\"onWish($event)\" [inWishList]=\"inWishList\">\n </rolatech-property-info>\n <!-- <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n ></rolatech-property-agent-renderer> -->\n <mat-divider></mat-divider>\n <rolatech-property-features [features]=\"features\"></rolatech-property-features>\n <rolatech-property-highlights [highlights]=\"highlights\"></rolatech-property-highlights>\n <rolatech-property-epc [epc]=\"epc\"></rolatech-property-epc>\n <rolatech-property-location [location]=\"property.location\"></rolatech-property-location>\n @if (property.videos) {\n @for (item of property.videos; track $index) {\n <rolatech-property-video [video]=\"item\"></rolatech-property-video>\n }\n }\n <div class=\"flex flex-col\">\n <div class=\"text-2xl font-bold pt-3\" i18n>Sections</div>\n @for (section of property.sections; track $index) {\n <rolatech-property-section [section]=\"section\"></rolatech-property-section>\n }\n <rolatech-comments [itemId]=\"property.id\"></rolatech-comments>\n </div>\n </div>\n <div class=\"w-full md:w-1/3\">\n <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n ></rolatech-property-agent-renderer>\n <rolatech-property-pricing (wish)=\"onWish($event)\" [property]=\"property\"></rolatech-property-pricing>\n <rolatech-property-actions\n [property]=\"property\"\n (offer)=\"onOffer($event)\"\n (deposit)=\"onOffer($event)\"\n (requestViewing)=\"onRequestViewing($event)\"\n >\n @if (user) {\n <rolatech-property-action-contact [email]=\"user.email\" [phone]=\"user.phone\"></rolatech-property-action-contact>\n }\n </rolatech-property-actions>\n </div>\n </div>\n </div>\n </rolatech-container>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: AngularCommonModule }, { kind: "ngmodule", type: AngularComponentsModule }, { kind: "component", type: i2$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "component", type: PropertyInfoComponent, selector: "rolatech-property-info", inputs: ["property", "inWishList"], outputs: ["wish"] }, { kind: "component", type: PropertyMediaComponent, selector: "rolatech-property-media", inputs: ["media", "min"] }, { kind: "component", type: PropertyPricingComponent, selector: "rolatech-property-pricing", inputs: ["property", "price"] }, { kind: "component", type: PropertySectionComponent, selector: "rolatech-property-section", inputs: ["section", "user", "username"] }, { kind: "component", type: PropertyActionsComponent, selector: "rolatech-property-actions", inputs: ["property"], outputs: ["requestViewing", "offer", "deposit"] }, { kind: "component", type: CommentsComponent, selector: "rolatech-comments", inputs: ["itemId"] }, { kind: "component", type: PropertyAgentRenderer, selector: "rolatech-property-agent-renderer", inputs: ["name", "avatar", "username", "subtitle"] }, { kind: "component", type: PropertyLocationComponent, selector: "rolatech-property-location", inputs: ["location"] }, { kind: "component", type: PropertyFeaturesComponent, selector: "rolatech-property-features", inputs: ["features"] }, { kind: "component", type: PropertyVideoComponent, selector: "rolatech-property-video", inputs: ["video"] }, { kind: "component", type: PropertyActionContactComponent, selector: "rolatech-property-action-contact", inputs: ["email", "phone"], outputs: ["callAgent", "emailAgent"] }, { kind: "component", type: PropertyHighlights, selector: "rolatech-property-highlights", inputs: ["highlights"] }, { kind: "component", type: PropertyEpc, selector: "rolatech-property-epc", inputs: ["epc"] }] });
1626
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.0", type: PropertyDetailsComponent, isStandalone: true, selector: "rolatech-property-details", usesInheritance: true, ngImport: i0, template: "@if (property) {\n <rolatech-container>\n <div class=\"flex flex-col w-full\">\n <div class=\"py-3\">\n <rolatech-property-media [media]=\"property.media\"></rolatech-property-media>\n </div>\n <div class=\"flex flex-col md:flex-row gap-3 w-full\">\n <div class=\"w-full md:w-2/3\">\n <rolatech-property-info [property]=\"property\" (wish)=\"onWish($event)\" [inWishList]=\"inWishList\">\n </rolatech-property-info>\n <!-- <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n ></rolatech-property-agent-renderer> -->\n <mat-divider></mat-divider>\n\n @if (features.length > 0) {\n <rolatech-property-features [features]=\"features\"></rolatech-property-features>\n }\n @if (highlights.length > 0) {\n <rolatech-property-highlights [highlights]=\"highlights\"></rolatech-property-highlights>\n }\n <!-- <rolatech-property-epc [epc]=\"epc\"></rolatech-property-epc> -->\n <rolatech-property-location [location]=\"property.location\"></rolatech-property-location>\n @if (videos) {\n @for (item of videos; track $index) {\n <rolatech-property-video [video]=\"item\"></rolatech-property-video>\n }\n }\n @if (epc && epc.currentScore) {\n <rolatech-property-epc [epc]=\"epc\"></rolatech-property-epc>\n }\n <div class=\"flex flex-col\">\n <div class=\"text-2xl font-bold pt-3\" i18n>Sections</div>\n @for (section of property.sections; track $index) {\n <rolatech-property-section [section]=\"section\"></rolatech-property-section>\n }\n <rolatech-comments [itemId]=\"property.id\"></rolatech-comments>\n </div>\n </div>\n <div class=\"w-full md:w-1/3\">\n <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n ></rolatech-property-agent-renderer>\n <rolatech-property-pricing (wish)=\"onWish($event)\" [property]=\"property\"></rolatech-property-pricing>\n <rolatech-property-actions\n [property]=\"property\"\n (offer)=\"onOffer($event)\"\n (deposit)=\"onOffer($event)\"\n (requestViewing)=\"onRequestViewing($event)\"\n >\n @if (user) {\n <rolatech-property-action-contact [email]=\"user.email\" [phone]=\"user.phone\"></rolatech-property-action-contact>\n }\n </rolatech-property-actions>\n </div>\n </div>\n </div>\n </rolatech-container>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: AngularCommonModule }, { kind: "ngmodule", type: AngularComponentsModule }, { kind: "component", type: i2$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "component", type: PropertyInfoComponent, selector: "rolatech-property-info", inputs: ["property", "inWishList"], outputs: ["wish"] }, { kind: "component", type: PropertyMediaComponent, selector: "rolatech-property-media", inputs: ["media", "min"] }, { kind: "component", type: PropertyPricingComponent, selector: "rolatech-property-pricing", inputs: ["property", "price"] }, { kind: "component", type: PropertySectionComponent, selector: "rolatech-property-section", inputs: ["section", "user", "username"] }, { kind: "component", type: PropertyActionsComponent, selector: "rolatech-property-actions", inputs: ["property"], outputs: ["requestViewing", "offer", "deposit"] }, { kind: "component", type: CommentsComponent, selector: "rolatech-comments", inputs: ["itemId"] }, { kind: "component", type: PropertyAgentRenderer, selector: "rolatech-property-agent-renderer", inputs: ["name", "avatar", "username", "subtitle"] }, { kind: "component", type: PropertyLocationComponent, selector: "rolatech-property-location", inputs: ["location"] }, { kind: "component", type: PropertyFeaturesComponent, selector: "rolatech-property-features", inputs: ["features"] }, { kind: "component", type: PropertyVideoComponent, selector: "rolatech-property-video", inputs: ["video"] }, { kind: "component", type: PropertyActionContactComponent, selector: "rolatech-property-action-contact", inputs: ["email", "phone"], outputs: ["callAgent", "emailAgent"] }, { kind: "component", type: PropertyHighlights, selector: "rolatech-property-highlights", inputs: ["highlights"] }, { kind: "component", type: PropertyEpc, selector: "rolatech-property-epc", inputs: ["epc"] }] });
1482
1627
  }
1483
1628
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyDetailsComponent, decorators: [{
1484
1629
  type: Component,
@@ -1498,8 +1643,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImpor
1498
1643
  PropertyVideoComponent,
1499
1644
  PropertyActionContactComponent,
1500
1645
  PropertyHighlights,
1501
- PropertyEpc
1502
- ], template: "@if (property) {\n <rolatech-container>\n <div class=\"flex flex-col w-full\">\n <div class=\"py-3\">\n <rolatech-property-media [media]=\"property.media\"></rolatech-property-media>\n </div>\n <div class=\"flex flex-col md:flex-row gap-3 w-full\">\n <div class=\"w-full md:w-2/3\">\n <rolatech-property-info [property]=\"property\" (wish)=\"onWish($event)\" [inWishList]=\"inWishList\">\n </rolatech-property-info>\n <!-- <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n ></rolatech-property-agent-renderer> -->\n <mat-divider></mat-divider>\n <rolatech-property-features [features]=\"features\"></rolatech-property-features>\n <rolatech-property-highlights [highlights]=\"highlights\"></rolatech-property-highlights>\n <rolatech-property-epc [epc]=\"epc\"></rolatech-property-epc>\n <rolatech-property-location [location]=\"property.location\"></rolatech-property-location>\n @if (property.videos) {\n @for (item of property.videos; track $index) {\n <rolatech-property-video [video]=\"item\"></rolatech-property-video>\n }\n }\n <div class=\"flex flex-col\">\n <div class=\"text-2xl font-bold pt-3\" i18n>Sections</div>\n @for (section of property.sections; track $index) {\n <rolatech-property-section [section]=\"section\"></rolatech-property-section>\n }\n <rolatech-comments [itemId]=\"property.id\"></rolatech-comments>\n </div>\n </div>\n <div class=\"w-full md:w-1/3\">\n <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n ></rolatech-property-agent-renderer>\n <rolatech-property-pricing (wish)=\"onWish($event)\" [property]=\"property\"></rolatech-property-pricing>\n <rolatech-property-actions\n [property]=\"property\"\n (offer)=\"onOffer($event)\"\n (deposit)=\"onOffer($event)\"\n (requestViewing)=\"onRequestViewing($event)\"\n >\n @if (user) {\n <rolatech-property-action-contact [email]=\"user.email\" [phone]=\"user.phone\"></rolatech-property-action-contact>\n }\n </rolatech-property-actions>\n </div>\n </div>\n </div>\n </rolatech-container>\n}\n" }]
1646
+ PropertyEpc,
1647
+ ], template: "@if (property) {\n <rolatech-container>\n <div class=\"flex flex-col w-full\">\n <div class=\"py-3\">\n <rolatech-property-media [media]=\"property.media\"></rolatech-property-media>\n </div>\n <div class=\"flex flex-col md:flex-row gap-3 w-full\">\n <div class=\"w-full md:w-2/3\">\n <rolatech-property-info [property]=\"property\" (wish)=\"onWish($event)\" [inWishList]=\"inWishList\">\n </rolatech-property-info>\n <!-- <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n ></rolatech-property-agent-renderer> -->\n <mat-divider></mat-divider>\n\n @if (features.length > 0) {\n <rolatech-property-features [features]=\"features\"></rolatech-property-features>\n }\n @if (highlights.length > 0) {\n <rolatech-property-highlights [highlights]=\"highlights\"></rolatech-property-highlights>\n }\n <!-- <rolatech-property-epc [epc]=\"epc\"></rolatech-property-epc> -->\n <rolatech-property-location [location]=\"property.location\"></rolatech-property-location>\n @if (videos) {\n @for (item of videos; track $index) {\n <rolatech-property-video [video]=\"item\"></rolatech-property-video>\n }\n }\n @if (epc && epc.currentScore) {\n <rolatech-property-epc [epc]=\"epc\"></rolatech-property-epc>\n }\n <div class=\"flex flex-col\">\n <div class=\"text-2xl font-bold pt-3\" i18n>Sections</div>\n @for (section of property.sections; track $index) {\n <rolatech-property-section [section]=\"section\"></rolatech-property-section>\n }\n <rolatech-comments [itemId]=\"property.id\"></rolatech-comments>\n </div>\n </div>\n <div class=\"w-full md:w-1/3\">\n <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n ></rolatech-property-agent-renderer>\n <rolatech-property-pricing (wish)=\"onWish($event)\" [property]=\"property\"></rolatech-property-pricing>\n <rolatech-property-actions\n [property]=\"property\"\n (offer)=\"onOffer($event)\"\n (deposit)=\"onOffer($event)\"\n (requestViewing)=\"onRequestViewing($event)\"\n >\n @if (user) {\n <rolatech-property-action-contact [email]=\"user.email\" [phone]=\"user.phone\"></rolatech-property-action-contact>\n }\n </rolatech-property-actions>\n </div>\n </div>\n </div>\n </rolatech-container>\n}\n" }]
1503
1648
  }], ctorParameters: () => [] });
1504
1649
 
1505
1650
  const MY_FORMATS$5 = {
@@ -2309,7 +2454,7 @@ const propertyRoutes = [
2309
2454
  children: [
2310
2455
  {
2311
2456
  path: '',
2312
- loadComponent: () => import('./rolatech-angular-property-property-index.component-Bg9L4p2Z.mjs').then((x) => x.PropertyIndexComponent),
2457
+ loadComponent: () => import('./rolatech-angular-property-property-index.component-DGFoqfbV.mjs').then((x) => x.PropertyIndexComponent),
2313
2458
  },
2314
2459
  ],
2315
2460
  },
@@ -2354,58 +2499,104 @@ const propertyRoutes = [
2354
2499
  },
2355
2500
  ];
2356
2501
 
2357
- class PropertyManageFilterComponent {
2358
- towns = ['London'];
2359
- filter = false;
2360
- searchOptions = {
2361
- town: '',
2362
- startDate: '',
2363
- endDate: '',
2364
- };
2365
- reset() { }
2366
- search() { }
2367
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyManageFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2368
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.0", type: PropertyManageFilterComponent, isStandalone: true, selector: "rolatech-property-manage-filter", ngImport: i0, template: "<div class=\"p-3\">\n <div class=\"bg-[--rt-raised-background] p-3 flex items-center justify-between rounded-md\">\n <div class=\"flex items-center\">\n <mat-form-field subscriptSizing=\"dynamic\">\n <mat-select #select=\"matSelect\" placeholder=\"Town\" i18n-placeholder [(ngModel)]=\"searchOptions.town\">\n @for (town of towns; track town) {\n <mat-option [value]=\"town\">\n {{ town }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <!-- <mat-form-field>\n <input />\n </mat-form-field> -->\n </div>\n <div class=\"flex gap-3\">\n <a mat-stroked-button class=\"w-[128px]\" (click)=\"reset()\" i18n>Reset</a>\n <a mat-flat-button class=\"w-full\" (click)=\"search()\" i18n>Search</a>\n </div>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i5.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i5.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
2369
- }
2370
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyManageFilterComponent, decorators: [{
2371
- type: Component,
2372
- args: [{ selector: 'rolatech-property-manage-filter', imports: [CommonModule, MatButtonModule, MatFormFieldModule, MatSelectModule, MatOptionModule, FormsModule], template: "<div class=\"p-3\">\n <div class=\"bg-[--rt-raised-background] p-3 flex items-center justify-between rounded-md\">\n <div class=\"flex items-center\">\n <mat-form-field subscriptSizing=\"dynamic\">\n <mat-select #select=\"matSelect\" placeholder=\"Town\" i18n-placeholder [(ngModel)]=\"searchOptions.town\">\n @for (town of towns; track town) {\n <mat-option [value]=\"town\">\n {{ town }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <!-- <mat-form-field>\n <input />\n </mat-form-field> -->\n </div>\n <div class=\"flex gap-3\">\n <a mat-stroked-button class=\"w-[128px]\" (click)=\"reset()\" i18n>Reset</a>\n <a mat-flat-button class=\"w-full\" (click)=\"search()\" i18n>Search</a>\n </div>\n </div>\n</div>\n" }]
2373
- }] });
2374
-
2375
2502
  class PropertyManageIndexComponent {
2376
2503
  hasClass = true;
2377
2504
  paginator = viewChild(MatPaginator, ...(ngDevMode ? [{ debugName: "paginator" }] : []));
2378
2505
  dialog = inject(MatDialog);
2379
2506
  snackBar = inject(MatSnackBar);
2507
+ router = inject(Router);
2508
+ destroyRef = inject(DestroyRef);
2509
+ route = inject(ActivatedRoute);
2510
+ gridView = true;
2511
+ util = inject(PropertyUtil);
2380
2512
  propertyService = inject(PropertyService);
2381
2513
  propertySearchService = inject(PropertySearchService);
2382
- isLoading = false;
2383
2514
  isSearch = false;
2384
- properties = [];
2515
+ // properties: Property[] = [];
2516
+ properties = signal([], ...(ngDevMode ? [{ debugName: "properties" }] : []));
2385
2517
  exporting = false;
2386
2518
  pageEvent;
2387
2519
  length = 100;
2388
2520
  pageSize = 15;
2389
2521
  pageSizeOptions = [5, 10, 25, 100];
2522
+ open = signal(false, ...(ngDevMode ? [{ debugName: "open" }] : []));
2523
+ pageIndex = signal(0, ...(ngDevMode ? [{ debugName: "pageIndex" }] : []));
2524
+ meta;
2525
+ loading = false;
2390
2526
  ngOnInit() {
2391
- this.findProperties();
2392
- }
2393
- findProperties(event) {
2394
- const page = event ? event.pageIndex + 1 : 1;
2395
- const limit = event ? event.pageSize : 15;
2396
- const options = {
2397
- page,
2398
- limit,
2399
- sort: 'updatedAt desc',
2400
- // filter: 'published:true',
2401
- };
2402
- this.propertyService.find(options).subscribe({
2527
+ // this.findProperties();
2528
+ const sub = this.route.queryParamMap.pipe(map((p) => {
2529
+ const page = p.get('page') ? Number(p.get('page')) : 1;
2530
+ this.pageIndex.set(Math.max(page - 1, 0));
2531
+ return {
2532
+ q: p.get('q') || undefined,
2533
+ city: p.get('city') || undefined,
2534
+ minBedrooms: p.get('minBedrooms') ? Number(p.get('minBedrooms')) : undefined,
2535
+ maxPricePence: p.get('maxPricePence') ? Number(p.get('maxPricePence')) : undefined,
2536
+ availableFrom: p.get('availableFrom') || undefined,
2537
+ availableTo: p.get('availableTo') || undefined,
2538
+ features: p.getAll('features')?.length ? p.getAll('features') : undefined,
2539
+ page,
2540
+ limit: p.get('limit') ? Number(p.get('limit')) : 15,
2541
+ sort: p.get('sort') || undefined,
2542
+ };
2543
+ }),
2544
+ // Cheap deep compare via JSON to avoid spam calls when nothing changed
2545
+ map((o) => JSON.stringify(o)), distinctUntilChanged(), map((s) => JSON.parse(s)), switchMap((params) => {
2546
+ this.loading = true;
2547
+ return this.propertySearchService.search(params).pipe(finalize(() => this.loading = false));
2548
+ })).subscribe({
2403
2549
  next: (res) => {
2404
- this.properties = res.data;
2550
+ this.properties.set(res.data);
2551
+ this.meta = res.meta;
2552
+ this.length = res.meta.pagination.count;
2553
+ },
2554
+ error: () => {
2555
+ this.properties.set([]);
2556
+ this.length = 0;
2557
+ }
2558
+ });
2559
+ // // auto-unsubscribe on destroy
2560
+ this.destroyRef.onDestroy(() => sub.unsubscribe());
2561
+ }
2562
+ toggleSearch() {
2563
+ this.open.update(v => !v);
2564
+ }
2565
+ toggleView() {
2566
+ if (this.gridView) {
2567
+ this.gridView = false;
2568
+ this.util.viewEvent.emit(PropertyViewType.LIST);
2569
+ }
2570
+ else {
2571
+ this.gridView = true;
2572
+ this.util.viewEvent.emit(PropertyViewType.GRID);
2573
+ }
2574
+ }
2575
+ searchByText(event) {
2576
+ this.router.navigate([], {
2577
+ queryParams: { q: event, page: 1, limit: 15 },
2578
+ queryParamsHandling: 'merge', // keep other params like sort, etc.
2579
+ });
2580
+ }
2581
+ search(params) {
2582
+ this.propertySearchService.search(params).subscribe({
2583
+ next: res => {
2584
+ this.properties.set(res.data);
2585
+ this.meta = res.meta;
2586
+ this.loading = false;
2405
2587
  this.length = res.meta.pagination.count;
2588
+ // this.pageIndex.set(Math.max(page - 1, 0));
2406
2589
  },
2590
+ error: error => {
2591
+ this.loading = false;
2592
+ }
2407
2593
  });
2408
2594
  }
2595
+ onCloseSearch() {
2596
+ // this.open.set(false);
2597
+ // this.router.navigate([], { queryParams: {}, queryParamsHandling: 'merge' });
2598
+ this.router.navigate(["/properties"]);
2599
+ }
2409
2600
  export() {
2410
2601
  this.exporting = true;
2411
2602
  this.propertyService.export().subscribe({
@@ -2426,8 +2617,15 @@ class PropertyManageIndexComponent {
2426
2617
  }
2427
2618
  });
2428
2619
  }
2620
+ onPage(e) {
2621
+ this.router.navigate([], {
2622
+ queryParams: { page: e.pageIndex + 1, limit: e.pageSize },
2623
+ queryParamsHandling: 'merge',
2624
+ replaceUrl: true, // optional: avoid stacking history on every page click
2625
+ });
2626
+ }
2429
2627
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyManageIndexComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2430
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.0", type: PropertyManageIndexComponent, isStandalone: true, selector: "rolatech-property-manage-index", host: { properties: { "class.rolatech-property-manage-index": "this.hasClass" } }, viewQueries: [{ propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true, isSignal: true }], ngImport: i0, template: "<rolatech-toolbar title=\"Properties\">\n <div class=\"flex items-center gap-2\">\n <button mat-flat-button routerLink=\"./create\">\n <mat-icon>add</mat-icon>\n <span i18n>Add property</span>\n </button>\n <!-- <button mat-flat-button (click)=\"export()\" [disabled]=\"exporting\">\n <mat-icon>download</mat-icon>\n <span i18n>Export</span>\n </button> -->\n <button mat-flat-button (click)=\"export()\" [disabled]=\"exporting\" aria-label=\"Export CSV\">\n @if (!exporting) {\n Export CSV\n } @else {\n Exporting\u2026\n }\n </button>\n </div>\n</rolatech-toolbar>\n@if (isLoading) {\n <div class=\"flex justify-center items-center\">\n <rolatech-spinner></rolatech-spinner>\n </div>\n} @else {\n <div class=\"bg-[--rt-rasised-background] h-full\">\n <rolatech-property-manage-filter></rolatech-property-manage-filter>\n <div class=\"flex flex-wrap p-3 gap-3\">\n @for (item of properties; track $index) {\n <rolatech-property-manage-item\n [property]=\"item\"\n routerLink=\"./{{ item.id }}/manage/info\"\n ></rolatech-property-manage-item>\n }\n </div>\n </div>\n}\n<mat-paginator\n #paginator\n [length]=\"length\"\n [pageSize]=\"pageSize\"\n [pageSizeOptions]=\"pageSizeOptions\"\n (page)=\"pageEvent = findProperties($event)\"\n hidePageSize\n showFirstLastButtons\n>\n</mat-paginator>\n", styles: ["mat-form-field{width:100%}table{width:100%}td.mat-column-actions{text-align:right;max-width:64px;font-size:.8rem;padding:0 8px}.mat-mdc-header-cell.actions{text-align:right;max-width:64px;width:64px}.mat-mdc-cell:nth-last-child(2),.mat-mdc-header-cell:nth-last-child(2),.mat-mdc-footer-cell:nth-last-child(2){text-align:right;max-width:180px;width:180px}mat-cell:last-of-type,mat-header-cell:last-of-type,mat-footer-cell:last-of-type{text-align:right;padding-right:8px!important}rolatech-property-manage-index{display:flex;flex-direction:column;--rt-property-view-items-per-row: 1}@media (min-width: 600px){rolatech-property-manage-index{--rt-property-view-items-per-row: 2}}@media (min-width: 768px){rolatech-property-manage-index{--rt-property-view-items-per-row: 3}}@media (min-width: 1280px){rolatech-property-manage-index{--rt-property-view-items-per-row: 3}}@media (min-width: 1536px){rolatech-property-manage-index{--rt-property-view-items-per-row: 4}}@media (min-width: 1920px){rolatech-property-manage-index{--rt-property-view-items-per-row: 5}}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTableModule }, { kind: "ngmodule", type: MatMenuModule }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i3$2.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: SpinnerComponent, selector: "rolatech-spinner", inputs: ["title"] }, { kind: "component", type: PropertyManageItemComponent, selector: "rolatech-property-manage-item", inputs: ["property", "thumbnail", "list"] }, { kind: "component", type: PropertyManageFilterComponent, selector: "rolatech-property-manage-filter" }], encapsulation: i0.ViewEncapsulation.None });
2628
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.0", type: PropertyManageIndexComponent, isStandalone: true, selector: "rolatech-property-manage-index", host: { properties: { "class.rolatech-property-manage-index": "this.hasClass" } }, viewQueries: [{ propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true, isSignal: true }], ngImport: i0, template: "<rolatech-toolbar title=\"Properties\">\n <div class=\"flex items-center gap-2\">\n <button mat-icon-button (click)=\"toggleSearch()\">\n <mat-icon>search</mat-icon>\n </button>\n <!-- <button mat-icon-button (click)=\"toggleView()\">\n <mat-icon>{{ gridView ? 'view_list' : 'grid_on' }}</mat-icon>\n </button> -->\n <button mat-flat-button routerLink=\"./create\">\n <mat-icon>add</mat-icon>\n <span i18n>Add property</span>\n </button>\n <!-- <button mat-flat-button (click)=\"export()\" [disabled]=\"exporting\">\n <mat-icon>download</mat-icon>\n <span i18n>Export</span>\n </button> -->\n <button mat-flat-button (click)=\"export()\" [disabled]=\"exporting\" aria-label=\"Export CSV\">\n @if (!exporting) {\n Export CSV\n } @else {\n Exporting\u2026\n }\n </button>\n </div>\n</rolatech-toolbar>\n<div class=\"p-2\">\n <rolatech-search-bar\n [(show)]=\"open\"\n #searchBar\n (search)=\"searchByText($event)\"\n (close)=\"onCloseSearch()\"\n ></rolatech-search-bar>\n</div>\n@if (loading) {\n <div class=\"flex justify-center items-center\">\n <rolatech-spinner></rolatech-spinner>\n </div>\n} @else {\n <div class=\"bg-[--rt-rasised-background] h-full\">\n <!-- <rolatech-property-manage-filter></rolatech-property-manage-filter> -->\n <div class=\"flex flex-wrap p-3 gap-3\">\n @for (item of properties(); track $index) {\n <rolatech-property-manage-item\n [property]=\"item\"\n routerLink=\"./{{ item.id }}/manage/info\"\n ></rolatech-property-manage-item>\n }\n </div>\n </div>\n}\n<mat-paginator\n #paginator\n [length]=\"length\"\n [pageSize]=\"pageSize\"\n [pageIndex]=\"pageIndex()\"\n [pageSizeOptions]=\"pageSizeOptions\"\n (page)=\"onPage($event)\"\n hidePageSize\n showFirstLastButtons\n>\n</mat-paginator>\n", styles: ["mat-form-field{width:100%}table{width:100%}td.mat-column-actions{text-align:right;max-width:64px;font-size:.8rem;padding:0 8px}.mat-mdc-header-cell.actions{text-align:right;max-width:64px;width:64px}.mat-mdc-cell:nth-last-child(2),.mat-mdc-header-cell:nth-last-child(2),.mat-mdc-footer-cell:nth-last-child(2){text-align:right;max-width:180px;width:180px}mat-cell:last-of-type,mat-header-cell:last-of-type,mat-footer-cell:last-of-type{text-align:right;padding-right:8px!important}rolatech-property-manage-index{display:flex;flex-direction:column;--rt-property-view-items-per-row: 1}@media (min-width: 600px){rolatech-property-manage-index{--rt-property-view-items-per-row: 2}}@media (min-width: 768px){rolatech-property-manage-index{--rt-property-view-items-per-row: 3}}@media (min-width: 1280px){rolatech-property-manage-index{--rt-property-view-items-per-row: 3}}@media (min-width: 1536px){rolatech-property-manage-index{--rt-property-view-items-per-row: 4}}@media (min-width: 1920px){rolatech-property-manage-index{--rt-property-view-items-per-row: 5}}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i1$4.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTableModule }, { kind: "ngmodule", type: MatMenuModule }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i3$2.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: SpinnerComponent, selector: "rolatech-spinner", inputs: ["title"] }, { kind: "component", type: PropertyManageItemComponent, selector: "rolatech-property-manage-item", inputs: ["property", "thumbnail", "list"] }, { kind: "component", type: SearchBar, selector: "rolatech-search-bar", inputs: ["show"], outputs: ["showChange", "search", "close"] }], encapsulation: i0.ViewEncapsulation.None });
2431
2629
  }
2432
2630
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyManageIndexComponent, decorators: [{
2433
2631
  type: Component,
@@ -2441,8 +2639,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImpor
2441
2639
  ToolbarComponent,
2442
2640
  SpinnerComponent,
2443
2641
  PropertyManageItemComponent,
2444
- PropertyManageFilterComponent,
2445
- ], encapsulation: ViewEncapsulation.None, template: "<rolatech-toolbar title=\"Properties\">\n <div class=\"flex items-center gap-2\">\n <button mat-flat-button routerLink=\"./create\">\n <mat-icon>add</mat-icon>\n <span i18n>Add property</span>\n </button>\n <!-- <button mat-flat-button (click)=\"export()\" [disabled]=\"exporting\">\n <mat-icon>download</mat-icon>\n <span i18n>Export</span>\n </button> -->\n <button mat-flat-button (click)=\"export()\" [disabled]=\"exporting\" aria-label=\"Export CSV\">\n @if (!exporting) {\n Export CSV\n } @else {\n Exporting\u2026\n }\n </button>\n </div>\n</rolatech-toolbar>\n@if (isLoading) {\n <div class=\"flex justify-center items-center\">\n <rolatech-spinner></rolatech-spinner>\n </div>\n} @else {\n <div class=\"bg-[--rt-rasised-background] h-full\">\n <rolatech-property-manage-filter></rolatech-property-manage-filter>\n <div class=\"flex flex-wrap p-3 gap-3\">\n @for (item of properties; track $index) {\n <rolatech-property-manage-item\n [property]=\"item\"\n routerLink=\"./{{ item.id }}/manage/info\"\n ></rolatech-property-manage-item>\n }\n </div>\n </div>\n}\n<mat-paginator\n #paginator\n [length]=\"length\"\n [pageSize]=\"pageSize\"\n [pageSizeOptions]=\"pageSizeOptions\"\n (page)=\"pageEvent = findProperties($event)\"\n hidePageSize\n showFirstLastButtons\n>\n</mat-paginator>\n", styles: ["mat-form-field{width:100%}table{width:100%}td.mat-column-actions{text-align:right;max-width:64px;font-size:.8rem;padding:0 8px}.mat-mdc-header-cell.actions{text-align:right;max-width:64px;width:64px}.mat-mdc-cell:nth-last-child(2),.mat-mdc-header-cell:nth-last-child(2),.mat-mdc-footer-cell:nth-last-child(2){text-align:right;max-width:180px;width:180px}mat-cell:last-of-type,mat-header-cell:last-of-type,mat-footer-cell:last-of-type{text-align:right;padding-right:8px!important}rolatech-property-manage-index{display:flex;flex-direction:column;--rt-property-view-items-per-row: 1}@media (min-width: 600px){rolatech-property-manage-index{--rt-property-view-items-per-row: 2}}@media (min-width: 768px){rolatech-property-manage-index{--rt-property-view-items-per-row: 3}}@media (min-width: 1280px){rolatech-property-manage-index{--rt-property-view-items-per-row: 3}}@media (min-width: 1536px){rolatech-property-manage-index{--rt-property-view-items-per-row: 4}}@media (min-width: 1920px){rolatech-property-manage-index{--rt-property-view-items-per-row: 5}}\n"] }]
2642
+ SearchBar
2643
+ ], encapsulation: ViewEncapsulation.None, template: "<rolatech-toolbar title=\"Properties\">\n <div class=\"flex items-center gap-2\">\n <button mat-icon-button (click)=\"toggleSearch()\">\n <mat-icon>search</mat-icon>\n </button>\n <!-- <button mat-icon-button (click)=\"toggleView()\">\n <mat-icon>{{ gridView ? 'view_list' : 'grid_on' }}</mat-icon>\n </button> -->\n <button mat-flat-button routerLink=\"./create\">\n <mat-icon>add</mat-icon>\n <span i18n>Add property</span>\n </button>\n <!-- <button mat-flat-button (click)=\"export()\" [disabled]=\"exporting\">\n <mat-icon>download</mat-icon>\n <span i18n>Export</span>\n </button> -->\n <button mat-flat-button (click)=\"export()\" [disabled]=\"exporting\" aria-label=\"Export CSV\">\n @if (!exporting) {\n Export CSV\n } @else {\n Exporting\u2026\n }\n </button>\n </div>\n</rolatech-toolbar>\n<div class=\"p-2\">\n <rolatech-search-bar\n [(show)]=\"open\"\n #searchBar\n (search)=\"searchByText($event)\"\n (close)=\"onCloseSearch()\"\n ></rolatech-search-bar>\n</div>\n@if (loading) {\n <div class=\"flex justify-center items-center\">\n <rolatech-spinner></rolatech-spinner>\n </div>\n} @else {\n <div class=\"bg-[--rt-rasised-background] h-full\">\n <!-- <rolatech-property-manage-filter></rolatech-property-manage-filter> -->\n <div class=\"flex flex-wrap p-3 gap-3\">\n @for (item of properties(); track $index) {\n <rolatech-property-manage-item\n [property]=\"item\"\n routerLink=\"./{{ item.id }}/manage/info\"\n ></rolatech-property-manage-item>\n }\n </div>\n </div>\n}\n<mat-paginator\n #paginator\n [length]=\"length\"\n [pageSize]=\"pageSize\"\n [pageIndex]=\"pageIndex()\"\n [pageSizeOptions]=\"pageSizeOptions\"\n (page)=\"onPage($event)\"\n hidePageSize\n showFirstLastButtons\n>\n</mat-paginator>\n", styles: ["mat-form-field{width:100%}table{width:100%}td.mat-column-actions{text-align:right;max-width:64px;font-size:.8rem;padding:0 8px}.mat-mdc-header-cell.actions{text-align:right;max-width:64px;width:64px}.mat-mdc-cell:nth-last-child(2),.mat-mdc-header-cell:nth-last-child(2),.mat-mdc-footer-cell:nth-last-child(2){text-align:right;max-width:180px;width:180px}mat-cell:last-of-type,mat-header-cell:last-of-type,mat-footer-cell:last-of-type{text-align:right;padding-right:8px!important}rolatech-property-manage-index{display:flex;flex-direction:column;--rt-property-view-items-per-row: 1}@media (min-width: 600px){rolatech-property-manage-index{--rt-property-view-items-per-row: 2}}@media (min-width: 768px){rolatech-property-manage-index{--rt-property-view-items-per-row: 3}}@media (min-width: 1280px){rolatech-property-manage-index{--rt-property-view-items-per-row: 3}}@media (min-width: 1536px){rolatech-property-manage-index{--rt-property-view-items-per-row: 4}}@media (min-width: 1920px){rolatech-property-manage-index{--rt-property-view-items-per-row: 5}}\n"] }]
2446
2644
  }], propDecorators: { hasClass: [{
2447
2645
  type: HostBinding,
2448
2646
  args: ['class.rolatech-property-manage-index']
@@ -3206,13 +3404,12 @@ class PropertyManageLocationComponent extends BaseComponent {
3206
3404
  longitude: '',
3207
3405
  latitude: '',
3208
3406
  }, ...(ngDevMode ? [{ debugName: "location" }] : []));
3209
- platformId = inject(PLATFORM_ID);
3210
3407
  placeAutocompleteElement;
3211
3408
  autocompleteInput;
3212
3409
  ngOnInit() {
3213
3410
  this.id = this.route.parent?.snapshot.paramMap.get('id');
3214
3411
  this.find();
3215
- if (isPlatformBrowser(this.platformId)) {
3412
+ if (this.isBrowser) {
3216
3413
  // this.autocompleteService = new google.maps.places.AutocompleteService();
3217
3414
  }
3218
3415
  }
@@ -3767,13 +3964,52 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImpor
3767
3964
  args: [{ selector: 'rolatech-property-manage-highlights', imports: [PropertyManageContentComponent, ToolbarComponent], template: "<rolatech-property-manage-content>\n <rolatech-toolbar title=\"Highlights\" class=\"hidden md:block\" divider></rolatech-toolbar>\n <div>\n @for (item of highlights; track $index) {\n <div class=\"font-bold p-1\">{{item}}</div>\n }\n </div>\n</rolatech-property-manage-content>\n" }]
3768
3965
  }] });
3769
3966
 
3770
- class PropertyManageEpc {
3771
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyManageEpc, deps: [], target: i0.ɵɵFactoryTarget.Component });
3772
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.2.0", type: PropertyManageEpc, isStandalone: true, selector: "rolatech-property-manage-epc", ngImport: i0, template: "<rolatech-property-manage-content>\n <rolatech-toolbar title=\"EPC\" class=\"hidden md:block\" divider></rolatech-toolbar>\n <div></div>\n</rolatech-property-manage-content>\n", styles: [""], dependencies: [{ kind: "component", type: PropertyManageContentComponent, selector: "rolatech-property-manage-content" }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }] });
3967
+ class PropertyManageEpc extends BaseComponent {
3968
+ propertyService = inject(PropertyService);
3969
+ currentRating = '';
3970
+ potentialRating = '';
3971
+ currentScore = 0;
3972
+ potentialScore = 0;
3973
+ ngOnInit() {
3974
+ this.id = this.route.parent?.snapshot.paramMap.get('id');
3975
+ this.get();
3976
+ }
3977
+ get() {
3978
+ this.propertyService.getEpc(this.id).subscribe({
3979
+ next: (res) => {
3980
+ this.currentScore = res.data.currentScore || 0;
3981
+ this.potentialScore = res.data.potentialScore || 0;
3982
+ }
3983
+ });
3984
+ }
3985
+ add() {
3986
+ const data = {
3987
+ currentScore: this.currentScore,
3988
+ potentialScore: this.potentialScore
3989
+ };
3990
+ this.propertyService.addEpc(this.id, data).subscribe({
3991
+ next: res => {
3992
+ this.snackBarService.open("EPC Added");
3993
+ }
3994
+ });
3995
+ }
3996
+ update() {
3997
+ const data = {
3998
+ currentScore: this.currentScore,
3999
+ potentialScore: this.potentialScore
4000
+ };
4001
+ this.propertyService.updateEpc(this.id, data).subscribe({
4002
+ next: res => {
4003
+ this.snackBarService.open("EPC Updated");
4004
+ }
4005
+ });
4006
+ }
4007
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyManageEpc, deps: null, target: i0.ɵɵFactoryTarget.Component });
4008
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.2.0", type: PropertyManageEpc, isStandalone: true, selector: "rolatech-property-manage-epc", usesInheritance: true, ngImport: i0, template: "<rolatech-property-manage-content>\n <rolatech-toolbar title=\"EPC\" class=\"hidden md:block\" divider></rolatech-toolbar>\n <div class=\"w-full md:max-w-[70%]\">\n <div class=\"p-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label>Current Score</mat-label>\n <input matInput [(ngModel)]=\"currentScore\" placeholder=\"Current Score\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label>Potential Score</mat-label>\n <input matInput [(ngModel)]=\"potentialScore\" placeholder=\"Potential Score\" />\n </mat-form-field>\n <button mat-flat-button (click)=\"add()\">Save</button>\n </div>\n <div>\n <div class=\"font-bold text-lg p-2\">Domestic EPC</div>\n <rolatech-epc-chart\n [currentScore]=\"currentScore\"\n [potentialScore]=\"potentialScore\"\n [showCaptions]=\"true\"\n ></rolatech-epc-chart>\n </div>\n </div>\n</rolatech-property-manage-content>\n", styles: ["mat-form-field{width:100%}\n"], dependencies: [{ kind: "component", type: PropertyManageContentComponent, selector: "rolatech-property-manage-content" }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: EpcChart, selector: "rolatech-epc-chart", inputs: ["currentScore", "potentialScore", "showCaptions"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1$2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }] });
3773
4009
  }
3774
4010
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImport: i0, type: PropertyManageEpc, decorators: [{
3775
4011
  type: Component,
3776
- args: [{ selector: 'rolatech-property-manage-epc', imports: [PropertyManageContentComponent, ToolbarComponent], template: "<rolatech-property-manage-content>\n <rolatech-toolbar title=\"EPC\" class=\"hidden md:block\" divider></rolatech-toolbar>\n <div></div>\n</rolatech-property-manage-content>\n" }]
4012
+ args: [{ selector: 'rolatech-property-manage-epc', imports: [PropertyManageContentComponent, ToolbarComponent, EpcChart, MatFormFieldModule, FormsModule, MatInputModule, MatButtonModule], template: "<rolatech-property-manage-content>\n <rolatech-toolbar title=\"EPC\" class=\"hidden md:block\" divider></rolatech-toolbar>\n <div class=\"w-full md:max-w-[70%]\">\n <div class=\"p-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label>Current Score</mat-label>\n <input matInput [(ngModel)]=\"currentScore\" placeholder=\"Current Score\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label>Potential Score</mat-label>\n <input matInput [(ngModel)]=\"potentialScore\" placeholder=\"Potential Score\" />\n </mat-form-field>\n <button mat-flat-button (click)=\"add()\">Save</button>\n </div>\n <div>\n <div class=\"font-bold text-lg p-2\">Domestic EPC</div>\n <rolatech-epc-chart\n [currentScore]=\"currentScore\"\n [potentialScore]=\"potentialScore\"\n [showCaptions]=\"true\"\n ></rolatech-epc-chart>\n </div>\n </div>\n</rolatech-property-manage-content>\n", styles: ["mat-form-field{width:100%}\n"] }]
3777
4013
  }] });
3778
4014
 
3779
4015
  class PropertyManageTranslation {
@@ -3948,7 +4184,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0", ngImpor
3948
4184
  const propertyManageViewingsRoutes = [
3949
4185
  {
3950
4186
  path: '',
3951
- loadComponent: () => import('./rolatech-angular-property-property-manage-viewings-index.component-UsM6RfhW.mjs').then((x) => x.PropertyManageViewingsIndexComponent),
4187
+ loadComponent: () => import('./rolatech-angular-property-property-manage-viewings-index.component-Dsk7BMQF.mjs').then((x) => x.PropertyManageViewingsIndexComponent),
3952
4188
  },
3953
4189
  {
3954
4190
  path: ':id',
@@ -4561,5 +4797,5 @@ const tenantManageRoutes = [
4561
4797
  * Generated bundle index. Do not edit.
4562
4798
  */
4563
4799
 
4564
- export { AdverseCreditStatus as A, EmploymentStatus as E, PropertyViewingItemComponent as P, ResidencyStatus as R, ViewingTime as V, propertyManageOffersRoutes as a, propertyRoutes as b, propertyManageRoutes as c, propertyManageViewingsRoutes as d, PropertyActionsComponent as e, featureManageRoutes as f, PropertyItemComponent as g, PropertyPricingComponent as h, PropertyPriceType as i, PropertyVideoProvider as j, PropertyStatus as k, lettingManageRoutes as l, PropertyType as m, PropertyInventoryStatus as n, PropertyScope as o, propertyReviewRoutes as p, PropertyViewingStatus as q, PropertyViewerCategory as r, PropertyOfferTimelineStatus as s, tenantManageRoutes as t, PropertyOfferType as u, PropertyOfferStatus as v, PropertyApplicantType as w };
4565
- //# sourceMappingURL=rolatech-angular-property-rolatech-angular-property-CQG71H-d.mjs.map
4800
+ export { AdverseCreditStatus as A, EmploymentStatus as E, PropertyUtil as P, ResidencyStatus as R, ViewingTime as V, PropertyViewType as a, PropertyViewingItemComponent as b, propertyManageOffersRoutes as c, propertyRoutes as d, propertyManageRoutes as e, featureManageRoutes as f, propertyManageViewingsRoutes as g, PropertyActionsComponent as h, PropertyItemComponent as i, PropertyPricingComponent as j, PropertyPriceType as k, lettingManageRoutes as l, PropertyVideoProvider as m, PropertyStatus as n, PropertyType as o, propertyReviewRoutes as p, PropertyInventoryStatus as q, PropertyScope as r, PropertyViewingStatus as s, tenantManageRoutes as t, PropertyViewerCategory as u, PropertyOfferTimelineStatus as v, PropertyOfferType as w, PropertyOfferStatus as x, PropertyApplicantType as y };
4801
+ //# sourceMappingURL=rolatech-angular-property-rolatech-angular-property-D6LNKZBf.mjs.map