@rolatech/angular-property 20.1.11 → 20.1.13

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.
@@ -1,17 +1,17 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, ElementRef, input, booleanAttribute, effect, HostBinding, ViewEncapsulation, Component, viewChild, PLATFORM_ID, output, computed, EventEmitter, Injectable, model, signal, Pipe, DestroyRef, ViewChild } from '@angular/core';
2
+ import { inject, ElementRef, input, booleanAttribute, effect, HostBinding, ViewEncapsulation, Component, viewChild, PLATFORM_ID, output, computed, signal, model, EventEmitter, Injectable, Pipe, 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';
6
6
  import { MatMenuModule } from '@angular/material/menu';
7
- import * as i1$6 from '@angular/material/paginator';
7
+ import * as i2$2 from '@angular/material/paginator';
8
8
  import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator';
9
9
  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, ActivatedRoute, Router, RouterLinkActive, RouterOutlet } from '@angular/router';
13
13
  import { ThumbnailComponent, ImagePlaceholderComponent, Skeleton, ToolbarComponent, ImagePreviewDialogComponent, BaseComponent, AcceptDialogComponent, RejectDialogComponent, RichLabelComponent, AngularComponentsModule, ConfirmationDialogComponent, TabsComponent, TabComponent, EmptyComponent, ListComponent, ContainerComponent, SearchBar, SpinnerComponent, MediaListComponent, MediaListItemComponent, InputComponent } from '@rolatech/angular-components';
14
- import { PropertyService, FeatureService, InvoiceService, FloorplanService, PropertyHighlightsService, TimeZoneService, PaymentService, PropertySearchService, DialogService } from '@rolatech/angular-services';
14
+ import { PropertyService, FeatureService, PropertyOfferService, InvoiceService, FloorplanService, PropertyHighlightsService, TimeZoneService, PaymentService, 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 { PricePipe, APP_CONFIG, AngularCommonModule, OptionsFormatPipe, DecimalDirective, DurationPipe, SafeUrlPipe } from '@rolatech/angular-common';
@@ -29,7 +29,7 @@ import * as i5 from '@angular/material/select';
29
29
  import { MatSelectModule } from '@angular/material/select';
30
30
  import * as i1$5 from '@angular/material/chips';
31
31
  import { MatChipsModule } from '@angular/material/chips';
32
- import { startWith, map, switchMap, distinctUntilChanged, finalize, forkJoin, from, concatMap, take, Observable } from 'rxjs';
32
+ import { startWith, map, distinctUntilChanged, switchMap, finalize, forkJoin, from, concatMap, take, Observable } from 'rxjs';
33
33
  import { ENTER, COMMA } from '@angular/cdk/keycodes';
34
34
  import * as i4$2 from '@angular/material/autocomplete';
35
35
  import { MatAutocompleteModule } from '@angular/material/autocomplete';
@@ -50,7 +50,7 @@ import * as i3$1 from '@angular/material/progress-spinner';
50
50
  import { MatProgressSpinner, MatProgressSpinnerModule } from '@angular/material/progress-spinner';
51
51
  import * as i8 from '@angular/material/progress-bar';
52
52
  import { MatProgressBarModule } from '@angular/material/progress-bar';
53
- import * as i1$7 from '@angular/material/checkbox';
53
+ import * as i1$6 from '@angular/material/checkbox';
54
54
  import { MatCheckboxModule } from '@angular/material/checkbox';
55
55
  import * as i4$3 from '@angular/cdk/drag-drop';
56
56
  import { moveItemInArray, DragDropModule } from '@angular/cdk/drag-drop';
@@ -414,11 +414,11 @@ class PropertyManageItemSkeleton {
414
414
  });
415
415
  }
416
416
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyManageItemSkeleton, deps: [], target: i0.ɵɵFactoryTarget.Component });
417
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.0", type: PropertyManageItemSkeleton, isStandalone: true, selector: "rolatech-property-manage-item-skeleton", inputs: { loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, list: { classPropertyName: "list", publicName: "list", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.rolatech-property-manage-item-skeleton": "this.hasClass" } }, ngImport: i0, template: "<div\n class=\"flex p-3 bg-[--rt-raised-background] hover:bg-[--rt-raised-background] rounded-md\"\n [ngClass]=\"list() ? 'w-full flex-row' : 'flex-col h-full'\"\n>\n <div>\n <div class=\"object-cover aspect-video rounded-lg\" [ngClass]=\"list() ? 'w-32 mr-3' : ''\">\n <!-- <rolatech-image-placeholder></rolatech-image-placeholder> -->\n <rolatech-skeleton class=\"w-full h-full\"></rolatech-skeleton>\n </div>\n </div>\n\n <div class=\"py-2\">\n <rolatech-skeleton class=\"w-full h-4\"></rolatech-skeleton>\n </div>\n <div class=\"flex-1\"></div>\n <rolatech-skeleton class=\"w-10 h-4\"></rolatech-skeleton>\n</div>\n", styles: ["rolatech-property-manage-item-skeleton{--rt-property-view-item-margin: 16px;margin-left:calc(var(--rt-property-view-item-margin) / 2);margin-right:calc(var(--rt-property-view-item-margin) / 2);margin-bottom:var(--rt-property-view-item-margin);width:calc(100% / var(--rt-property-view-items-per-row) - var(--rt-property-view-item-margin))}rolatech-property-manage-item-skeleton[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: Skeleton, selector: "rolatech-skeleton" }], encapsulation: i0.ViewEncapsulation.None });
417
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.0", type: PropertyManageItemSkeleton, isStandalone: true, selector: "rolatech-property-manage-item-skeleton", inputs: { loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, list: { classPropertyName: "list", publicName: "list", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.rolatech-property-manage-item-skeleton": "this.hasClass" } }, ngImport: i0, template: "<div class=\"flex w-full\" [ngClass]=\"list() ? 'flex-row' : 'flex-col'\">\n <div class=\"object-cover aspect-video rounded-lg\" [ngClass]=\"list() ? 'w-1/3 mr-3' : ''\">\n <rolatech-skeleton class=\"w-full h-full\"></rolatech-skeleton>\n </div>\n <div class=\"flex flex-col justify-between\" [ngClass]=\"list() ? 'w-2/3' : ''\">\n <rolatech-skeleton class=\"w-2/3 h-5 my-1\"></rolatech-skeleton>\n <rolatech-skeleton class=\"w-12 h-4 my-1\"></rolatech-skeleton>\n </div>\n</div>\n", styles: ["rolatech-property-manage-item-skeleton{--rt-property-view-item-margin: 16px;margin-left:calc(var(--rt-property-view-item-margin) / 2);margin-right:calc(var(--rt-property-view-item-margin) / 2);margin-bottom:var(--rt-property-view-item-margin);width:calc(100% / var(--rt-property-view-items-per-row) - var(--rt-property-view-item-margin))}rolatech-property-manage-item-skeleton[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: Skeleton, selector: "rolatech-skeleton" }], encapsulation: i0.ViewEncapsulation.None });
418
418
  }
419
419
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyManageItemSkeleton, decorators: [{
420
420
  type: Component,
421
- args: [{ selector: 'rolatech-property-manage-item-skeleton', imports: [CommonModule, Skeleton], encapsulation: ViewEncapsulation.None, template: "<div\n class=\"flex p-3 bg-[--rt-raised-background] hover:bg-[--rt-raised-background] rounded-md\"\n [ngClass]=\"list() ? 'w-full flex-row' : 'flex-col h-full'\"\n>\n <div>\n <div class=\"object-cover aspect-video rounded-lg\" [ngClass]=\"list() ? 'w-32 mr-3' : ''\">\n <!-- <rolatech-image-placeholder></rolatech-image-placeholder> -->\n <rolatech-skeleton class=\"w-full h-full\"></rolatech-skeleton>\n </div>\n </div>\n\n <div class=\"py-2\">\n <rolatech-skeleton class=\"w-full h-4\"></rolatech-skeleton>\n </div>\n <div class=\"flex-1\"></div>\n <rolatech-skeleton class=\"w-10 h-4\"></rolatech-skeleton>\n</div>\n", styles: ["rolatech-property-manage-item-skeleton{--rt-property-view-item-margin: 16px;margin-left:calc(var(--rt-property-view-item-margin) / 2);margin-right:calc(var(--rt-property-view-item-margin) / 2);margin-bottom:var(--rt-property-view-item-margin);width:calc(100% / var(--rt-property-view-items-per-row) - var(--rt-property-view-item-margin))}rolatech-property-manage-item-skeleton[list]{--rt-property-view-items-per-row: 1}\n"] }]
421
+ args: [{ selector: 'rolatech-property-manage-item-skeleton', imports: [CommonModule, Skeleton], encapsulation: ViewEncapsulation.None, template: "<div class=\"flex w-full\" [ngClass]=\"list() ? 'flex-row' : 'flex-col'\">\n <div class=\"object-cover aspect-video rounded-lg\" [ngClass]=\"list() ? 'w-1/3 mr-3' : ''\">\n <rolatech-skeleton class=\"w-full h-full\"></rolatech-skeleton>\n </div>\n <div class=\"flex flex-col justify-between\" [ngClass]=\"list() ? 'w-2/3' : ''\">\n <rolatech-skeleton class=\"w-2/3 h-5 my-1\"></rolatech-skeleton>\n <rolatech-skeleton class=\"w-12 h-4 my-1\"></rolatech-skeleton>\n </div>\n</div>\n", styles: ["rolatech-property-manage-item-skeleton{--rt-property-view-item-margin: 16px;margin-left:calc(var(--rt-property-view-item-margin) / 2);margin-right:calc(var(--rt-property-view-item-margin) / 2);margin-bottom:var(--rt-property-view-item-margin);width:calc(100% / var(--rt-property-view-items-per-row) - var(--rt-property-view-item-margin))}rolatech-property-manage-item-skeleton[list]{--rt-property-view-items-per-row: 1}\n"] }]
422
422
  }], ctorParameters: () => [], propDecorators: { hasClass: [{
423
423
  type: HostBinding,
424
424
  args: ['class.rolatech-property-manage-item-skeleton']
@@ -1023,8 +1023,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
1023
1023
  args: [{ selector: 'rolatech-property-offer-item', imports: [MatIconModule, ThumbnailComponent, ImagePlaceholderComponent, PricePipe], template: "<div class=\"flex flex-col hover:bg-[--rt-raised-background] cursor-pointer p-3\">\n <div>\n <div class=\"flex justify-between w-full mb-2\">\n <a class=\"flex items-center gap-3\">\n <span>Offer ID: {{ offer().id }}</span>\n </a>\n <span class=\"font-medium text-sm\">{{ status[offer().status] }}</span>\n </div>\n @if (offer().item) {\n <div class=\"flex flex-row py-2\">\n @if (offer().item.media) {\n <div class=\"min-w-24 w-36 object-cover aspect-video rounded-lg mr-3\">\n @defer {\n <rolatech-thumbnail [src]=\"offer().item.media ? offer().item.media[0].url : ''\" size=\"medium\" mode=\"clip\">\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=\"min-w-24 w-36 object-cover aspect-video rounded-lg mr-3\">\n <rolatech-image-placeholder></rolatech-image-placeholder>\n </div>\n }\n <div class=\"flex w-full justify-between\">\n <div class=\"flex justify-between w-full\">\n <div class=\"flex flex-col\">\n <div class=\"font-bold\">{{ offer().item.title }}</div>\n <div class=\"inline-flex gap-1 mt-2\">\n <div>\n <span class=\"mr-1\">{{ offer().item.bedrooms }}</span>\n <span i18n>Bedrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ offer().item.bathrooms }}</span>\n <span i18n>Bathrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ offer().item.receptions }}</span>\n <span i18n>Receptions</span>\n </div>\n </div>\n </div>\n <div class=\"text-right\">\n <div class=\"text-sm\">{{ offer().item.amount | price }}</div>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n</div>\n" }]
1024
1024
  }], propDecorators: { offer: [{ type: i0.Input, args: [{ isSignal: true, alias: "offer", required: true }] }] } });
1025
1025
 
1026
+ class OfferItemSkeleton {
1027
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: OfferItemSkeleton, deps: [], target: i0.ɵɵFactoryTarget.Component });
1028
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.0", type: OfferItemSkeleton, isStandalone: true, selector: "rolatech-offer-item-skeleton", ngImport: i0, template: "<div class=\"flex flex-col py-3\">\n <div class=\"flex justify-between w-full mb-2\">\n <rolatech-skeleton class=\"w-52 h-5\"></rolatech-skeleton>\n <rolatech-skeleton class=\"w-11 h-5\"></rolatech-skeleton>\n </div>\n <div class=\"flex flex-row py-2\">\n <div class=\"min-w-24 w-36 object-cover aspect-video rounded-lg mr-3\">\n <rolatech-skeleton class=\"w-full h-full\"></rolatech-skeleton>\n </div>\n <div class=\"flex w-full justify-between\">\n <div class=\"flex justify-between w-full\">\n <div class=\"flex flex-col\">\n <rolatech-skeleton class=\"w-40 h-4\"></rolatech-skeleton>\n <div class=\"inline-flex gap-1 mt-2\">\n <rolatech-skeleton class=\"w-20 h-4\"></rolatech-skeleton>\n </div>\n </div>\n <div class=\"text-right\">\n <rolatech-skeleton class=\"w-8 h-4\"></rolatech-skeleton>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Skeleton, selector: "rolatech-skeleton" }] });
1029
+ }
1030
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: OfferItemSkeleton, decorators: [{
1031
+ type: Component,
1032
+ args: [{ selector: 'rolatech-offer-item-skeleton', imports: [CommonModule, Skeleton], template: "<div class=\"flex flex-col py-3\">\n <div class=\"flex justify-between w-full mb-2\">\n <rolatech-skeleton class=\"w-52 h-5\"></rolatech-skeleton>\n <rolatech-skeleton class=\"w-11 h-5\"></rolatech-skeleton>\n </div>\n <div class=\"flex flex-row py-2\">\n <div class=\"min-w-24 w-36 object-cover aspect-video rounded-lg mr-3\">\n <rolatech-skeleton class=\"w-full h-full\"></rolatech-skeleton>\n </div>\n <div class=\"flex w-full justify-between\">\n <div class=\"flex justify-between w-full\">\n <div class=\"flex flex-col\">\n <rolatech-skeleton class=\"w-40 h-4\"></rolatech-skeleton>\n <div class=\"inline-flex gap-1 mt-2\">\n <rolatech-skeleton class=\"w-20 h-4\"></rolatech-skeleton>\n </div>\n </div>\n <div class=\"text-right\">\n <rolatech-skeleton class=\"w-8 h-4\"></rolatech-skeleton>\n </div>\n </div>\n </div>\n </div>\n</div>\n" }]
1033
+ }] });
1034
+
1026
1035
  class PropertyManageOfferIndexComponent extends BaseComponent {
1027
1036
  propertyService = inject(PropertyService);
1037
+ propertyOfferService = inject(PropertyOfferService);
1028
1038
  select = 0;
1029
1039
  links = [
1030
1040
  {
@@ -1032,9 +1042,9 @@ class PropertyManageOfferIndexComponent extends BaseComponent {
1032
1042
  icon: 'dashboard',
1033
1043
  },
1034
1044
  {
1035
- name: 'Pending',
1045
+ name: 'Created',
1036
1046
  icon: 'category',
1037
- status: 'pending',
1047
+ status: 'created',
1038
1048
  },
1039
1049
  {
1040
1050
  name: 'Accepted',
@@ -1052,47 +1062,61 @@ class PropertyManageOfferIndexComponent extends BaseComponent {
1052
1062
  status: 'cancelled',
1053
1063
  },
1054
1064
  ];
1055
- filterOptions = {
1056
- type: '',
1057
- status: '',
1058
- };
1059
- offers = [];
1065
+ offers = signal([], ...(ngDevMode ? [{ debugName: "offers" }] : []));
1066
+ meta;
1067
+ pageEvent;
1068
+ length = 100;
1069
+ pageSize = 15;
1070
+ pageSizeOptions = [5, 10, 25, 100];
1071
+ pageIndex = signal(0, ...(ngDevMode ? [{ debugName: "pageIndex" }] : []));
1072
+ loading = false;
1060
1073
  ngOnInit() {
1061
- this.route.queryParams.subscribe(({ status }) => {
1062
- this.select = this.links.findIndex((item) => item.status === status);
1074
+ const sub = this.route.queryParamMap
1075
+ .pipe(map((p) => {
1076
+ const page = p.get('page') ? Number(p.get('page')) : 1;
1077
+ this.pageIndex.set(Math.max(page - 1, 0));
1078
+ const status = p.get('status') || undefined;
1079
+ let filter = '';
1063
1080
  if (status) {
1064
- this.filterOptions.status = status.toUpperCase();
1081
+ this.select = this.links.findIndex((item) => item.status === status);
1082
+ filter = `status:${status?.toUpperCase()}`;
1065
1083
  }
1066
- else {
1067
- delete this.filterOptions.status;
1068
- }
1069
- this.findOffers();
1070
- });
1071
- }
1072
- findOffers() {
1073
- const options = {
1074
- sort: 'updatedAt desc',
1075
- };
1076
- const filterString = this.convertFilterOptions(this.filterOptions);
1077
- if (filterString) {
1078
- options['filter'] = filterString;
1079
- }
1080
- this.propertyService.findOffersByAgent(options).subscribe({
1084
+ return {
1085
+ page,
1086
+ filter,
1087
+ limit: p.get('limit') ? Number(p.get('limit')) : 15,
1088
+ sort: p.get('sort') || undefined,
1089
+ };
1090
+ }),
1091
+ // Cheap deep compare via JSON to avoid spam calls when nothing changed
1092
+ map((o) => JSON.stringify(o)), distinctUntilChanged(), map((s) => JSON.parse(s)), switchMap((params) => {
1093
+ this.loading = true;
1094
+ params['sort'] = 'updatedAt desc';
1095
+ return this.propertyOfferService.findOffers(params).pipe(finalize(() => (this.loading = false)));
1096
+ }))
1097
+ .subscribe({
1081
1098
  next: (res) => {
1082
- this.offers = res.data;
1099
+ this.offers.set(res.data);
1100
+ this.meta = res.meta;
1101
+ this.length = res.meta.pagination.count;
1102
+ },
1103
+ error: () => {
1104
+ this.offers.set([]);
1105
+ this.length = 0;
1083
1106
  },
1084
1107
  });
1108
+ // // auto-unsubscribe on destroy
1109
+ this.destroyRef.onDestroy(() => sub.unsubscribe());
1085
1110
  }
1086
- convertFilterOptions(jsonObj) {
1087
- return Object.entries(jsonObj)
1088
- .filter(([key, value]) => value !== '' && value !== undefined)
1089
- .map(([key, value]) => {
1090
- return `${key}:${value}`;
1091
- })
1092
- .join(',');
1111
+ onPage(e) {
1112
+ this.router.navigate([], {
1113
+ queryParams: { page: e.pageIndex + 1, limit: e.pageSize },
1114
+ queryParamsHandling: 'merge',
1115
+ replaceUrl: true, // optional: avoid stacking history on every page click
1116
+ });
1093
1117
  }
1094
1118
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyManageOfferIndexComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1095
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: PropertyManageOfferIndexComponent, isStandalone: true, selector: "rolatech-property-manage-offer-index", usesInheritance: true, ngImport: i0, template: "<rolatech-toolbar title=\"Offers\">\n <div class=\"flex items-center gap-2\"></div>\n</rolatech-toolbar>\n<rolatech-tabs [select]=\"select\">\n @for (item of links; track item) {\n @if (item.status) {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\" [queryParams]=\"{ status: item.status }\"></rolatech-tab>\n } @else {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\"></rolatech-tab>\n }\n }\n</rolatech-tabs>\n<rolatech-list>\n @if (offers) {\n @for (item of offers; track item) {\n <rolatech-property-offer-item [routerLink]=\"['./', item.id]\" [offer]=\"item\"></rolatech-property-offer-item>\n }\n } @else {\n <rolatech-empty></rolatech-empty>\n }\n</rolatech-list>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: TabsComponent, selector: "rolatech-tabs", inputs: ["select", "loading"], outputs: ["selectChange"] }, { kind: "component", type: TabComponent, selector: "rolatech-tab", inputs: ["label"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: PropertyOfferItemComponent, selector: "rolatech-property-offer-item", inputs: ["offer"] }, { kind: "component", type: EmptyComponent, selector: "rolatech-empty" }, { kind: "component", type: ListComponent, selector: "rolatech-list" }] });
1119
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: PropertyManageOfferIndexComponent, isStandalone: true, selector: "rolatech-property-manage-offer-index", usesInheritance: true, ngImport: i0, template: "<rolatech-toolbar title=\"Offers\">\n <div class=\"flex items-center gap-2\"></div>\n</rolatech-toolbar>\n<rolatech-tabs [select]=\"select\">\n @for (item of links; track item) {\n @if (item.status) {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\" [queryParams]=\"{ status: item.status }\"></rolatech-tab>\n } @else {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\"></rolatech-tab>\n }\n }\n</rolatech-tabs>\n@if (loading) {\n <div class=\"divide-y divide-[--rt-10-percent-layer] flex flex-col px-3\">\n @for (row of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; track row) {\n <rolatech-offer-item-skeleton></rolatech-offer-item-skeleton>\n }\n </div>\n} @else {\n <rolatech-list>\n @if (offers() && offers().length > 0) {\n @for (item of offers(); track item) {\n <rolatech-property-offer-item [routerLink]=\"['./', item.id]\" [offer]=\"item\"></rolatech-property-offer-item>\n }\n } @else {\n <rolatech-empty></rolatech-empty>\n }\n </rolatech-list>\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: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: TabsComponent, selector: "rolatech-tabs", inputs: ["select", "loading"], outputs: ["selectChange"] }, { kind: "component", type: TabComponent, selector: "rolatech-tab", inputs: ["label"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: PropertyOfferItemComponent, selector: "rolatech-property-offer-item", inputs: ["offer"] }, { kind: "component", type: EmptyComponent, selector: "rolatech-empty" }, { kind: "component", type: ListComponent, selector: "rolatech-list" }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i2$2.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "component", type: OfferItemSkeleton, selector: "rolatech-offer-item-skeleton" }] });
1096
1120
  }
1097
1121
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyManageOfferIndexComponent, decorators: [{
1098
1122
  type: Component,
@@ -1104,12 +1128,55 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
1104
1128
  RouterModule,
1105
1129
  PropertyOfferItemComponent,
1106
1130
  EmptyComponent,
1107
- ListComponent
1108
- ], template: "<rolatech-toolbar title=\"Offers\">\n <div class=\"flex items-center gap-2\"></div>\n</rolatech-toolbar>\n<rolatech-tabs [select]=\"select\">\n @for (item of links; track item) {\n @if (item.status) {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\" [queryParams]=\"{ status: item.status }\"></rolatech-tab>\n } @else {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\"></rolatech-tab>\n }\n }\n</rolatech-tabs>\n<rolatech-list>\n @if (offers) {\n @for (item of offers; track item) {\n <rolatech-property-offer-item [routerLink]=\"['./', item.id]\" [offer]=\"item\"></rolatech-property-offer-item>\n }\n } @else {\n <rolatech-empty></rolatech-empty>\n }\n</rolatech-list>\n" }]
1131
+ ListComponent,
1132
+ MatPaginatorModule,
1133
+ OfferItemSkeleton,
1134
+ ], template: "<rolatech-toolbar title=\"Offers\">\n <div class=\"flex items-center gap-2\"></div>\n</rolatech-toolbar>\n<rolatech-tabs [select]=\"select\">\n @for (item of links; track item) {\n @if (item.status) {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\" [queryParams]=\"{ status: item.status }\"></rolatech-tab>\n } @else {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\"></rolatech-tab>\n }\n }\n</rolatech-tabs>\n@if (loading) {\n <div class=\"divide-y divide-[--rt-10-percent-layer] flex flex-col px-3\">\n @for (row of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; track row) {\n <rolatech-offer-item-skeleton></rolatech-offer-item-skeleton>\n }\n </div>\n} @else {\n <rolatech-list>\n @if (offers() && offers().length > 0) {\n @for (item of offers(); track item) {\n <rolatech-property-offer-item [routerLink]=\"['./', item.id]\" [offer]=\"item\"></rolatech-property-offer-item>\n }\n } @else {\n <rolatech-empty></rolatech-empty>\n }\n </rolatech-list>\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" }]
1109
1135
  }] });
1110
1136
 
1137
+ const MY_FORMATS$7 = {
1138
+ parse: {
1139
+ dateInput: 'YYYY-MM-DD',
1140
+ },
1141
+ display: {
1142
+ dateInput: 'YYYY-MM-DD',
1143
+ monthYearLabel: 'MMM YYYY',
1144
+ dateA11yLabel: 'YYYY-MM-DD',
1145
+ monthYearA11yLabel: 'MMMM YYYY',
1146
+ },
1147
+ };
1148
+ class OfferEdit extends BaseComponent {
1149
+ minDate = new Date();
1150
+ offer = model.required(...(ngDevMode ? [{ debugName: "offer" }] : []));
1151
+ output = output();
1152
+ ngDoCheck() {
1153
+ this.output.emit(this.offer());
1154
+ }
1155
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: OfferEdit, deps: null, target: i0.ɵɵFactoryTarget.Component });
1156
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.0", type: OfferEdit, isStandalone: true, selector: "rolatech-offer-edit", inputs: { offer: { classPropertyName: "offer", publicName: "offer", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { offer: "offerChange", output: "output" }, providers: [
1157
+ {
1158
+ provide: DateAdapter,
1159
+ useClass: MomentDateAdapter,
1160
+ deps: [MAT_DATE_LOCALE],
1161
+ },
1162
+ { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS$7 },
1163
+ ], usesInheritance: true, ngImport: i0, template: "<div class=\"flex flex-col gap-2\">\n <div class=\"flex justify-between gap-3\">\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-label>Firstname</mat-label>\n <input matInput [(ngModel)]=\"offer().firstName\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-label>Lastname</mat-label>\n <input matInput [(ngModel)]=\"offer().lastName\" />\n </mat-form-field>\n </div>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-label>Email</mat-label>\n <input matInput [(ngModel)]=\"offer().email\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-label>Phone</mat-label>\n <input matInput [(ngModel)]=\"offer().phone\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-label>Amount</mat-label>\n <input matInput [(ngModel)]=\"offer().amount\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-label i18n>Move-in date</mat-label>\n <!-- [max]=\"maxDate\" -->\n <input\n matInput\n placeholder=\"Move-in date\"\n [min]=\"minDate\"\n [matDatepicker]=\"startDatePicker\"\n (focus)=\"startDatePicker.open()\"\n [(ngModel)]=\"offer().startDate\"\n (dateInput)=\"offer().startDate = $event.value.format('YYYY-MM-DD')\"\n required\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>\n", styles: ["mat-form-field{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { 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: "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: "directive", type: i1$2.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i6.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i6.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i6.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: MatOptionModule }] });
1164
+ }
1165
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: OfferEdit, decorators: [{
1166
+ type: Component,
1167
+ args: [{ selector: 'rolatech-offer-edit', imports: [CommonModule, FormsModule, MatInputModule, MatDatepickerModule, MatSelectModule, MatOptionModule], providers: [
1168
+ {
1169
+ provide: DateAdapter,
1170
+ useClass: MomentDateAdapter,
1171
+ deps: [MAT_DATE_LOCALE],
1172
+ },
1173
+ { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS$7 },
1174
+ ], template: "<div class=\"flex flex-col gap-2\">\n <div class=\"flex justify-between gap-3\">\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-label>Firstname</mat-label>\n <input matInput [(ngModel)]=\"offer().firstName\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-label>Lastname</mat-label>\n <input matInput [(ngModel)]=\"offer().lastName\" />\n </mat-form-field>\n </div>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-label>Email</mat-label>\n <input matInput [(ngModel)]=\"offer().email\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-label>Phone</mat-label>\n <input matInput [(ngModel)]=\"offer().phone\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-label>Amount</mat-label>\n <input matInput [(ngModel)]=\"offer().amount\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-label i18n>Move-in date</mat-label>\n <!-- [max]=\"maxDate\" -->\n <input\n matInput\n placeholder=\"Move-in date\"\n [min]=\"minDate\"\n [matDatepicker]=\"startDatePicker\"\n (focus)=\"startDatePicker.open()\"\n [(ngModel)]=\"offer().startDate\"\n (dateInput)=\"offer().startDate = $event.value.format('YYYY-MM-DD')\"\n required\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>\n", styles: ["mat-form-field{width:100%}\n"] }]
1175
+ }], propDecorators: { offer: [{ type: i0.Input, args: [{ isSignal: true, alias: "offer", required: true }] }, { type: i0.Output, args: ["offerChange"] }], output: [{ type: i0.Output, args: ["output"] }] } });
1176
+
1111
1177
  class PropertyManageOfferDetailComponent extends BaseComponent {
1112
1178
  propertyService = inject(PropertyService);
1179
+ propertyOfferService = inject(PropertyOfferService);
1113
1180
  authUserService = inject(AuthUserService);
1114
1181
  invoiceService = inject(InvoiceService);
1115
1182
  offer;
@@ -1122,7 +1189,7 @@ class PropertyManageOfferDetailComponent extends BaseComponent {
1122
1189
  this.getOffer();
1123
1190
  }
1124
1191
  getOffer() {
1125
- this.propertyService.getOffer(this.id).subscribe({
1192
+ this.propertyOfferService.getOffer(this.id).subscribe({
1126
1193
  next: (res) => {
1127
1194
  this.offer = res.data;
1128
1195
  this.name = this.offer.firstName + ', ' + this.offer.lastName;
@@ -1155,7 +1222,7 @@ class PropertyManageOfferDetailComponent extends BaseComponent {
1155
1222
  });
1156
1223
  dialogRef.afterClosed().subscribe((result) => {
1157
1224
  if (result) {
1158
- this.propertyService.acceptOffer(this.id).subscribe({
1225
+ this.propertyOfferService.acceptOffer(this.id).subscribe({
1159
1226
  next: (res) => {
1160
1227
  this.offer.status = 'ACCEPTED';
1161
1228
  this.snackBarService.open('Accepted');
@@ -1176,7 +1243,7 @@ class PropertyManageOfferDetailComponent extends BaseComponent {
1176
1243
  });
1177
1244
  dialogRef.afterClosed().subscribe((result) => {
1178
1245
  if (result) {
1179
- this.propertyService.rejectOffer(this.id, { reason: result.content }).subscribe({
1246
+ this.propertyOfferService.rejectOffer(this.id, { reason: result.content }).subscribe({
1180
1247
  next: (res) => {
1181
1248
  this.offer.status = 'REJECTED';
1182
1249
  this.snackBarService.open('Rejected');
@@ -1199,7 +1266,7 @@ class PropertyManageOfferDetailComponent extends BaseComponent {
1199
1266
  });
1200
1267
  dialogRef.afterClosed().subscribe((result) => {
1201
1268
  if (result) {
1202
- this.propertyService.referencesAccept(this.id).subscribe({
1269
+ this.propertyOfferService.referencesAccept(this.id).subscribe({
1203
1270
  next: (res) => {
1204
1271
  this.offer.status = 'REFERENCES_PASSED';
1205
1272
  this.snackBarService.open('Passed');
@@ -1220,7 +1287,7 @@ class PropertyManageOfferDetailComponent extends BaseComponent {
1220
1287
  });
1221
1288
  dialogRef.afterClosed().subscribe((result) => {
1222
1289
  if (result) {
1223
- this.propertyService.referencesReject(this.id, { notes: result.content }).subscribe({
1290
+ this.propertyOfferService.referencesReject(this.id, { notes: result.content }).subscribe({
1224
1291
  next: (res) => {
1225
1292
  this.offer.status = 'REFERENCES_FAILED';
1226
1293
  this.snackBarService.open('Failed');
@@ -1232,12 +1299,52 @@ class PropertyManageOfferDetailComponent extends BaseComponent {
1232
1299
  }
1233
1300
  });
1234
1301
  }
1302
+ edit() {
1303
+ const options = {
1304
+ title: 'Update offer',
1305
+ cancelText: 'Cancel',
1306
+ confirmText: 'Confirm',
1307
+ data: {
1308
+ offer: this.offer,
1309
+ },
1310
+ component: OfferEdit,
1311
+ };
1312
+ this.dialogService.open(options);
1313
+ this.dialogService.confirmed().subscribe({
1314
+ next: (res) => {
1315
+ if (res) {
1316
+ const data = {
1317
+ firstName: res.firstName,
1318
+ lastName: res.lastName,
1319
+ email: res.email,
1320
+ phone: res.phone,
1321
+ amount: res.amount,
1322
+ moveInDate: res.startDate,
1323
+ };
1324
+ this.propertyOfferService.updateOffer(this.id, data).subscribe({
1325
+ next: (res) => {
1326
+ this.snackBarService.open('Offer updated');
1327
+ },
1328
+ });
1329
+ }
1330
+ },
1331
+ });
1332
+ }
1235
1333
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyManageOfferDetailComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1236
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: PropertyManageOfferDetailComponent, isStandalone: true, selector: "rolatech-property-manage-offer-detail", usesInheritance: true, ngImport: i0, template: "@if (offer) {\n <rolatech-toolbar [title]=\"status[offer.status]\" large link=\"../\">\n @if (offer.status.toString() === 'CREATED') {\n <button mat-flat-button (click)=\"accept()\" i18n>Accept</button>\n <button mat-flat-button (click)=\"counter()\" i18n>Counter offer</button>\n <button mat-button (click)=\"reject()\" i18n>Reject</button>\n }\n <!-- References -->\n @if (offer.status.toString() === 'HOLDING_DEPOSIT_PAID') {\n <button mat-flat-button (click)=\"rfAccept()\" i18n>References passed</button>\n <button mat-flat-button (click)=\"rfReject()\" i18n>References failed</button>\n }\n </rolatech-toolbar>\n <div class=\"px-4\">\n <div>\n <div class=\"text-lg font-bold py-2\">Viewer</div>\n <hr class=\"mb-2\" />\n <div class=\"flex flex-col md:flex-row gap-1 md:gap-4\">\n <rolatech-rich-label label=\"Name\" [title]=\"name\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Email\" [title]=\"offer.email\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Phone\" [title]=\"offer.phone\"></rolatech-rich-label>\n </div>\n </div>\n <div>\n <div class=\"text-lg font-bold py-2\">Qualification</div>\n <hr class=\"mb-2\" />\n <div class=\"flex flex-col md:flex-row gap-1 md:gap-4\">\n <rolatech-rich-label label=\"Move-in date\" [title]=\"offer.startDate\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Tenancy duration\" [title]=\"offer.tenancyDuration\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Number of tenants\" [title]=\"offer.numberOfTenants\"></rolatech-rich-label>\n </div>\n <div class=\"flex flex-col md:flex-row gap-1 md:gap-4\">\n <rolatech-rich-label label=\"Employment status\" [title]=\"employmentStatus[offer.employmentStatus]\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Employer\" [title]=\"offer.startDate\"></rolatech-rich-label>\n @if (offer.income) {\n <rolatech-rich-label label=\"Annual income\" [title]=\"offer.income\"></rolatech-rich-label>\n }\n </div>\n </div>\n <div>\n <div class=\"text-lg font-bold py-2\">Property details</div>\n <hr class=\"mb-2\" />\n <div class=\"flex items-center py-2\">\n <div class=\"min-w-24 w-24 object-cover aspect-video rounded-md mr-3\">\n @defer {\n <rolatech-thumbnail [src]=\"offer.item.media[0].url\" size=\"medium\" mode=\"clip\"> </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 <div class=\"flex w-full justify-between\">\n <div class=\"flex justify-between w-full\">\n <div class=\"flex flex-col\">\n <div>{{ offer.item.title }}</div>\n <div class=\"inline-flex gap-1 mt-2\">\n <div>\n <span class=\"mr-1\">{{ offer.item.bedrooms }}</span>\n <span i18n>Bedrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ offer.item.bathrooms }}</span>\n <span i18n>Bathrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ offer.item.receptions }}</span>\n <span i18n>Receptions</span>\n </div>\n </div>\n </div>\n <div class=\"text-right\">\n <div class=\"text-sm\">{{ offer.item.amount | price }}</div>\n </div>\n </div>\n </div>\n <div class=\"hidden md:flex flex-col px-3\"></div>\n </div>\n </div>\n\n <div>\n <div class=\"text-lg font-bold py-2\">Viewing agent</div>\n <hr class=\"mb-2\" />\n @if (agent) {\n <div>\n <rolatech-rich-label label=\"Move-in date\" [title]=\"offer.startDate\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Tenancy duration\" [title]=\"offer.tenancyDuration\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Phone\" [title]=\"agent.phone\"></rolatech-rich-label>\n </div>\n }\n </div>\n </div>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: RichLabelComponent, selector: "rolatech-rich-label", inputs: ["label", "title"] }, { 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: "pipe", type: PricePipe, name: "price" }], deferBlockDependencies: [() => [ThumbnailComponent]] });
1334
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: PropertyManageOfferDetailComponent, isStandalone: true, selector: "rolatech-property-manage-offer-detail", usesInheritance: true, ngImport: i0, template: "@if (offer) {\n <rolatech-toolbar [title]=\"status[offer.status]\" large link=\"../\">\n <div class=\"hidden md:flex gap-2\">\n @if (offer.status.toString() === 'CREATED') {\n <button mat-flat-button (click)=\"accept()\" i18n>Accept</button>\n <button mat-flat-button (click)=\"counter()\" i18n>Counter offer</button>\n <button mat-button (click)=\"reject()\" i18n>Reject</button>\n <button mat-button (click)=\"edit()\" i18n>Edit</button>\n }\n <!-- References -->\n @if (offer.status.toString() === 'HOLDING_DEPOSIT_PAID') {\n <button mat-flat-button (click)=\"rfAccept()\" i18n>References passed</button>\n <button mat-flat-button (click)=\"rfReject()\" i18n>References failed</button>\n }\n </div>\n <div class=\"block md:hidden\">\n <button mat-icon-button [matMenuTriggerFor]=\"moreMenu\">\n <mat-icon>more_vert</mat-icon>\n </button>\n </div>\n </rolatech-toolbar>\n <div class=\"px-4\">\n <div>\n <div class=\"text-lg font-bold py-2\">Viewer</div>\n <hr class=\"mb-2\" />\n <div class=\"flex flex-col md:flex-row gap-1 md:gap-4\">\n <rolatech-rich-label label=\"Name\" [title]=\"name\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Email\" [title]=\"offer.email\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Phone\" [title]=\"offer.phone\"></rolatech-rich-label>\n </div>\n </div>\n <div>\n <div class=\"text-lg font-bold py-2\">Qualification</div>\n <hr class=\"mb-2\" />\n <div class=\"flex flex-col md:flex-row gap-1 md:gap-4\">\n <rolatech-rich-label label=\"Move-in date\" [title]=\"offer.startDate\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Tenancy duration\" [title]=\"offer.tenancyDuration\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Number of tenants\" [title]=\"offer.numberOfTenants\"></rolatech-rich-label>\n </div>\n <div class=\"flex flex-col md:flex-row gap-1 md:gap-4\">\n <rolatech-rich-label label=\"Employment status\" [title]=\"employmentStatus[offer.employmentStatus]\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Employer\" [title]=\"offer.startDate\"></rolatech-rich-label>\n @if (offer.income) {\n <rolatech-rich-label label=\"Annual income\" [title]=\"offer.income\"></rolatech-rich-label>\n }\n </div>\n </div>\n <div>\n <div class=\"text-lg font-bold py-2\">Property details</div>\n <hr class=\"mb-2\" />\n <div class=\"flex items-center py-2\">\n <div class=\"min-w-24 w-24 object-cover aspect-video rounded-md mr-3\">\n @defer {\n <rolatech-thumbnail [src]=\"offer.item.media[0].url\" size=\"medium\" mode=\"clip\"> </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 <div class=\"flex w-full justify-between\">\n <div class=\"flex justify-between w-full\">\n <div class=\"flex flex-col\">\n <div>{{ offer.item.title }}</div>\n <div class=\"inline-flex gap-1 mt-2\">\n <div>\n <span class=\"mr-1\">{{ offer.item.bedrooms }}</span>\n <span i18n>Bedrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ offer.item.bathrooms }}</span>\n <span i18n>Bathrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ offer.item.receptions }}</span>\n <span i18n>Receptions</span>\n </div>\n </div>\n </div>\n <div class=\"text-right\">\n <div class=\"text-sm\">{{ offer.item.amount | price }}</div>\n </div>\n </div>\n </div>\n <div class=\"hidden md:flex flex-col px-3\"></div>\n </div>\n </div>\n\n <div>\n <div class=\"text-lg font-bold py-2\">Viewing agent</div>\n <hr class=\"mb-2\" />\n @if (agent) {\n <div>\n <rolatech-rich-label label=\"Move-in date\" [title]=\"offer.startDate\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Tenancy duration\" [title]=\"offer.tenancyDuration\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Phone\" [title]=\"agent.phone\"></rolatech-rich-label>\n </div>\n }\n </div>\n </div>\n <mat-menu #moreMenu=\"matMenu\" xPosition=\"after\" class=\"divide-y divide-light-900\">\n @if (offer.status.toString() === 'CREATED') {\n <button mat-menu-item (click)=\"accept()\" i18n>Accept</button>\n <button mat-menu-item (click)=\"counter()\" i18n>Counter offer</button>\n <button mat-menu-item (click)=\"reject()\" i18n>Reject</button>\n }\n <!-- References -->\n @if (offer.status.toString() === 'HOLDING_DEPOSIT_PAID') {\n <button mat-menu-item (click)=\"rfAccept()\" i18n>References passed</button>\n <button mat-menu-item (click)=\"rfReject()\" i18n>References failed</button>\n }\n <button mat-menu-item (click)=\"edit()\">Edit</button>\n </mat-menu>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: RichLabelComponent, selector: "rolatech-rich-label", inputs: ["label", "title"] }, { 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: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i4.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i4.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i4.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "pipe", type: PricePipe, name: "price" }], deferBlockDependencies: [() => [ThumbnailComponent]] });
1237
1335
  }
1238
1336
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyManageOfferDetailComponent, decorators: [{
1239
1337
  type: Component,
1240
- args: [{ selector: 'rolatech-property-manage-offer-detail', imports: [CommonModule, ToolbarComponent, RichLabelComponent, ThumbnailComponent, MatButtonModule, PricePipe], template: "@if (offer) {\n <rolatech-toolbar [title]=\"status[offer.status]\" large link=\"../\">\n @if (offer.status.toString() === 'CREATED') {\n <button mat-flat-button (click)=\"accept()\" i18n>Accept</button>\n <button mat-flat-button (click)=\"counter()\" i18n>Counter offer</button>\n <button mat-button (click)=\"reject()\" i18n>Reject</button>\n }\n <!-- References -->\n @if (offer.status.toString() === 'HOLDING_DEPOSIT_PAID') {\n <button mat-flat-button (click)=\"rfAccept()\" i18n>References passed</button>\n <button mat-flat-button (click)=\"rfReject()\" i18n>References failed</button>\n }\n </rolatech-toolbar>\n <div class=\"px-4\">\n <div>\n <div class=\"text-lg font-bold py-2\">Viewer</div>\n <hr class=\"mb-2\" />\n <div class=\"flex flex-col md:flex-row gap-1 md:gap-4\">\n <rolatech-rich-label label=\"Name\" [title]=\"name\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Email\" [title]=\"offer.email\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Phone\" [title]=\"offer.phone\"></rolatech-rich-label>\n </div>\n </div>\n <div>\n <div class=\"text-lg font-bold py-2\">Qualification</div>\n <hr class=\"mb-2\" />\n <div class=\"flex flex-col md:flex-row gap-1 md:gap-4\">\n <rolatech-rich-label label=\"Move-in date\" [title]=\"offer.startDate\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Tenancy duration\" [title]=\"offer.tenancyDuration\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Number of tenants\" [title]=\"offer.numberOfTenants\"></rolatech-rich-label>\n </div>\n <div class=\"flex flex-col md:flex-row gap-1 md:gap-4\">\n <rolatech-rich-label label=\"Employment status\" [title]=\"employmentStatus[offer.employmentStatus]\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Employer\" [title]=\"offer.startDate\"></rolatech-rich-label>\n @if (offer.income) {\n <rolatech-rich-label label=\"Annual income\" [title]=\"offer.income\"></rolatech-rich-label>\n }\n </div>\n </div>\n <div>\n <div class=\"text-lg font-bold py-2\">Property details</div>\n <hr class=\"mb-2\" />\n <div class=\"flex items-center py-2\">\n <div class=\"min-w-24 w-24 object-cover aspect-video rounded-md mr-3\">\n @defer {\n <rolatech-thumbnail [src]=\"offer.item.media[0].url\" size=\"medium\" mode=\"clip\"> </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 <div class=\"flex w-full justify-between\">\n <div class=\"flex justify-between w-full\">\n <div class=\"flex flex-col\">\n <div>{{ offer.item.title }}</div>\n <div class=\"inline-flex gap-1 mt-2\">\n <div>\n <span class=\"mr-1\">{{ offer.item.bedrooms }}</span>\n <span i18n>Bedrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ offer.item.bathrooms }}</span>\n <span i18n>Bathrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ offer.item.receptions }}</span>\n <span i18n>Receptions</span>\n </div>\n </div>\n </div>\n <div class=\"text-right\">\n <div class=\"text-sm\">{{ offer.item.amount | price }}</div>\n </div>\n </div>\n </div>\n <div class=\"hidden md:flex flex-col px-3\"></div>\n </div>\n </div>\n\n <div>\n <div class=\"text-lg font-bold py-2\">Viewing agent</div>\n <hr class=\"mb-2\" />\n @if (agent) {\n <div>\n <rolatech-rich-label label=\"Move-in date\" [title]=\"offer.startDate\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Tenancy duration\" [title]=\"offer.tenancyDuration\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Phone\" [title]=\"agent.phone\"></rolatech-rich-label>\n </div>\n }\n </div>\n </div>\n}\n" }]
1338
+ args: [{ selector: 'rolatech-property-manage-offer-detail', imports: [
1339
+ CommonModule,
1340
+ ToolbarComponent,
1341
+ RichLabelComponent,
1342
+ ThumbnailComponent,
1343
+ MatButtonModule,
1344
+ MatIcon,
1345
+ MatMenuModule,
1346
+ PricePipe,
1347
+ ], template: "@if (offer) {\n <rolatech-toolbar [title]=\"status[offer.status]\" large link=\"../\">\n <div class=\"hidden md:flex gap-2\">\n @if (offer.status.toString() === 'CREATED') {\n <button mat-flat-button (click)=\"accept()\" i18n>Accept</button>\n <button mat-flat-button (click)=\"counter()\" i18n>Counter offer</button>\n <button mat-button (click)=\"reject()\" i18n>Reject</button>\n <button mat-button (click)=\"edit()\" i18n>Edit</button>\n }\n <!-- References -->\n @if (offer.status.toString() === 'HOLDING_DEPOSIT_PAID') {\n <button mat-flat-button (click)=\"rfAccept()\" i18n>References passed</button>\n <button mat-flat-button (click)=\"rfReject()\" i18n>References failed</button>\n }\n </div>\n <div class=\"block md:hidden\">\n <button mat-icon-button [matMenuTriggerFor]=\"moreMenu\">\n <mat-icon>more_vert</mat-icon>\n </button>\n </div>\n </rolatech-toolbar>\n <div class=\"px-4\">\n <div>\n <div class=\"text-lg font-bold py-2\">Viewer</div>\n <hr class=\"mb-2\" />\n <div class=\"flex flex-col md:flex-row gap-1 md:gap-4\">\n <rolatech-rich-label label=\"Name\" [title]=\"name\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Email\" [title]=\"offer.email\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Phone\" [title]=\"offer.phone\"></rolatech-rich-label>\n </div>\n </div>\n <div>\n <div class=\"text-lg font-bold py-2\">Qualification</div>\n <hr class=\"mb-2\" />\n <div class=\"flex flex-col md:flex-row gap-1 md:gap-4\">\n <rolatech-rich-label label=\"Move-in date\" [title]=\"offer.startDate\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Tenancy duration\" [title]=\"offer.tenancyDuration\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Number of tenants\" [title]=\"offer.numberOfTenants\"></rolatech-rich-label>\n </div>\n <div class=\"flex flex-col md:flex-row gap-1 md:gap-4\">\n <rolatech-rich-label label=\"Employment status\" [title]=\"employmentStatus[offer.employmentStatus]\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Employer\" [title]=\"offer.startDate\"></rolatech-rich-label>\n @if (offer.income) {\n <rolatech-rich-label label=\"Annual income\" [title]=\"offer.income\"></rolatech-rich-label>\n }\n </div>\n </div>\n <div>\n <div class=\"text-lg font-bold py-2\">Property details</div>\n <hr class=\"mb-2\" />\n <div class=\"flex items-center py-2\">\n <div class=\"min-w-24 w-24 object-cover aspect-video rounded-md mr-3\">\n @defer {\n <rolatech-thumbnail [src]=\"offer.item.media[0].url\" size=\"medium\" mode=\"clip\"> </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 <div class=\"flex w-full justify-between\">\n <div class=\"flex justify-between w-full\">\n <div class=\"flex flex-col\">\n <div>{{ offer.item.title }}</div>\n <div class=\"inline-flex gap-1 mt-2\">\n <div>\n <span class=\"mr-1\">{{ offer.item.bedrooms }}</span>\n <span i18n>Bedrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ offer.item.bathrooms }}</span>\n <span i18n>Bathrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ offer.item.receptions }}</span>\n <span i18n>Receptions</span>\n </div>\n </div>\n </div>\n <div class=\"text-right\">\n <div class=\"text-sm\">{{ offer.item.amount | price }}</div>\n </div>\n </div>\n </div>\n <div class=\"hidden md:flex flex-col px-3\"></div>\n </div>\n </div>\n\n <div>\n <div class=\"text-lg font-bold py-2\">Viewing agent</div>\n <hr class=\"mb-2\" />\n @if (agent) {\n <div>\n <rolatech-rich-label label=\"Move-in date\" [title]=\"offer.startDate\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Tenancy duration\" [title]=\"offer.tenancyDuration\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Phone\" [title]=\"agent.phone\"></rolatech-rich-label>\n </div>\n }\n </div>\n </div>\n <mat-menu #moreMenu=\"matMenu\" xPosition=\"after\" class=\"divide-y divide-light-900\">\n @if (offer.status.toString() === 'CREATED') {\n <button mat-menu-item (click)=\"accept()\" i18n>Accept</button>\n <button mat-menu-item (click)=\"counter()\" i18n>Counter offer</button>\n <button mat-menu-item (click)=\"reject()\" i18n>Reject</button>\n }\n <!-- References -->\n @if (offer.status.toString() === 'HOLDING_DEPOSIT_PAID') {\n <button mat-menu-item (click)=\"rfAccept()\" i18n>References passed</button>\n <button mat-menu-item (click)=\"rfReject()\" i18n>References failed</button>\n }\n <button mat-menu-item (click)=\"edit()\">Edit</button>\n </mat-menu>\n}\n" }]
1241
1348
  }] });
1242
1349
 
1243
1350
  const propertyManageOffersRoutes = [
@@ -2217,6 +2324,7 @@ class PropertyOfferComponent extends BaseComponent {
2217
2324
  authService = inject(AuthService);
2218
2325
  authUserService = inject(AuthUserService);
2219
2326
  propertyService = inject(PropertyService);
2327
+ propertyOfferService = inject(PropertyOfferService);
2220
2328
  offer = {
2221
2329
  firstName: '',
2222
2330
  lastName: '',
@@ -2288,7 +2396,7 @@ class PropertyOfferComponent extends BaseComponent {
2288
2396
  onResidencyStatusSelect(event) { }
2289
2397
  sendRequest() {
2290
2398
  this.sending = true;
2291
- this.propertyService.makeOffer(this.id, this.offer).subscribe({
2399
+ this.propertyOfferService.makeOffer(this.id, this.offer).subscribe({
2292
2400
  next: (res) => {
2293
2401
  this.sending = false;
2294
2402
  this.snackBarService.open('Sent successfully');
@@ -2339,14 +2447,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
2339
2447
 
2340
2448
  class PropertyOfferIndexComponent extends BaseComponent {
2341
2449
  propertyService = inject(PropertyService);
2342
- offers;
2450
+ propertyOfferService = inject(PropertyOfferService);
2343
2451
  offerType = PropertyOfferType;
2344
2452
  offerStatus = PropertyOfferStatus;
2345
2453
  filter = false;
2346
- filterOptions = {
2347
- type: '',
2348
- status: '',
2349
- };
2350
2454
  select = 0;
2351
2455
  links = [
2352
2456
  {
@@ -2374,54 +2478,64 @@ class PropertyOfferIndexComponent extends BaseComponent {
2374
2478
  status: 'cancelled',
2375
2479
  },
2376
2480
  ];
2481
+ loading = false;
2482
+ offers = signal([], ...(ngDevMode ? [{ debugName: "offers" }] : []));
2483
+ meta;
2484
+ pageEvent;
2485
+ length = 100;
2486
+ pageSize = 15;
2487
+ pageSizeOptions = [5, 10, 25, 100];
2488
+ pageIndex = signal(0, ...(ngDevMode ? [{ debugName: "pageIndex" }] : []));
2377
2489
  ngOnInit() {
2378
- this.findOffers();
2379
- this.route.queryParams.subscribe(({ status }) => {
2380
- this.select = this.links.findIndex((item) => item.status === status);
2490
+ const sub = this.route.queryParamMap
2491
+ .pipe(map((p) => {
2492
+ const page = p.get('page') ? Number(p.get('page')) : 1;
2493
+ this.pageIndex.set(Math.max(page - 1, 0));
2494
+ const status = p.get('status') || undefined;
2495
+ let filter = '';
2381
2496
  if (status) {
2382
- this.filterOptions.status = status.toUpperCase();
2497
+ this.select = this.links.findIndex((item) => item.status === status);
2498
+ filter = `status:${status?.toUpperCase()}`;
2383
2499
  }
2384
- else {
2385
- delete this.filterOptions.status;
2386
- }
2387
- this.findOffers();
2388
- });
2389
- }
2390
- findOffers() {
2391
- const options = {
2392
- sort: 'updatedAt desc',
2393
- };
2394
- const filterString = this.convertFilterOptions(this.filterOptions);
2395
- if (filterString) {
2396
- options['filter'] = filterString;
2397
- }
2398
- this.propertyService.findOffersByUser(options).subscribe({
2500
+ return {
2501
+ page,
2502
+ filter,
2503
+ limit: p.get('limit') ? Number(p.get('limit')) : 15,
2504
+ sort: p.get('sort') || undefined,
2505
+ };
2506
+ }),
2507
+ // Cheap deep compare via JSON to avoid spam calls when nothing changed
2508
+ map((o) => JSON.stringify(o)), distinctUntilChanged(), map((s) => JSON.parse(s)), switchMap((params) => {
2509
+ this.loading = true;
2510
+ params['sort'] = 'updatedAt desc';
2511
+ return this.propertyOfferService.findOffers(params).pipe(finalize(() => (this.loading = false)));
2512
+ }))
2513
+ .subscribe({
2399
2514
  next: (res) => {
2400
- this.offers = res.data;
2515
+ this.offers.set(res.data);
2516
+ this.meta = res.meta;
2517
+ this.length = res.meta.pagination.count;
2518
+ },
2519
+ error: () => {
2520
+ this.offers.set([]);
2521
+ this.length = 0;
2401
2522
  },
2402
2523
  });
2403
- }
2404
- findProperties(ids) { }
2405
- resetFilter() {
2406
- this.filterOptions = {
2407
- type: '',
2408
- };
2409
- this.filter = false;
2410
- this.findOffers();
2524
+ // // auto-unsubscribe on destroy
2525
+ this.destroyRef.onDestroy(() => sub.unsubscribe());
2411
2526
  }
2412
2527
  statusCompareFn(t1, t2) {
2413
2528
  return t1 === t2;
2414
2529
  }
2415
- convertFilterOptions(jsonObj) {
2416
- return Object.entries(jsonObj)
2417
- .filter(([key, value]) => value !== '' && value !== undefined)
2418
- .map(([key, value]) => {
2419
- return `${key}:${value}`;
2420
- })
2421
- .join(',');
2530
+ onPage(e) {
2531
+ this.router.navigate([], {
2532
+ queryParams: { page: e.pageIndex + 1, limit: e.pageSize },
2533
+ queryParamsHandling: 'merge',
2534
+ replaceUrl: true, // optional: avoid stacking history on every page click
2535
+ });
2422
2536
  }
2423
2537
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyOfferIndexComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2424
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: PropertyOfferIndexComponent, isStandalone: true, selector: "rolatech-property-offer-index", usesInheritance: true, ngImport: i0, template: "<rolatech-container>\n <rolatech-toolbar title=\"Offers\" large> </rolatech-toolbar>\n <rolatech-tabs [select]=\"select\">\n @for (item of links; track item) {\n @if (item.status) {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\" [queryParams]=\"{ status: item.status }\"></rolatech-tab>\n } @else {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\"></rolatech-tab>\n }\n }\n </rolatech-tabs>\n <rolatech-list>\n @if (offers) {\n @for (item of offers; track item) {\n <rolatech-property-offer-item [routerLink]=\"['./', item.id]\" [offer]=\"item\"></rolatech-property-offer-item>\n }\n } @else {\n <rolatech-empty></rolatech-empty>\n }\n </rolatech-list>\n</rolatech-container>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: TabsComponent, selector: "rolatech-tabs", inputs: ["select", "loading"], outputs: ["selectChange"] }, { kind: "component", type: TabComponent, selector: "rolatech-tab", inputs: ["label"] }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: ListComponent, selector: "rolatech-list" }, { kind: "component", type: EmptyComponent, selector: "rolatech-empty" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "ngmodule", type: MatOptionModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: PropertyOfferItemComponent, selector: "rolatech-property-offer-item", inputs: ["offer"] }], encapsulation: i0.ViewEncapsulation.None });
2538
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: PropertyOfferIndexComponent, isStandalone: true, selector: "rolatech-property-offer-index", usesInheritance: true, ngImport: i0, template: "<rolatech-container>\n <rolatech-toolbar title=\"Offers\" large> </rolatech-toolbar>\n <rolatech-tabs [select]=\"select\">\n @for (item of links; track item) {\n @if (item.status) {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\" [queryParams]=\"{ status: item.status }\"></rolatech-tab>\n } @else {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\"></rolatech-tab>\n }\n }\n </rolatech-tabs>\n @if (loading) {\n <div class=\"divide-y divide-[--rt-10-percent-layer] flex flex-col\">\n @for (row of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; track row) {\n <rolatech-offer-item-skeleton></rolatech-offer-item-skeleton>\n }\n </div>\n } @else {\n <rolatech-list>\n @if (offers() && offers().length > 0) {\n @for (item of offers(); track item) {\n <rolatech-property-offer-item [routerLink]=\"['./', item.id]\" [offer]=\"item\"></rolatech-property-offer-item>\n }\n } @else {\n <rolatech-empty></rolatech-empty>\n }\n </rolatech-list>\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</rolatech-container>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: TabsComponent, selector: "rolatech-tabs", inputs: ["select", "loading"], outputs: ["selectChange"] }, { kind: "component", type: TabComponent, selector: "rolatech-tab", inputs: ["label"] }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: ListComponent, selector: "rolatech-list" }, { kind: "component", type: EmptyComponent, selector: "rolatech-empty" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "ngmodule", type: MatOptionModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: PropertyOfferItemComponent, selector: "rolatech-property-offer-item", inputs: ["offer"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i2$2.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "component", type: OfferItemSkeleton, selector: "rolatech-offer-item-skeleton" }], encapsulation: i0.ViewEncapsulation.None });
2425
2539
  }
2426
2540
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyOfferIndexComponent, decorators: [{
2427
2541
  type: Component,
@@ -2444,7 +2558,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
2444
2558
  MatSelectModule,
2445
2559
  MatButtonModule,
2446
2560
  PropertyOfferItemComponent,
2447
- ], encapsulation: ViewEncapsulation.None, template: "<rolatech-container>\n <rolatech-toolbar title=\"Offers\" large> </rolatech-toolbar>\n <rolatech-tabs [select]=\"select\">\n @for (item of links; track item) {\n @if (item.status) {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\" [queryParams]=\"{ status: item.status }\"></rolatech-tab>\n } @else {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\"></rolatech-tab>\n }\n }\n </rolatech-tabs>\n <rolatech-list>\n @if (offers) {\n @for (item of offers; track item) {\n <rolatech-property-offer-item [routerLink]=\"['./', item.id]\" [offer]=\"item\"></rolatech-property-offer-item>\n }\n } @else {\n <rolatech-empty></rolatech-empty>\n }\n </rolatech-list>\n</rolatech-container>\n" }]
2561
+ MatPaginatorModule,
2562
+ OfferItemSkeleton,
2563
+ ], encapsulation: ViewEncapsulation.None, template: "<rolatech-container>\n <rolatech-toolbar title=\"Offers\" large> </rolatech-toolbar>\n <rolatech-tabs [select]=\"select\">\n @for (item of links; track item) {\n @if (item.status) {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\" [queryParams]=\"{ status: item.status }\"></rolatech-tab>\n } @else {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\"></rolatech-tab>\n }\n }\n </rolatech-tabs>\n @if (loading) {\n <div class=\"divide-y divide-[--rt-10-percent-layer] flex flex-col\">\n @for (row of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; track row) {\n <rolatech-offer-item-skeleton></rolatech-offer-item-skeleton>\n }\n </div>\n } @else {\n <rolatech-list>\n @if (offers() && offers().length > 0) {\n @for (item of offers(); track item) {\n <rolatech-property-offer-item [routerLink]=\"['./', item.id]\" [offer]=\"item\"></rolatech-property-offer-item>\n }\n } @else {\n <rolatech-empty></rolatech-empty>\n }\n </rolatech-list>\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</rolatech-container>\n" }]
2448
2564
  }] });
2449
2565
 
2450
2566
  class PropertyViewingItemComponent {
@@ -2582,6 +2698,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
2582
2698
 
2583
2699
  class PropertyOfferDetailComponent extends BaseComponent {
2584
2700
  propertyService = inject(PropertyService);
2701
+ propertyOfferService = inject(PropertyOfferService);
2585
2702
  authUserService = inject(AuthUserService);
2586
2703
  paymentService = inject(PaymentService);
2587
2704
  offer;
@@ -2608,7 +2725,7 @@ class PropertyOfferDetailComponent extends BaseComponent {
2608
2725
  this.route.queryParams.subscribe(async (params) => {
2609
2726
  const sessionId = params['session_id'];
2610
2727
  if (sessionId) {
2611
- this.propertyService.checkOfferPaymentStatus(this.id, sessionId).subscribe({
2728
+ this.propertyOfferService.checkOfferPaymentStatus(this.id, sessionId).subscribe({
2612
2729
  next: (res) => {
2613
2730
  if (res.status === 'paid') {
2614
2731
  this.offer.status = PropertyOfferStatus.HOLDING_DEPOSIT_PAID;
@@ -2623,7 +2740,7 @@ class PropertyOfferDetailComponent extends BaseComponent {
2623
2740
  this.checkouting = false;
2624
2741
  }
2625
2742
  get(id) {
2626
- this.propertyService.getOffer(id).subscribe({
2743
+ this.propertyOfferService.getOffer(id).subscribe({
2627
2744
  next: (res) => {
2628
2745
  this.offer = res.data;
2629
2746
  this.getProperty(this.offer.propertyId);
@@ -2635,7 +2752,7 @@ class PropertyOfferDetailComponent extends BaseComponent {
2635
2752
  timeline() {
2636
2753
  this.info = true;
2637
2754
  this.loadingTimeline = true;
2638
- this.propertyService.offerTimeline(this.id).subscribe({
2755
+ this.propertyOfferService.offerTimeline(this.id).subscribe({
2639
2756
  next: (res) => {
2640
2757
  this.timelineData = res.data;
2641
2758
  this.loadingTimeline = false;
@@ -2661,7 +2778,7 @@ class PropertyOfferDetailComponent extends BaseComponent {
2661
2778
  });
2662
2779
  }
2663
2780
  cancel() {
2664
- this.propertyService.cancelOffer(this.id).subscribe({
2781
+ this.propertyOfferService.cancelOffer(this.id).subscribe({
2665
2782
  next: (res) => {
2666
2783
  this.offer.status = 'CANCELLED';
2667
2784
  this.snackBarService.open('Cancelled');
@@ -2714,7 +2831,7 @@ class PropertyOfferDetailComponent extends BaseComponent {
2714
2831
  successUrl: window.location.href + '?session_id={CHECKOUT_SESSION_ID}',
2715
2832
  cancelUrl: window.location.href,
2716
2833
  };
2717
- this.propertyService.createSecurityDepositCheckout(this.id, data).subscribe({
2834
+ this.propertyOfferService.createSecurityDepositCheckout(this.id, data).subscribe({
2718
2835
  next: (res) => {
2719
2836
  window.location.href = res.data.checkoutUrl;
2720
2837
  },
@@ -2857,7 +2974,7 @@ const propertyRoutes = [
2857
2974
  children: [
2858
2975
  {
2859
2976
  path: '',
2860
- loadComponent: () => import('./rolatech-angular-property-property-index.component-Cm9kerTY.mjs').then((x) => x.PropertyIndexComponent),
2977
+ loadComponent: () => import('./rolatech-angular-property-property-index.component-CxrKoVak.mjs').then((x) => x.PropertyIndexComponent),
2861
2978
  },
2862
2979
  ],
2863
2980
  },
@@ -2902,18 +3019,14 @@ const propertyRoutes = [
2902
3019
  },
2903
3020
  ];
2904
3021
 
2905
- class PropertyManageIndexComponent {
3022
+ class PropertyManageIndexComponent extends BaseComponent {
2906
3023
  hasClass = true;
3024
+ propertyService = inject(PropertyService);
3025
+ propertySearchService = inject(PropertySearchService);
3026
+ util = inject(PropertyUtil);
2907
3027
  paginator = viewChild(MatPaginator, ...(ngDevMode ? [{ debugName: "paginator" }] : []));
2908
- dialog = inject(MatDialog);
2909
3028
  snackBar = inject(MatSnackBar);
2910
- router = inject(Router);
2911
- destroyRef = inject(DestroyRef);
2912
- route = inject(ActivatedRoute);
2913
3029
  gridView = true;
2914
- util = inject(PropertyUtil);
2915
- propertyService = inject(PropertyService);
2916
- propertySearchService = inject(PropertySearchService);
2917
3030
  isSearch = false;
2918
3031
  // properties: Property[] = [];
2919
3032
  properties = signal([], ...(ngDevMode ? [{ debugName: "properties" }] : []));
@@ -3031,8 +3144,8 @@ class PropertyManageIndexComponent {
3031
3144
  replaceUrl: true, // optional: avoid stacking history on every page click
3032
3145
  });
3033
3146
  }
3034
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyManageIndexComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3035
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.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=\"bg-[--rt-rasised-background] h-full\">\n <!-- <rolatech-property-manage-filter></rolatech-property-manage-filter> -->\n <div class=\"flex flex-wrap px-2\">\n @for (row of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; track row) {\n <rolatech-property-manage-item-skeleton></rolatech-property-manage-item-skeleton>\n }\n </div>\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 px-2\">\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: i1$6.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: PropertyManageItemComponent, selector: "rolatech-property-manage-item", inputs: ["property", "thumbnail", "list"] }, { kind: "component", type: SearchBar, selector: "rolatech-search-bar", inputs: ["show"], outputs: ["showChange", "search", "close"] }, { kind: "component", type: PropertyManageItemSkeleton, selector: "rolatech-property-manage-item-skeleton", inputs: ["loading", "list"] }], encapsulation: i0.ViewEncapsulation.None });
3147
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyManageIndexComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
3148
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.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 }], usesInheritance: 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=\"bg-[--rt-rasised-background] h-full\">\n <div class=\"flex flex-wrap px-2\">\n @for (row of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; track row) {\n <rolatech-property-manage-item-skeleton></rolatech-property-manage-item-skeleton>\n }\n </div>\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 px-2\">\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: i2$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: PropertyManageItemComponent, selector: "rolatech-property-manage-item", inputs: ["property", "thumbnail", "list"] }, { kind: "component", type: SearchBar, selector: "rolatech-search-bar", inputs: ["show"], outputs: ["showChange", "search", "close"] }, { kind: "component", type: PropertyManageItemSkeleton, selector: "rolatech-property-manage-item-skeleton", inputs: ["loading", "list"] }], encapsulation: i0.ViewEncapsulation.None });
3036
3149
  }
3037
3150
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyManageIndexComponent, decorators: [{
3038
3151
  type: Component,
@@ -3047,7 +3160,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
3047
3160
  PropertyManageItemComponent,
3048
3161
  SearchBar,
3049
3162
  PropertyManageItemSkeleton,
3050
- ], 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=\"bg-[--rt-rasised-background] h-full\">\n <!-- <rolatech-property-manage-filter></rolatech-property-manage-filter> -->\n <div class=\"flex flex-wrap px-2\">\n @for (row of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; track row) {\n <rolatech-property-manage-item-skeleton></rolatech-property-manage-item-skeleton>\n }\n </div>\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 px-2\">\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"] }]
3163
+ ], 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=\"bg-[--rt-rasised-background] h-full\">\n <div class=\"flex flex-wrap px-2\">\n @for (row of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; track row) {\n <rolatech-property-manage-item-skeleton></rolatech-property-manage-item-skeleton>\n }\n </div>\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 px-2\">\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"] }]
3051
3164
  }], propDecorators: { hasClass: [{
3052
3165
  type: HostBinding,
3053
3166
  args: ['class.rolatech-property-manage-index']
@@ -3762,7 +3875,7 @@ class PropertyManageFeaturesComponent extends BaseComponent {
3762
3875
  return binding;
3763
3876
  }
3764
3877
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyManageFeaturesComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
3765
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: PropertyManageFeaturesComponent, isStandalone: true, selector: "rolatech-property-manage-features", usesInheritance: true, ngImport: i0, template: "<rolatech-property-manage-content>\n <rolatech-toolbar title=\"Features\" class=\"hidden md:block\" divider></rolatech-toolbar>\n <div>\n @for (feature of features; track $index) {\n <div>\n <h4>{{ feature.name }}</h4>\n @for (value of feature.values; track $index) {\n <mat-checkbox\n [checked]=\"selected[feature.id] ? selected[feature.id].includes(value.id) : false\"\n (change)=\"toggleValue(feature.id, value.id, $event.checked)\"\n >\n {{ value.name }}\n </mat-checkbox>\n }\n </div>\n }\n </div>\n\n <!-- @for (item of features; track item) {\n <section class=\"example-section\">\n <span class=\"example-list-section\">\n <h4>{{ item.name }}</h4>\n <mat-checkbox\n class=\"example-margin\"\n [checked]=\"item.selected\"\n [indeterminate]=\"partiallyComplete(item)()\"\n (change)=\"sectionChange(item, $event.checked)\"\n >\n {{ item.name }}\n </mat-checkbox>\n </span>\n <div class=\"example-list-section\">\n <div>\n @for (value of item.values; track value; let i = $index) {\n <mat-checkbox [checked]=\"value.selected\" (change)=\"sectionChange(item, $event.checked, i)\">\n {{ value.name }}\n </mat-checkbox>\n }\n </div>\n </div>\n </section>\n } -->\n <!-- <div class=\"px-3 mb-3\">\n @for (item of features; track $index) {\n <div class=\"text-xl font-bold py-2\">{{ item.name }}</div>\n @for (value of item.values; track value; let i = $index) {\n <mat-checkbox\n class=\"text-lg font-medium\"\n (click)=\"$event.stopPropagation()\"\n [checked]=\"value.selected\"\n (change)=\"sectionChange($event.checked, i)\"\n >\n {{ value.name }}\n </mat-checkbox>\n }\n }\n </div> -->\n <button mat-flat-button (click)=\"save()\" i18n>Save</button>\n</rolatech-property-manage-content>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: PropertyManageContentComponent, selector: "rolatech-property-manage-content" }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i1$7.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { 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"] }] });
3878
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: PropertyManageFeaturesComponent, isStandalone: true, selector: "rolatech-property-manage-features", usesInheritance: true, ngImport: i0, template: "<rolatech-property-manage-content>\n <rolatech-toolbar title=\"Features\" class=\"hidden md:block\" divider></rolatech-toolbar>\n <div>\n @for (feature of features; track $index) {\n <div>\n <h4>{{ feature.name }}</h4>\n @for (value of feature.values; track $index) {\n <mat-checkbox\n [checked]=\"selected[feature.id] ? selected[feature.id].includes(value.id) : false\"\n (change)=\"toggleValue(feature.id, value.id, $event.checked)\"\n >\n {{ value.name }}\n </mat-checkbox>\n }\n </div>\n }\n </div>\n\n <!-- @for (item of features; track item) {\n <section class=\"example-section\">\n <span class=\"example-list-section\">\n <h4>{{ item.name }}</h4>\n <mat-checkbox\n class=\"example-margin\"\n [checked]=\"item.selected\"\n [indeterminate]=\"partiallyComplete(item)()\"\n (change)=\"sectionChange(item, $event.checked)\"\n >\n {{ item.name }}\n </mat-checkbox>\n </span>\n <div class=\"example-list-section\">\n <div>\n @for (value of item.values; track value; let i = $index) {\n <mat-checkbox [checked]=\"value.selected\" (change)=\"sectionChange(item, $event.checked, i)\">\n {{ value.name }}\n </mat-checkbox>\n }\n </div>\n </div>\n </section>\n } -->\n <!-- <div class=\"px-3 mb-3\">\n @for (item of features; track $index) {\n <div class=\"text-xl font-bold py-2\">{{ item.name }}</div>\n @for (value of item.values; track value; let i = $index) {\n <mat-checkbox\n class=\"text-lg font-medium\"\n (click)=\"$event.stopPropagation()\"\n [checked]=\"value.selected\"\n (change)=\"sectionChange($event.checked, i)\"\n >\n {{ value.name }}\n </mat-checkbox>\n }\n }\n </div> -->\n <button mat-flat-button (click)=\"save()\" i18n>Save</button>\n</rolatech-property-manage-content>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: PropertyManageContentComponent, selector: "rolatech-property-manage-content" }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i1$6.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { 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"] }] });
3766
3879
  }
3767
3880
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyManageFeaturesComponent, decorators: [{
3768
3881
  type: Component,
@@ -4780,7 +4893,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
4780
4893
  const propertyManageViewingsRoutes = [
4781
4894
  {
4782
4895
  path: '',
4783
- loadComponent: () => import('./rolatech-angular-property-property-manage-viewings-index.component-B18t09BQ.mjs').then((x) => x.PropertyManageViewingsIndexComponent),
4896
+ loadComponent: () => import('./rolatech-angular-property-property-manage-viewings-index.component-BeqUutwr.mjs').then((x) => x.PropertyManageViewingsIndexComponent),
4784
4897
  },
4785
4898
  {
4786
4899
  path: ':id',
@@ -4816,12 +4929,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
4816
4929
  args: ['class.rolatech-letting-manage-item']
4817
4930
  }], letting: [{ type: i0.Input, args: [{ isSignal: true, alias: "letting", required: true }] }], thumbnail: [{ type: i0.Input, args: [{ isSignal: true, alias: "thumbnail", required: false }] }], list: [{ type: i0.Input, args: [{ isSignal: true, alias: "list", required: false }] }] } });
4818
4931
 
4819
- class LettingManageIndex {
4932
+ class LettingManageIndex extends BaseComponent {
4820
4933
  propertyService = inject(PropertyService);
4821
4934
  propertySearchService = inject(PropertySearchService);
4822
- router = inject(Router);
4823
- destroyRef = inject(DestroyRef);
4824
- route = inject(ActivatedRoute);
4825
4935
  loading = false;
4826
4936
  lettings = signal([], ...(ngDevMode ? [{ debugName: "lettings" }] : []));
4827
4937
  pageEvent;
@@ -4889,8 +4999,8 @@ class LettingManageIndex {
4889
4999
  replaceUrl: true, // optional: avoid stacking history on every page click
4890
5000
  });
4891
5001
  }
4892
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: LettingManageIndex, deps: [], target: i0.ɵɵFactoryTarget.Component });
4893
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: LettingManageIndex, isStandalone: true, selector: "rolatech-letting-manage-index", ngImport: i0, template: "<rolatech-toolbar title=\"Lettings\"> </rolatech-toolbar>\n@if (loading) {\n<div class=\"bg-[--rt-rasised-background] h-full\">\n <!-- <rolatech-property-manage-filter></rolatech-property-manage-filter> -->\n <div class=\"flex flex-wrap px-2\">\n @for (row of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; track row) {\n <rolatech-property-manage-item-skeleton></rolatech-property-manage-item-skeleton>\n }\n </div>\n</div>\n} @else {\n<div class=\"bg-[--rt-rasised-background] h-full\">\n <div class=\"flex flex-wrap px-2\">\n @for (item of lettings(); track $index) {\n <rolatech-letting-manage-item [letting]=\"item\" routerLink=\"./{{ item.id }}\"></rolatech-letting-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: ["rolatech-letting-manage-index{display:flex;flex-direction:column;--rt-letting-view-items-per-row: 1;--rt-property-view-items-per-row: 1}@media(min-width:600px){rolatech-letting-manage-index{--rt-letting-view-items-per-row: 2;--rt-property-view-items-per-row: 2}}@media(min-width:768px){rolatech-letting-manage-index{--rt-letting-view-items-per-row: 3;--rt-property-view-items-per-row: 3}}@media(min-width:1280px){rolatech-letting-manage-index{--rt-letting-view-items-per-row: 3;--rt-property-view-items-per-row: 3}}@media(min-width:1536px){rolatech-letting-manage-index{--rt-letting-view-items-per-row: 4;--rt-property-view-items-per-row: 4}}@media(min-width:1920px){rolatech-letting-manage-index{--rt-letting-view-items-per-row: 5;--rt-property-view-items-per-row: 5}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: LettingManageItem, selector: "rolatech-letting-manage-item", inputs: ["letting", "thumbnail", "list"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i1$6.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "component", type: PropertyManageItemSkeleton, selector: "rolatech-property-manage-item-skeleton", inputs: ["loading", "list"] }], encapsulation: i0.ViewEncapsulation.None });
5002
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: LettingManageIndex, deps: null, target: i0.ɵɵFactoryTarget.Component });
5003
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: LettingManageIndex, isStandalone: true, selector: "rolatech-letting-manage-index", usesInheritance: true, ngImport: i0, template: "<rolatech-toolbar title=\"Lettings\"> </rolatech-toolbar>\n@if (loading) {\n<div class=\"bg-[--rt-rasised-background] h-full\">\n <!-- <rolatech-property-manage-filter></rolatech-property-manage-filter> -->\n <div class=\"flex flex-wrap px-2\">\n @for (row of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; track row) {\n <rolatech-property-manage-item-skeleton></rolatech-property-manage-item-skeleton>\n }\n </div>\n</div>\n} @else {\n<div class=\"bg-[--rt-rasised-background] h-full\">\n <div class=\"flex flex-wrap px-2\">\n @for (item of lettings(); track $index) {\n <rolatech-letting-manage-item [letting]=\"item\" routerLink=\"./{{ item.id }}\"></rolatech-letting-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: ["rolatech-letting-manage-index{display:flex;flex-direction:column;--rt-letting-view-items-per-row: 1;--rt-property-view-items-per-row: 1}@media(min-width:600px){rolatech-letting-manage-index{--rt-letting-view-items-per-row: 2;--rt-property-view-items-per-row: 2}}@media(min-width:768px){rolatech-letting-manage-index{--rt-letting-view-items-per-row: 3;--rt-property-view-items-per-row: 3}}@media(min-width:1280px){rolatech-letting-manage-index{--rt-letting-view-items-per-row: 3;--rt-property-view-items-per-row: 3}}@media(min-width:1536px){rolatech-letting-manage-index{--rt-letting-view-items-per-row: 4;--rt-property-view-items-per-row: 4}}@media(min-width:1920px){rolatech-letting-manage-index{--rt-letting-view-items-per-row: 5;--rt-property-view-items-per-row: 5}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: LettingManageItem, selector: "rolatech-letting-manage-item", inputs: ["letting", "thumbnail", "list"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i2$2.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "component", type: PropertyManageItemSkeleton, selector: "rolatech-property-manage-item-skeleton", inputs: ["loading", "list"] }], encapsulation: i0.ViewEncapsulation.None });
4894
5004
  }
4895
5005
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: LettingManageIndex, decorators: [{
4896
5006
  type: Component,
@@ -5219,6 +5329,7 @@ class LettingManageOfferRequest extends BaseComponent {
5219
5329
  authService = inject(AuthService);
5220
5330
  authUserService = inject(AuthUserService);
5221
5331
  propertyService = inject(PropertyService);
5332
+ propertyOfferService = inject(PropertyOfferService);
5222
5333
  offer = {
5223
5334
  startDate: '',
5224
5335
  notes: '',
@@ -5227,7 +5338,6 @@ class LettingManageOfferRequest extends BaseComponent {
5227
5338
  get formattedAmount() {
5228
5339
  return this.offer.amount.toFixed(2); // equivalent to | number:'1.2-2'
5229
5340
  }
5230
- ;
5231
5341
  property;
5232
5342
  minDate = new Date();
5233
5343
  sending = false;
@@ -5256,7 +5366,7 @@ class LettingManageOfferRequest extends BaseComponent {
5256
5366
  this.propertyService.findTenants({}).subscribe({
5257
5367
  next: (res) => {
5258
5368
  this.tenants = res.data;
5259
- }
5369
+ },
5260
5370
  });
5261
5371
  }
5262
5372
  onCategorySelect(event) {
@@ -5265,7 +5375,7 @@ class LettingManageOfferRequest extends BaseComponent {
5265
5375
  onResidencyStatusSelect(event) { }
5266
5376
  sendRequest() {
5267
5377
  this.sending = true;
5268
- this.propertyService.makeOffer(this.id, this.offer).subscribe({
5378
+ this.propertyOfferService.makeOffer(this.id, this.offer).subscribe({
5269
5379
  next: (res) => {
5270
5380
  this.sending = false;
5271
5381
  this.snackBarService.open('Sent successfully');
@@ -5301,7 +5411,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
5301
5411
  MatSelectModule,
5302
5412
  MatDatepickerModule,
5303
5413
  MatProgressSpinner,
5304
- PropertyPricingComponent
5414
+ PropertyPricingComponent,
5305
5415
  ], providers: [
5306
5416
  {
5307
5417
  provide: DateAdapter,
@@ -5615,6 +5725,7 @@ const propertyAgentViewingRoutes = [
5615
5725
 
5616
5726
  class PropertyAgentOfferDetail extends BaseComponent {
5617
5727
  propertyService = inject(PropertyService);
5728
+ propertyOfferService = inject(PropertyOfferService);
5618
5729
  authUserService = inject(AuthUserService);
5619
5730
  invoiceService = inject(InvoiceService);
5620
5731
  offer;
@@ -5627,7 +5738,7 @@ class PropertyAgentOfferDetail extends BaseComponent {
5627
5738
  this.getOffer();
5628
5739
  }
5629
5740
  getOffer() {
5630
- this.propertyService.getOffer(this.id).subscribe({
5741
+ this.propertyOfferService.getOffer(this.id).subscribe({
5631
5742
  next: (res) => {
5632
5743
  this.offer = res.data;
5633
5744
  this.name = this.offer.firstName + ', ' + this.offer.lastName;
@@ -5660,7 +5771,7 @@ class PropertyAgentOfferDetail extends BaseComponent {
5660
5771
  });
5661
5772
  dialogRef.afterClosed().subscribe((result) => {
5662
5773
  if (result) {
5663
- this.propertyService.acceptOffer(this.id).subscribe({
5774
+ this.propertyOfferService.acceptOffer(this.id).subscribe({
5664
5775
  next: (res) => {
5665
5776
  this.offer.status = 'ACCEPTED';
5666
5777
  this.snackBarService.open('Accepted');
@@ -5681,7 +5792,7 @@ class PropertyAgentOfferDetail extends BaseComponent {
5681
5792
  });
5682
5793
  dialogRef.afterClosed().subscribe((result) => {
5683
5794
  if (result) {
5684
- this.propertyService.rejectOffer(this.id, { notes: result.content }).subscribe({
5795
+ this.propertyOfferService.rejectOffer(this.id, { notes: result.content }).subscribe({
5685
5796
  next: (res) => {
5686
5797
  this.offer.status = 'REJECTED';
5687
5798
  this.snackBarService.open('Rejected');
@@ -5704,7 +5815,7 @@ class PropertyAgentOfferDetail extends BaseComponent {
5704
5815
  });
5705
5816
  dialogRef.afterClosed().subscribe((result) => {
5706
5817
  if (result) {
5707
- this.propertyService.referencesAccept(this.id).subscribe({
5818
+ this.propertyOfferService.referencesAccept(this.id).subscribe({
5708
5819
  next: (res) => {
5709
5820
  this.offer.status = 'REFERENCES_PASSED';
5710
5821
  this.snackBarService.open('Passed');
@@ -5725,7 +5836,7 @@ class PropertyAgentOfferDetail extends BaseComponent {
5725
5836
  });
5726
5837
  dialogRef.afterClosed().subscribe((result) => {
5727
5838
  if (result) {
5728
- this.propertyService.referencesReject(this.id, { reason: result.content }).subscribe({
5839
+ this.propertyOfferService.referencesReject(this.id, { reason: result.content }).subscribe({
5729
5840
  next: (res) => {
5730
5841
  this.offer.status = 'REFERENCES_FAILED';
5731
5842
  this.snackBarService.open('Failed');
@@ -5747,6 +5858,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
5747
5858
 
5748
5859
  class PropertyAgentOfferIndex extends BaseComponent {
5749
5860
  propertyService = inject(PropertyService);
5861
+ propertyOfferService = inject(PropertyOfferService);
5750
5862
  select = 0;
5751
5863
  links = [
5752
5864
  {
@@ -5754,9 +5866,9 @@ class PropertyAgentOfferIndex extends BaseComponent {
5754
5866
  icon: 'dashboard',
5755
5867
  },
5756
5868
  {
5757
- name: 'Pending',
5869
+ name: 'Created',
5758
5870
  icon: 'category',
5759
- status: 'pending',
5871
+ status: 'created',
5760
5872
  },
5761
5873
  {
5762
5874
  name: 'Accepted',
@@ -5774,47 +5886,61 @@ class PropertyAgentOfferIndex extends BaseComponent {
5774
5886
  status: 'cancelled',
5775
5887
  },
5776
5888
  ];
5777
- filterOptions = {
5778
- type: '',
5779
- status: '',
5780
- };
5781
- offers = [];
5889
+ loading = false;
5890
+ offers = signal([], ...(ngDevMode ? [{ debugName: "offers" }] : []));
5891
+ meta;
5892
+ pageEvent;
5893
+ length = 100;
5894
+ pageSize = 15;
5895
+ pageSizeOptions = [5, 10, 25, 100];
5896
+ pageIndex = signal(0, ...(ngDevMode ? [{ debugName: "pageIndex" }] : []));
5782
5897
  ngOnInit() {
5783
- this.route.queryParams.subscribe(({ status }) => {
5784
- this.select = this.links.findIndex((item) => item.status === status);
5898
+ const sub = this.route.queryParamMap
5899
+ .pipe(map((p) => {
5900
+ const page = p.get('page') ? Number(p.get('page')) : 1;
5901
+ this.pageIndex.set(Math.max(page - 1, 0));
5902
+ const status = p.get('status') || undefined;
5903
+ let filter = '';
5785
5904
  if (status) {
5786
- this.filterOptions.status = status.toUpperCase();
5787
- }
5788
- else {
5789
- delete this.filterOptions.status;
5905
+ this.select = this.links.findIndex((item) => item.status === status);
5906
+ filter = `status:${status?.toUpperCase()}`;
5790
5907
  }
5791
- this.findOffers();
5792
- });
5793
- }
5794
- findOffers() {
5795
- const options = {
5796
- sort: 'updatedAt desc',
5797
- };
5798
- const filterString = this.convertFilterOptions(this.filterOptions);
5799
- if (filterString) {
5800
- options['filter'] = filterString;
5801
- }
5802
- this.propertyService.findOffersByAgent(options).subscribe({
5908
+ return {
5909
+ page,
5910
+ filter,
5911
+ limit: p.get('limit') ? Number(p.get('limit')) : 15,
5912
+ sort: p.get('sort') || undefined,
5913
+ };
5914
+ }),
5915
+ // Cheap deep compare via JSON to avoid spam calls when nothing changed
5916
+ map((o) => JSON.stringify(o)), distinctUntilChanged(), map((s) => JSON.parse(s)), switchMap((params) => {
5917
+ this.loading = true;
5918
+ params['sort'] = 'updatedAt desc';
5919
+ return this.propertyOfferService.findOffers(params).pipe(finalize(() => (this.loading = false)));
5920
+ }))
5921
+ .subscribe({
5803
5922
  next: (res) => {
5804
- this.offers = res.data;
5923
+ this.offers.set(res.data);
5924
+ this.meta = res.meta;
5925
+ this.length = res.meta.pagination.count;
5926
+ },
5927
+ error: () => {
5928
+ this.offers.set([]);
5929
+ this.length = 0;
5805
5930
  },
5806
5931
  });
5932
+ // // auto-unsubscribe on destroy
5933
+ this.destroyRef.onDestroy(() => sub.unsubscribe());
5807
5934
  }
5808
- convertFilterOptions(jsonObj) {
5809
- return Object.entries(jsonObj)
5810
- .filter(([key, value]) => value !== '' && value !== undefined)
5811
- .map(([key, value]) => {
5812
- return `${key}:${value}`;
5813
- })
5814
- .join(',');
5935
+ onPage(e) {
5936
+ this.router.navigate([], {
5937
+ queryParams: { page: e.pageIndex + 1, limit: e.pageSize },
5938
+ queryParamsHandling: 'merge',
5939
+ replaceUrl: true, // optional: avoid stacking history on every page click
5940
+ });
5815
5941
  }
5816
5942
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyAgentOfferIndex, deps: null, target: i0.ɵɵFactoryTarget.Component });
5817
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: PropertyAgentOfferIndex, isStandalone: true, selector: "rolatech-property-agent-offer-index", usesInheritance: true, ngImport: i0, template: "<rolatech-toolbar title=\"Offers\">\n <div class=\"flex items-center gap-2\"></div>\n</rolatech-toolbar>\n<rolatech-tabs [select]=\"select\">\n @for (item of links; track item) { @if (item.status) {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\" [queryParams]=\"{ status: item.status }\"></rolatech-tab>\n } @else {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\"></rolatech-tab>\n } }\n</rolatech-tabs>\n<rolatech-list>\n @if (offers) { @for (item of offers; track item) {\n <rolatech-property-offer-item [routerLink]=\"['./', item.id]\" [offer]=\"item\"></rolatech-property-offer-item>\n } } @else {\n <rolatech-empty></rolatech-empty>\n }\n</rolatech-list>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: TabsComponent, selector: "rolatech-tabs", inputs: ["select", "loading"], outputs: ["selectChange"] }, { kind: "component", type: TabComponent, selector: "rolatech-tab", inputs: ["label"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: PropertyOfferItemComponent, selector: "rolatech-property-offer-item", inputs: ["offer"] }, { kind: "component", type: EmptyComponent, selector: "rolatech-empty" }, { kind: "component", type: ListComponent, selector: "rolatech-list" }] });
5943
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: PropertyAgentOfferIndex, isStandalone: true, selector: "rolatech-property-agent-offer-index", usesInheritance: true, ngImport: i0, template: "<rolatech-toolbar title=\"Offers\">\n <div class=\"flex items-center gap-2\"></div>\n</rolatech-toolbar>\n<rolatech-tabs [select]=\"select\">\n @for (item of links; track item) { @if (item.status) {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\" [queryParams]=\"{ status: item.status }\"></rolatech-tab>\n } @else {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\"></rolatech-tab>\n } }\n</rolatech-tabs>\n@if (loading) {\n<div class=\"divide-y divide-[--rt-10-percent-layer] flex flex-col px-3\">\n @for (row of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; track row) {\n <rolatech-offer-item-skeleton></rolatech-offer-item-skeleton>\n }\n</div>\n} @else {\n<rolatech-list>\n @if (offers()&& offers().length> 0) { @for (item of offers(); track item) {\n <rolatech-property-offer-item [routerLink]=\"['./', item.id]\" [offer]=\"item\"></rolatech-property-offer-item>\n } } @else {\n <rolatech-empty></rolatech-empty>\n }\n</rolatech-list>\n}\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: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: TabsComponent, selector: "rolatech-tabs", inputs: ["select", "loading"], outputs: ["selectChange"] }, { kind: "component", type: TabComponent, selector: "rolatech-tab", inputs: ["label"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: PropertyOfferItemComponent, selector: "rolatech-property-offer-item", inputs: ["offer"] }, { kind: "component", type: EmptyComponent, selector: "rolatech-empty" }, { kind: "component", type: ListComponent, selector: "rolatech-list" }, { kind: "component", type: OfferItemSkeleton, selector: "rolatech-offer-item-skeleton" }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i2$2.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }] });
5818
5944
  }
5819
5945
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyAgentOfferIndex, decorators: [{
5820
5946
  type: Component,
@@ -5827,7 +5953,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
5827
5953
  PropertyOfferItemComponent,
5828
5954
  EmptyComponent,
5829
5955
  ListComponent,
5830
- ], template: "<rolatech-toolbar title=\"Offers\">\n <div class=\"flex items-center gap-2\"></div>\n</rolatech-toolbar>\n<rolatech-tabs [select]=\"select\">\n @for (item of links; track item) { @if (item.status) {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\" [queryParams]=\"{ status: item.status }\"></rolatech-tab>\n } @else {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\"></rolatech-tab>\n } }\n</rolatech-tabs>\n<rolatech-list>\n @if (offers) { @for (item of offers; track item) {\n <rolatech-property-offer-item [routerLink]=\"['./', item.id]\" [offer]=\"item\"></rolatech-property-offer-item>\n } } @else {\n <rolatech-empty></rolatech-empty>\n }\n</rolatech-list>\n" }]
5956
+ OfferItemSkeleton,
5957
+ MatPaginatorModule,
5958
+ ], template: "<rolatech-toolbar title=\"Offers\">\n <div class=\"flex items-center gap-2\"></div>\n</rolatech-toolbar>\n<rolatech-tabs [select]=\"select\">\n @for (item of links; track item) { @if (item.status) {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\" [queryParams]=\"{ status: item.status }\"></rolatech-tab>\n } @else {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\"></rolatech-tab>\n } }\n</rolatech-tabs>\n@if (loading) {\n<div class=\"divide-y divide-[--rt-10-percent-layer] flex flex-col px-3\">\n @for (row of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; track row) {\n <rolatech-offer-item-skeleton></rolatech-offer-item-skeleton>\n }\n</div>\n} @else {\n<rolatech-list>\n @if (offers()&& offers().length> 0) { @for (item of offers(); track item) {\n <rolatech-property-offer-item [routerLink]=\"['./', item.id]\" [offer]=\"item\"></rolatech-property-offer-item>\n } } @else {\n <rolatech-empty></rolatech-empty>\n }\n</rolatech-list>\n}\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" }]
5831
5959
  }] });
5832
5960
 
5833
5961
  const propertyAgentOfferRoutes = [
@@ -5860,4 +5988,4 @@ const propertyManageOverviewRoutes = [
5860
5988
  */
5861
5989
 
5862
5990
  export { PropertyOfferTimelineStatus as A, PropertyOfferType as B, PropertyOfferStatus as C, ResidencyStatus as D, EmploymentStatus as E, PropertyApplicantType as F, AdverseCreditStatus as G, BedroomRange as H, PriceRange as I, Market as M, PropertyUtil as P, RentFrequency as R, ViewingTime as V, PropertyViewType as a, PropertyManageItemSkeleton as b, PropertyViewingItemComponent as c, propertyManageOffersRoutes as d, propertyRoutes as e, featureManageRoutes as f, propertyManageRoutes as g, propertyManageViewingsRoutes as h, propertyAgentViewingRoutes as i, propertyAgentOfferRoutes as j, propertyAgentOverviewRoutes as k, lettingManageRoutes as l, propertyManageOverviewRoutes as m, PropertyActionsComponent as n, PropertyItemComponent as o, propertyReviewRoutes as p, PropertyPricingComponent as q, PropertyPriceType as r, PropertyVideoProvider as s, tenantManageRoutes as t, PropertyStatus as u, PropertyType as v, PropertyInventoryStatus as w, PropertyScope as x, PropertyViewingStatus as y, PropertyViewerCategory as z };
5863
- //# sourceMappingURL=rolatech-angular-property-rolatech-angular-property-WeijIFtF.mjs.map
5991
+ //# sourceMappingURL=rolatech-angular-property-rolatech-angular-property-UmclChvG.mjs.map