@rolatech/angular-property 20.2.4-beta.2 → 20.2.5

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.
@@ -10,7 +10,7 @@ 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
- import { ThumbnailComponent, ImagePlaceholderComponent, Skeleton, ToolbarComponent, AbstractLoading, ImagePreviewDialogComponent, BaseComponent, AcceptDialogComponent, RejectDialogComponent, RichLabelComponent, AngularComponentsModule, ConfirmationDialogComponent, TabsComponent, TabComponent, EmptyComponent, ListComponent, ContainerComponent, SearchBar, SpinnerComponent, MediaListComponent, MediaListItemComponent, InputComponent } from '@rolatech/angular-components';
13
+ import { ThumbnailComponent, ImagePlaceholderComponent, Skeleton, ToolbarComponent, Loading, ImagePreviewDialogComponent, BaseComponent, AcceptDialogComponent, RejectDialogComponent, RichLabelComponent, AngularComponentsModule, ConfirmationDialogComponent, TabsComponent, TabComponent, EmptyComponent, ListComponent, ContainerComponent, SearchBar, SpinnerComponent, MediaListComponent, MediaListItemComponent, InputComponent } from '@rolatech/angular-components';
14
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';
@@ -464,7 +464,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
464
464
  args: ['class.rolatech-property-manage-index']
465
465
  }], paginator: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MatPaginator), { isSignal: true }] }] } });
466
466
 
467
- class PropertyMediaComponent extends AbstractLoading {
467
+ class PropertyMediaComponent extends Loading {
468
468
  hasClass = true;
469
469
  disableScrollbar = true;
470
470
  media = input(...(ngDevMode ? [undefined, { debugName: "media" }] : []));
@@ -1686,7 +1686,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
1686
1686
  args: [{ selector: 'rolatech-property-pricing', imports: [CommonModule, MatButtonModule, AvailableDatePipe, PricePipe], encapsulation: ViewEncapsulation.None, template: "<div class=\"py-3 flex flex-col gap-3\">\n <div class=\"flex justify-between items-center\">\n @if (market() === 'LETTINGS' && rentFrequency() === 'MONTHLY') {\n <div class=\"text-lg font-bold\" i18n>Rent per month</div>\n }\n @if (market() === 'LETTINGS' && rentFrequency() === 'WEEKLY') {\n <div class=\"text-lg font-bold\" i18n>Rent per week</div>\n }\n @if (market() === 'LETTINGS' && rentFrequency() === 'NOT_SPECIFIED') {\n <div class=\"text-lg font-bold\" i18n>Rent price</div>\n }\n @if (market() === 'SALES') {\n <div class=\"text-lg font-bold\" i18n>Price</div>\n }\n <div class=\"text-xl font-bold\">{{ displayPrice() | price }}</div>\n </div>\n <div class=\"flex justify-between items-center\">\n <div>Available</div>\n <div>{{ property().availableDate | availableDate }}</div>\n </div>\n @if (market() === 'LETTINGS') {\n <div class=\"flex justify-between items-center\">\n <span i18n>Holding Deposit</span>\n <span>{{ holdingDeposit | price }}</span>\n </div>\n <div class=\"flex justify-between items-center font-bold\">\n <span i18n>Security Deposit</span>\n <span>{{ securityDeposit | price }}</span>\n </div>\n }\n</div>\n" }]
1687
1687
  }], propDecorators: { property: [{ type: i0.Input, args: [{ isSignal: true, alias: "property", required: true }] }], price: [{ type: i0.Input, args: [{ isSignal: true, alias: "price", required: false }] }] } });
1688
1688
 
1689
- class PropertyInfoComponent extends AbstractLoading {
1689
+ class PropertyInfoComponent extends Loading {
1690
1690
  property = input.required(...(ngDevMode ? [{ debugName: "property" }] : []));
1691
1691
  wish = output();
1692
1692
  inWishList = input(false, ...(ngDevMode ? [{ debugName: "inWishList" }] : []));
@@ -1965,7 +1965,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
1965
1965
  args: [{ selector: 'rolatech-property-media-skeleton', imports: [Skeleton], template: "<div class=\"py-3\">\n <div class=\"object-cover aspect-video bg-[--rt-raised-background]\">\n <rolatech-skeleton></rolatech-skeleton>\n </div>\n\n <div class=\"flex overflow-y-hidden overflow-x-scroll scrollbar-hide pb-4\">\n @for (dummy of [0, 1, 2, 3]; track dummy) {\n <div class=\"flex flex-row mt-3 mr-3 rounded-md min-w-32 object-cover aspect-video bg-[--rt-raised-background]\">\n <rolatech-skeleton></rolatech-skeleton>\n </div>\n }\n </div>\n</div>\n" }]
1966
1966
  }] });
1967
1967
 
1968
- class PropertyInfoSkeleton extends AbstractLoading {
1968
+ class PropertyInfoSkeleton extends Loading {
1969
1969
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyInfoSkeleton, deps: null, target: i0.ɵɵFactoryTarget.Component });
1970
1970
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.0", type: PropertyInfoSkeleton, isStandalone: true, selector: "rolatech-property-info-skeleton", usesInheritance: true, ngImport: i0, template: "<div>\n <div class=\"flex justify-between items-start gap-3\">\n <!-- title -->\n <rolatech-skeleton class=\"w-[80%] h-8 mb-3\"></rolatech-skeleton>\n <!-- action button -->\n <rolatech-skeleton class=\"w-6 h-6\"></rolatech-skeleton>\n </div>\n <div class=\"font-bold mb-3\">\n <!-- short info -->\n <rolatech-skeleton class=\"w-[50%] h-6\"></rolatech-skeleton>\n </div>\n <!-- description -->\n <rolatech-skeleton class=\"w-full aspect-video\"></rolatech-skeleton>\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: Skeleton, selector: "rolatech-skeleton" }], encapsulation: i0.ViewEncapsulation.None });
1971
1971
  }
@@ -1974,7 +1974,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
1974
1974
  args: [{ selector: 'rolatech-property-info-skeleton', imports: [Skeleton], encapsulation: ViewEncapsulation.None, template: "<div>\n <div class=\"flex justify-between items-start gap-3\">\n <!-- title -->\n <rolatech-skeleton class=\"w-[80%] h-8 mb-3\"></rolatech-skeleton>\n <!-- action button -->\n <rolatech-skeleton class=\"w-6 h-6\"></rolatech-skeleton>\n </div>\n <div class=\"font-bold mb-3\">\n <!-- short info -->\n <rolatech-skeleton class=\"w-[50%] h-6\"></rolatech-skeleton>\n </div>\n <!-- description -->\n <rolatech-skeleton class=\"w-full aspect-video\"></rolatech-skeleton>\n</div>\n" }]
1975
1975
  }] });
1976
1976
 
1977
- class PropertyAgentSkeleton extends AbstractLoading {
1977
+ class PropertyAgentSkeleton extends Loading {
1978
1978
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyAgentSkeleton, deps: null, target: i0.ɵɵFactoryTarget.Component });
1979
1979
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.0", type: PropertyAgentSkeleton, isStandalone: true, selector: "rolatech-property-agent-skeleton", usesInheritance: true, ngImport: i0, template: "<div class=\"flex flex-col\">\n <div class=\"flex flex-row items-center pb-3\">\n <div class=\"flex mr-3 gap-2 items-center w-full\">\n <!-- avatar -->\n <rolatech-skeleton class=\"w-14 h-14 rounded-full\"></rolatech-skeleton>\n <rolatech-skeleton class=\"flex-1 h-6\"></rolatech-skeleton>\n </div>\n </div>\n <div class=\"text-sm opacity-70\">\n <rolatech-skeleton class=\"w-full h-6\"></rolatech-skeleton>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: Skeleton, selector: "rolatech-skeleton" }], encapsulation: i0.ViewEncapsulation.None });
1980
1980
  }
@@ -2157,7 +2157,7 @@ class PropertyDetailsComponent extends BaseComponent {
2157
2157
  }
2158
2158
  }
2159
2159
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyDetailsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2160
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: PropertyDetailsComponent, isStandalone: true, selector: "rolatech-property-details", usesInheritance: true, ngImport: i0, template: "<rolatech-container>\n <div class=\"flex flex-col w-full\">\n @if (loading()) {\n <rolatech-property-media-skeleton></rolatech-property-media-skeleton>\n\n <div class=\"flex flex-col md:flex-row gap-3 w-full\">\n <rolatech-property-info-skeleton class=\"w-full md:w-2/3\"></rolatech-property-info-skeleton>\n <rolatech-property-agent-skeleton class=\"w-full md:w-1/3\"></rolatech-property-agent-skeleton>\n </div>\n } @else {\n @if (property(); as property) {\n <rolatech-property-media [media]=\"property.media ? property.media : []\"></rolatech-property-media>\n <div class=\"flex flex-col md:flex-row gap-3 w-full\">\n <div class=\"w-full md:w-2/3\">\n <rolatech-property-info [property]=\"property\" (wish)=\"onWish($event)\" [inWishList]=\"inWishList\">\n </rolatech-property-info>\n <!-- <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n ></rolatech-property-agent-renderer> -->\n @if (features.length > 0) {\n <rolatech-property-features [features]=\"features\"></rolatech-property-features>\n }\n @if (highlights.length > 0) {\n <rolatech-property-highlights [highlights]=\"highlights\"></rolatech-property-highlights>\n }\n @if (floorplans.length > 0) {\n <rolatech-property-floorplan [floorplans]=\"floorplans\"></rolatech-property-floorplan>\n }\n @if (property.location) {\n <rolatech-property-location [location]=\"property.location\"></rolatech-property-location>\n }\n <div>{{ videos().length }}</div>\n @if (videos() && videos().length > 0) {\n @for (item of videos(); track $index) {\n <rolatech-property-video [video]=\"item\"></rolatech-property-video>\n }\n }\n @if (epc && epc.currentScore) {\n <rolatech-property-epc [epc]=\"epc\"></rolatech-property-epc>\n }\n <div class=\"flex flex-col\">\n <div class=\"text-2xl font-bold pt-3\" i18n>Sections</div>\n @for (section of property.sections; track $index) {\n <rolatech-property-section [section]=\"section\"></rolatech-property-section>\n }\n <rolatech-comments [itemId]=\"property.id\"></rolatech-comments>\n </div>\n </div>\n <div class=\"w-full md:w-1/3\">\n <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n ></rolatech-property-agent-renderer>\n <rolatech-property-pricing (wish)=\"onWish($event)\" [property]=\"property\"></rolatech-property-pricing>\n <rolatech-property-actions\n [property]=\"property\"\n (offer)=\"onOffer($event)\"\n (deposit)=\"onOffer($event)\"\n (requestViewing)=\"onRequestViewing($event)\"\n >\n @if (user) {\n <rolatech-property-action-contact [email]=\"user.email\" [phone]=\"user.phone\"></rolatech-property-action-contact>\n }\n </rolatech-property-actions>\n </div>\n </div>\n }\n }\n </div>\n</rolatech-container>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: AngularCommonModule }, { kind: "ngmodule", type: AngularComponentsModule }, { kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "component", type: PropertyInfoComponent, selector: "rolatech-property-info", inputs: ["property", "inWishList"], outputs: ["wish"] }, { kind: "component", type: PropertyMediaComponent, selector: "rolatech-property-media", inputs: ["media", "min"] }, { kind: "component", type: PropertyPricingComponent, selector: "rolatech-property-pricing", inputs: ["property", "price"] }, { kind: "component", type: PropertySectionComponent, selector: "rolatech-property-section", inputs: ["section", "user", "username"] }, { kind: "component", type: PropertyActionsComponent, selector: "rolatech-property-actions", inputs: ["property"], outputs: ["requestViewing", "offer", "deposit"] }, { kind: "component", type: CommentsComponent, selector: "rolatech-comments", inputs: ["itemId"] }, { kind: "component", type: PropertyAgentRenderer, selector: "rolatech-property-agent-renderer", inputs: ["name", "avatar", "username", "subtitle"] }, { kind: "component", type: PropertyLocationComponent, selector: "rolatech-property-location", inputs: ["location"] }, { kind: "component", type: PropertyFeaturesComponent, selector: "rolatech-property-features", inputs: ["features"] }, { kind: "component", type: PropertyVideoComponent, selector: "rolatech-property-video", inputs: ["video"] }, { kind: "component", type: PropertyActionContactComponent, selector: "rolatech-property-action-contact", inputs: ["email", "phone"], outputs: ["callAgent", "emailAgent"] }, { kind: "component", type: PropertyHighlights, selector: "rolatech-property-highlights", inputs: ["highlights"] }, { kind: "component", type: PropertyEpc, selector: "rolatech-property-epc", inputs: ["epc"] }, { kind: "component", type: PropertyFloorplan, selector: "rolatech-property-floorplan", inputs: ["floorplans"] }, { kind: "component", type: PropertyMediaSkeleton, selector: "rolatech-property-media-skeleton" }, { kind: "component", type: PropertyInfoSkeleton, selector: "rolatech-property-info-skeleton" }, { kind: "component", type: PropertyAgentSkeleton, selector: "rolatech-property-agent-skeleton" }] });
2160
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: PropertyDetailsComponent, isStandalone: true, selector: "rolatech-property-details", usesInheritance: true, ngImport: i0, template: "<rolatech-container>\n <div class=\"flex flex-col w-full\">\n @if (loading()) {\n <rolatech-property-media-skeleton></rolatech-property-media-skeleton>\n\n <div class=\"flex flex-col md:flex-row gap-3 w-full\">\n <rolatech-property-info-skeleton class=\"w-full md:w-2/3\"></rolatech-property-info-skeleton>\n <rolatech-property-agent-skeleton class=\"w-full md:w-1/3\"></rolatech-property-agent-skeleton>\n </div>\n } @else {\n @if (property(); as property) {\n <rolatech-property-media [media]=\"property.media ? property.media : []\"></rolatech-property-media>\n <div class=\"flex flex-col md:flex-row gap-3 w-full\">\n <div class=\"w-full md:w-2/3\">\n <rolatech-property-info [property]=\"property\" (wish)=\"onWish($event)\" [inWishList]=\"inWishList\">\n </rolatech-property-info>\n <!-- <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n ></rolatech-property-agent-renderer> -->\n @if (features.length > 0) {\n <rolatech-property-features [features]=\"features\"></rolatech-property-features>\n }\n @if (highlights.length > 0) {\n <rolatech-property-highlights [highlights]=\"highlights\"></rolatech-property-highlights>\n }\n @if (floorplans.length > 0) {\n <rolatech-property-floorplan [floorplans]=\"floorplans\"></rolatech-property-floorplan>\n }\n @if (property.location) {\n <rolatech-property-location [location]=\"property.location\"></rolatech-property-location>\n }\n @if (videos() && videos().length > 0) {\n @for (item of videos(); track $index) {\n <rolatech-property-video [video]=\"item\"></rolatech-property-video>\n }\n }\n @if (epc && epc.currentScore) {\n <rolatech-property-epc [epc]=\"epc\"></rolatech-property-epc>\n }\n <div class=\"flex flex-col\">\n <div class=\"text-2xl font-bold pt-3\" i18n>Sections</div>\n @for (section of property.sections; track $index) {\n <rolatech-property-section [section]=\"section\"></rolatech-property-section>\n }\n <rolatech-comments [itemId]=\"property.id\"></rolatech-comments>\n </div>\n </div>\n <div class=\"w-full md:w-1/3\">\n <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n ></rolatech-property-agent-renderer>\n <rolatech-property-pricing (wish)=\"onWish($event)\" [property]=\"property\"></rolatech-property-pricing>\n <rolatech-property-actions\n [property]=\"property\"\n (offer)=\"onOffer($event)\"\n (deposit)=\"onOffer($event)\"\n (requestViewing)=\"onRequestViewing($event)\"\n >\n @if (user) {\n <rolatech-property-action-contact [email]=\"user.email\" [phone]=\"user.phone\"></rolatech-property-action-contact>\n }\n </rolatech-property-actions>\n </div>\n </div>\n }\n }\n </div>\n</rolatech-container>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: AngularCommonModule }, { kind: "ngmodule", type: AngularComponentsModule }, { kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "component", type: PropertyInfoComponent, selector: "rolatech-property-info", inputs: ["property", "inWishList"], outputs: ["wish"] }, { kind: "component", type: PropertyMediaComponent, selector: "rolatech-property-media", inputs: ["media", "min"] }, { kind: "component", type: PropertyPricingComponent, selector: "rolatech-property-pricing", inputs: ["property", "price"] }, { kind: "component", type: PropertySectionComponent, selector: "rolatech-property-section", inputs: ["section", "user", "username"] }, { kind: "component", type: PropertyActionsComponent, selector: "rolatech-property-actions", inputs: ["property"], outputs: ["requestViewing", "offer", "deposit"] }, { kind: "component", type: CommentsComponent, selector: "rolatech-comments", inputs: ["itemId"] }, { kind: "component", type: PropertyAgentRenderer, selector: "rolatech-property-agent-renderer", inputs: ["name", "avatar", "username", "subtitle"] }, { kind: "component", type: PropertyLocationComponent, selector: "rolatech-property-location", inputs: ["location"] }, { kind: "component", type: PropertyFeaturesComponent, selector: "rolatech-property-features", inputs: ["features"] }, { kind: "component", type: PropertyVideoComponent, selector: "rolatech-property-video", inputs: ["video"] }, { kind: "component", type: PropertyActionContactComponent, selector: "rolatech-property-action-contact", inputs: ["email", "phone"], outputs: ["callAgent", "emailAgent"] }, { kind: "component", type: PropertyHighlights, selector: "rolatech-property-highlights", inputs: ["highlights"] }, { kind: "component", type: PropertyEpc, selector: "rolatech-property-epc", inputs: ["epc"] }, { kind: "component", type: PropertyFloorplan, selector: "rolatech-property-floorplan", inputs: ["floorplans"] }, { kind: "component", type: PropertyMediaSkeleton, selector: "rolatech-property-media-skeleton" }, { kind: "component", type: PropertyInfoSkeleton, selector: "rolatech-property-info-skeleton" }, { kind: "component", type: PropertyAgentSkeleton, selector: "rolatech-property-agent-skeleton" }] });
2161
2161
  }
2162
2162
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyDetailsComponent, decorators: [{
2163
2163
  type: Component,
@@ -2182,7 +2182,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
2182
2182
  PropertyMediaSkeleton,
2183
2183
  PropertyInfoSkeleton,
2184
2184
  PropertyAgentSkeleton,
2185
- ], template: "<rolatech-container>\n <div class=\"flex flex-col w-full\">\n @if (loading()) {\n <rolatech-property-media-skeleton></rolatech-property-media-skeleton>\n\n <div class=\"flex flex-col md:flex-row gap-3 w-full\">\n <rolatech-property-info-skeleton class=\"w-full md:w-2/3\"></rolatech-property-info-skeleton>\n <rolatech-property-agent-skeleton class=\"w-full md:w-1/3\"></rolatech-property-agent-skeleton>\n </div>\n } @else {\n @if (property(); as property) {\n <rolatech-property-media [media]=\"property.media ? property.media : []\"></rolatech-property-media>\n <div class=\"flex flex-col md:flex-row gap-3 w-full\">\n <div class=\"w-full md:w-2/3\">\n <rolatech-property-info [property]=\"property\" (wish)=\"onWish($event)\" [inWishList]=\"inWishList\">\n </rolatech-property-info>\n <!-- <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n ></rolatech-property-agent-renderer> -->\n @if (features.length > 0) {\n <rolatech-property-features [features]=\"features\"></rolatech-property-features>\n }\n @if (highlights.length > 0) {\n <rolatech-property-highlights [highlights]=\"highlights\"></rolatech-property-highlights>\n }\n @if (floorplans.length > 0) {\n <rolatech-property-floorplan [floorplans]=\"floorplans\"></rolatech-property-floorplan>\n }\n @if (property.location) {\n <rolatech-property-location [location]=\"property.location\"></rolatech-property-location>\n }\n <div>{{ videos().length }}</div>\n @if (videos() && videos().length > 0) {\n @for (item of videos(); track $index) {\n <rolatech-property-video [video]=\"item\"></rolatech-property-video>\n }\n }\n @if (epc && epc.currentScore) {\n <rolatech-property-epc [epc]=\"epc\"></rolatech-property-epc>\n }\n <div class=\"flex flex-col\">\n <div class=\"text-2xl font-bold pt-3\" i18n>Sections</div>\n @for (section of property.sections; track $index) {\n <rolatech-property-section [section]=\"section\"></rolatech-property-section>\n }\n <rolatech-comments [itemId]=\"property.id\"></rolatech-comments>\n </div>\n </div>\n <div class=\"w-full md:w-1/3\">\n <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n ></rolatech-property-agent-renderer>\n <rolatech-property-pricing (wish)=\"onWish($event)\" [property]=\"property\"></rolatech-property-pricing>\n <rolatech-property-actions\n [property]=\"property\"\n (offer)=\"onOffer($event)\"\n (deposit)=\"onOffer($event)\"\n (requestViewing)=\"onRequestViewing($event)\"\n >\n @if (user) {\n <rolatech-property-action-contact [email]=\"user.email\" [phone]=\"user.phone\"></rolatech-property-action-contact>\n }\n </rolatech-property-actions>\n </div>\n </div>\n }\n }\n </div>\n</rolatech-container>\n" }]
2185
+ ], template: "<rolatech-container>\n <div class=\"flex flex-col w-full\">\n @if (loading()) {\n <rolatech-property-media-skeleton></rolatech-property-media-skeleton>\n\n <div class=\"flex flex-col md:flex-row gap-3 w-full\">\n <rolatech-property-info-skeleton class=\"w-full md:w-2/3\"></rolatech-property-info-skeleton>\n <rolatech-property-agent-skeleton class=\"w-full md:w-1/3\"></rolatech-property-agent-skeleton>\n </div>\n } @else {\n @if (property(); as property) {\n <rolatech-property-media [media]=\"property.media ? property.media : []\"></rolatech-property-media>\n <div class=\"flex flex-col md:flex-row gap-3 w-full\">\n <div class=\"w-full md:w-2/3\">\n <rolatech-property-info [property]=\"property\" (wish)=\"onWish($event)\" [inWishList]=\"inWishList\">\n </rolatech-property-info>\n <!-- <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n ></rolatech-property-agent-renderer> -->\n @if (features.length > 0) {\n <rolatech-property-features [features]=\"features\"></rolatech-property-features>\n }\n @if (highlights.length > 0) {\n <rolatech-property-highlights [highlights]=\"highlights\"></rolatech-property-highlights>\n }\n @if (floorplans.length > 0) {\n <rolatech-property-floorplan [floorplans]=\"floorplans\"></rolatech-property-floorplan>\n }\n @if (property.location) {\n <rolatech-property-location [location]=\"property.location\"></rolatech-property-location>\n }\n @if (videos() && videos().length > 0) {\n @for (item of videos(); track $index) {\n <rolatech-property-video [video]=\"item\"></rolatech-property-video>\n }\n }\n @if (epc && epc.currentScore) {\n <rolatech-property-epc [epc]=\"epc\"></rolatech-property-epc>\n }\n <div class=\"flex flex-col\">\n <div class=\"text-2xl font-bold pt-3\" i18n>Sections</div>\n @for (section of property.sections; track $index) {\n <rolatech-property-section [section]=\"section\"></rolatech-property-section>\n }\n <rolatech-comments [itemId]=\"property.id\"></rolatech-comments>\n </div>\n </div>\n <div class=\"w-full md:w-1/3\">\n <rolatech-property-agent-renderer\n [name]=\"fullname\"\n [avatar]=\"user?.avatar\"\n [username]=\"username\"\n ></rolatech-property-agent-renderer>\n <rolatech-property-pricing (wish)=\"onWish($event)\" [property]=\"property\"></rolatech-property-pricing>\n <rolatech-property-actions\n [property]=\"property\"\n (offer)=\"onOffer($event)\"\n (deposit)=\"onOffer($event)\"\n (requestViewing)=\"onRequestViewing($event)\"\n >\n @if (user) {\n <rolatech-property-action-contact [email]=\"user.email\" [phone]=\"user.phone\"></rolatech-property-action-contact>\n }\n </rolatech-property-actions>\n </div>\n </div>\n }\n }\n </div>\n</rolatech-container>\n" }]
2186
2186
  }], ctorParameters: () => [] });
2187
2187
 
2188
2188
  const MY_FORMATS$5 = {
@@ -2605,20 +2605,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
2605
2605
  ], 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" }]
2606
2606
  }] });
2607
2607
 
2608
- class PropertyViewingItemComponent {
2608
+ class PropertyViewingItemComponent extends Loading {
2609
2609
  viewing = input.required(...(ngDevMode ? [{ debugName: "viewing" }] : []));
2610
2610
  status = PropertyViewingStatus;
2611
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyViewingItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2612
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: PropertyViewingItemComponent, isStandalone: true, selector: "rolatech-property-viewing-item", inputs: { viewing: { classPropertyName: "viewing", publicName: "viewing", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, 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>Viewing ID: {{ viewing().id }}</span>\n </a>\n <span class=\"font-medium text-sm\">{{ status[viewing().status] }}</span>\n </div>\n @if (viewing().item) {\n <div class=\"flex flex-col overflow-x-scroll scrollbar-hide\">\n <div class=\"flex flex-row py-2\">\n @if (viewing().item.media) {\n <div class=\"min-w-24 w-36 object-cover aspect-video rounded-lg mr-3\">\n @defer {\n <rolatech-thumbnail [src]=\"viewing().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 } @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>{{ viewing().item.title }}</div>\n <div class=\"inline-flex gap-1 mt-2\">\n <div>\n <span class=\"mr-1\">{{ viewing().item.bedrooms }}</span>\n <span i18n>Bedrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ viewing().item.bathrooms }}</span>\n <span i18n>Bathrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ viewing().item.receptions }}</span>\n <span i18n>Receptions</span>\n </div>\n </div>\n </div>\n <div class=\"text-right\">\n <div class=\"text-sm\">{{ viewing().item.price | price }}</div>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: ImagePlaceholderComponent, selector: "rolatech-image-placeholder", inputs: ["ratio"] }, { kind: "pipe", type: PricePipe, name: "price" }], deferBlockDependencies: [() => [ThumbnailComponent]] });
2611
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyViewingItemComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2612
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: PropertyViewingItemComponent, isStandalone: true, selector: "rolatech-property-viewing-item", inputs: { viewing: { classPropertyName: "viewing", publicName: "viewing", isSignal: true, isRequired: true, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "@if (loading()) {\n <div class=\"flex flex-col p-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} @else {\n <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>Viewing ID: {{ viewing().id }}</span>\n </a>\n <span class=\"font-medium text-sm\">{{ status[viewing().status] }}</span>\n </div>\n @if (viewing().item) {\n <div class=\"flex flex-col overflow-x-scroll scrollbar-hide\">\n <div class=\"flex flex-row py-2\">\n @if (viewing().item.media) {\n <div class=\"min-w-24 w-36 object-cover aspect-video rounded-lg mr-3\">\n @defer {\n <rolatech-thumbnail [src]=\"viewing().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 } @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\">{{ viewing().item.title }}</div>\n <div class=\"inline-flex gap-1 mt-2\">\n <div>\n <span class=\"mr-1\">{{ viewing().item.bedrooms }}</span>\n <span i18n>Bedrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ viewing().item.bathrooms }}</span>\n <span i18n>Bathrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ viewing().item.receptions }}</span>\n <span i18n>Receptions</span>\n </div>\n </div>\n </div>\n <div class=\"text-right\">\n <div class=\"text-sm\">{{ viewing().item.price | price }}</div>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: ImagePlaceholderComponent, selector: "rolatech-image-placeholder", inputs: ["ratio"] }, { kind: "component", type: Skeleton, selector: "rolatech-skeleton" }, { kind: "pipe", type: PricePipe, name: "price" }], deferBlockDependencies: [() => [ThumbnailComponent]] });
2613
2613
  }
2614
2614
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyViewingItemComponent, decorators: [{
2615
2615
  type: Component,
2616
- args: [{ selector: 'rolatech-property-viewing-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>Viewing ID: {{ viewing().id }}</span>\n </a>\n <span class=\"font-medium text-sm\">{{ status[viewing().status] }}</span>\n </div>\n @if (viewing().item) {\n <div class=\"flex flex-col overflow-x-scroll scrollbar-hide\">\n <div class=\"flex flex-row py-2\">\n @if (viewing().item.media) {\n <div class=\"min-w-24 w-36 object-cover aspect-video rounded-lg mr-3\">\n @defer {\n <rolatech-thumbnail [src]=\"viewing().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 } @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>{{ viewing().item.title }}</div>\n <div class=\"inline-flex gap-1 mt-2\">\n <div>\n <span class=\"mr-1\">{{ viewing().item.bedrooms }}</span>\n <span i18n>Bedrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ viewing().item.bathrooms }}</span>\n <span i18n>Bathrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ viewing().item.receptions }}</span>\n <span i18n>Receptions</span>\n </div>\n </div>\n </div>\n <div class=\"text-right\">\n <div class=\"text-sm\">{{ viewing().item.price | price }}</div>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n</div>\n" }]
2616
+ args: [{ selector: 'rolatech-property-viewing-item', imports: [MatIconModule, ThumbnailComponent, ImagePlaceholderComponent, Skeleton, PricePipe], template: "@if (loading()) {\n <div class=\"flex flex-col p-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} @else {\n <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>Viewing ID: {{ viewing().id }}</span>\n </a>\n <span class=\"font-medium text-sm\">{{ status[viewing().status] }}</span>\n </div>\n @if (viewing().item) {\n <div class=\"flex flex-col overflow-x-scroll scrollbar-hide\">\n <div class=\"flex flex-row py-2\">\n @if (viewing().item.media) {\n <div class=\"min-w-24 w-36 object-cover aspect-video rounded-lg mr-3\">\n @defer {\n <rolatech-thumbnail [src]=\"viewing().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 } @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\">{{ viewing().item.title }}</div>\n <div class=\"inline-flex gap-1 mt-2\">\n <div>\n <span class=\"mr-1\">{{ viewing().item.bedrooms }}</span>\n <span i18n>Bedrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ viewing().item.bathrooms }}</span>\n <span i18n>Bathrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ viewing().item.receptions }}</span>\n <span i18n>Receptions</span>\n </div>\n </div>\n </div>\n <div class=\"text-right\">\n <div class=\"text-sm\">{{ viewing().item.price | price }}</div>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n}\n" }]
2617
2617
  }], propDecorators: { viewing: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewing", required: true }] }] } });
2618
2618
 
2619
2619
  class PropertyViewingIndexComponent extends BaseComponent {
2620
2620
  propertyService = inject(PropertyService);
2621
- viewings;
2622
2621
  viewerCategory = PropertyViewerCategory;
2623
2622
  tenantCategory = PropertyApplicantType;
2624
2623
  viewingStatus = PropertyViewingStatus;
@@ -2645,53 +2644,66 @@ class PropertyViewingIndexComponent extends BaseComponent {
2645
2644
  status: 'cancelled',
2646
2645
  },
2647
2646
  ];
2647
+ loading = false;
2648
+ viewings = signal([], ...(ngDevMode ? [{ debugName: "viewings" }] : []));
2649
+ meta;
2650
+ pageEvent;
2651
+ length = 100;
2652
+ pageSize = 15;
2653
+ pageSizeOptions = [5, 10, 25, 100];
2654
+ pageIndex = signal(0, ...(ngDevMode ? [{ debugName: "pageIndex" }] : []));
2648
2655
  ngOnInit() {
2649
- this.route.queryParams.subscribe(({ status }) => {
2650
- this.select = this.links.findIndex((item) => item.status === status);
2656
+ const sub = this.route.queryParamMap
2657
+ .pipe(map((p) => {
2658
+ const page = p.get('page') ? Number(p.get('page')) : 1;
2659
+ this.pageIndex.set(Math.max(page - 1, 0));
2660
+ const status = p.get('status') || undefined;
2661
+ let filter = '';
2651
2662
  if (status) {
2652
- this.filterOptions.status = status.toUpperCase();
2653
- }
2654
- else {
2655
- delete this.filterOptions.status;
2663
+ this.select = this.links.findIndex((item) => item.status === status);
2664
+ filter = `status:${status?.toUpperCase()}`;
2656
2665
  }
2657
- this.findViewings();
2658
- });
2659
- }
2660
- findViewings() {
2661
- const options = {
2662
- sort: 'updatedAt desc',
2663
- };
2664
- const filterString = this.convertFilterOptions(this.filterOptions);
2665
- if (filterString) {
2666
- options['filter'] = filterString;
2667
- }
2668
- this.propertyService.findViewingsByUser(options).subscribe({
2666
+ return {
2667
+ page,
2668
+ filter,
2669
+ limit: p.get('limit') ? Number(p.get('limit')) : 15,
2670
+ sort: p.get('sort') || undefined,
2671
+ };
2672
+ }),
2673
+ // Cheap deep compare via JSON to avoid spam calls when nothing changed
2674
+ map((o) => JSON.stringify(o)), distinctUntilChanged(), map((s) => JSON.parse(s)), switchMap((params) => {
2675
+ this.loading = true;
2676
+ params['sort'] = 'updatedAt desc';
2677
+ return this.propertyService.findViewingsByUser(params).pipe(finalize(() => (this.loading = false)));
2678
+ }))
2679
+ .subscribe({
2669
2680
  next: (res) => {
2670
- this.viewings = res.data;
2681
+ this.viewings.set(res.data);
2682
+ this.meta = res.meta;
2683
+ this.length = res.meta.pagination.count;
2684
+ this.loading = false;
2685
+ },
2686
+ error: () => {
2687
+ this.viewings.set([]);
2688
+ this.length = 0;
2689
+ this.loading = false;
2671
2690
  },
2672
2691
  });
2673
- }
2674
- findProperties(ids) { }
2675
- resetFilter() {
2676
- this.filterOptions = {
2677
- type: '',
2678
- };
2679
- this.filter = false;
2680
- this.findViewings();
2692
+ // // auto-unsubscribe on destroy
2693
+ this.destroyRef.onDestroy(() => sub.unsubscribe());
2681
2694
  }
2682
2695
  statusCompareFn(t1, t2) {
2683
2696
  return t1 === t2;
2684
2697
  }
2685
- convertFilterOptions(jsonObj) {
2686
- return Object.entries(jsonObj)
2687
- .filter(([key, value]) => value !== '' && value !== undefined)
2688
- .map(([key, value]) => {
2689
- return `${key}:${value}`;
2690
- })
2691
- .join(',');
2698
+ onPage(e) {
2699
+ this.router.navigate([], {
2700
+ queryParams: { page: e.pageIndex + 1, limit: e.pageSize },
2701
+ queryParamsHandling: 'merge',
2702
+ replaceUrl: true, // optional: avoid stacking history on every page click
2703
+ });
2692
2704
  }
2693
2705
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyViewingIndexComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2694
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: PropertyViewingIndexComponent, isStandalone: true, selector: "rolatech-property-viewing-index", usesInheritance: true, ngImport: i0, template: "<rolatech-container>\n <rolatech-toolbar title=\"Viewings\" 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 (viewings) {\n @for (item of viewings; track item) {\n <rolatech-property-viewing-item [routerLink]=\"['./', item.id]\" [viewing]=\"item\"></rolatech-property-viewing-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: PropertyViewingItemComponent, selector: "rolatech-property-viewing-item", inputs: ["viewing"] }] });
2706
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: PropertyViewingIndexComponent, isStandalone: true, selector: "rolatech-property-viewing-index", usesInheritance: true, ngImport: i0, template: "<rolatech-container>\n <rolatech-toolbar title=\"Viewings\" 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 (viewings(); as viewings) {\n @for (item of viewings; track item) {\n <rolatech-property-viewing-item\n [loading]=\"loading\"\n [routerLink]=\"['./', item.id]\"\n [viewing]=\"item\"\n ></rolatech-property-viewing-item>\n }\n } @else {\n <rolatech-empty></rolatech-empty>\n }\n </rolatech-list>\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: PropertyViewingItemComponent, selector: "rolatech-property-viewing-item", inputs: ["viewing"] }, { 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"] }] });
2695
2707
  }
2696
2708
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyViewingIndexComponent, decorators: [{
2697
2709
  type: Component,
@@ -2714,7 +2726,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
2714
2726
  MatSelectModule,
2715
2727
  MatButtonModule,
2716
2728
  PropertyViewingItemComponent,
2717
- ], template: "<rolatech-container>\n <rolatech-toolbar title=\"Viewings\" 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 (viewings) {\n @for (item of viewings; track item) {\n <rolatech-property-viewing-item [routerLink]=\"['./', item.id]\" [viewing]=\"item\"></rolatech-property-viewing-item>\n }\n } @else {\n <rolatech-empty></rolatech-empty>\n }\n </rolatech-list>\n</rolatech-container>\n" }]
2729
+ MatPaginatorModule,
2730
+ ], template: "<rolatech-container>\n <rolatech-toolbar title=\"Viewings\" 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 (viewings(); as viewings) {\n @for (item of viewings; track item) {\n <rolatech-property-viewing-item\n [loading]=\"loading\"\n [routerLink]=\"['./', item.id]\"\n [viewing]=\"item\"\n ></rolatech-property-viewing-item>\n }\n } @else {\n <rolatech-empty></rolatech-empty>\n }\n </rolatech-list>\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" }]
2718
2731
  }] });
2719
2732
 
2720
2733
  class DuePipe {
@@ -2911,7 +2924,6 @@ class PropertyViewingDetailComponent extends BaseComponent {
2911
2924
  loadingTimeline = false;
2912
2925
  status = PropertyViewingStatus;
2913
2926
  env = inject(APP_CONFIG);
2914
- property;
2915
2927
  async ngOnInit() {
2916
2928
  this.route.params.subscribe((params) => {
2917
2929
  const id = params['id'];
@@ -2922,19 +2934,10 @@ class PropertyViewingDetailComponent extends BaseComponent {
2922
2934
  this.propertyService.getViewing(id).subscribe({
2923
2935
  next: (res) => {
2924
2936
  this.viewing = res.data;
2925
- this.getProperty(this.viewing.propertyId);
2926
2937
  // this.findAgentInfo();
2927
2938
  },
2928
2939
  });
2929
2940
  }
2930
- getProperty(propertyId) {
2931
- this.propertyService.get(propertyId).subscribe({
2932
- next: (res) => {
2933
- this.property = res.data;
2934
- this.getAgentPublicInfo(this.property.agentId);
2935
- },
2936
- });
2937
- }
2938
2941
  getAgentPublicInfo(agentId) {
2939
2942
  this.authUserService.getPublicUserInfo(agentId).subscribe({
2940
2943
  next: (res) => {
@@ -2954,7 +2957,7 @@ class PropertyViewingDetailComponent extends BaseComponent {
2954
2957
  });
2955
2958
  }
2956
2959
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyViewingDetailComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2957
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: PropertyViewingDetailComponent, isStandalone: true, selector: "rolatech-property-viewing-detail", usesInheritance: true, ngImport: i0, template: "@if (viewing) {\n <rolatech-container>\n <rolatech-toolbar [title]=\"status[viewing.status]\" large link=\"../\"> </rolatech-toolbar>\n <div>\n <div>\n <div class=\"text-lg font-bold py-2\" i18n>Property details</div>\n <hr class=\"mb-2\" />\n @if (property) {\n <div\n class=\"flex items-center py-2 cursor-pointer hover:bg-[--rt-raised-background]\"\n [routerLink]=\"['../../', property.id]\"\n >\n <div class=\"min-w-24 w-24 object-cover aspect-video rounded-md mr-3\">\n @defer {\n <rolatech-thumbnail [src]=\"property.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>{{ property.title }}</div>\n <div class=\"inline-flex gap-1 mt-2\">\n <div>\n <span class=\"mr-1\">{{ property.bedrooms }}</span>\n <span i18n>Bedrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ property.bathrooms }}</span>\n <span i18n>Bathrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ property.receptions }}</span>\n <span i18n>Receptions</span>\n </div>\n </div>\n </div>\n <div class=\"text-right\">\n <div class=\"text-sm\">{{ property.price | price }}</div>\n </div>\n </div>\n </div>\n <div class=\"hidden md:flex flex-col px-3\"></div>\n </div>\n }\n </div>\n\n <div>\n <div class=\"text-lg font-bold py-2\" i18n>Proposed times</div>\n <hr class=\"mb-2\" />\n @for (item of viewing.proposedSlots; track $index) {\n <div class=\"flex flex-row items-center gap-3 py-3\">\n <rolatech-rich-label label=\"Date\" [title]=\"item.date\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Time\" [title]=\"item.time\"></rolatech-rich-label>\n @if (viewing.viewingDate && viewing.viewingTime) {\n @if (item.date === viewing.viewingDate && item.time === viewing.viewingTime) {\n <div class=\"ml-3\"><button mat-flat-button i18n disabled=\"\">Confirmed</button></div>\n }\n }\n </div>\n }\n </div>\n <!-- safe area -->\n <div class=\"pb-16 sm:pb-3\"></div>\n <div class=\"\">\n <div class=\"flex items-center justify-end\">\n @if (viewing.status.toString() !== 'CANCELLED') {\n <button mat-flat-button class=\"min-h-11\" (click)=\"cancel()\" i18n>Cancel</button>\n }\n </div>\n </div>\n </div>\n </rolatech-container>\n}\n@if (info) {\n <div\n [ngClass]=\"loadingTimeline ? 'translate-x-full' : 'translate-none'\"\n class=\"fixed top-0 right-0 z-[1001] h-screen p-4 overflow-y-auto transition-transform bg-[--rt-raised-background] w-80 sm:w-[300px] shadow-xl\"\n >\n <div class=\"flex justify-between items-center sm:p-4\">\n <div class=\"text-xl font-bold\" i18n>Status</div>\n <button mat-icon-button (click)=\"info = !info\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n}\n\n<div\n (click)=\"info = !info\"\n [ngClass]=\"info ? 'visible' : 'invisible'\"\n class=\"bg-[--rt-10-percent-layer] fixed inset-0 z-[1000]\"\n></div>\n", styles: [""], 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: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: RichLabelComponent, selector: "rolatech-rich-label", inputs: ["label", "title"] }, { kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: PricePipe, name: "price" }], deferBlockDependencies: [() => [ThumbnailComponent]] });
2960
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: PropertyViewingDetailComponent, isStandalone: true, selector: "rolatech-property-viewing-detail", usesInheritance: true, ngImport: i0, template: "@if (viewing) {\n <rolatech-container>\n <rolatech-toolbar [title]=\"status[viewing.status]\" large link=\"../\"> </rolatech-toolbar>\n <div>\n @if (viewing.item) {\n <div>\n <div class=\"text-lg font-bold py-2\" i18n>Property details</div>\n <hr class=\"mb-2\" />\n <div\n class=\"flex items-center py-2 cursor-pointer hover:bg-[--rt-raised-background]\"\n [routerLink]=\"['../../', viewing.item.propertyId]\"\n >\n <div class=\"min-w-24 w-24 object-cover aspect-video rounded-md mr-3\">\n @defer {\n <rolatech-thumbnail [src]=\"viewing.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>{{ viewing.item.title }}</div>\n <div class=\"inline-flex gap-1 mt-2\">\n <div>\n <span class=\"mr-1\">{{ viewing.item.bedrooms }}</span>\n <span i18n>Bedrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ viewing.item.bathrooms }}</span>\n <span i18n>Bathrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ viewing.item.receptions }}</span>\n <span i18n>Receptions</span>\n </div>\n </div>\n </div>\n <div class=\"text-right\">\n <div class=\"text-sm\">{{ viewing.item.price | 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\n <div>\n <div class=\"text-lg font-bold py-2\" i18n>Proposed times</div>\n <hr class=\"mb-2\" />\n @for (item of viewing.proposedSlots; track $index) {\n <div class=\"flex flex-row items-center gap-3 py-3\">\n <rolatech-rich-label label=\"Date\" [title]=\"item.date\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Time\" [title]=\"item.time\"></rolatech-rich-label>\n @if (viewing.viewingDate && viewing.viewingTime) {\n @if (item.date === viewing.viewingDate && item.time === viewing.viewingTime) {\n <div class=\"ml-3\"><button mat-flat-button i18n disabled=\"\">Confirmed</button></div>\n }\n }\n </div>\n }\n </div>\n <!-- safe area -->\n <div class=\"pb-16 sm:pb-3\"></div>\n <div class=\"\">\n <div class=\"flex items-center justify-end\">\n @if (viewing.status.toString() !== 'CANCELLED') {\n <button mat-flat-button class=\"min-h-11\" (click)=\"cancel()\" i18n>Cancel</button>\n }\n </div>\n </div>\n </div>\n </rolatech-container>\n}\n@if (info) {\n <div\n [ngClass]=\"loadingTimeline ? 'translate-x-full' : 'translate-none'\"\n class=\"fixed top-0 right-0 z-[1001] h-screen p-4 overflow-y-auto transition-transform bg-[--rt-raised-background] w-80 sm:w-[300px] shadow-xl\"\n >\n <div class=\"flex justify-between items-center sm:p-4\">\n <div class=\"text-xl font-bold\" i18n>Status</div>\n <button mat-icon-button (click)=\"info = !info\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n}\n\n<div\n (click)=\"info = !info\"\n [ngClass]=\"info ? 'visible' : 'invisible'\"\n class=\"bg-[--rt-10-percent-layer] fixed inset-0 z-[1000]\"\n></div>\n", styles: [""], 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: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: RichLabelComponent, selector: "rolatech-rich-label", inputs: ["label", "title"] }, { kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: PricePipe, name: "price" }], deferBlockDependencies: [() => [ThumbnailComponent]] });
2958
2961
  }
2959
2962
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyViewingDetailComponent, decorators: [{
2960
2963
  type: Component,
@@ -2968,7 +2971,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
2968
2971
  ToolbarComponent,
2969
2972
  RouterLink,
2970
2973
  PricePipe,
2971
- ], template: "@if (viewing) {\n <rolatech-container>\n <rolatech-toolbar [title]=\"status[viewing.status]\" large link=\"../\"> </rolatech-toolbar>\n <div>\n <div>\n <div class=\"text-lg font-bold py-2\" i18n>Property details</div>\n <hr class=\"mb-2\" />\n @if (property) {\n <div\n class=\"flex items-center py-2 cursor-pointer hover:bg-[--rt-raised-background]\"\n [routerLink]=\"['../../', property.id]\"\n >\n <div class=\"min-w-24 w-24 object-cover aspect-video rounded-md mr-3\">\n @defer {\n <rolatech-thumbnail [src]=\"property.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>{{ property.title }}</div>\n <div class=\"inline-flex gap-1 mt-2\">\n <div>\n <span class=\"mr-1\">{{ property.bedrooms }}</span>\n <span i18n>Bedrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ property.bathrooms }}</span>\n <span i18n>Bathrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ property.receptions }}</span>\n <span i18n>Receptions</span>\n </div>\n </div>\n </div>\n <div class=\"text-right\">\n <div class=\"text-sm\">{{ property.price | price }}</div>\n </div>\n </div>\n </div>\n <div class=\"hidden md:flex flex-col px-3\"></div>\n </div>\n }\n </div>\n\n <div>\n <div class=\"text-lg font-bold py-2\" i18n>Proposed times</div>\n <hr class=\"mb-2\" />\n @for (item of viewing.proposedSlots; track $index) {\n <div class=\"flex flex-row items-center gap-3 py-3\">\n <rolatech-rich-label label=\"Date\" [title]=\"item.date\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Time\" [title]=\"item.time\"></rolatech-rich-label>\n @if (viewing.viewingDate && viewing.viewingTime) {\n @if (item.date === viewing.viewingDate && item.time === viewing.viewingTime) {\n <div class=\"ml-3\"><button mat-flat-button i18n disabled=\"\">Confirmed</button></div>\n }\n }\n </div>\n }\n </div>\n <!-- safe area -->\n <div class=\"pb-16 sm:pb-3\"></div>\n <div class=\"\">\n <div class=\"flex items-center justify-end\">\n @if (viewing.status.toString() !== 'CANCELLED') {\n <button mat-flat-button class=\"min-h-11\" (click)=\"cancel()\" i18n>Cancel</button>\n }\n </div>\n </div>\n </div>\n </rolatech-container>\n}\n@if (info) {\n <div\n [ngClass]=\"loadingTimeline ? 'translate-x-full' : 'translate-none'\"\n class=\"fixed top-0 right-0 z-[1001] h-screen p-4 overflow-y-auto transition-transform bg-[--rt-raised-background] w-80 sm:w-[300px] shadow-xl\"\n >\n <div class=\"flex justify-between items-center sm:p-4\">\n <div class=\"text-xl font-bold\" i18n>Status</div>\n <button mat-icon-button (click)=\"info = !info\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n}\n\n<div\n (click)=\"info = !info\"\n [ngClass]=\"info ? 'visible' : 'invisible'\"\n class=\"bg-[--rt-10-percent-layer] fixed inset-0 z-[1000]\"\n></div>\n" }]
2974
+ ], template: "@if (viewing) {\n <rolatech-container>\n <rolatech-toolbar [title]=\"status[viewing.status]\" large link=\"../\"> </rolatech-toolbar>\n <div>\n @if (viewing.item) {\n <div>\n <div class=\"text-lg font-bold py-2\" i18n>Property details</div>\n <hr class=\"mb-2\" />\n <div\n class=\"flex items-center py-2 cursor-pointer hover:bg-[--rt-raised-background]\"\n [routerLink]=\"['../../', viewing.item.propertyId]\"\n >\n <div class=\"min-w-24 w-24 object-cover aspect-video rounded-md mr-3\">\n @defer {\n <rolatech-thumbnail [src]=\"viewing.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>{{ viewing.item.title }}</div>\n <div class=\"inline-flex gap-1 mt-2\">\n <div>\n <span class=\"mr-1\">{{ viewing.item.bedrooms }}</span>\n <span i18n>Bedrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ viewing.item.bathrooms }}</span>\n <span i18n>Bathrooms</span>\n </div>\n <div>\n <span class=\"mr-1\">{{ viewing.item.receptions }}</span>\n <span i18n>Receptions</span>\n </div>\n </div>\n </div>\n <div class=\"text-right\">\n <div class=\"text-sm\">{{ viewing.item.price | 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\n <div>\n <div class=\"text-lg font-bold py-2\" i18n>Proposed times</div>\n <hr class=\"mb-2\" />\n @for (item of viewing.proposedSlots; track $index) {\n <div class=\"flex flex-row items-center gap-3 py-3\">\n <rolatech-rich-label label=\"Date\" [title]=\"item.date\"></rolatech-rich-label>\n <rolatech-rich-label label=\"Time\" [title]=\"item.time\"></rolatech-rich-label>\n @if (viewing.viewingDate && viewing.viewingTime) {\n @if (item.date === viewing.viewingDate && item.time === viewing.viewingTime) {\n <div class=\"ml-3\"><button mat-flat-button i18n disabled=\"\">Confirmed</button></div>\n }\n }\n </div>\n }\n </div>\n <!-- safe area -->\n <div class=\"pb-16 sm:pb-3\"></div>\n <div class=\"\">\n <div class=\"flex items-center justify-end\">\n @if (viewing.status.toString() !== 'CANCELLED') {\n <button mat-flat-button class=\"min-h-11\" (click)=\"cancel()\" i18n>Cancel</button>\n }\n </div>\n </div>\n </div>\n </rolatech-container>\n}\n@if (info) {\n <div\n [ngClass]=\"loadingTimeline ? 'translate-x-full' : 'translate-none'\"\n class=\"fixed top-0 right-0 z-[1001] h-screen p-4 overflow-y-auto transition-transform bg-[--rt-raised-background] w-80 sm:w-[300px] shadow-xl\"\n >\n <div class=\"flex justify-between items-center sm:p-4\">\n <div class=\"text-xl font-bold\" i18n>Status</div>\n <button mat-icon-button (click)=\"info = !info\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n}\n\n<div\n (click)=\"info = !info\"\n [ngClass]=\"info ? 'visible' : 'invisible'\"\n class=\"bg-[--rt-10-percent-layer] fixed inset-0 z-[1000]\"\n></div>\n" }]
2972
2975
  }] });
2973
2976
 
2974
2977
  class PropertyWishlistComponent extends BaseComponent {
@@ -3016,7 +3019,7 @@ const propertyRoutes = [
3016
3019
  children: [
3017
3020
  {
3018
3021
  path: '',
3019
- loadComponent: () => import('./rolatech-angular-property-property-index.component-CsZrVAXq.mjs').then((x) => x.PropertyIndexComponent),
3022
+ loadComponent: () => import('./rolatech-angular-property-property-index.component-DepoNMLG.mjs').then((x) => x.PropertyIndexComponent),
3020
3023
  },
3021
3024
  ],
3022
3025
  },
@@ -4930,7 +4933,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
4930
4933
  const propertyManageViewingsRoutes = [
4931
4934
  {
4932
4935
  path: '',
4933
- loadComponent: () => import('./rolatech-angular-property-property-manage-viewings-index.component-CHPBayaX.mjs').then((x) => x.PropertyManageViewingsIndexComponent),
4936
+ loadComponent: () => import('./rolatech-angular-property-property-manage-viewings-index.component-BmG4wx99.mjs').then((x) => x.PropertyManageViewingsIndexComponent),
4934
4937
  },
4935
4938
  {
4936
4939
  path: ':id',
@@ -5621,43 +5624,63 @@ class PropertyAgentViewingIndex extends BaseComponent {
5621
5624
  type: '',
5622
5625
  status: '',
5623
5626
  };
5624
- viewings = [];
5627
+ loading = false;
5628
+ viewings = signal([], ...(ngDevMode ? [{ debugName: "viewings" }] : []));
5629
+ meta;
5630
+ pageEvent;
5631
+ length = 100;
5632
+ pageSize = 15;
5633
+ pageSizeOptions = [5, 10, 25, 100];
5634
+ pageIndex = signal(0, ...(ngDevMode ? [{ debugName: "pageIndex" }] : []));
5625
5635
  ngOnInit() {
5626
- this.route.queryParams.subscribe(({ status }) => {
5627
- this.select = this.links.findIndex((item) => item.status === status);
5636
+ const sub = this.route.queryParamMap
5637
+ .pipe(map((p) => {
5638
+ const page = p.get('page') ? Number(p.get('page')) : 1;
5639
+ this.pageIndex.set(Math.max(page - 1, 0));
5640
+ const status = p.get('status') || undefined;
5641
+ let filter = '';
5628
5642
  if (status) {
5629
- this.filterOptions.status = status.toUpperCase();
5630
- }
5631
- else {
5632
- delete this.filterOptions.status;
5643
+ this.select = this.links.findIndex((item) => item.status === status);
5644
+ filter = `status:${status?.toUpperCase()}`;
5633
5645
  }
5634
- this.findViewings();
5635
- });
5636
- }
5637
- findViewings() {
5638
- const options = {
5639
- sort: 'updatedAt desc',
5640
- };
5641
- const filterString = this.convertFilterOptions(this.filterOptions);
5642
- if (filterString) {
5643
- options['filter'] = filterString;
5644
- }
5645
- this.propertyService.findViewingsByAgent(options).subscribe({
5646
+ return {
5647
+ page,
5648
+ filter,
5649
+ limit: p.get('limit') ? Number(p.get('limit')) : 15,
5650
+ sort: p.get('sort') || undefined,
5651
+ };
5652
+ }),
5653
+ // Cheap deep compare via JSON to avoid spam calls when nothing changed
5654
+ map((o) => JSON.stringify(o)), distinctUntilChanged(), map((s) => JSON.parse(s)), switchMap((params) => {
5655
+ this.loading = true;
5656
+ params['sort'] = 'updatedAt desc';
5657
+ return this.propertyService.findViewingsByAgent(params).pipe(finalize(() => (this.loading = false)));
5658
+ }))
5659
+ .subscribe({
5646
5660
  next: (res) => {
5647
- this.viewings = res.data;
5661
+ this.viewings.set(res.data);
5662
+ this.meta = res.meta;
5663
+ this.length = res.meta.pagination.count;
5664
+ this.loading = false;
5665
+ },
5666
+ error: () => {
5667
+ this.viewings.set([]);
5668
+ this.length = 0;
5669
+ this.loading = false;
5648
5670
  },
5649
5671
  });
5672
+ // // auto-unsubscribe on destroy
5673
+ this.destroyRef.onDestroy(() => sub.unsubscribe());
5650
5674
  }
5651
- convertFilterOptions(jsonObj) {
5652
- return Object.entries(jsonObj)
5653
- .filter(([key, value]) => value !== '' && value !== undefined)
5654
- .map(([key, value]) => {
5655
- return `${key}:${value}`;
5656
- })
5657
- .join(',');
5675
+ onPage(e) {
5676
+ this.router.navigate([], {
5677
+ queryParams: { page: e.pageIndex + 1, limit: e.pageSize },
5678
+ queryParamsHandling: 'merge',
5679
+ replaceUrl: true, // optional: avoid stacking history on every page click
5680
+ });
5658
5681
  }
5659
5682
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyAgentViewingIndex, deps: null, target: i0.ɵɵFactoryTarget.Component });
5660
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: PropertyAgentViewingIndex, isStandalone: true, selector: "rolatech-property-agent-viewing-index", usesInheritance: true, ngImport: i0, template: "<rolatech-toolbar title=\"Viewings\">\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<div>\n @if (viewings) { @for (item of viewings; track $index) {\n <rolatech-property-viewing-item [routerLink]=\"['./', item.id]\" [viewing]=\"item\"></rolatech-property-viewing-item>\n } } @else {\n <rolatech-empty></rolatech-empty>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "ngmodule", type: MatButtonModule }, { 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: EmptyComponent, selector: "rolatech-empty" }, { kind: "component", type: PropertyViewingItemComponent, selector: "rolatech-property-viewing-item", inputs: ["viewing"] }] });
5683
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: PropertyAgentViewingIndex, isStandalone: true, selector: "rolatech-property-agent-viewing-index", usesInheritance: true, ngImport: i0, template: "<rolatech-toolbar title=\"Viewings\">\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<div>\n @if (viewings(); as viewings) { @for (item of viewings; track $index) {\n <rolatech-property-viewing-item\n [loading]=\"loading\"\n [routerLink]=\"['./', item.id]\"\n [viewing]=\"item\"\n ></rolatech-property-viewing-item>\n } } @else {\n <rolatech-empty></rolatech-empty>\n }\n</div>\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: "ngmodule", type: MatButtonModule }, { 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: EmptyComponent, selector: "rolatech-empty" }, { kind: "component", type: PropertyViewingItemComponent, selector: "rolatech-property-viewing-item", inputs: ["viewing"] }, { 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"] }] });
5661
5684
  }
5662
5685
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: PropertyAgentViewingIndex, decorators: [{
5663
5686
  type: Component,
@@ -5670,7 +5693,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
5670
5693
  RouterModule,
5671
5694
  EmptyComponent,
5672
5695
  PropertyViewingItemComponent,
5673
- ], template: "<rolatech-toolbar title=\"Viewings\">\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<div>\n @if (viewings) { @for (item of viewings; track $index) {\n <rolatech-property-viewing-item [routerLink]=\"['./', item.id]\" [viewing]=\"item\"></rolatech-property-viewing-item>\n } } @else {\n <rolatech-empty></rolatech-empty>\n }\n</div>\n" }]
5696
+ MatPaginatorModule,
5697
+ ], template: "<rolatech-toolbar title=\"Viewings\">\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<div>\n @if (viewings(); as viewings) { @for (item of viewings; track $index) {\n <rolatech-property-viewing-item\n [loading]=\"loading\"\n [routerLink]=\"['./', item.id]\"\n [viewing]=\"item\"\n ></rolatech-property-viewing-item>\n } } @else {\n <rolatech-empty></rolatech-empty>\n }\n</div>\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" }]
5674
5698
  }] });
5675
5699
 
5676
5700
  class PropertyAgentViewingDetail extends BaseComponent {
@@ -6025,4 +6049,4 @@ const propertyManageOverviewRoutes = [
6025
6049
  */
6026
6050
 
6027
6051
  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 };
6028
- //# sourceMappingURL=rolatech-angular-property-rolatech-angular-property-CvuaMAgZ.mjs.map
6052
+ //# sourceMappingURL=rolatech-angular-property-rolatech-angular-property-BwNQMVlJ.mjs.map