@rolatech/angular-property 20.2.8-beta.2 → 20.2.8-beta.4

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,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, ElementRef, input, booleanAttribute, effect, HostBinding, ViewEncapsulation, Component, viewChild, PLATFORM_ID, output, computed, signal, model, EventEmitter, Injectable, Pipe, InjectionToken, ViewChild } from '@angular/core';
2
+ import { inject, ElementRef, input, booleanAttribute, effect, HostBinding, ViewEncapsulation, Component, viewChild, PLATFORM_ID, output, computed, signal, model, Injectable, EventEmitter, Pipe, InjectionToken, ViewChild } from '@angular/core';
3
3
  import * as i1$3 from '@angular/material/button';
4
4
  import { MatButtonModule } from '@angular/material/button';
5
5
  import * as i4$1 from '@angular/material/menu';
@@ -13,7 +13,7 @@ import { RouterLink, RouterModule, ActivatedRoute, Router, RouterLinkActive, Rou
13
13
  import { ThumbnailComponent, ImagePlaceholderComponent, Skeleton, ToolbarComponent, Loading, ImagePreviewDialogComponent, BaseComponent, AcceptDialogComponent, RejectDialogComponent, RichLabelComponent, AngularComponentsModule, ConfirmationDialogComponent, TabsComponent, TabComponent, EmptyComponent, ListComponent, ContainerComponent, SearchBar, MediaListComponent, MediaListItemComponent, InputComponent, SpinnerComponent } from '@rolatech/angular-components';
14
14
  import { PropertyService, FeatureService, PropertyOfferService, InvoiceService, FloorplanService, PropertyHighlightsService, TimeZoneService, PropertyOfferStatus as PropertyOfferStatus$1, PaymentService, TitleService, PropertySearchService, DialogService } from '@rolatech/angular-services';
15
15
  import * as i1 from '@angular/common';
16
- import { CommonModule, NgClass, isPlatformBrowser, ViewportScroller, KeyValuePipe, Location } from '@angular/common';
16
+ import { CommonModule, NgClass, isPlatformBrowser, ViewportScroller, Location, KeyValuePipe } from '@angular/common';
17
17
  import { PricePipe, APP_CONFIG, AngularCommonModule, OptionsFormatPipe, DecimalDirective, DurationPipe, SafeUrlPipe } from '@rolatech/angular-common';
18
18
  import * as i2 from '@angular/material/icon';
19
19
  import { MatIconModule, MatIcon } from '@angular/material/icon';
@@ -46,10 +46,10 @@ import { CommentsComponent } from '@rolatech/angular-comment';
46
46
  import { DomSanitizer } from '@angular/platform-browser';
47
47
  import * as i4$2 from '@angular/cdk/text-field';
48
48
  import { TextFieldModule } from '@angular/cdk/text-field';
49
- import * as i5 from '@angular/material/progress-spinner';
50
- import { MatProgressSpinner, MatProgressSpinnerModule } from '@angular/material/progress-spinner';
49
+ import * as i5$1 from '@angular/material/progress-spinner';
50
+ import { MatProgressSpinnerModule, MatProgressSpinner } from '@angular/material/progress-spinner';
51
51
  import { MatStepperModule } from '@angular/material/stepper';
52
- import * as i6$1 from '@angular/material/slide-toggle';
52
+ import * as i5 from '@angular/material/slide-toggle';
53
53
  import { MatSlideToggleModule } from '@angular/material/slide-toggle';
54
54
  import * as i2$4 from '@angular/material/expansion';
55
55
  import { MatExpansionModule } from '@angular/material/expansion';
@@ -1040,11 +1040,11 @@ class PropertyOfferItemComponent {
1040
1040
  return this.offer().amount.toFixed(2);
1041
1041
  }, ...(ngDevMode ? [{ debugName: "total" }] : []));
1042
1042
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PropertyOfferItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1043
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: PropertyOfferItemComponent, isStandalone: true, selector: "rolatech-property-offer-item", inputs: { offer: { classPropertyName: "offer", publicName: "offer", 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>Offer ID: {{ offer().id }}</span>\n </a>\n <span class=\"font-medium text-sm text-[--rt-brand-color]\">{{ status[offer().status] }}</span>\n </div>\n @if (offer().item) {\n <div class=\"flex flex-row py-2\">\n @if (offer().item.media.length > 0) {\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", styles: [""], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: ImagePlaceholderComponent, selector: "rolatech-image-placeholder", inputs: ["ratio"] }, { kind: "pipe", type: PricePipe, name: "price" }], deferBlockDependencies: [() => [ThumbnailComponent]] });
1043
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: PropertyOfferItemComponent, isStandalone: true, selector: "rolatech-property-offer-item", inputs: { offer: { classPropertyName: "offer", publicName: "offer", 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 <div class=\"flex items-center\">\n <span class=\"\">Offer: {{ offer().id }}</span>\n <!-- Type badge -->\n <span class=\"ml-3 px-2.5 py-1 border border-bg-[--rt-outline] rounded-full text-xs font-semibold\">\n {{ offer().type }}\n </span>\n </div>\n <span class=\"font-medium text-sm text-[--rt-brand-color]\">{{ status[offer().status] }}</span>\n </div>\n @if (offer().item) {\n <div class=\"flex flex-row py-2\">\n @if (offer().item.media.length > 0) {\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", styles: [""], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: ImagePlaceholderComponent, selector: "rolatech-image-placeholder", inputs: ["ratio"] }, { kind: "pipe", type: PricePipe, name: "price" }], deferBlockDependencies: [() => [ThumbnailComponent]] });
1044
1044
  }
1045
1045
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PropertyOfferItemComponent, decorators: [{
1046
1046
  type: Component,
1047
- 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 text-[--rt-brand-color]\">{{ status[offer().status] }}</span>\n </div>\n @if (offer().item) {\n <div class=\"flex flex-row py-2\">\n @if (offer().item.media.length > 0) {\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" }]
1047
+ 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 <div class=\"flex items-center\">\n <span class=\"\">Offer: {{ offer().id }}</span>\n <!-- Type badge -->\n <span class=\"ml-3 px-2.5 py-1 border border-bg-[--rt-outline] rounded-full text-xs font-semibold\">\n {{ offer().type }}\n </span>\n </div>\n <span class=\"font-medium text-sm text-[--rt-brand-color]\">{{ status[offer().status] }}</span>\n </div>\n @if (offer().item) {\n <div class=\"flex flex-row py-2\">\n @if (offer().item.media.length > 0) {\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" }]
1048
1048
  }], propDecorators: { offer: [{ type: i0.Input, args: [{ isSignal: true, alias: "offer", required: true }] }] } });
1049
1049
 
1050
1050
  class OfferItemSkeleton {
@@ -1066,9 +1066,9 @@ class PropertyManageOfferIndexComponent extends BaseComponent {
1066
1066
  icon: 'dashboard',
1067
1067
  },
1068
1068
  {
1069
- name: 'Created',
1069
+ name: 'Submitted',
1070
1070
  icon: 'category',
1071
- status: 'created',
1071
+ status: 'submitted',
1072
1072
  },
1073
1073
  {
1074
1074
  name: 'Accepted',
@@ -1158,7 +1158,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
1158
1158
  ], 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" }]
1159
1159
  }] });
1160
1160
 
1161
- const MY_FORMATS$a = {
1161
+ const MY_FORMATS$9 = {
1162
1162
  parse: {
1163
1163
  dateInput: 'YYYY-MM-DD',
1164
1164
  },
@@ -1183,7 +1183,7 @@ class OfferEdit extends BaseComponent {
1183
1183
  useClass: MomentDateAdapter,
1184
1184
  deps: [MAT_DATE_LOCALE],
1185
1185
  },
1186
- { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS$a },
1186
+ { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS$9 },
1187
1187
  ], 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>Offer 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$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.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: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.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 }] });
1188
1188
  }
1189
1189
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferEdit, decorators: [{
@@ -1194,16 +1194,291 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
1194
1194
  useClass: MomentDateAdapter,
1195
1195
  deps: [MAT_DATE_LOCALE],
1196
1196
  },
1197
- { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS$a },
1197
+ { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS$9 },
1198
1198
  ], 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>Offer 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"] }]
1199
1199
  }], propDecorators: { offer: [{ type: i0.Input, args: [{ isSignal: true, alias: "offer", required: true }] }, { type: i0.Output, args: ["offerChange"] }], output: [{ type: i0.Output, args: ["output"] }] } });
1200
1200
 
1201
+ class OfferDetailContext {
1202
+ api = inject(PropertyOfferService);
1203
+ // input
1204
+ offerId = signal(null, ...(ngDevMode ? [{ debugName: "offerId" }] : []));
1205
+ // state (single source of truth)
1206
+ offer = signal(null, ...(ngDevMode ? [{ debugName: "offer" }] : []));
1207
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
1208
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
1209
+ constructor() {
1210
+ effect(() => {
1211
+ const id = this.offerId();
1212
+ if (!id)
1213
+ return;
1214
+ this.fetchOffer(id);
1215
+ });
1216
+ }
1217
+ fetchOffer(id) {
1218
+ this.loading.set(true);
1219
+ this.error.set(null);
1220
+ this.api.getOffer(id).subscribe({
1221
+ next: (res) => {
1222
+ // adapt if your API shape is { data: ... }
1223
+ this.offer.set(res.data ?? res);
1224
+ },
1225
+ error: (err) => {
1226
+ this.error.set('Failed to load offer');
1227
+ console.error(err);
1228
+ },
1229
+ complete: () => {
1230
+ this.loading.set(false);
1231
+ },
1232
+ });
1233
+ }
1234
+ init(id) {
1235
+ this.offerId.set(id);
1236
+ }
1237
+ isRental = computed(() => this.offer()?.type === 'RENTAL', ...(ngDevMode ? [{ debugName: "isRental" }] : []));
1238
+ isSale = computed(() => this.offer()?.type === 'SALE', ...(ngDevMode ? [{ debugName: "isSale" }] : []));
1239
+ invoiceOptionLabel = {
1240
+ COMBINED: 'Combined',
1241
+ SEPARATE: 'Separate',
1242
+ };
1243
+ asText(v) {
1244
+ if (v === null || v === undefined)
1245
+ return '—';
1246
+ if (typeof v === 'string' && v.trim() === '')
1247
+ return '—';
1248
+ return String(v);
1249
+ }
1250
+ asBool(v) {
1251
+ if (v === null || v === undefined)
1252
+ return '—';
1253
+ return v ? 'Yes' : 'No';
1254
+ }
1255
+ asMoney(amount) {
1256
+ if (amount === null || amount === undefined)
1257
+ return '—';
1258
+ try {
1259
+ return new Intl.NumberFormat('en-GB', { style: 'currency', currency: 'GBP' }).format(amount);
1260
+ }
1261
+ catch {
1262
+ return String(amount);
1263
+ }
1264
+ }
1265
+ asList(list) {
1266
+ if (!list || list.length === 0)
1267
+ return '—';
1268
+ return list.join(', ');
1269
+ }
1270
+ ageFromDob(dob) {
1271
+ if (!dob)
1272
+ return '—';
1273
+ const birth = new Date(dob);
1274
+ if (Number.isNaN(birth.getTime()))
1275
+ return '—';
1276
+ const today = new Date();
1277
+ let age = today.getFullYear() - birth.getFullYear();
1278
+ const m = today.getMonth() - birth.getMonth();
1279
+ if (m < 0 || (m === 0 && today.getDate() < birth.getDate())) {
1280
+ age--;
1281
+ }
1282
+ return age >= 0 ? `${age}` : '—';
1283
+ }
1284
+ fullAddress(a) {
1285
+ if (!a)
1286
+ return '—';
1287
+ const parts = [a.line1, a.line2, a.city, a.postcode, a.country].filter((p) => !!p && p.trim() !== '');
1288
+ return parts.length ? parts.join(', ') : '—';
1289
+ }
1290
+ isEmptyAddress(a) {
1291
+ if (!a)
1292
+ return true;
1293
+ const parts = [a.line1, a.line2, a.city, a.postcode, a.country].map((v) => (v ?? '').trim());
1294
+ return parts.every((v) => v === '');
1295
+ }
1296
+ isEmptyGuarantor(g) {
1297
+ if (!g)
1298
+ return true;
1299
+ // treat "guarantor": { "address": {} } as empty
1300
+ const addressEmpty = this.isEmptyAddress(g.address);
1301
+ const fields = [
1302
+ g.fullName,
1303
+ g.dob,
1304
+ g.relationship,
1305
+ g.phone,
1306
+ g.email,
1307
+ g.type,
1308
+ g.employmentStatus,
1309
+ g.companyName,
1310
+ g.jobTitle,
1311
+ g.annualSalary,
1312
+ g.companyNumber,
1313
+ g.taxReturnSubmitted,
1314
+ g.additionalFinancialSupport,
1315
+ ];
1316
+ const fieldsEmpty = fields.every((v) => v === null || v === undefined || (typeof v === 'string' && v.trim() === ''));
1317
+ return addressEmpty && fieldsEmpty;
1318
+ }
1319
+ isIndividual(t) {
1320
+ return t.applicantType === 'INDIVIDUAL';
1321
+ }
1322
+ isCorporate(t) {
1323
+ return t.applicantType === 'CORPORATE';
1324
+ }
1325
+ isStudent(t) {
1326
+ return t.applicantType === 'STUDENT';
1327
+ }
1328
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferDetailContext, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1329
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferDetailContext });
1330
+ }
1331
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferDetailContext, decorators: [{
1332
+ type: Injectable
1333
+ }], ctorParameters: () => [] });
1334
+
1335
+ class OfferRentalTermsCard {
1336
+ ctx = inject(OfferDetailContext);
1337
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferRentalTermsCard, deps: [], target: i0.ɵɵFactoryTarget.Component });
1338
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: OfferRentalTermsCard, isStandalone: true, selector: "rolatech-offer-rental-terms-card", host: { classAttribute: "block" }, ngImport: i0, template: "@if (ctx.offer(); as o) {\n<section class=\"rounded-2xl border border-[--rt-outline] p-4 space-y-3\">\n <div>\n <div class=\"text-sm font-semibold\">Rental terms</div>\n <div class=\"text-xs text-[--rt-text-secondary]\">o.rentalTerms</div>\n </div>\n\n @if (o.rentalTerms; as rt) {\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-4 text-sm\">\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Amount</div>\n <div class=\"font-medium\">{{ rt.amount | price }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Move-in date</div>\n <div class=\"font-medium\">{{ rt.moveInDate ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Payment frequency</div>\n <div class=\"font-medium\">{{ rt.paymentFrequency ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Tenancy length</div>\n <div class=\"font-medium\">{{ rt.tenancyLengthMonths ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Break clause</div>\n <div class=\"font-medium\">{{ rt.breakClauseMonths ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Pets</div>\n <div class=\"font-medium\">{{ rt.pets.length > 0 ? rt.pets.join(', ') : '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Smoker</div>\n <div class=\"font-medium\">{{ rt.smoker === null ? '\u2014' : (rt.smoker ? 'Yes' : 'No') }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Furniture</div>\n <div class=\"font-medium\">{{ rt.furnitureRequirement ?? '\u2014' }}</div>\n </div>\n <div class=\"sm:col-span-2\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Additional requests</div>\n <div class=\"font-medium whitespace-pre-wrap\">{{ rt.additionalRequests ?? '\u2014' }}</div>\n </div>\n </div>\n }\n</section>\n}\n", styles: [""], dependencies: [{ kind: "pipe", type: PricePipe, name: "price" }], encapsulation: i0.ViewEncapsulation.None });
1339
+ }
1340
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferRentalTermsCard, decorators: [{
1341
+ type: Component,
1342
+ args: [{ selector: 'rolatech-offer-rental-terms-card', imports: [PricePipe], encapsulation: ViewEncapsulation.None, host: { class: 'block' }, template: "@if (ctx.offer(); as o) {\n<section class=\"rounded-2xl border border-[--rt-outline] p-4 space-y-3\">\n <div>\n <div class=\"text-sm font-semibold\">Rental terms</div>\n <div class=\"text-xs text-[--rt-text-secondary]\">o.rentalTerms</div>\n </div>\n\n @if (o.rentalTerms; as rt) {\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-4 text-sm\">\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Amount</div>\n <div class=\"font-medium\">{{ rt.amount | price }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Move-in date</div>\n <div class=\"font-medium\">{{ rt.moveInDate ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Payment frequency</div>\n <div class=\"font-medium\">{{ rt.paymentFrequency ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Tenancy length</div>\n <div class=\"font-medium\">{{ rt.tenancyLengthMonths ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Break clause</div>\n <div class=\"font-medium\">{{ rt.breakClauseMonths ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Pets</div>\n <div class=\"font-medium\">{{ rt.pets.length > 0 ? rt.pets.join(', ') : '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Smoker</div>\n <div class=\"font-medium\">{{ rt.smoker === null ? '\u2014' : (rt.smoker ? 'Yes' : 'No') }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Furniture</div>\n <div class=\"font-medium\">{{ rt.furnitureRequirement ?? '\u2014' }}</div>\n </div>\n <div class=\"sm:col-span-2\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Additional requests</div>\n <div class=\"font-medium whitespace-pre-wrap\">{{ rt.additionalRequests ?? '\u2014' }}</div>\n </div>\n </div>\n }\n</section>\n}\n" }]
1343
+ }] });
1344
+
1345
+ class OfferTenantExpanded {
1346
+ ctx = inject(OfferDetailContext);
1347
+ tenant = input.required(...(ngDevMode ? [{ debugName: "tenant" }] : []));
1348
+ formatAddress(a) {
1349
+ const parts = [a?.line1, a?.line2, a?.city, a?.postcode, a?.country].filter((v) => !!v && v.trim() !== '');
1350
+ return parts.length ? parts.join(', ') : '—';
1351
+ }
1352
+ genderLabel = {
1353
+ MALE: 'Male',
1354
+ FEMALE: 'Female',
1355
+ OTHER: 'Other',
1356
+ PREFER_NOT_TO_SAY: 'Prefer not to say',
1357
+ };
1358
+ guarantor = computed(() => this.tenant()?.guarantor ?? null, ...(ngDevMode ? [{ debugName: "guarantor" }] : []));
1359
+ hasGuarantor = computed(() => !!this.guarantor(), ...(ngDevMode ? [{ debugName: "hasGuarantor" }] : []));
1360
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferTenantExpanded, deps: [], target: i0.ɵɵFactoryTarget.Component });
1361
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: OfferTenantExpanded, isStandalone: true, selector: "rolatech-offer-tenant-expanded", inputs: { tenant: { classPropertyName: "tenant", publicName: "tenant", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"p-4 border-t border-[--rt-outline] space-y-4\">\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-4 text-sm\">\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Age</div>\n <div class=\"font-medium\">{{ ctx.ageFromDob(tenant().dob) }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Gender</div>\n <div class=\"font-medium\">@if (tenant().gender) { {{ genderLabel[tenant().gender!] }} } @else { \u2014 }</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Applicant type</div>\n <div class=\"font-medium\">{{ tenant().applicantType ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Nationality</div>\n <div class=\"font-medium\">{{ tenant().nationality }}</div>\n </div>\n\n <div class=\"sm:col-span-2\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Address</div>\n <div class=\"font-medium\">{{ formatAddress(tenant().address) }}</div>\n </div>\n </div>\n\n @switch (tenant().applicantType) { @case ('INDIVIDUAL') {\n <div class=\"rounded-xl border border-[--rt-outline] p-3 space-y-2\">\n <div class=\"text-xs font-semibold\">Individual</div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Employment</div>\n <div class=\"font-medium\">{{ tenant().employmentStatus ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Company</div>\n <div class=\"font-medium\">{{ tenant().companyName ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Job title</div>\n <div class=\"font-medium\">{{ tenant().jobTitle ?? '\u2014' }}</div>\n </div>\n </div>\n } @case ('CORPORATE') {\n <div class=\"rounded-xl border border-[--rt-outline] p-3 space-y-2\">\n <div class=\"text-xs font-semibold\">Corporate</div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Company</div>\n <div class=\"font-medium\">{{ tenant().corporateCompanyName ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Company number</div>\n <div class=\"font-medium\">{{ tenant().corporateCompanyNumber ?? '\u2014' }}</div>\n </div>\n </div>\n } @case ('STUDENT') {\n <div class=\"rounded-xl border border-[--rt-outline] p-3 space-y-2\">\n <div class=\"text-xs font-semibold\">Student</div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">University</div>\n <div class=\"font-medium\">{{ tenant().universityName ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Course</div>\n <div class=\"font-medium\">{{ tenant().courseTitle ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Years of study</div>\n <div class=\"font-medium\">{{ tenant().yearOfStudy ?? '-' }}</div>\n </div>\n </div>\n } }\n <!-- \u2705 Guarantor -->\n @if (hasGuarantor(); as _unused) { @if (guarantor(); as g) {\n <div class=\"mt-6 rounded-2xl border border-[--rt-outline] p-4\">\n <div class=\"flex items-center justify-between\">\n <div class=\"text-sm font-semibold\">Guarantor</div>\n <div class=\"text-xs text-[--rt-text-secondary]\">{{ g.type }}</div>\n </div>\n\n <div class=\"mt-3 grid grid-cols-12 gap-3 text-sm\">\n <div class=\"col-span-12 lg:col-span-6\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Full name</div>\n <div class=\"font-medium\">{{ g.fullName ?? '\u2014' }}</div>\n </div>\n\n <div class=\"col-span-12 lg:col-span-3\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Age</div>\n <div class=\"font-medium\">{{ ctx.ageFromDob(g.dob) }}</div>\n </div>\n\n <div class=\"col-span-12 lg:col-span-3\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Phone</div>\n <div class=\"font-medium\">{{ g.phone ?? '\u2014' }}</div>\n </div>\n\n <div class=\"col-span-12 lg:col-span-6\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Email</div>\n <div class=\"font-medium\">{{ g.email ?? '\u2014' }}</div>\n </div>\n\n <div class=\"col-span-12 lg:col-span-6\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Address</div>\n @if (g.address; as a) {\n <div class=\"font-medium\">\n {{ a.line1 ?? '\u2014' }} @if (a.line2) { <span>, {{ a.line2 }}</span> } @if (a.city) { <span>, {{ a.city }}</span> } @if\n (a.postcode) { <span>, {{ a.postcode }}</span> } @if (a.country) { <span>, {{ a.country }}</span> }\n </div>\n } @else {\n <div class=\"font-medium\">\u2014</div>\n }\n </div>\n\n <!-- INDIVIDUAL fields -->\n @if (g.type === 'INDIVIDUAL') {\n <div class=\"col-span-12 lg:col-span-4\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Employment status</div>\n <div class=\"font-medium\">{{ g.employmentStatus ?? '\u2014' }}</div>\n </div>\n\n @if (g.employmentStatus === 'EMPLOYED') {\n <div class=\"col-span-12 lg:col-span-4\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Job title</div>\n <div class=\"font-medium\">{{ g.jobTitle ?? '\u2014' }}</div>\n </div>\n\n <div class=\"col-span-12 lg:col-span-4\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Company name</div>\n <div class=\"font-medium\">{{ g.companyName ?? '\u2014' }}</div>\n </div>\n\n <div class=\"col-span-12 lg:col-span-4\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Annual salary</div>\n <div class=\"font-medium\">{{ g.annualSalary| price }}</div>\n </div>\n } @if (g.employmentStatus === 'SELF_EMPLOYED') {\n <div class=\"col-span-12 lg:col-span-6\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Company name</div>\n <div class=\"font-medium\">{{ g.companyName ?? '\u2014' }}</div>\n </div>\n\n <div class=\"col-span-12 lg:col-span-6\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Annual salary</div>\n <div class=\"font-medium\">{{ g.annualSalary ?? '\u2014' }}</div>\n </div>\n } @if (g.employmentStatus === 'UNEMPLOYED') {\n <div class=\"col-span-12\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Additional financial support</div>\n <div class=\"font-medium whitespace-pre-wrap\">{{ g.additionalFinancialSupport ?? '\u2014' }}</div>\n </div>\n } }\n\n <!-- COMPANY fields (if you later add them on backend) -->\n @if (g.type === 'COMPANY') {\n <div class=\"col-span-12\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Company guarantor</div>\n <div class=\"font-medium\">\u2014</div>\n </div>\n }\n </div>\n </div>\n } }\n</div>\n", styles: [""], dependencies: [{ kind: "pipe", type: PricePipe, name: "price" }] });
1362
+ }
1363
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferTenantExpanded, decorators: [{
1364
+ type: Component,
1365
+ args: [{ selector: 'rolatech-offer-tenant-expanded', imports: [PricePipe], template: "<div class=\"p-4 border-t border-[--rt-outline] space-y-4\">\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-4 text-sm\">\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Age</div>\n <div class=\"font-medium\">{{ ctx.ageFromDob(tenant().dob) }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Gender</div>\n <div class=\"font-medium\">@if (tenant().gender) { {{ genderLabel[tenant().gender!] }} } @else { \u2014 }</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Applicant type</div>\n <div class=\"font-medium\">{{ tenant().applicantType ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Nationality</div>\n <div class=\"font-medium\">{{ tenant().nationality }}</div>\n </div>\n\n <div class=\"sm:col-span-2\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Address</div>\n <div class=\"font-medium\">{{ formatAddress(tenant().address) }}</div>\n </div>\n </div>\n\n @switch (tenant().applicantType) { @case ('INDIVIDUAL') {\n <div class=\"rounded-xl border border-[--rt-outline] p-3 space-y-2\">\n <div class=\"text-xs font-semibold\">Individual</div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Employment</div>\n <div class=\"font-medium\">{{ tenant().employmentStatus ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Company</div>\n <div class=\"font-medium\">{{ tenant().companyName ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Job title</div>\n <div class=\"font-medium\">{{ tenant().jobTitle ?? '\u2014' }}</div>\n </div>\n </div>\n } @case ('CORPORATE') {\n <div class=\"rounded-xl border border-[--rt-outline] p-3 space-y-2\">\n <div class=\"text-xs font-semibold\">Corporate</div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Company</div>\n <div class=\"font-medium\">{{ tenant().corporateCompanyName ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Company number</div>\n <div class=\"font-medium\">{{ tenant().corporateCompanyNumber ?? '\u2014' }}</div>\n </div>\n </div>\n } @case ('STUDENT') {\n <div class=\"rounded-xl border border-[--rt-outline] p-3 space-y-2\">\n <div class=\"text-xs font-semibold\">Student</div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">University</div>\n <div class=\"font-medium\">{{ tenant().universityName ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Course</div>\n <div class=\"font-medium\">{{ tenant().courseTitle ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Years of study</div>\n <div class=\"font-medium\">{{ tenant().yearOfStudy ?? '-' }}</div>\n </div>\n </div>\n } }\n <!-- \u2705 Guarantor -->\n @if (hasGuarantor(); as _unused) { @if (guarantor(); as g) {\n <div class=\"mt-6 rounded-2xl border border-[--rt-outline] p-4\">\n <div class=\"flex items-center justify-between\">\n <div class=\"text-sm font-semibold\">Guarantor</div>\n <div class=\"text-xs text-[--rt-text-secondary]\">{{ g.type }}</div>\n </div>\n\n <div class=\"mt-3 grid grid-cols-12 gap-3 text-sm\">\n <div class=\"col-span-12 lg:col-span-6\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Full name</div>\n <div class=\"font-medium\">{{ g.fullName ?? '\u2014' }}</div>\n </div>\n\n <div class=\"col-span-12 lg:col-span-3\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Age</div>\n <div class=\"font-medium\">{{ ctx.ageFromDob(g.dob) }}</div>\n </div>\n\n <div class=\"col-span-12 lg:col-span-3\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Phone</div>\n <div class=\"font-medium\">{{ g.phone ?? '\u2014' }}</div>\n </div>\n\n <div class=\"col-span-12 lg:col-span-6\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Email</div>\n <div class=\"font-medium\">{{ g.email ?? '\u2014' }}</div>\n </div>\n\n <div class=\"col-span-12 lg:col-span-6\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Address</div>\n @if (g.address; as a) {\n <div class=\"font-medium\">\n {{ a.line1 ?? '\u2014' }} @if (a.line2) { <span>, {{ a.line2 }}</span> } @if (a.city) { <span>, {{ a.city }}</span> } @if\n (a.postcode) { <span>, {{ a.postcode }}</span> } @if (a.country) { <span>, {{ a.country }}</span> }\n </div>\n } @else {\n <div class=\"font-medium\">\u2014</div>\n }\n </div>\n\n <!-- INDIVIDUAL fields -->\n @if (g.type === 'INDIVIDUAL') {\n <div class=\"col-span-12 lg:col-span-4\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Employment status</div>\n <div class=\"font-medium\">{{ g.employmentStatus ?? '\u2014' }}</div>\n </div>\n\n @if (g.employmentStatus === 'EMPLOYED') {\n <div class=\"col-span-12 lg:col-span-4\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Job title</div>\n <div class=\"font-medium\">{{ g.jobTitle ?? '\u2014' }}</div>\n </div>\n\n <div class=\"col-span-12 lg:col-span-4\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Company name</div>\n <div class=\"font-medium\">{{ g.companyName ?? '\u2014' }}</div>\n </div>\n\n <div class=\"col-span-12 lg:col-span-4\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Annual salary</div>\n <div class=\"font-medium\">{{ g.annualSalary| price }}</div>\n </div>\n } @if (g.employmentStatus === 'SELF_EMPLOYED') {\n <div class=\"col-span-12 lg:col-span-6\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Company name</div>\n <div class=\"font-medium\">{{ g.companyName ?? '\u2014' }}</div>\n </div>\n\n <div class=\"col-span-12 lg:col-span-6\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Annual salary</div>\n <div class=\"font-medium\">{{ g.annualSalary ?? '\u2014' }}</div>\n </div>\n } @if (g.employmentStatus === 'UNEMPLOYED') {\n <div class=\"col-span-12\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Additional financial support</div>\n <div class=\"font-medium whitespace-pre-wrap\">{{ g.additionalFinancialSupport ?? '\u2014' }}</div>\n </div>\n } }\n\n <!-- COMPANY fields (if you later add them on backend) -->\n @if (g.type === 'COMPANY') {\n <div class=\"col-span-12\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Company guarantor</div>\n <div class=\"font-medium\">\u2014</div>\n </div>\n }\n </div>\n </div>\n } }\n</div>\n" }]
1366
+ }], propDecorators: { tenant: [{ type: i0.Input, args: [{ isSignal: true, alias: "tenant", required: true }] }] } });
1367
+
1368
+ class OfferTenantCard {
1369
+ // ---- signal inputs
1370
+ index = input.required(...(ngDevMode ? [{ debugName: "index" }] : []));
1371
+ expanded = input.required(...(ngDevMode ? [{ debugName: "expanded" }] : []));
1372
+ tenant = input.required(...(ngDevMode ? [{ debugName: "tenant" }] : []));
1373
+ // ---- label maps (for tooltips / pretty labels)
1374
+ paymentFrequencyLabel = {
1375
+ MONTHLY: 'Monthly',
1376
+ QUARTERLY: 'Quarterly',
1377
+ SEMI_ANNUALLY: 'Semi-annually',
1378
+ ANNUALLY: 'Annually',
1379
+ };
1380
+ furnitureRequirementLabel = {
1381
+ FURNISHED: 'Furnished',
1382
+ UNFURNISHED: 'Unfurnished',
1383
+ };
1384
+ applicantTypeLabel = {
1385
+ INDIVIDUAL: 'Individual',
1386
+ CORPORATE: 'Corporate',
1387
+ STUDENT: 'Student',
1388
+ };
1389
+ employmentStatusLabel = {
1390
+ EMPLOYED: 'Employed',
1391
+ SELF_EMPLOYED: 'Self-employed',
1392
+ UNEMPLOYED: 'Unemployed',
1393
+ };
1394
+ visaStatusLabel = {
1395
+ CITIZEN: 'Citizen',
1396
+ VISA_HOLDER: 'Visa Holder',
1397
+ WAITING_FOR_VISA: 'Waiting For Visa',
1398
+ NOT_YET_APPLIED_FOR_VISA: 'Not Yet Applied For Visa',
1399
+ };
1400
+ adverseCreditStatusLabel = {
1401
+ NONE: 'None',
1402
+ ACTIVE_CCJ: 'Active Ccj',
1403
+ SATISFIED_CCJ: 'Satisfied Ccj',
1404
+ DEBT_MANAGEMENT_PLAN: 'Debt Management Plan',
1405
+ LOW_CREDIT_SCORE: 'Low Credit Score',
1406
+ OTHER: 'Other',
1407
+ };
1408
+ // ---- callback input instead of Output
1409
+ onToggleInput = input.required(...(ngDevMode ? [{ debugName: "onToggleInput" }] : []));
1410
+ onToggle() {
1411
+ this.onToggleInput()(this.index());
1412
+ }
1413
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferTenantCard, deps: [], target: i0.ɵɵFactoryTarget.Component });
1414
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: OfferTenantCard, isStandalone: true, selector: "rolatech-offer-tenant-card", inputs: { index: { classPropertyName: "index", publicName: "index", isSignal: true, isRequired: true, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: true, transformFunction: null }, tenant: { classPropertyName: "tenant", publicName: "tenant", isSignal: true, isRequired: true, transformFunction: null }, onToggleInput: { classPropertyName: "onToggleInput", publicName: "onToggleInput", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"rounded-xl border border-[--rt-outline] bg-[--rt-base-background] overflow-hidden\">\n <button\n type=\"button\"\n class=\"w-full text-left p-4 flex items-start justify-between gap-3 hover:bg-[--rt-raised-background]\"\n (click)=\"onToggle()\"\n >\n <div class=\"min-w-0 space-y-1\">\n <div class=\"text-sm font-semibold truncate\">{{ tenant().fullName ?? '--' }}</div>\n <div class=\"text-xs text-[--rt-text-secondary] truncate\">{{ tenant().email ?? '--' }} \u00B7 {{ tenant().phone ?? '--' }}</div>\n <div class=\"flex flex-wrap gap-2 pt-1 text-xs\">\n <span class=\"px-2 py-1 rounded-full border\">\n @if (tenant().applicantType) { {{ applicantTypeLabel[tenant().applicantType!] }} } @else { Applicant: -- }\n </span>\n\n <span class=\"px-2 py-1 rounded-full border\">\n @if (tenant().employmentStatus) { {{ employmentStatusLabel[tenant().employmentStatus!] }} } @else { Employment: --}\n </span>\n\n <span class=\"px-2 py-1 rounded-full border\">\n @if (tenant().adverseCreditStatus) { {{ adverseCreditStatusLabel[tenant().adverseCreditStatus!] }} } @else { Credit:\n -- }\n </span>\n\n <span class=\"px-2 py-1 rounded-full border\">\n @if (tenant().visaStatus) { {{ visaStatusLabel[tenant().visaStatus!] }} } @else { Visa: \u2014 }\n </span>\n </div>\n </div>\n\n <div class=\"flex items-center gap-2 shrink-0\">\n <span class=\"text-xs px-2 py-1 rounded-full border\"> {{ expanded() ? 'Expanded' : 'Collapsed' }} </span>\n <svg class=\"w-4 h-4 transition-transform\" [class.rotate-180]=\"expanded()\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M5.23 7.21a.75.75 0 0 1 1.06.02L10 11.168l3.71-3.936a.75.75 0 1 1 1.08 1.04l-4.24 4.5a.75.75 0 0 1-1.08 0l-4.24-4.5a.75.75 0 0 1 .02-1.06z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </div>\n </button>\n\n @if (expanded()) {\n <rolatech-offer-tenant-expanded [tenant]=\"tenant()\" />\n }\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: OfferTenantExpanded, selector: "rolatech-offer-tenant-expanded", inputs: ["tenant"] }] });
1415
+ }
1416
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferTenantCard, decorators: [{
1417
+ type: Component,
1418
+ args: [{ selector: 'rolatech-offer-tenant-card', imports: [OfferTenantExpanded], template: "<div class=\"rounded-xl border border-[--rt-outline] bg-[--rt-base-background] overflow-hidden\">\n <button\n type=\"button\"\n class=\"w-full text-left p-4 flex items-start justify-between gap-3 hover:bg-[--rt-raised-background]\"\n (click)=\"onToggle()\"\n >\n <div class=\"min-w-0 space-y-1\">\n <div class=\"text-sm font-semibold truncate\">{{ tenant().fullName ?? '--' }}</div>\n <div class=\"text-xs text-[--rt-text-secondary] truncate\">{{ tenant().email ?? '--' }} \u00B7 {{ tenant().phone ?? '--' }}</div>\n <div class=\"flex flex-wrap gap-2 pt-1 text-xs\">\n <span class=\"px-2 py-1 rounded-full border\">\n @if (tenant().applicantType) { {{ applicantTypeLabel[tenant().applicantType!] }} } @else { Applicant: -- }\n </span>\n\n <span class=\"px-2 py-1 rounded-full border\">\n @if (tenant().employmentStatus) { {{ employmentStatusLabel[tenant().employmentStatus!] }} } @else { Employment: --}\n </span>\n\n <span class=\"px-2 py-1 rounded-full border\">\n @if (tenant().adverseCreditStatus) { {{ adverseCreditStatusLabel[tenant().adverseCreditStatus!] }} } @else { Credit:\n -- }\n </span>\n\n <span class=\"px-2 py-1 rounded-full border\">\n @if (tenant().visaStatus) { {{ visaStatusLabel[tenant().visaStatus!] }} } @else { Visa: \u2014 }\n </span>\n </div>\n </div>\n\n <div class=\"flex items-center gap-2 shrink-0\">\n <span class=\"text-xs px-2 py-1 rounded-full border\"> {{ expanded() ? 'Expanded' : 'Collapsed' }} </span>\n <svg class=\"w-4 h-4 transition-transform\" [class.rotate-180]=\"expanded()\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M5.23 7.21a.75.75 0 0 1 1.06.02L10 11.168l3.71-3.936a.75.75 0 1 1 1.08 1.04l-4.24 4.5a.75.75 0 0 1-1.08 0l-4.24-4.5a.75.75 0 0 1 .02-1.06z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </div>\n </button>\n\n @if (expanded()) {\n <rolatech-offer-tenant-expanded [tenant]=\"tenant()\" />\n }\n</div>\n" }]
1419
+ }], propDecorators: { index: [{ type: i0.Input, args: [{ isSignal: true, alias: "index", required: true }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: true }] }], tenant: [{ type: i0.Input, args: [{ isSignal: true, alias: "tenant", required: true }] }], onToggleInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "onToggleInput", required: true }] }] } });
1420
+
1421
+ class OfferTenantsAccordion {
1422
+ ctx = inject(OfferDetailContext);
1423
+ // tenants snapshot from ctx
1424
+ tenants = computed(() => this.ctx.offer()?.tenants ?? [], ...(ngDevMode ? [{ debugName: "tenants" }] : []));
1425
+ // index-based expanded state (per your requirement)
1426
+ expandedIndexes = signal(new Set(), ...(ngDevMode ? [{ debugName: "expandedIndexes" }] : []));
1427
+ isExpanded(i) {
1428
+ return this.expandedIndexes().has(i);
1429
+ }
1430
+ toggle = (index) => {
1431
+ this.expandedIndexes.update((prev) => {
1432
+ const next = new Set(prev);
1433
+ if (next.has(index))
1434
+ next.delete(index);
1435
+ else
1436
+ next.add(index);
1437
+ return next;
1438
+ });
1439
+ };
1440
+ expandAll(count) {
1441
+ const next = new Set();
1442
+ for (let i = 0; i < count; i++)
1443
+ next.add(i);
1444
+ this.expandedIndexes.set(next);
1445
+ }
1446
+ collapseAll() {
1447
+ this.expandedIndexes.set(new Set());
1448
+ }
1449
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferTenantsAccordion, deps: [], target: i0.ɵɵFactoryTarget.Component });
1450
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: OfferTenantsAccordion, isStandalone: true, selector: "rolatech-offer-tenants-accordion", host: { classAttribute: "block" }, ngImport: i0, template: "@if (tenants(); as ts) {\n<section class=\"rounded-2xl border border-[--rt-outline] p-4 space-y-3\">\n <div class=\"flex items-start justify-between gap-3\">\n <div>\n <div class=\"text-sm font-semibold\">Tenants</div>\n <div class=\"text-xs text-[--rt-text-secondary]\">o.tenants</div>\n </div>\n\n <div class=\"flex items-center gap-2\">\n <button\n type=\"button\"\n class=\"text-xs px-3 py-1 rounded-full border bg-[--rt-base-background]\"\n (click)=\"expandAll(ts.length)\"\n [disabled]=\"ts.length === 0\"\n >\n Expand all\n </button>\n <button\n type=\"button\"\n class=\"text-xs px-3 py-1 rounded-full border border-[--rt-outline] bg-[--rt-base-background]\"\n (click)=\"collapseAll()\"\n [disabled]=\"expandedIndexes().size === 0\"\n >\n Collapse all\n </button>\n <span class=\"text-xs px-2 py-1 rounded-full border border-[--rt-outline] bg-[--rt-base-background]\"\n >count: {{ ts.length }}</span\n >\n </div>\n </div>\n\n @if (ts.length > 0) {\n <div class=\"space-y-3\">\n @for (t of ts; track $index) {\n <rolatech-offer-tenant-card [index]=\"$index\" [expanded]=\"isExpanded($index)\" [tenant]=\"t\" [onToggleInput]=\"toggle\" />\n }\n </div>\n } @else {\n <div class=\"text-sm text-[--rt-text-secondary]\">No tenants</div>\n }\n</section>\n}\n", styles: [""], dependencies: [{ kind: "component", type: OfferTenantCard, selector: "rolatech-offer-tenant-card", inputs: ["index", "expanded", "tenant", "onToggleInput"] }], encapsulation: i0.ViewEncapsulation.None });
1451
+ }
1452
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferTenantsAccordion, decorators: [{
1453
+ type: Component,
1454
+ args: [{ selector: 'rolatech-offer-tenants-accordion', imports: [OfferTenantCard], encapsulation: ViewEncapsulation.None, host: { class: 'block' }, template: "@if (tenants(); as ts) {\n<section class=\"rounded-2xl border border-[--rt-outline] p-4 space-y-3\">\n <div class=\"flex items-start justify-between gap-3\">\n <div>\n <div class=\"text-sm font-semibold\">Tenants</div>\n <div class=\"text-xs text-[--rt-text-secondary]\">o.tenants</div>\n </div>\n\n <div class=\"flex items-center gap-2\">\n <button\n type=\"button\"\n class=\"text-xs px-3 py-1 rounded-full border bg-[--rt-base-background]\"\n (click)=\"expandAll(ts.length)\"\n [disabled]=\"ts.length === 0\"\n >\n Expand all\n </button>\n <button\n type=\"button\"\n class=\"text-xs px-3 py-1 rounded-full border border-[--rt-outline] bg-[--rt-base-background]\"\n (click)=\"collapseAll()\"\n [disabled]=\"expandedIndexes().size === 0\"\n >\n Collapse all\n </button>\n <span class=\"text-xs px-2 py-1 rounded-full border border-[--rt-outline] bg-[--rt-base-background]\"\n >count: {{ ts.length }}</span\n >\n </div>\n </div>\n\n @if (ts.length > 0) {\n <div class=\"space-y-3\">\n @for (t of ts; track $index) {\n <rolatech-offer-tenant-card [index]=\"$index\" [expanded]=\"isExpanded($index)\" [tenant]=\"t\" [onToggleInput]=\"toggle\" />\n }\n </div>\n } @else {\n <div class=\"text-sm text-[--rt-text-secondary]\">No tenants</div>\n }\n</section>\n}\n" }]
1455
+ }] });
1456
+
1457
+ class OfferItemCard {
1458
+ ctx = inject(OfferDetailContext);
1459
+ firstMediaUrl(o) {
1460
+ const m = o.item?.media?.[0];
1461
+ return m?.url ?? null;
1462
+ }
1463
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferItemCard, deps: [], target: i0.ɵɵFactoryTarget.Component });
1464
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: OfferItemCard, isStandalone: true, selector: "rolatech-offer-item-card", host: { classAttribute: "block" }, ngImport: i0, template: "@if (ctx.offer(); as o) {\n<section class=\"rounded-2xl border border-[--rt-outline] overflow-hidden\">\n <div class=\"p-4 flex items-start justify-between\">\n <div>\n <div class=\"text-sm font-semibold\">Property item</div>\n <div class=\"text-xs text-[--rt-text-secondary]\">property snapshot</div>\n </div>\n <span class=\"text-xs px-2 py-1 rounded-full border bg-[--rt-base-background]\"> propertyId: {{ o.item.propertyId }} </span>\n </div>\n\n <div class=\"p-4 pt-0 space-y-4\">\n <div class=\"flex flex-col lg:flex-row gap-4\">\n <img\n class=\"w-full lg:w-72 h-44 rounded-xl object-cover bg-gray-100\"\n [src]=\"firstMediaUrl(o) ?? '/assets/placeholder.jpg'\"\n [alt]=\"o.item.title\"\n />\n\n <div class=\"flex-1 space-y-2\">\n <div class=\"text-base font-semibold\">{{ o.item.title }}</div>\n\n <div class=\"grid grid-cols-2 gap-3 text-sm pt-2\">\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Amount</div>\n <div class=\"font-medium\">{{ o.item.amount | price }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Bedrooms</div>\n <div class=\"font-medium\">{{ o.item.bedrooms }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Bathrooms</div>\n <div class=\"font-medium\">{{ o.item.bathrooms }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Receptions</div>\n <div class=\"font-medium\">{{ o.item.receptions }}</div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</section>\n}\n", styles: [""], dependencies: [{ kind: "pipe", type: PricePipe, name: "price" }] });
1465
+ }
1466
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferItemCard, decorators: [{
1467
+ type: Component,
1468
+ args: [{ selector: 'rolatech-offer-item-card', imports: [PricePipe], host: { class: 'block' }, template: "@if (ctx.offer(); as o) {\n<section class=\"rounded-2xl border border-[--rt-outline] overflow-hidden\">\n <div class=\"p-4 flex items-start justify-between\">\n <div>\n <div class=\"text-sm font-semibold\">Property item</div>\n <div class=\"text-xs text-[--rt-text-secondary]\">property snapshot</div>\n </div>\n <span class=\"text-xs px-2 py-1 rounded-full border bg-[--rt-base-background]\"> propertyId: {{ o.item.propertyId }} </span>\n </div>\n\n <div class=\"p-4 pt-0 space-y-4\">\n <div class=\"flex flex-col lg:flex-row gap-4\">\n <img\n class=\"w-full lg:w-72 h-44 rounded-xl object-cover bg-gray-100\"\n [src]=\"firstMediaUrl(o) ?? '/assets/placeholder.jpg'\"\n [alt]=\"o.item.title\"\n />\n\n <div class=\"flex-1 space-y-2\">\n <div class=\"text-base font-semibold\">{{ o.item.title }}</div>\n\n <div class=\"grid grid-cols-2 gap-3 text-sm pt-2\">\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Amount</div>\n <div class=\"font-medium\">{{ o.item.amount | price }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Bedrooms</div>\n <div class=\"font-medium\">{{ o.item.bedrooms }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Bathrooms</div>\n <div class=\"font-medium\">{{ o.item.bathrooms }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Receptions</div>\n <div class=\"font-medium\">{{ o.item.receptions }}</div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</section>\n}\n" }]
1469
+ }] });
1470
+
1201
1471
  class PropertyManageOfferDetailComponent extends BaseComponent {
1202
1472
  propertyService = inject(PropertyService);
1203
1473
  propertyOfferService = inject(PropertyOfferService);
1204
1474
  authUserService = inject(AuthUserService);
1205
1475
  invoiceService = inject(InvoiceService);
1476
+ ctx = inject(OfferDetailContext);
1206
1477
  invoiceOptionDraft = signal(null, ...(ngDevMode ? [{ debugName: "invoiceOptionDraft" }] : []));
1478
+ invoiceOptionLabel = {
1479
+ COMBINED: 'Combined',
1480
+ SEPARATE: 'Separate',
1481
+ };
1207
1482
  offer;
1208
1483
  name = '';
1209
1484
  property;
@@ -1214,6 +1489,7 @@ class PropertyManageOfferDetailComponent extends BaseComponent {
1214
1489
  isSale = computed(() => this.offer.type.toString() === 'SALE', ...(ngDevMode ? [{ debugName: "isSale" }] : []));
1215
1490
  ngOnInit() {
1216
1491
  this.getOffer();
1492
+ this.ctx.init(this.id);
1217
1493
  }
1218
1494
  getOffer() {
1219
1495
  this.propertyOfferService.getOffer(this.id).subscribe({
@@ -1447,21 +1723,23 @@ class PropertyManageOfferDetailComponent extends BaseComponent {
1447
1723
  });
1448
1724
  }
1449
1725
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PropertyManageOfferDetailComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1450
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", 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 <button mat-flat-button (click)=\"copyText(true)\">\n <mat-icon>content_copy</mat-icon>\n <span i18n>Copy</span>\n </button>\n @if (offer.status.toString() === 'SUBMITTED') {\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)=\"underOffer()\" i18n>Under offer</button>\n }\n @if (offer.status.toString() === 'UNDER_OFFER') {\n <button mat-flat-button (click)=\"rfPassed()\" i18n>References passed</button>\n <button mat-flat-button (click)=\"rfFailed()\" i18n>References failed</button>\n }\n <!-- Completed -->\n @if (offer.status.toString() === 'MOVE_IN_PAYMENT_PAID') {\n <button mat-flat-button (click)=\"completed()\" i18n>Completed</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\n <div class=\"grid gap-4 lg:grid-cols-12 p-4\">\n <!-- Main column -->\n <div class=\"lg:col-span-8 space-y-4\">\n <!-- Summary card -->\n <section class=\"rounded-2xl border border-[--rt-border-color] bg-[--rt-base-background] p-4\">\n <div class=\"flex items-start justify-between gap-3\">\n <div>\n <div class=\"text-sm font-semibold\">Offer summary</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">Key details for pricing, move-in, and terms.</div>\n </div>\n </div>\n\n <div class=\"mt-4 grid gap-3 sm:grid-cols-2\">\n <div class=\"rounded-xl border border-[--rt-border-color] p-3\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Offer amount</div>\n <div class=\"mt-1 text-lg font-semibold\">\n {{ offer.rentalTerms?.amount | price }}\n <span class=\"text-sm font-medium text-[--rt-text-secondary]\">pcm</span>\n </div>\n </div>\n\n <div class=\"rounded-xl border border-[--rt-border-color] p-3\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Move-in date</div>\n <div class=\"mt-1 text-lg font-semibold\">{{ offer.rentalTerms?.moveInDate | date: 'mediumDate' }}</div>\n </div>\n\n <div class=\"rounded-xl border border-[--rt-border-color] p-3\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Tenancy term</div>\n <div class=\"mt-1 text-lg font-semibold\">\n {{ offer.rentalTerms?.tenancyLengthMonths }}\n <span class=\"text-sm font-medium text-[--rt-text-secondary]\">months</span>\n </div>\n </div>\n <div class=\"rounded-xl border border-[--rt-border-color] p-3\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Number of tenants</div>\n <div class=\"mt-1 text-lg font-semibold\">\n {{ offer.tenants?.length }} <span class=\"text-sm font-medium text-[--rt-text-secondary]\"></span>\n </div>\n </div>\n <div class=\"rounded-xl border border-[--rt-border-color] p-3\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Employment status</div>\n <div class=\"mt-1 text-lg font-semibold\">\n {{ offer.tenants }} <span class=\"text-sm font-medium text-[--rt-text-secondary]\"></span>\n </div>\n </div>\n </div>\n </section>\n <!-- Move-in billing -->\n <section class=\"rounded-2xl border border-[--rt-border-color] bg-[--rt-base-background] p-4\">\n <div class=\"flex items-start justify-between gap-3\">\n <div>\n <div class=\"text-sm font-semibold\">Move-in billing</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">\n Choose whether Security Deposit and First Rent are combined or separate invoices.\n </div>\n </div>\n\n <button mat-flat-button type=\"button\" (click)=\"saveInvoiceOption(offer.id)\">Save</button>\n </div>\n\n <div class=\"mt-4 rounded-xl border border-[--rt-border-color] bg-[--rt-surface-2] p-3\">\n <mat-radio-group class=\"block\" [value]=\"offer.invoiceOption\" (change)=\"setInvoiceOption($event.value)\">\n <div class=\"grid gap-2 sm:grid-cols-2\">\n <!-- Combined -->\n <div\n class=\"rounded-xl border border-[--rt-border-color] bg-[--rt-base-background] p-3 hover:border-[--rt-border-color] transition\"\n >\n <div class=\"flex items-start gap-3\">\n <mat-radio-button value=\"COMBINED\"></mat-radio-button>\n <div class=\"min-w-0\">\n <div class=\"text-sm font-semibold\">Combined</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">\n One invoice with 2 lines: Security deposit + First rent.\n </div>\n </div>\n </div>\n </div>\n\n <!-- Separate -->\n <div\n class=\"rounded-xl border border-[--rt-border-color] bg-[--rt-base-background] p-3 hover:border-[--rt-border-color] transition\"\n >\n <div class=\"flex items-start gap-3\">\n <mat-radio-button value=\"SEPARATE\"></mat-radio-button>\n <div class=\"min-w-0\">\n <div class=\"text-sm font-semibold\">Separate</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">\n Two invoices: Security deposit invoice, then First rent invoice.\n </div>\n </div>\n </div>\n </div>\n </div>\n </mat-radio-group>\n </div>\n </section>\n <!-- Property card -->\n <section class=\"rounded-2xl border border-[--rt-border-color] bg-[--rt-base-background] p-4\">\n <div class=\"flex items-start justify-between gap-3\">\n <div>\n <div class=\"text-sm font-semibold\">Property</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">Offer property snapshot.</div>\n </div>\n </div>\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>\n </section>\n </div>\n\n <!-- Right rail -->\n <div class=\"lg:col-span-4 space-y-4\">\n <!-- Offer user card -->\n <section class=\"rounded-2xl border border-[--rt-border-color] bg-[--rt-base-background] p-4\">\n <div class=\"flex items-start justify-between\">\n <div>\n <div class=\"text-sm font-semibold\">Applicant</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">Contact and identity details.</div>\n </div>\n </div>\n\n <div class=\"mt-4 flex items-center gap-3\">\n <div class=\"h-10 w-10 overflow-hidden rounded-full border bg-[--rt-surface-2]\"></div>\n\n <div class=\"min-w-0 flex-1\">\n <div class=\"truncate text-sm font-semibold\">{{ name }}</div>\n <div class=\"truncate text-xs text-[--rt-text-secondary]\">User ID: {{ offer.id }}</div>\n </div>\n </div>\n\n <div class=\"mt-4 space-y-2\">\n @if (offer.id) {\n <div class=\"flex items-center gap-2 text-sm\">\n <mat-icon class=\"!text-base text-[--rt-text-secondary]\">mail</mat-icon>\n <span class=\"truncate\">{{ offer.id }}</span>\n </div>\n }\n @if (offer.id) {\n <div class=\"flex items-center gap-2 text-sm\">\n <mat-icon class=\"!text-base text-[--rt-text-secondary]\">call</mat-icon>\n <span class=\"truncate\">{{ offer.id }}</span>\n </div>\n }\n </div>\n\n <div class=\"mt-4 grid grid-cols-2 gap-2\">\n <button mat-stroked-button type=\"button\" [disabled]=\"!offer.id\" (click)=\"emailApplicant(offer.id!)\">Email</button>\n <button mat-stroked-button type=\"button\" [disabled]=\"!offer.id\" (click)=\"callApplicant(offer.id!)\">Call</button>\n </div>\n </section>\n <!-- Offer viewing agent -->\n <section class=\"rounded-2xl border border-[--rt-border-color] bg-[--rt-base-background] p-4\">\n <div class=\"flex items-start justify-between\">\n <div>\n <div class=\"text-sm font-semibold\">Agent</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">Contact and identity details.</div>\n </div>\n </div>\n\n <div class=\"mt-4 flex items-center gap-3\">\n <div class=\"h-10 w-10 overflow-hidden rounded-full border bg-[--rt-surface-2]\"></div>\n\n <div class=\"min-w-0 flex-1\">\n <div class=\"truncate text-sm font-semibold\">{{ name }}</div>\n <div class=\"truncate text-xs text-[--rt-text-secondary]\">Agent ID: {{ offer.agentId }}</div>\n </div>\n </div>\n\n <div class=\"mt-4 space-y-2\">\n @if (offer.id) {\n <div class=\"flex items-center gap-2 text-sm\">\n <mat-icon class=\"!text-base text-[--rt-text-secondary]\">mail</mat-icon>\n <span class=\"truncate\">{{ offer.id }}</span>\n </div>\n }\n @if (agent) {\n <div class=\"flex items-center gap-2 text-sm\">\n <mat-icon class=\"!text-base text-[--rt-text-secondary]\">call</mat-icon>\n <span class=\"truncate\">{{ agent.phone }}</span>\n </div>\n }\n </div>\n\n <div class=\"mt-4 grid grid-cols-2 gap-2\">\n <button mat-stroked-button type=\"button\" [disabled]=\"!offer.id\" (click)=\"emailApplicant(offer.id!)\">Email</button>\n <button mat-stroked-button type=\"button\" [disabled]=\"!offer.id\" (click)=\"callApplicant(offer.id!)\">Call</button>\n </div>\n </section>\n\n <!-- Quick actions card (optional) -->\n <section class=\"rounded-2xl border border-[--rt-border-color] bg-[--rt-base-background] p-4\">\n <div class=\"text-sm font-semibold\">Quick actions</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">Common operations for this offer.</div>\n <div class=\"mt-4 space-y-2\">\n @if (offer.status.toString() === 'SUBMITTED') {\n <button mat-flat-button type=\"button\" class=\"w-full\" (click)=\"accept()\">Accept</button>\n <button mat-stroked-button type=\"button\" class=\"w-full\" (click)=\"counter()\">Counter</button>\n <button mat-stroked-button type=\"button\" class=\"w-full\" (click)=\"reject()\">Reject</button>\n }\n @if (offer.status.toString() === 'UNDER_OFFER') {\n <button mat-flat-button (click)=\"rfPassed()\" class=\"w-full\">References passed</button>\n <button mat-stroked-button (click)=\"rfFailed()\" class=\"w-full\">References failed</button>\n }\n </div>\n </section>\n </div>\n </div>\n\n <mat-menu #moreMenu=\"matMenu\" xPosition=\"after\" class=\"divide-y divide-light-900\">\n <button mat-menu-item (click)=\"copyText(true)\">\n <span i18n>Copy</span>\n </button>\n @if (offer.status.toString() === 'SUBMITTED') {\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() === 'UNDER_OFFER') {\n <button mat-menu-item (click)=\"rfPassed()\" i18n>References passed</button>\n <button mat-menu-item (click)=\"rfFailed()\" 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: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$3.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$3.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$1.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$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i4$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatRadioModule }, { kind: "directive", type: i3$1.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i3$1.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "ngmodule", type: FormsModule }, { kind: "pipe", type: i1.DatePipe, name: "date" }, { kind: "pipe", type: PricePipe, name: "price" }], deferBlockDependencies: [() => [ThumbnailComponent]] });
1726
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: PropertyManageOfferDetailComponent, isStandalone: true, selector: "rolatech-property-manage-offer-detail", providers: [OfferDetailContext], 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 <button mat-flat-button (click)=\"copyText(true)\">\n <mat-icon>content_copy</mat-icon>\n <span i18n>Copy</span>\n </button>\n @if (offer.status.toString() === 'SUBMITTED') {\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)=\"underOffer()\" i18n>Under offer</button>\n }\n @if (offer.status.toString() === 'UNDER_OFFER') {\n <button mat-flat-button (click)=\"rfPassed()\" i18n>References passed</button>\n <button mat-flat-button (click)=\"rfFailed()\" i18n>References failed</button>\n }\n <!-- Completed -->\n @if (offer.status.toString() === 'MOVE_IN_PAYMENT_PAID') {\n <button mat-flat-button (click)=\"completed()\" i18n>Completed</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\n <div class=\"grid grid-cols-1 lg:grid-cols-12 gap-4 p-4\">\n <!-- Main column -->\n <div class=\"grid grid-cols-1 lg:col-span-8 space-y-4\">\n <rolatech-offer-item-card />\n <!-- Summary card -->\n <section class=\"rounded-2xl border border-[--rt-border-color] bg-[--rt-base-background] p-4\">\n <div class=\"flex items-start justify-between gap-3\">\n <div>\n <div class=\"text-sm font-semibold\">Offer summary</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">Key details for pricing, move-in, and terms.</div>\n </div>\n </div>\n\n <div class=\"mt-4 grid gap-3 sm:grid-cols-2\">\n <div class=\"rounded-xl border border-[--rt-border-color] p-3\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Offer amount</div>\n <div class=\"mt-1 text-lg font-semibold\">\n {{ offer.rentalTerms?.amount | price }}\n <span class=\"text-sm font-medium text-[--rt-text-secondary]\">pcm</span>\n </div>\n </div>\n\n <div class=\"rounded-xl border border-[--rt-border-color] p-3\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Move-in date</div>\n <div class=\"mt-1 text-lg font-semibold\">{{ offer.rentalTerms?.moveInDate | date: 'mediumDate' }}</div>\n </div>\n\n <div class=\"rounded-xl border border-[--rt-border-color] p-3\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Tenancy term</div>\n <div class=\"mt-1 text-lg font-semibold\">\n {{ offer.rentalTerms?.tenancyLengthMonths }}\n <span class=\"text-sm font-medium text-[--rt-text-secondary]\">months</span>\n </div>\n </div>\n <div class=\"rounded-xl border border-[--rt-border-color] p-3\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Number of tenants</div>\n <div class=\"mt-1 text-lg font-semibold\">\n {{ offer.tenants?.length }} <span class=\"text-sm font-medium text-[--rt-text-secondary]\"></span>\n </div>\n </div>\n </div>\n </section>\n\n <!-- Tenants card -->\n @if (ctx.isRental()) {\n <rolatech-offer-rental-terms-card />\n <rolatech-offer-tenants-accordion />\n }\n </div>\n\n <!-- Right rail -->\n <div class=\"lg:col-span-4 space-y-4\">\n <!-- Move-in billing -->\n <section class=\"rounded-2xl border border-[--rt-border-color] bg-[--rt-base-background] p-4\">\n <div class=\"flex items-start justify-between gap-3\">\n <div>\n <div class=\"text-sm font-semibold\">Move-in billing</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">\n Choose whether Security Deposit and First Rent are combined or separate invoices.\n </div>\n </div>\n\n <button mat-flat-button type=\"button\" (click)=\"saveInvoiceOption(offer.id)\">Save</button>\n </div>\n\n <div class=\"mt-4 rounded-xl border border-[--rt-border-color] bg-[--rt-surface-2] p-3\">\n <mat-radio-group class=\"block\" [value]=\"offer.invoiceOption\" (change)=\"setInvoiceOption($event.value)\">\n <div class=\"grid grid-cols-1 gap-2\">\n <!-- Combined -->\n <div\n class=\"rounded-xl border border-[--rt-border-color] bg-[--rt-base-background] p-3 hover:border-[--rt-border-color] transition\"\n >\n <div class=\"flex items-start gap-3\">\n <mat-radio-button value=\"COMBINED\"></mat-radio-button>\n <div class=\"min-w-0\">\n <div class=\"text-sm font-semibold\">Combined</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">\n One invoice with 2 lines: Security deposit + First rent.\n </div>\n </div>\n </div>\n </div>\n\n <!-- Separate -->\n <div\n class=\"rounded-xl border border-[--rt-border-color] bg-[--rt-base-background] p-3 hover:border-[--rt-border-color] transition\"\n >\n <div class=\"flex items-start gap-3\">\n <mat-radio-button value=\"SEPARATE\"></mat-radio-button>\n <div class=\"min-w-0\">\n <div class=\"text-sm font-semibold\">Separate</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">\n Two invoices: Security deposit invoice, then First rent invoice.\n </div>\n </div>\n </div>\n </div>\n </div>\n </mat-radio-group>\n </div>\n </section>\n <!-- Offer user card -->\n <section class=\"rounded-2xl border border-[--rt-border-color] bg-[--rt-base-background] p-4\">\n <div class=\"flex items-start justify-between\">\n <div>\n <div class=\"text-sm font-semibold\">Applicant</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">Contact and identity details.</div>\n </div>\n </div>\n\n <div class=\"mt-4 flex items-center gap-3\">\n <div class=\"h-10 w-10 overflow-hidden rounded-full border bg-[--rt-surface-2]\"></div>\n\n <div class=\"min-w-0 flex-1\">\n <div class=\"truncate text-sm font-semibold\">{{ name }}</div>\n <div class=\"truncate text-xs text-[--rt-text-secondary]\">User ID: {{ offer.id }}</div>\n </div>\n </div>\n\n <div class=\"mt-4 space-y-2\">\n @if (offer.id) {\n <div class=\"flex items-center gap-2 text-sm\">\n <mat-icon class=\"!text-base text-[--rt-text-secondary]\">mail</mat-icon>\n <span class=\"truncate\">{{ offer.id }}</span>\n </div>\n }\n @if (offer.id) {\n <div class=\"flex items-center gap-2 text-sm\">\n <mat-icon class=\"!text-base text-[--rt-text-secondary]\">call</mat-icon>\n <span class=\"truncate\">{{ offer.id }}</span>\n </div>\n }\n </div>\n\n <div class=\"mt-4 grid grid-cols-2 gap-2\">\n <button mat-stroked-button type=\"button\" [disabled]=\"!offer.id\" (click)=\"emailApplicant(offer.id!)\">Email</button>\n <button mat-stroked-button type=\"button\" [disabled]=\"!offer.id\" (click)=\"callApplicant(offer.id!)\">Call</button>\n </div>\n </section>\n <!-- Offer viewing agent -->\n <section class=\"rounded-2xl border border-[--rt-border-color] bg-[--rt-base-background] p-4\">\n <div class=\"flex items-start justify-between\">\n <div>\n <div class=\"text-sm font-semibold\">Agent</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">Contact and identity details.</div>\n </div>\n </div>\n\n <div class=\"mt-4 flex items-center gap-3\">\n <div class=\"h-10 w-10 overflow-hidden rounded-full border bg-[--rt-surface-2]\"></div>\n\n <div class=\"min-w-0 flex-1\">\n <div class=\"truncate text-sm font-semibold\">{{ name }}</div>\n <div class=\"truncate text-xs text-[--rt-text-secondary]\">Agent ID: {{ offer.agentId }}</div>\n </div>\n </div>\n\n <div class=\"mt-4 space-y-2\">\n @if (offer.id) {\n <div class=\"flex items-center gap-2 text-sm\">\n <mat-icon class=\"!text-base text-[--rt-text-secondary]\">mail</mat-icon>\n <span class=\"truncate\">{{ offer.id }}</span>\n </div>\n }\n @if (agent) {\n <div class=\"flex items-center gap-2 text-sm\">\n <mat-icon class=\"!text-base text-[--rt-text-secondary]\">call</mat-icon>\n <span class=\"truncate\">{{ agent.phone }}</span>\n </div>\n }\n </div>\n\n <div class=\"mt-4 grid grid-cols-2 gap-2\">\n <button mat-stroked-button type=\"button\" [disabled]=\"!offer.id\" (click)=\"emailApplicant(offer.id!)\">Email</button>\n <button mat-stroked-button type=\"button\" [disabled]=\"!offer.id\" (click)=\"callApplicant(offer.id!)\">Call</button>\n </div>\n </section>\n\n <!-- Quick actions card (optional) -->\n <section class=\"rounded-2xl border border-[--rt-border-color] bg-[--rt-base-background] p-4\">\n <div class=\"text-sm font-semibold\">Quick actions</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">Common operations for this offer.</div>\n <div class=\"mt-4 space-y-2\">\n @if (offer.status.toString() === 'SUBMITTED') {\n <button mat-flat-button type=\"button\" class=\"w-full\" (click)=\"accept()\">Accept</button>\n <button mat-stroked-button type=\"button\" class=\"w-full\" (click)=\"counter()\">Counter</button>\n <button mat-stroked-button type=\"button\" class=\"w-full\" (click)=\"reject()\">Reject</button>\n }\n @if (offer.status.toString() === 'UNDER_OFFER') {\n <button mat-flat-button (click)=\"rfPassed()\" class=\"w-full\">References passed</button>\n <button mat-stroked-button (click)=\"rfFailed()\" class=\"w-full\">References failed</button>\n }\n </div>\n </section>\n </div>\n </div>\n\n <mat-menu #moreMenu=\"matMenu\" xPosition=\"after\" class=\"divide-y divide-light-900\">\n <button mat-menu-item (click)=\"copyText(true)\">\n <span i18n>Copy</span>\n </button>\n @if (offer.status.toString() === 'SUBMITTED') {\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() === 'UNDER_OFFER') {\n <button mat-menu-item (click)=\"rfPassed()\" i18n>References passed</button>\n <button mat-menu-item (click)=\"rfFailed()\" 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: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$3.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$3.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$1.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$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i4$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatRadioModule }, { kind: "directive", type: i3$1.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i3$1.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: OfferRentalTermsCard, selector: "rolatech-offer-rental-terms-card" }, { kind: "component", type: OfferTenantsAccordion, selector: "rolatech-offer-tenants-accordion" }, { kind: "component", type: OfferItemCard, selector: "rolatech-offer-item-card" }, { kind: "pipe", type: i1.DatePipe, name: "date" }, { kind: "pipe", type: PricePipe, name: "price" }] });
1451
1727
  }
1452
1728
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PropertyManageOfferDetailComponent, decorators: [{
1453
1729
  type: Component,
1454
1730
  args: [{ selector: 'rolatech-property-manage-offer-detail', imports: [
1455
1731
  CommonModule,
1456
1732
  ToolbarComponent,
1457
- ThumbnailComponent,
1458
1733
  MatButtonModule,
1459
1734
  MatIcon,
1460
1735
  MatMenuModule,
1461
1736
  PricePipe,
1462
1737
  MatRadioModule,
1463
1738
  FormsModule,
1464
- ], template: "@if (offer) {\n <rolatech-toolbar [title]=\"status[offer.status]\" large link=\"../\">\n <div class=\"hidden md:flex gap-2\">\n <button mat-flat-button (click)=\"copyText(true)\">\n <mat-icon>content_copy</mat-icon>\n <span i18n>Copy</span>\n </button>\n @if (offer.status.toString() === 'SUBMITTED') {\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)=\"underOffer()\" i18n>Under offer</button>\n }\n @if (offer.status.toString() === 'UNDER_OFFER') {\n <button mat-flat-button (click)=\"rfPassed()\" i18n>References passed</button>\n <button mat-flat-button (click)=\"rfFailed()\" i18n>References failed</button>\n }\n <!-- Completed -->\n @if (offer.status.toString() === 'MOVE_IN_PAYMENT_PAID') {\n <button mat-flat-button (click)=\"completed()\" i18n>Completed</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\n <div class=\"grid gap-4 lg:grid-cols-12 p-4\">\n <!-- Main column -->\n <div class=\"lg:col-span-8 space-y-4\">\n <!-- Summary card -->\n <section class=\"rounded-2xl border border-[--rt-border-color] bg-[--rt-base-background] p-4\">\n <div class=\"flex items-start justify-between gap-3\">\n <div>\n <div class=\"text-sm font-semibold\">Offer summary</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">Key details for pricing, move-in, and terms.</div>\n </div>\n </div>\n\n <div class=\"mt-4 grid gap-3 sm:grid-cols-2\">\n <div class=\"rounded-xl border border-[--rt-border-color] p-3\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Offer amount</div>\n <div class=\"mt-1 text-lg font-semibold\">\n {{ offer.rentalTerms?.amount | price }}\n <span class=\"text-sm font-medium text-[--rt-text-secondary]\">pcm</span>\n </div>\n </div>\n\n <div class=\"rounded-xl border border-[--rt-border-color] p-3\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Move-in date</div>\n <div class=\"mt-1 text-lg font-semibold\">{{ offer.rentalTerms?.moveInDate | date: 'mediumDate' }}</div>\n </div>\n\n <div class=\"rounded-xl border border-[--rt-border-color] p-3\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Tenancy term</div>\n <div class=\"mt-1 text-lg font-semibold\">\n {{ offer.rentalTerms?.tenancyLengthMonths }}\n <span class=\"text-sm font-medium text-[--rt-text-secondary]\">months</span>\n </div>\n </div>\n <div class=\"rounded-xl border border-[--rt-border-color] p-3\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Number of tenants</div>\n <div class=\"mt-1 text-lg font-semibold\">\n {{ offer.tenants?.length }} <span class=\"text-sm font-medium text-[--rt-text-secondary]\"></span>\n </div>\n </div>\n <div class=\"rounded-xl border border-[--rt-border-color] p-3\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Employment status</div>\n <div class=\"mt-1 text-lg font-semibold\">\n {{ offer.tenants }} <span class=\"text-sm font-medium text-[--rt-text-secondary]\"></span>\n </div>\n </div>\n </div>\n </section>\n <!-- Move-in billing -->\n <section class=\"rounded-2xl border border-[--rt-border-color] bg-[--rt-base-background] p-4\">\n <div class=\"flex items-start justify-between gap-3\">\n <div>\n <div class=\"text-sm font-semibold\">Move-in billing</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">\n Choose whether Security Deposit and First Rent are combined or separate invoices.\n </div>\n </div>\n\n <button mat-flat-button type=\"button\" (click)=\"saveInvoiceOption(offer.id)\">Save</button>\n </div>\n\n <div class=\"mt-4 rounded-xl border border-[--rt-border-color] bg-[--rt-surface-2] p-3\">\n <mat-radio-group class=\"block\" [value]=\"offer.invoiceOption\" (change)=\"setInvoiceOption($event.value)\">\n <div class=\"grid gap-2 sm:grid-cols-2\">\n <!-- Combined -->\n <div\n class=\"rounded-xl border border-[--rt-border-color] bg-[--rt-base-background] p-3 hover:border-[--rt-border-color] transition\"\n >\n <div class=\"flex items-start gap-3\">\n <mat-radio-button value=\"COMBINED\"></mat-radio-button>\n <div class=\"min-w-0\">\n <div class=\"text-sm font-semibold\">Combined</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">\n One invoice with 2 lines: Security deposit + First rent.\n </div>\n </div>\n </div>\n </div>\n\n <!-- Separate -->\n <div\n class=\"rounded-xl border border-[--rt-border-color] bg-[--rt-base-background] p-3 hover:border-[--rt-border-color] transition\"\n >\n <div class=\"flex items-start gap-3\">\n <mat-radio-button value=\"SEPARATE\"></mat-radio-button>\n <div class=\"min-w-0\">\n <div class=\"text-sm font-semibold\">Separate</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">\n Two invoices: Security deposit invoice, then First rent invoice.\n </div>\n </div>\n </div>\n </div>\n </div>\n </mat-radio-group>\n </div>\n </section>\n <!-- Property card -->\n <section class=\"rounded-2xl border border-[--rt-border-color] bg-[--rt-base-background] p-4\">\n <div class=\"flex items-start justify-between gap-3\">\n <div>\n <div class=\"text-sm font-semibold\">Property</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">Offer property snapshot.</div>\n </div>\n </div>\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>\n </section>\n </div>\n\n <!-- Right rail -->\n <div class=\"lg:col-span-4 space-y-4\">\n <!-- Offer user card -->\n <section class=\"rounded-2xl border border-[--rt-border-color] bg-[--rt-base-background] p-4\">\n <div class=\"flex items-start justify-between\">\n <div>\n <div class=\"text-sm font-semibold\">Applicant</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">Contact and identity details.</div>\n </div>\n </div>\n\n <div class=\"mt-4 flex items-center gap-3\">\n <div class=\"h-10 w-10 overflow-hidden rounded-full border bg-[--rt-surface-2]\"></div>\n\n <div class=\"min-w-0 flex-1\">\n <div class=\"truncate text-sm font-semibold\">{{ name }}</div>\n <div class=\"truncate text-xs text-[--rt-text-secondary]\">User ID: {{ offer.id }}</div>\n </div>\n </div>\n\n <div class=\"mt-4 space-y-2\">\n @if (offer.id) {\n <div class=\"flex items-center gap-2 text-sm\">\n <mat-icon class=\"!text-base text-[--rt-text-secondary]\">mail</mat-icon>\n <span class=\"truncate\">{{ offer.id }}</span>\n </div>\n }\n @if (offer.id) {\n <div class=\"flex items-center gap-2 text-sm\">\n <mat-icon class=\"!text-base text-[--rt-text-secondary]\">call</mat-icon>\n <span class=\"truncate\">{{ offer.id }}</span>\n </div>\n }\n </div>\n\n <div class=\"mt-4 grid grid-cols-2 gap-2\">\n <button mat-stroked-button type=\"button\" [disabled]=\"!offer.id\" (click)=\"emailApplicant(offer.id!)\">Email</button>\n <button mat-stroked-button type=\"button\" [disabled]=\"!offer.id\" (click)=\"callApplicant(offer.id!)\">Call</button>\n </div>\n </section>\n <!-- Offer viewing agent -->\n <section class=\"rounded-2xl border border-[--rt-border-color] bg-[--rt-base-background] p-4\">\n <div class=\"flex items-start justify-between\">\n <div>\n <div class=\"text-sm font-semibold\">Agent</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">Contact and identity details.</div>\n </div>\n </div>\n\n <div class=\"mt-4 flex items-center gap-3\">\n <div class=\"h-10 w-10 overflow-hidden rounded-full border bg-[--rt-surface-2]\"></div>\n\n <div class=\"min-w-0 flex-1\">\n <div class=\"truncate text-sm font-semibold\">{{ name }}</div>\n <div class=\"truncate text-xs text-[--rt-text-secondary]\">Agent ID: {{ offer.agentId }}</div>\n </div>\n </div>\n\n <div class=\"mt-4 space-y-2\">\n @if (offer.id) {\n <div class=\"flex items-center gap-2 text-sm\">\n <mat-icon class=\"!text-base text-[--rt-text-secondary]\">mail</mat-icon>\n <span class=\"truncate\">{{ offer.id }}</span>\n </div>\n }\n @if (agent) {\n <div class=\"flex items-center gap-2 text-sm\">\n <mat-icon class=\"!text-base text-[--rt-text-secondary]\">call</mat-icon>\n <span class=\"truncate\">{{ agent.phone }}</span>\n </div>\n }\n </div>\n\n <div class=\"mt-4 grid grid-cols-2 gap-2\">\n <button mat-stroked-button type=\"button\" [disabled]=\"!offer.id\" (click)=\"emailApplicant(offer.id!)\">Email</button>\n <button mat-stroked-button type=\"button\" [disabled]=\"!offer.id\" (click)=\"callApplicant(offer.id!)\">Call</button>\n </div>\n </section>\n\n <!-- Quick actions card (optional) -->\n <section class=\"rounded-2xl border border-[--rt-border-color] bg-[--rt-base-background] p-4\">\n <div class=\"text-sm font-semibold\">Quick actions</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">Common operations for this offer.</div>\n <div class=\"mt-4 space-y-2\">\n @if (offer.status.toString() === 'SUBMITTED') {\n <button mat-flat-button type=\"button\" class=\"w-full\" (click)=\"accept()\">Accept</button>\n <button mat-stroked-button type=\"button\" class=\"w-full\" (click)=\"counter()\">Counter</button>\n <button mat-stroked-button type=\"button\" class=\"w-full\" (click)=\"reject()\">Reject</button>\n }\n @if (offer.status.toString() === 'UNDER_OFFER') {\n <button mat-flat-button (click)=\"rfPassed()\" class=\"w-full\">References passed</button>\n <button mat-stroked-button (click)=\"rfFailed()\" class=\"w-full\">References failed</button>\n }\n </div>\n </section>\n </div>\n </div>\n\n <mat-menu #moreMenu=\"matMenu\" xPosition=\"after\" class=\"divide-y divide-light-900\">\n <button mat-menu-item (click)=\"copyText(true)\">\n <span i18n>Copy</span>\n </button>\n @if (offer.status.toString() === 'SUBMITTED') {\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() === 'UNDER_OFFER') {\n <button mat-menu-item (click)=\"rfPassed()\" i18n>References passed</button>\n <button mat-menu-item (click)=\"rfFailed()\" i18n>References failed</button>\n }\n <button mat-menu-item (click)=\"edit()\">Edit</button>\n </mat-menu>\n}\n" }]
1739
+ OfferRentalTermsCard,
1740
+ OfferTenantsAccordion,
1741
+ OfferItemCard,
1742
+ ], providers: [OfferDetailContext], template: "@if (offer) {\n <rolatech-toolbar [title]=\"status[offer.status]\" large link=\"../\">\n <div class=\"hidden md:flex gap-2\">\n <button mat-flat-button (click)=\"copyText(true)\">\n <mat-icon>content_copy</mat-icon>\n <span i18n>Copy</span>\n </button>\n @if (offer.status.toString() === 'SUBMITTED') {\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)=\"underOffer()\" i18n>Under offer</button>\n }\n @if (offer.status.toString() === 'UNDER_OFFER') {\n <button mat-flat-button (click)=\"rfPassed()\" i18n>References passed</button>\n <button mat-flat-button (click)=\"rfFailed()\" i18n>References failed</button>\n }\n <!-- Completed -->\n @if (offer.status.toString() === 'MOVE_IN_PAYMENT_PAID') {\n <button mat-flat-button (click)=\"completed()\" i18n>Completed</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\n <div class=\"grid grid-cols-1 lg:grid-cols-12 gap-4 p-4\">\n <!-- Main column -->\n <div class=\"grid grid-cols-1 lg:col-span-8 space-y-4\">\n <rolatech-offer-item-card />\n <!-- Summary card -->\n <section class=\"rounded-2xl border border-[--rt-border-color] bg-[--rt-base-background] p-4\">\n <div class=\"flex items-start justify-between gap-3\">\n <div>\n <div class=\"text-sm font-semibold\">Offer summary</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">Key details for pricing, move-in, and terms.</div>\n </div>\n </div>\n\n <div class=\"mt-4 grid gap-3 sm:grid-cols-2\">\n <div class=\"rounded-xl border border-[--rt-border-color] p-3\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Offer amount</div>\n <div class=\"mt-1 text-lg font-semibold\">\n {{ offer.rentalTerms?.amount | price }}\n <span class=\"text-sm font-medium text-[--rt-text-secondary]\">pcm</span>\n </div>\n </div>\n\n <div class=\"rounded-xl border border-[--rt-border-color] p-3\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Move-in date</div>\n <div class=\"mt-1 text-lg font-semibold\">{{ offer.rentalTerms?.moveInDate | date: 'mediumDate' }}</div>\n </div>\n\n <div class=\"rounded-xl border border-[--rt-border-color] p-3\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Tenancy term</div>\n <div class=\"mt-1 text-lg font-semibold\">\n {{ offer.rentalTerms?.tenancyLengthMonths }}\n <span class=\"text-sm font-medium text-[--rt-text-secondary]\">months</span>\n </div>\n </div>\n <div class=\"rounded-xl border border-[--rt-border-color] p-3\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Number of tenants</div>\n <div class=\"mt-1 text-lg font-semibold\">\n {{ offer.tenants?.length }} <span class=\"text-sm font-medium text-[--rt-text-secondary]\"></span>\n </div>\n </div>\n </div>\n </section>\n\n <!-- Tenants card -->\n @if (ctx.isRental()) {\n <rolatech-offer-rental-terms-card />\n <rolatech-offer-tenants-accordion />\n }\n </div>\n\n <!-- Right rail -->\n <div class=\"lg:col-span-4 space-y-4\">\n <!-- Move-in billing -->\n <section class=\"rounded-2xl border border-[--rt-border-color] bg-[--rt-base-background] p-4\">\n <div class=\"flex items-start justify-between gap-3\">\n <div>\n <div class=\"text-sm font-semibold\">Move-in billing</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">\n Choose whether Security Deposit and First Rent are combined or separate invoices.\n </div>\n </div>\n\n <button mat-flat-button type=\"button\" (click)=\"saveInvoiceOption(offer.id)\">Save</button>\n </div>\n\n <div class=\"mt-4 rounded-xl border border-[--rt-border-color] bg-[--rt-surface-2] p-3\">\n <mat-radio-group class=\"block\" [value]=\"offer.invoiceOption\" (change)=\"setInvoiceOption($event.value)\">\n <div class=\"grid grid-cols-1 gap-2\">\n <!-- Combined -->\n <div\n class=\"rounded-xl border border-[--rt-border-color] bg-[--rt-base-background] p-3 hover:border-[--rt-border-color] transition\"\n >\n <div class=\"flex items-start gap-3\">\n <mat-radio-button value=\"COMBINED\"></mat-radio-button>\n <div class=\"min-w-0\">\n <div class=\"text-sm font-semibold\">Combined</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">\n One invoice with 2 lines: Security deposit + First rent.\n </div>\n </div>\n </div>\n </div>\n\n <!-- Separate -->\n <div\n class=\"rounded-xl border border-[--rt-border-color] bg-[--rt-base-background] p-3 hover:border-[--rt-border-color] transition\"\n >\n <div class=\"flex items-start gap-3\">\n <mat-radio-button value=\"SEPARATE\"></mat-radio-button>\n <div class=\"min-w-0\">\n <div class=\"text-sm font-semibold\">Separate</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">\n Two invoices: Security deposit invoice, then First rent invoice.\n </div>\n </div>\n </div>\n </div>\n </div>\n </mat-radio-group>\n </div>\n </section>\n <!-- Offer user card -->\n <section class=\"rounded-2xl border border-[--rt-border-color] bg-[--rt-base-background] p-4\">\n <div class=\"flex items-start justify-between\">\n <div>\n <div class=\"text-sm font-semibold\">Applicant</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">Contact and identity details.</div>\n </div>\n </div>\n\n <div class=\"mt-4 flex items-center gap-3\">\n <div class=\"h-10 w-10 overflow-hidden rounded-full border bg-[--rt-surface-2]\"></div>\n\n <div class=\"min-w-0 flex-1\">\n <div class=\"truncate text-sm font-semibold\">{{ name }}</div>\n <div class=\"truncate text-xs text-[--rt-text-secondary]\">User ID: {{ offer.id }}</div>\n </div>\n </div>\n\n <div class=\"mt-4 space-y-2\">\n @if (offer.id) {\n <div class=\"flex items-center gap-2 text-sm\">\n <mat-icon class=\"!text-base text-[--rt-text-secondary]\">mail</mat-icon>\n <span class=\"truncate\">{{ offer.id }}</span>\n </div>\n }\n @if (offer.id) {\n <div class=\"flex items-center gap-2 text-sm\">\n <mat-icon class=\"!text-base text-[--rt-text-secondary]\">call</mat-icon>\n <span class=\"truncate\">{{ offer.id }}</span>\n </div>\n }\n </div>\n\n <div class=\"mt-4 grid grid-cols-2 gap-2\">\n <button mat-stroked-button type=\"button\" [disabled]=\"!offer.id\" (click)=\"emailApplicant(offer.id!)\">Email</button>\n <button mat-stroked-button type=\"button\" [disabled]=\"!offer.id\" (click)=\"callApplicant(offer.id!)\">Call</button>\n </div>\n </section>\n <!-- Offer viewing agent -->\n <section class=\"rounded-2xl border border-[--rt-border-color] bg-[--rt-base-background] p-4\">\n <div class=\"flex items-start justify-between\">\n <div>\n <div class=\"text-sm font-semibold\">Agent</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">Contact and identity details.</div>\n </div>\n </div>\n\n <div class=\"mt-4 flex items-center gap-3\">\n <div class=\"h-10 w-10 overflow-hidden rounded-full border bg-[--rt-surface-2]\"></div>\n\n <div class=\"min-w-0 flex-1\">\n <div class=\"truncate text-sm font-semibold\">{{ name }}</div>\n <div class=\"truncate text-xs text-[--rt-text-secondary]\">Agent ID: {{ offer.agentId }}</div>\n </div>\n </div>\n\n <div class=\"mt-4 space-y-2\">\n @if (offer.id) {\n <div class=\"flex items-center gap-2 text-sm\">\n <mat-icon class=\"!text-base text-[--rt-text-secondary]\">mail</mat-icon>\n <span class=\"truncate\">{{ offer.id }}</span>\n </div>\n }\n @if (agent) {\n <div class=\"flex items-center gap-2 text-sm\">\n <mat-icon class=\"!text-base text-[--rt-text-secondary]\">call</mat-icon>\n <span class=\"truncate\">{{ agent.phone }}</span>\n </div>\n }\n </div>\n\n <div class=\"mt-4 grid grid-cols-2 gap-2\">\n <button mat-stroked-button type=\"button\" [disabled]=\"!offer.id\" (click)=\"emailApplicant(offer.id!)\">Email</button>\n <button mat-stroked-button type=\"button\" [disabled]=\"!offer.id\" (click)=\"callApplicant(offer.id!)\">Call</button>\n </div>\n </section>\n\n <!-- Quick actions card (optional) -->\n <section class=\"rounded-2xl border border-[--rt-border-color] bg-[--rt-base-background] p-4\">\n <div class=\"text-sm font-semibold\">Quick actions</div>\n <div class=\"mt-1 text-xs text-[--rt-text-secondary]\">Common operations for this offer.</div>\n <div class=\"mt-4 space-y-2\">\n @if (offer.status.toString() === 'SUBMITTED') {\n <button mat-flat-button type=\"button\" class=\"w-full\" (click)=\"accept()\">Accept</button>\n <button mat-stroked-button type=\"button\" class=\"w-full\" (click)=\"counter()\">Counter</button>\n <button mat-stroked-button type=\"button\" class=\"w-full\" (click)=\"reject()\">Reject</button>\n }\n @if (offer.status.toString() === 'UNDER_OFFER') {\n <button mat-flat-button (click)=\"rfPassed()\" class=\"w-full\">References passed</button>\n <button mat-stroked-button (click)=\"rfFailed()\" class=\"w-full\">References failed</button>\n }\n </div>\n </section>\n </div>\n </div>\n\n <mat-menu #moreMenu=\"matMenu\" xPosition=\"after\" class=\"divide-y divide-light-900\">\n <button mat-menu-item (click)=\"copyText(true)\">\n <span i18n>Copy</span>\n </button>\n @if (offer.status.toString() === 'SUBMITTED') {\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() === 'UNDER_OFFER') {\n <button mat-menu-item (click)=\"rfPassed()\" i18n>References passed</button>\n <button mat-menu-item (click)=\"rfFailed()\" i18n>References failed</button>\n }\n <button mat-menu-item (click)=\"edit()\">Edit</button>\n </mat-menu>\n}\n" }]
1465
1743
  }] });
1466
1744
 
1467
1745
  const propertyManageOffersRoutes = [
@@ -1492,7 +1770,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
1492
1770
  }]
1493
1771
  }] });
1494
1772
 
1495
- const MY_FORMATS$9 = {
1773
+ const MY_FORMATS$8 = {
1496
1774
  parse: {
1497
1775
  dateInput: 'YYYY-MM-DD',
1498
1776
  },
@@ -1608,7 +1886,7 @@ class PropertyFilterBar {
1608
1886
  useClass: MomentDateAdapter,
1609
1887
  deps: [MAT_DATE_LOCALE],
1610
1888
  },
1611
- { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS$9 },
1889
+ { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS$8 },
1612
1890
  ], ngImport: i0, template: "<div class=\"px-2 mb-3 close\" [class.open]=\"show()\">\n <div class=\"flex flex-col h-min justify-center items-center gap-3\">\n <div class=\"flex flex-col md:flex-row gap-3 w-full items-center\">\n <div class=\"flex flex-col w-full md:w-1/4\">\n <div class=\"py-1\">Market</div>\n <div>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-select #select=\"matSelect\" placeholder=\"Market\" [(ngModel)]=\"options().market\">\n @for (m of market; track m) {\n <mat-option [value]=\"m\"> {{ m }} </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n </div>\n <div class=\"flex flex-col w-full md:w-1/4\">\n <div class=\"py-1\">Type</div>\n <div>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-select #select=\"matSelect\" placeholder=\"Type\" [(ngModel)]=\"options().type\">\n @for (type of types | keyvalue; track type) {\n <mat-option [value]=\"type.key\"> {{ type.value }} </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n </div>\n <div class=\"flex flex-col w-full md:w-1/4\">\n <div class=\"py-1\">Town</div>\n <div>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-select #select=\"matSelect\" placeholder=\"Town\" [(ngModel)]=\"options().town\">\n @for (town of towns; track town) {\n <mat-option [value]=\"town\"> {{ town }} </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n </div>\n <div class=\"flex flex-col w-full md:w-1/4\">\n <div class=\"py-1\">Available date</div>\n <div>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\" class=\"z-[1000]\">\n <input\n matInput\n placeholder=\"Available\"\n [matDatepicker]=\"startDatePicker\"\n [min]=\"minDate\"\n (focus)=\"startDatePicker.open()\"\n name=\"available\"\n [(ngModel)]=\"options().availableFrom\"\n (dateInput)=\"options().availableFrom = $event.value.format('YYYY-MM-DD')\"\n readonly\n />\n <mat-datepicker-toggle matIconPrefix [for]=\"startDatePicker\"></mat-datepicker-toggle>\n <mat-datepicker panelClass=\"datepicker-on-top\" #startDatePicker></mat-datepicker>\n </mat-form-field>\n </div>\n </div>\n </div>\n <div class=\"flex flex-col md:flex-row gap-3 w-full items-center\">\n <div class=\"flex flex-col w-full md:w-1/3 overflow-hidden\">\n <div class=\"py-1\">Price range (\u00A3)</div>\n <div class=\"flex flex-row items-center\">\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-label>Min (PCM)</mat-label>\n <mat-select [(ngModel)]=\"options().minPrice\">\n @for (opt of minOptions(); track opt.value) {\n <mat-option [value]=\"opt.value\">{{ opt.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n <div class=\"px-2\">-</div>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-label>Max (PCM)</mat-label>\n <mat-select [(ngModel)]=\"options().maxPrice\">\n @for (opt of maxOptions(); track opt.value) {\n <mat-option [value]=\"opt.value\">{{ opt.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n </div>\n <div class=\"flex flex-col w-full md:w-1/3\">\n <div class=\"py-1\">No. of bedrooms</div>\n <div class=\"flex flex-row items-center\">\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-label>Min</mat-label>\n <mat-select [(ngModel)]=\"options().minBedrooms\">\n @for (opt of minBedroom(); track opt.value) {\n <mat-option [value]=\"opt.value\">{{ opt.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n <div class=\"px-2\">-</div>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-label>Max</mat-label>\n <mat-select [(ngModel)]=\"options().maxBedrooms\">\n @for (opt of maxBedRoom(); track opt.value) {\n <mat-option [value]=\"opt.value\">{{ opt.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n </div>\n <div class=\"h-14 md:w-1/3 self-end w-full\">\n <button mat-flat-button (click)=\"onSearch()\" class=\"w-full min-h-14\">\n <a i18n>Search</a>\n </button>\n </div>\n </div>\n </div>\n</div>\n", styles: ["mat-form-field{width:100%}.close{max-height:0;overflow:hidden;transition:max-height .5s cubic-bezier(.4,0,.2,1)}.open{max-height:1000px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { 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: "pipe", type: i1.KeyValuePipe, name: "keyvalue" }], encapsulation: i0.ViewEncapsulation.None });
1613
1891
  }
1614
1892
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PropertyFilterBar, decorators: [{
@@ -1628,7 +1906,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
1628
1906
  useClass: MomentDateAdapter,
1629
1907
  deps: [MAT_DATE_LOCALE],
1630
1908
  },
1631
- { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS$9 },
1909
+ { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS$8 },
1632
1910
  ], encapsulation: ViewEncapsulation.None, template: "<div class=\"px-2 mb-3 close\" [class.open]=\"show()\">\n <div class=\"flex flex-col h-min justify-center items-center gap-3\">\n <div class=\"flex flex-col md:flex-row gap-3 w-full items-center\">\n <div class=\"flex flex-col w-full md:w-1/4\">\n <div class=\"py-1\">Market</div>\n <div>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-select #select=\"matSelect\" placeholder=\"Market\" [(ngModel)]=\"options().market\">\n @for (m of market; track m) {\n <mat-option [value]=\"m\"> {{ m }} </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n </div>\n <div class=\"flex flex-col w-full md:w-1/4\">\n <div class=\"py-1\">Type</div>\n <div>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-select #select=\"matSelect\" placeholder=\"Type\" [(ngModel)]=\"options().type\">\n @for (type of types | keyvalue; track type) {\n <mat-option [value]=\"type.key\"> {{ type.value }} </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n </div>\n <div class=\"flex flex-col w-full md:w-1/4\">\n <div class=\"py-1\">Town</div>\n <div>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-select #select=\"matSelect\" placeholder=\"Town\" [(ngModel)]=\"options().town\">\n @for (town of towns; track town) {\n <mat-option [value]=\"town\"> {{ town }} </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n </div>\n <div class=\"flex flex-col w-full md:w-1/4\">\n <div class=\"py-1\">Available date</div>\n <div>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\" class=\"z-[1000]\">\n <input\n matInput\n placeholder=\"Available\"\n [matDatepicker]=\"startDatePicker\"\n [min]=\"minDate\"\n (focus)=\"startDatePicker.open()\"\n name=\"available\"\n [(ngModel)]=\"options().availableFrom\"\n (dateInput)=\"options().availableFrom = $event.value.format('YYYY-MM-DD')\"\n readonly\n />\n <mat-datepicker-toggle matIconPrefix [for]=\"startDatePicker\"></mat-datepicker-toggle>\n <mat-datepicker panelClass=\"datepicker-on-top\" #startDatePicker></mat-datepicker>\n </mat-form-field>\n </div>\n </div>\n </div>\n <div class=\"flex flex-col md:flex-row gap-3 w-full items-center\">\n <div class=\"flex flex-col w-full md:w-1/3 overflow-hidden\">\n <div class=\"py-1\">Price range (\u00A3)</div>\n <div class=\"flex flex-row items-center\">\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-label>Min (PCM)</mat-label>\n <mat-select [(ngModel)]=\"options().minPrice\">\n @for (opt of minOptions(); track opt.value) {\n <mat-option [value]=\"opt.value\">{{ opt.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n <div class=\"px-2\">-</div>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-label>Max (PCM)</mat-label>\n <mat-select [(ngModel)]=\"options().maxPrice\">\n @for (opt of maxOptions(); track opt.value) {\n <mat-option [value]=\"opt.value\">{{ opt.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n </div>\n <div class=\"flex flex-col w-full md:w-1/3\">\n <div class=\"py-1\">No. of bedrooms</div>\n <div class=\"flex flex-row items-center\">\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-label>Min</mat-label>\n <mat-select [(ngModel)]=\"options().minBedrooms\">\n @for (opt of minBedroom(); track opt.value) {\n <mat-option [value]=\"opt.value\">{{ opt.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n <div class=\"px-2\">-</div>\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-label>Max</mat-label>\n <mat-select [(ngModel)]=\"options().maxBedrooms\">\n @for (opt of maxBedRoom(); track opt.value) {\n <mat-option [value]=\"opt.value\">{{ opt.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n </div>\n <div class=\"h-14 md:w-1/3 self-end w-full\">\n <button mat-flat-button (click)=\"onSearch()\" class=\"w-full min-h-14\">\n <a i18n>Search</a>\n </button>\n </div>\n </div>\n </div>\n</div>\n", styles: ["mat-form-field{width:100%}.close{max-height:0;overflow:hidden;transition:max-height .5s cubic-bezier(.4,0,.2,1)}.open{max-height:1000px}\n"] }]
1633
1911
  }], ctorParameters: () => [], propDecorators: { search: [{ type: i0.Output, args: ["search"] }], reset: [{ type: i0.Output, args: ["reset"] }], show: [{ type: i0.Input, args: [{ isSignal: true, alias: "show", required: false }] }, { type: i0.Output, args: ["showChange"] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }, { type: i0.Output, args: ["optionsChange"] }] } });
1634
1912
 
@@ -2302,7 +2580,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
2302
2580
  ], 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" }]
2303
2581
  }], ctorParameters: () => [] });
2304
2582
 
2305
- const MY_FORMATS$8 = {
2583
+ const MY_FORMATS$7 = {
2306
2584
  parse: {
2307
2585
  dateInput: 'YYYY-MM-DD',
2308
2586
  },
@@ -2337,7 +2615,7 @@ class PropertyViewingTimeComponent {
2337
2615
  useClass: MomentDateAdapter,
2338
2616
  deps: [MAT_DATE_LOCALE],
2339
2617
  },
2340
- { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS$8 },
2618
+ { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS$7 },
2341
2619
  ], ngImport: i0, template: "<div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Viewing Date</mat-label>\n <!-- [max]=\"maxDate\" -->\n <input\n matInput\n placeholder=\"Viewing date\"\n [matDatepicker]=\"startDatePicker\"\n [min]=\"minDate\"\n (focus)=\"startDatePicker.open()\"\n name=\"viewingDate\"\n [(ngModel)]=\"proposedTime()!.date\"\n (dateInput)=\"proposedTime()!.date = $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 <mat-form-field appearance=\"fill\">\n <mat-label i18n>Viewing time</mat-label>\n <mat-icon matIconPrefix>schedule</mat-icon>\n <mat-select [(ngModel)]=\"proposedTime()!.time\" required readonly>\n @for (d of time; track d) {\n <mat-option [value]=\"d\">\n {{ d }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n</div>\n", styles: ["mat-form-field{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { 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: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }] });
2342
2620
  }
2343
2621
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PropertyViewingTimeComponent, decorators: [{
@@ -2357,11 +2635,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
2357
2635
  useClass: MomentDateAdapter,
2358
2636
  deps: [MAT_DATE_LOCALE],
2359
2637
  },
2360
- { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS$8 },
2638
+ { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS$7 },
2361
2639
  ], template: "<div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Viewing Date</mat-label>\n <!-- [max]=\"maxDate\" -->\n <input\n matInput\n placeholder=\"Viewing date\"\n [matDatepicker]=\"startDatePicker\"\n [min]=\"minDate\"\n (focus)=\"startDatePicker.open()\"\n name=\"viewingDate\"\n [(ngModel)]=\"proposedTime()!.date\"\n (dateInput)=\"proposedTime()!.date = $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 <mat-form-field appearance=\"fill\">\n <mat-label i18n>Viewing time</mat-label>\n <mat-icon matIconPrefix>schedule</mat-icon>\n <mat-select [(ngModel)]=\"proposedTime()!.time\" required readonly>\n @for (d of time; track d) {\n <mat-option [value]=\"d\">\n {{ d }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n</div>\n", styles: ["mat-form-field{width:100%}\n"] }]
2362
2640
  }], propDecorators: { output: [{ type: i0.Output, args: ["output"] }], select: [{ type: i0.Output, args: ["select"] }], proposedTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "proposedTime", required: false }] }] } });
2363
2641
 
2364
- const MY_FORMATS$7 = {
2642
+ const MY_FORMATS$6 = {
2365
2643
  parse: {
2366
2644
  dateInput: 'YYYY-MM-DD',
2367
2645
  },
@@ -2399,178 +2677,51 @@ class PropertyViewingRequestComponent extends BaseComponent {
2399
2677
  adverseCreditStatus = AdverseCreditStatus;
2400
2678
  countries = ['United Kingdom', 'China'];
2401
2679
  selectedCountry;
2402
- displayPrice = computed(() => {
2403
- return this.property ? this.property.price.toFixed(2) : 0;
2404
- }, ...(ngDevMode ? [{ debugName: "displayPrice" }] : []));
2405
- ngOnInit() {
2406
- this.getProperty();
2407
- // this.viewing['country'] = this.countries[0];
2408
- }
2409
- getProperty() {
2410
- this.propertyService.get(this.id).subscribe({
2411
- next: (res) => {
2412
- this.property = res.data;
2413
- this.titleService.setTitle(`${this.property.title}`);
2414
- },
2415
- });
2416
- }
2417
- onCountrySelect(event) {
2418
- this.viewing['country'] = event.value;
2419
- }
2420
- onViewerSelectionChange(event) {
2421
- this.selectedViewerCategory = event.value;
2422
- }
2423
- sendRequest() {
2424
- this.propertyService.requestViewing(this.id, this.viewing).subscribe({
2425
- next: (res) => {
2426
- this.snackBarService.open('Request viewing successfully');
2427
- this.router.navigate([`/properties/viewings/${res.data.id}`]);
2428
- },
2429
- error: (error) => {
2430
- this.snackBarService.open(error.message);
2431
- },
2432
- });
2433
- }
2434
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PropertyViewingRequestComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2435
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: PropertyViewingRequestComponent, isStandalone: true, selector: "rolatech-property-viewing-request", providers: [
2436
- {
2437
- provide: DateAdapter,
2438
- useClass: MomentDateAdapter,
2439
- deps: [MAT_DATE_LOCALE],
2440
- },
2441
- { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS$7 },
2442
- ], usesInheritance: true, ngImport: i0, template: "<rolatech-container>\n <div class=\"flex flex-col-reverse md:flex-row w-full py-2 mb-3 gap-3\">\n <div class=\"w-full md:w-2/3\">\n <div>\n <div class=\"text-xl font-bold py-2 mb-3\" i18n>Request a viewing</div>\n <div class=\"mb-3\">\n <mat-radio-group\n aria-label=\"Select an option\"\n [(ngModel)]=\"viewing.viewerCategory\"\n (change)=\"onViewerSelectionChange($event)\"\n >\n <mat-radio-button [value]=\"viewerCategory.TENANT\" i18n>I'm a tenant</mat-radio-button>\n <mat-radio-button [value]=\"viewerCategory.AGENT\" i18n>I'm an agent</mat-radio-button>\n </mat-radio-group>\n </div>\n @if (selectedViewerCategory === 'Tenant') {\n <div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>First name</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"viewing.firstName\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Last name</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"viewing.lastName\" />\n </mat-form-field>\n </div>\n <div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Phone</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"viewing.phone\" />\n </mat-form-field>\n </div>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Email</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"viewing.email\" />\n </mat-form-field>\n <mat-form-field>\n <mat-label i18n>Tenant type</mat-label>\n <mat-select placeholder=\"Tenant type\" [(ngModel)]=\"viewing.applicantType\">\n @for (applicantType of applicantTypes | keyvalue; track applicantType) {\n <mat-option [value]=\"applicantType.key\">\n {{ applicantType.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n } @else {\n <div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Your email</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"viewing.email\" />\n </mat-form-field>\n </div>\n <div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Number of tenants</mat-label>\n <input matInput type=\"number\" [(ngModel)]=\"viewing.numberOfTenants\" />\n </mat-form-field>\n </div>\n <mat-form-field>\n <mat-label i18n>Applicant type</mat-label>\n <mat-select placeholder=\"Applicant type\" [(ngModel)]=\"viewing.applicantType\">\n @for (applicantType of applicantTypes | keyvalue; track applicantType) {\n <mat-option [value]=\"applicantType.key\">\n {{ applicantType.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <input\n matInput\n placeholder=\"Start date\"\n [matDatepicker]=\"startDatePicker\"\n [min]=\"minDate\"\n (focus)=\"startDatePicker.open()\"\n name=\"startDate\"\n [(ngModel)]=\"viewing.startDate\"\n (dateInput)=\"viewing.startDate = $event.value.format('YYYY-MM-DD')\"\n readonly\n />\n <mat-datepicker-toggle matIconPrefix [for]=\"startDatePicker\"></mat-datepicker-toggle>\n <mat-datepicker #startDatePicker></mat-datepicker>\n </mat-form-field>\n <div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Tenancy length</mat-label>\n <span matTextSuffix>months</span>\n <input matInput type=\"number\" [(ngModel)]=\"viewing.tenancyDuration\" />\n </mat-form-field>\n </div>\n <mat-form-field appearance=\"fill\" floatLabel=\"always\">\n <mat-label i18n>Annual income(All tenants combined)</mat-label>\n <span matTextPrefix>\u00A3&nbsp;</span>\n <input matInput type=\"text\" placeholder=\"00.00\" [(ngModel)]=\"viewing.income\" />\n </mat-form-field>\n <mat-form-field>\n <mat-label i18n>Employment Status</mat-label>\n <mat-select placeholder=\"Employment Status\" [(ngModel)]=\"viewing.employmentStatus\">\n @for (item of employmentStatus | keyvalue; track item) {\n <mat-option [value]=\"item.key\">\n {{ item.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field>\n <mat-label i18n>AdverseCredit Status</mat-label>\n <mat-select placeholder=\"AdverseCredit Status\" [(ngModel)]=\"viewing.adverseCreditStatus\">\n @for (item of adverseCreditStatus | keyvalue; track item) {\n <mat-option [value]=\"item.key\">\n {{ item.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <div>\n <div class=\"mb-3\">\n <div class=\"text-lg font-bold\" i18n>Viewing date</div>\n <div class=\"opacity-70\" i18n>\n Please choose 3 different times on at least 2 different days that would work for you.\n </div>\n </div>\n @for (item of viewing.proposedSlots; track $index) {\n <rolatech-property-viewing-time [proposedTime]=\"item\"></rolatech-property-viewing-time>\n }\n </div>\n </div>\n <button mat-flat-button (click)=\"sendRequest()\" i18n>Send request</button>\n </div>\n <div class=\"w-full md:w-1/2 py-2 mb-3\">\n @if (property) {\n <div class=\"text-xl font-bold py-2 mb-3\" i18n>Property info</div>\n <div>\n <rolatech-thumbnail [src]=\"property ? property.media[0].url : ''\" size=\"small\"></rolatech-thumbnail>\n </div>\n <div class=\"text-xl font-bold\">{{ property.title }}</div>\n <div class=\"\">Available: {{ property.availableDate | availableDate }}</div>\n @if (property.market.toString() === 'LETTINGS' && property.rentFrequency.toString() === 'MONTHLY') {\n <div class=\"py-3 text-xl font-bold\">{{ property.price | price }}pcm</div>\n } @else {\n <div class=\"py-3 text-xl font-bold\">{{ property.price | price }}</div>\n }\n }\n </div>\n </div>\n</rolatech-container>\n", styles: ["mat-form-field{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i2$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.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$2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: TextFieldModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$3.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: ThumbnailComponent, selector: "rolatech-thumbnail", inputs: ["src", "size", "mode", "ratio", "width", "height"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { 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: MatRadioModule }, { kind: "directive", type: i3$1.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i3$1.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "component", type: PropertyViewingTimeComponent, selector: "rolatech-property-viewing-time", inputs: ["proposedTime"], outputs: ["output", "select"] }, { kind: "pipe", type: i1.KeyValuePipe, name: "keyvalue" }, { kind: "pipe", type: AvailableDatePipe, name: "availableDate" }, { kind: "pipe", type: PricePipe, name: "price" }] });
2443
- }
2444
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PropertyViewingRequestComponent, decorators: [{
2445
- type: Component,
2446
- args: [{ selector: 'rolatech-property-viewing-request', imports: [
2447
- CommonModule,
2448
- ContainerComponent,
2449
- MatFormFieldModule,
2450
- FormsModule,
2451
- MatInputModule,
2452
- TextFieldModule,
2453
- MatButtonModule,
2454
- ThumbnailComponent,
2455
- MatSelectModule,
2456
- MatDatepickerModule,
2457
- MatRadioModule,
2458
- PropertyViewingTimeComponent,
2459
- AvailableDatePipe,
2460
- PricePipe,
2461
- ], providers: [
2462
- {
2463
- provide: DateAdapter,
2464
- useClass: MomentDateAdapter,
2465
- deps: [MAT_DATE_LOCALE],
2466
- },
2467
- { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS$7 },
2468
- ], template: "<rolatech-container>\n <div class=\"flex flex-col-reverse md:flex-row w-full py-2 mb-3 gap-3\">\n <div class=\"w-full md:w-2/3\">\n <div>\n <div class=\"text-xl font-bold py-2 mb-3\" i18n>Request a viewing</div>\n <div class=\"mb-3\">\n <mat-radio-group\n aria-label=\"Select an option\"\n [(ngModel)]=\"viewing.viewerCategory\"\n (change)=\"onViewerSelectionChange($event)\"\n >\n <mat-radio-button [value]=\"viewerCategory.TENANT\" i18n>I'm a tenant</mat-radio-button>\n <mat-radio-button [value]=\"viewerCategory.AGENT\" i18n>I'm an agent</mat-radio-button>\n </mat-radio-group>\n </div>\n @if (selectedViewerCategory === 'Tenant') {\n <div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>First name</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"viewing.firstName\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Last name</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"viewing.lastName\" />\n </mat-form-field>\n </div>\n <div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Phone</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"viewing.phone\" />\n </mat-form-field>\n </div>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Email</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"viewing.email\" />\n </mat-form-field>\n <mat-form-field>\n <mat-label i18n>Tenant type</mat-label>\n <mat-select placeholder=\"Tenant type\" [(ngModel)]=\"viewing.applicantType\">\n @for (applicantType of applicantTypes | keyvalue; track applicantType) {\n <mat-option [value]=\"applicantType.key\">\n {{ applicantType.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n } @else {\n <div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Your email</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"viewing.email\" />\n </mat-form-field>\n </div>\n <div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Number of tenants</mat-label>\n <input matInput type=\"number\" [(ngModel)]=\"viewing.numberOfTenants\" />\n </mat-form-field>\n </div>\n <mat-form-field>\n <mat-label i18n>Applicant type</mat-label>\n <mat-select placeholder=\"Applicant type\" [(ngModel)]=\"viewing.applicantType\">\n @for (applicantType of applicantTypes | keyvalue; track applicantType) {\n <mat-option [value]=\"applicantType.key\">\n {{ applicantType.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <input\n matInput\n placeholder=\"Start date\"\n [matDatepicker]=\"startDatePicker\"\n [min]=\"minDate\"\n (focus)=\"startDatePicker.open()\"\n name=\"startDate\"\n [(ngModel)]=\"viewing.startDate\"\n (dateInput)=\"viewing.startDate = $event.value.format('YYYY-MM-DD')\"\n readonly\n />\n <mat-datepicker-toggle matIconPrefix [for]=\"startDatePicker\"></mat-datepicker-toggle>\n <mat-datepicker #startDatePicker></mat-datepicker>\n </mat-form-field>\n <div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Tenancy length</mat-label>\n <span matTextSuffix>months</span>\n <input matInput type=\"number\" [(ngModel)]=\"viewing.tenancyDuration\" />\n </mat-form-field>\n </div>\n <mat-form-field appearance=\"fill\" floatLabel=\"always\">\n <mat-label i18n>Annual income(All tenants combined)</mat-label>\n <span matTextPrefix>\u00A3&nbsp;</span>\n <input matInput type=\"text\" placeholder=\"00.00\" [(ngModel)]=\"viewing.income\" />\n </mat-form-field>\n <mat-form-field>\n <mat-label i18n>Employment Status</mat-label>\n <mat-select placeholder=\"Employment Status\" [(ngModel)]=\"viewing.employmentStatus\">\n @for (item of employmentStatus | keyvalue; track item) {\n <mat-option [value]=\"item.key\">\n {{ item.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field>\n <mat-label i18n>AdverseCredit Status</mat-label>\n <mat-select placeholder=\"AdverseCredit Status\" [(ngModel)]=\"viewing.adverseCreditStatus\">\n @for (item of adverseCreditStatus | keyvalue; track item) {\n <mat-option [value]=\"item.key\">\n {{ item.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <div>\n <div class=\"mb-3\">\n <div class=\"text-lg font-bold\" i18n>Viewing date</div>\n <div class=\"opacity-70\" i18n>\n Please choose 3 different times on at least 2 different days that would work for you.\n </div>\n </div>\n @for (item of viewing.proposedSlots; track $index) {\n <rolatech-property-viewing-time [proposedTime]=\"item\"></rolatech-property-viewing-time>\n }\n </div>\n </div>\n <button mat-flat-button (click)=\"sendRequest()\" i18n>Send request</button>\n </div>\n <div class=\"w-full md:w-1/2 py-2 mb-3\">\n @if (property) {\n <div class=\"text-xl font-bold py-2 mb-3\" i18n>Property info</div>\n <div>\n <rolatech-thumbnail [src]=\"property ? property.media[0].url : ''\" size=\"small\"></rolatech-thumbnail>\n </div>\n <div class=\"text-xl font-bold\">{{ property.title }}</div>\n <div class=\"\">Available: {{ property.availableDate | availableDate }}</div>\n @if (property.market.toString() === 'LETTINGS' && property.rentFrequency.toString() === 'MONTHLY') {\n <div class=\"py-3 text-xl font-bold\">{{ property.price | price }}pcm</div>\n } @else {\n <div class=\"py-3 text-xl font-bold\">{{ property.price | price }}</div>\n }\n }\n </div>\n </div>\n</rolatech-container>\n", styles: ["mat-form-field{width:100%}\n"] }]
2469
- }] });
2470
-
2471
- const MY_FORMATS$6 = {
2472
- parse: {
2473
- dateInput: 'YYYY-MM-DD',
2474
- },
2475
- display: {
2476
- dateInput: 'YYYY-MM-DD',
2477
- monthYearLabel: 'MMM YYYY',
2478
- dateA11yLabel: 'YYYY-MM-DD',
2479
- monthYearA11yLabel: 'MMMM YYYY',
2480
- },
2481
- };
2482
- class PropertyOfferComponent extends BaseComponent {
2483
- authService = inject(AuthService);
2484
- authUserService = inject(AuthUserService);
2485
- propertyService = inject(PropertyService);
2486
- propertyOfferService = inject(PropertyOfferService);
2487
- offer = {
2488
- firstName: '',
2489
- lastName: '',
2490
- phone: '',
2491
- email: '',
2492
- applicantType: '',
2493
- residencyStatus: '',
2494
- employmentStatus: '',
2495
- adverseCreditStatus: '',
2496
- startDate: '',
2497
- notes: '',
2498
- amount: 0,
2499
- };
2500
- get formattedAmount() {
2501
- return this.offer.amount.toFixed(2); // equivalent to | number:'1.2-2'
2502
- } // applicantTypes = PropertyApplicantType;
2503
- applicantTypes = Object.keys(PropertyApplicantType); // ['INDIVIDUAL', 'CORPORATE', ...]
2504
- PropertyApplicantType = PropertyApplicantType;
2505
- residencyStatus = ResidencyStatus;
2506
- employmentStatus = EmploymentStatus;
2507
- adverseCreditStatus = AdverseCreditStatus;
2508
- selectedCountry;
2509
- property = signal(null, ...(ngDevMode ? [{ debugName: "property" }] : []));
2510
- firstImageUrl = computed(() => {
2511
- const p = this.property();
2512
- return p?.media?.[0]?.url || '';
2513
- }, ...(ngDevMode ? [{ debugName: "firstImageUrl" }] : []));
2514
- minDate = new Date();
2515
- sending = false;
2516
- constructor() {
2517
- super();
2518
- effect(() => {
2519
- const p = this.property();
2520
- if (p) {
2521
- this.titleService.setTitle(p.title);
2522
- }
2523
- });
2524
- }
2680
+ displayPrice = computed(() => {
2681
+ return this.property ? this.property.price.toFixed(2) : 0;
2682
+ }, ...(ngDevMode ? [{ debugName: "displayPrice" }] : []));
2525
2683
  ngOnInit() {
2526
2684
  this.getProperty();
2527
- }
2528
- onAmountChange(event) {
2529
- const inputValue = event.target.value;
2530
- const regex = /^\d*\.?\d{0,2}$/;
2531
- if (regex.test(inputValue)) {
2532
- this.offer.amount = inputValue;
2533
- }
2685
+ // this.viewing['country'] = this.countries[0];
2534
2686
  }
2535
2687
  getProperty() {
2536
2688
  this.propertyService.get(this.id).subscribe({
2537
2689
  next: (res) => {
2538
- this.property.set(res.data);
2539
- // this.titleService.setTitle(`${this.property.title}`);
2690
+ this.property = res.data;
2691
+ this.titleService.setTitle(`${this.property.title}`);
2540
2692
  },
2541
2693
  });
2542
2694
  }
2543
- onCategorySelect(event) {
2544
- this.offer['category'] = event.value;
2695
+ onCountrySelect(event) {
2696
+ this.viewing['country'] = event.value;
2697
+ }
2698
+ onViewerSelectionChange(event) {
2699
+ this.selectedViewerCategory = event.value;
2545
2700
  }
2546
- onResidencyStatusSelect(event) { }
2547
2701
  sendRequest() {
2548
- this.sending = true;
2549
- this.propertyOfferService.makeOffer(this.id, this.offer).subscribe({
2702
+ this.propertyService.requestViewing(this.id, this.viewing).subscribe({
2550
2703
  next: (res) => {
2551
- this.sending = false;
2552
- this.snackBarService.open('Sent successfully');
2553
- this.router.navigate([`/properties/offers/${res.data.id}`]);
2704
+ this.snackBarService.open('Request viewing successfully');
2705
+ this.router.navigate([`/properties/viewings/${res.data.id}`]);
2554
2706
  },
2555
2707
  error: (error) => {
2556
- this.sending = false;
2557
2708
  this.snackBarService.open(error.message);
2558
2709
  },
2559
2710
  });
2560
2711
  }
2561
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PropertyOfferComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2562
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: PropertyOfferComponent, isStandalone: true, selector: "rolatech-property-offer", providers: [
2712
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PropertyViewingRequestComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2713
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: PropertyViewingRequestComponent, isStandalone: true, selector: "rolatech-property-viewing-request", providers: [
2563
2714
  {
2564
2715
  provide: DateAdapter,
2565
2716
  useClass: MomentDateAdapter,
2566
2717
  deps: [MAT_DATE_LOCALE],
2567
2718
  },
2568
2719
  { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS$6 },
2569
- ], usesInheritance: true, ngImport: i0, template: "<rolatech-container>\n <div class=\"flex flex-col-reverse md:flex-row w-full py-2 mb-3 gap-3\">\n <div class=\"w-full md:w-2/3\">\n <div>\n <div class=\"text-xl font-bold py-2 mb-3\">\n <!-- <span i18n>Offer for </span><span>{{ property()?.title : '' }}</span> -->\n <span i18n=\"@@offerFor\">Offer for {{ property()?.title }}</span>\n </div>\n <div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>First name</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"offer.firstName\" required />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Last name</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"offer.lastName\" required />\n </mat-form-field>\n </div>\n <div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Phone</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"offer.phone\" required />\n </mat-form-field>\n </div>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Email</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"offer.email\" required />\n </mat-form-field>\n\n <mat-form-field appearance=\"fill\" floatLabel=\"always\">\n <mat-label i18n>Offer amount</mat-label>\n <span matTextPrefix>\u00A3&nbsp;</span>\n <input matInput type=\"text\" placeholder=\"0.00\" [(ngModel)]=\"offer.amount\" required />\n <!-- <input\n matInput\n type=\"number\"\n placeholder=\"0.00\"\n [value]=\"formattedAmount\"\n (input)=\"onAmountChange($event)\"\n required\n /> -->\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Tenancy Length</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"offer.tenancyDuration\" required />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Number Of Tenants</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"offer.numberOfTenants\" required />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label>Start date</mat-label>\n <input\n matInput\n placeholder=\"Start date\"\n [matDatepicker]=\"startDatePicker\"\n [min]=\"minDate\"\n (focus)=\"startDatePicker.open()\"\n name=\"startDate\"\n [(ngModel)]=\"offer.startDate\"\n (dateInput)=\"offer.startDate = $event.value.format('YYYY-MM-DD')\"\n readonly\n required\n />\n <mat-datepicker-toggle matIconPrefix [for]=\"startDatePicker\"></mat-datepicker-toggle>\n <mat-datepicker #startDatePicker></mat-datepicker>\n </mat-form-field>\n <mat-form-field>\n <mat-label i18n>Applicant type</mat-label>\n <mat-select placeholder=\"Applicant type\" [(ngModel)]=\"offer.applicantType\" required>\n @for (key of applicantTypes; track key) {\n <mat-option [value]=\"key\">\n {{ PropertyApplicantType[key] }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <!-- subscriptSizing=\"dynamic\" -->\n <mat-form-field>\n <mat-label i18n>Residency status</mat-label>\n <mat-select placeholder=\"Residency status\" [(ngModel)]=\"offer.residencyStatus\" required>\n @for (status of residencyStatus | keyvalue; track status) {\n <mat-option [value]=\"status.key\">\n {{ status.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field>\n <mat-label i18n>Employment Status</mat-label>\n <mat-select placeholder=\"Employment Status\" [(ngModel)]=\"offer.employmentStatus\" required>\n @for (item of employmentStatus | keyvalue; track item) {\n <mat-option [value]=\"item.key\">\n {{ item.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field>\n <mat-label i18n>AdverseCredit Status</mat-label>\n <mat-select placeholder=\"AdverseCredit Status\" [(ngModel)]=\"offer.adverseCreditStatus\" required>\n @for (item of adverseCreditStatus | keyvalue; track item) {\n <mat-option [value]=\"item.key\">\n {{ item.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n <div>\n <div class=\"text-md py-2\" i18n>Your message(Optional)</div>\n <mat-form-field appearance=\"fill\">\n <textarea matInput type=\"text\" [(ngModel)]=\"offer.notes\" cdkTextareaAutosize cdkAutosizeMinRows=\"3\"></textarea>\n </mat-form-field>\n </div>\n <!-- <button mat-flat-button (click)=\"sendRequest()\" i18n>Send request</button> -->\n <button mat-flat-button (click)=\"sendRequest()\" [disabled]=\"sending\">\n <span style=\"display: flex; align-items: center\">\n @if (sending) {\n <mat-progress-spinner diameter=\"20\" mode=\"indeterminate\" [style.marginRight.px]=\"8\"></mat-progress-spinner>\n }\n {{ sending ? 'Requesting...' : 'Send request' }}\n </span>\n </button>\n </div>\n <div class=\"w-full md:w-1/2 py-2 mb-3\">\n @if (property()) {\n <div class=\"text-xl font-bold py-2 mb-3\" i18n>Property info</div>\n <div>\n <rolatech-thumbnail [src]=\"firstImageUrl()\" size=\"small\"></rolatech-thumbnail>\n </div>\n <div class=\"text-xl font-bold\">{{ property()!.title }}</div>\n <div class=\"\">Available: {{ property()!.availableDate | availableDate }}</div>\n @if (property()!.market.toString() === 'LETTINGS' && property()!.rentFrequency.toString() === 'MONTHLY') {\n <div class=\"py-3 text-xl font-bold\">{{ property()!.price | price }}pcm</div>\n } @else {\n <div class=\"py-3 text-xl font-bold\">{{ property()!.price | price }}</div>\n }\n }\n </div>\n </div>\n</rolatech-container>\n", styles: ["mat-form-field{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.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: "directive", type: i4$2.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "ngmodule", type: TextFieldModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$3.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: ThumbnailComponent, selector: "rolatech-thumbnail", inputs: ["src", "size", "mode", "ratio", "width", "height"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { 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: "component", type: MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "pipe", type: i1.KeyValuePipe, name: "keyvalue" }, { kind: "pipe", type: AvailableDatePipe, name: "availableDate" }, { kind: "pipe", type: PricePipe, name: "price" }] });
2720
+ ], usesInheritance: true, ngImport: i0, template: "<rolatech-container>\n <div class=\"flex flex-col-reverse md:flex-row w-full py-2 mb-3 gap-3\">\n <div class=\"w-full md:w-2/3\">\n <div>\n <div class=\"text-xl font-bold py-2 mb-3\" i18n>Request a viewing</div>\n <div class=\"mb-3\">\n <mat-radio-group\n aria-label=\"Select an option\"\n [(ngModel)]=\"viewing.viewerCategory\"\n (change)=\"onViewerSelectionChange($event)\"\n >\n <mat-radio-button [value]=\"viewerCategory.TENANT\" i18n>I'm a tenant</mat-radio-button>\n <mat-radio-button [value]=\"viewerCategory.AGENT\" i18n>I'm an agent</mat-radio-button>\n </mat-radio-group>\n </div>\n @if (selectedViewerCategory === 'Tenant') {\n <div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>First name</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"viewing.firstName\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Last name</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"viewing.lastName\" />\n </mat-form-field>\n </div>\n <div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Phone</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"viewing.phone\" />\n </mat-form-field>\n </div>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Email</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"viewing.email\" />\n </mat-form-field>\n <mat-form-field>\n <mat-label i18n>Tenant type</mat-label>\n <mat-select placeholder=\"Tenant type\" [(ngModel)]=\"viewing.applicantType\">\n @for (applicantType of applicantTypes | keyvalue; track applicantType) {\n <mat-option [value]=\"applicantType.key\">\n {{ applicantType.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n } @else {\n <div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Your email</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"viewing.email\" />\n </mat-form-field>\n </div>\n <div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Number of tenants</mat-label>\n <input matInput type=\"number\" [(ngModel)]=\"viewing.numberOfTenants\" />\n </mat-form-field>\n </div>\n <mat-form-field>\n <mat-label i18n>Applicant type</mat-label>\n <mat-select placeholder=\"Applicant type\" [(ngModel)]=\"viewing.applicantType\">\n @for (applicantType of applicantTypes | keyvalue; track applicantType) {\n <mat-option [value]=\"applicantType.key\">\n {{ applicantType.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <input\n matInput\n placeholder=\"Start date\"\n [matDatepicker]=\"startDatePicker\"\n [min]=\"minDate\"\n (focus)=\"startDatePicker.open()\"\n name=\"startDate\"\n [(ngModel)]=\"viewing.startDate\"\n (dateInput)=\"viewing.startDate = $event.value.format('YYYY-MM-DD')\"\n readonly\n />\n <mat-datepicker-toggle matIconPrefix [for]=\"startDatePicker\"></mat-datepicker-toggle>\n <mat-datepicker #startDatePicker></mat-datepicker>\n </mat-form-field>\n <div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Tenancy length</mat-label>\n <span matTextSuffix>months</span>\n <input matInput type=\"number\" [(ngModel)]=\"viewing.tenancyDuration\" />\n </mat-form-field>\n </div>\n <mat-form-field appearance=\"fill\" floatLabel=\"always\">\n <mat-label i18n>Annual income(All tenants combined)</mat-label>\n <span matTextPrefix>\u00A3&nbsp;</span>\n <input matInput type=\"text\" placeholder=\"00.00\" [(ngModel)]=\"viewing.income\" />\n </mat-form-field>\n <mat-form-field>\n <mat-label i18n>Employment Status</mat-label>\n <mat-select placeholder=\"Employment Status\" [(ngModel)]=\"viewing.employmentStatus\">\n @for (item of employmentStatus | keyvalue; track item) {\n <mat-option [value]=\"item.key\">\n {{ item.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field>\n <mat-label i18n>AdverseCredit Status</mat-label>\n <mat-select placeholder=\"AdverseCredit Status\" [(ngModel)]=\"viewing.adverseCreditStatus\">\n @for (item of adverseCreditStatus | keyvalue; track item) {\n <mat-option [value]=\"item.key\">\n {{ item.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <div>\n <div class=\"mb-3\">\n <div class=\"text-lg font-bold\" i18n>Viewing date</div>\n <div class=\"opacity-70\" i18n>\n Please choose 3 different times on at least 2 different days that would work for you.\n </div>\n </div>\n @for (item of viewing.proposedSlots; track $index) {\n <rolatech-property-viewing-time [proposedTime]=\"item\"></rolatech-property-viewing-time>\n }\n </div>\n </div>\n <button mat-flat-button (click)=\"sendRequest()\" i18n>Send request</button>\n </div>\n <div class=\"w-full md:w-1/2 py-2 mb-3\">\n @if (property) {\n <div class=\"text-xl font-bold py-2 mb-3\" i18n>Property info</div>\n <div>\n <rolatech-thumbnail [src]=\"property ? property.media[0].url : ''\" size=\"small\"></rolatech-thumbnail>\n </div>\n <div class=\"text-xl font-bold\">{{ property.title }}</div>\n <div class=\"\">Available: {{ property.availableDate | availableDate }}</div>\n @if (property.market.toString() === 'LETTINGS' && property.rentFrequency.toString() === 'MONTHLY') {\n <div class=\"py-3 text-xl font-bold\">{{ property.price | price }}pcm</div>\n } @else {\n <div class=\"py-3 text-xl font-bold\">{{ property.price | price }}</div>\n }\n }\n </div>\n </div>\n</rolatech-container>\n", styles: ["mat-form-field{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i2$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.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$2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: TextFieldModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$3.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: ThumbnailComponent, selector: "rolatech-thumbnail", inputs: ["src", "size", "mode", "ratio", "width", "height"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { 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: MatRadioModule }, { kind: "directive", type: i3$1.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i3$1.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "component", type: PropertyViewingTimeComponent, selector: "rolatech-property-viewing-time", inputs: ["proposedTime"], outputs: ["output", "select"] }, { kind: "pipe", type: i1.KeyValuePipe, name: "keyvalue" }, { kind: "pipe", type: AvailableDatePipe, name: "availableDate" }, { kind: "pipe", type: PricePipe, name: "price" }] });
2570
2721
  }
2571
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PropertyOfferComponent, decorators: [{
2722
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PropertyViewingRequestComponent, decorators: [{
2572
2723
  type: Component,
2573
- args: [{ selector: 'rolatech-property-offer', imports: [
2724
+ args: [{ selector: 'rolatech-property-viewing-request', imports: [
2574
2725
  CommonModule,
2575
2726
  ContainerComponent,
2576
2727
  MatFormFieldModule,
@@ -2580,9 +2731,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
2580
2731
  MatButtonModule,
2581
2732
  ThumbnailComponent,
2582
2733
  MatSelectModule,
2583
- KeyValuePipe,
2584
2734
  MatDatepickerModule,
2585
- MatProgressSpinner,
2735
+ MatRadioModule,
2736
+ PropertyViewingTimeComponent,
2586
2737
  AvailableDatePipe,
2587
2738
  PricePipe,
2588
2739
  ], providers: [
@@ -2592,8 +2743,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
2592
2743
  deps: [MAT_DATE_LOCALE],
2593
2744
  },
2594
2745
  { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS$6 },
2595
- ], template: "<rolatech-container>\n <div class=\"flex flex-col-reverse md:flex-row w-full py-2 mb-3 gap-3\">\n <div class=\"w-full md:w-2/3\">\n <div>\n <div class=\"text-xl font-bold py-2 mb-3\">\n <!-- <span i18n>Offer for </span><span>{{ property()?.title : '' }}</span> -->\n <span i18n=\"@@offerFor\">Offer for {{ property()?.title }}</span>\n </div>\n <div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>First name</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"offer.firstName\" required />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Last name</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"offer.lastName\" required />\n </mat-form-field>\n </div>\n <div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Phone</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"offer.phone\" required />\n </mat-form-field>\n </div>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Email</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"offer.email\" required />\n </mat-form-field>\n\n <mat-form-field appearance=\"fill\" floatLabel=\"always\">\n <mat-label i18n>Offer amount</mat-label>\n <span matTextPrefix>\u00A3&nbsp;</span>\n <input matInput type=\"text\" placeholder=\"0.00\" [(ngModel)]=\"offer.amount\" required />\n <!-- <input\n matInput\n type=\"number\"\n placeholder=\"0.00\"\n [value]=\"formattedAmount\"\n (input)=\"onAmountChange($event)\"\n required\n /> -->\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Tenancy Length</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"offer.tenancyDuration\" required />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Number Of Tenants</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"offer.numberOfTenants\" required />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label>Start date</mat-label>\n <input\n matInput\n placeholder=\"Start date\"\n [matDatepicker]=\"startDatePicker\"\n [min]=\"minDate\"\n (focus)=\"startDatePicker.open()\"\n name=\"startDate\"\n [(ngModel)]=\"offer.startDate\"\n (dateInput)=\"offer.startDate = $event.value.format('YYYY-MM-DD')\"\n readonly\n required\n />\n <mat-datepicker-toggle matIconPrefix [for]=\"startDatePicker\"></mat-datepicker-toggle>\n <mat-datepicker #startDatePicker></mat-datepicker>\n </mat-form-field>\n <mat-form-field>\n <mat-label i18n>Applicant type</mat-label>\n <mat-select placeholder=\"Applicant type\" [(ngModel)]=\"offer.applicantType\" required>\n @for (key of applicantTypes; track key) {\n <mat-option [value]=\"key\">\n {{ PropertyApplicantType[key] }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <!-- subscriptSizing=\"dynamic\" -->\n <mat-form-field>\n <mat-label i18n>Residency status</mat-label>\n <mat-select placeholder=\"Residency status\" [(ngModel)]=\"offer.residencyStatus\" required>\n @for (status of residencyStatus | keyvalue; track status) {\n <mat-option [value]=\"status.key\">\n {{ status.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field>\n <mat-label i18n>Employment Status</mat-label>\n <mat-select placeholder=\"Employment Status\" [(ngModel)]=\"offer.employmentStatus\" required>\n @for (item of employmentStatus | keyvalue; track item) {\n <mat-option [value]=\"item.key\">\n {{ item.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field>\n <mat-label i18n>AdverseCredit Status</mat-label>\n <mat-select placeholder=\"AdverseCredit Status\" [(ngModel)]=\"offer.adverseCreditStatus\" required>\n @for (item of adverseCreditStatus | keyvalue; track item) {\n <mat-option [value]=\"item.key\">\n {{ item.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n <div>\n <div class=\"text-md py-2\" i18n>Your message(Optional)</div>\n <mat-form-field appearance=\"fill\">\n <textarea matInput type=\"text\" [(ngModel)]=\"offer.notes\" cdkTextareaAutosize cdkAutosizeMinRows=\"3\"></textarea>\n </mat-form-field>\n </div>\n <!-- <button mat-flat-button (click)=\"sendRequest()\" i18n>Send request</button> -->\n <button mat-flat-button (click)=\"sendRequest()\" [disabled]=\"sending\">\n <span style=\"display: flex; align-items: center\">\n @if (sending) {\n <mat-progress-spinner diameter=\"20\" mode=\"indeterminate\" [style.marginRight.px]=\"8\"></mat-progress-spinner>\n }\n {{ sending ? 'Requesting...' : 'Send request' }}\n </span>\n </button>\n </div>\n <div class=\"w-full md:w-1/2 py-2 mb-3\">\n @if (property()) {\n <div class=\"text-xl font-bold py-2 mb-3\" i18n>Property info</div>\n <div>\n <rolatech-thumbnail [src]=\"firstImageUrl()\" size=\"small\"></rolatech-thumbnail>\n </div>\n <div class=\"text-xl font-bold\">{{ property()!.title }}</div>\n <div class=\"\">Available: {{ property()!.availableDate | availableDate }}</div>\n @if (property()!.market.toString() === 'LETTINGS' && property()!.rentFrequency.toString() === 'MONTHLY') {\n <div class=\"py-3 text-xl font-bold\">{{ property()!.price | price }}pcm</div>\n } @else {\n <div class=\"py-3 text-xl font-bold\">{{ property()!.price | price }}</div>\n }\n }\n </div>\n </div>\n</rolatech-container>\n", styles: ["mat-form-field{width:100%}\n"] }]
2596
- }], ctorParameters: () => [] });
2746
+ ], template: "<rolatech-container>\n <div class=\"flex flex-col-reverse md:flex-row w-full py-2 mb-3 gap-3\">\n <div class=\"w-full md:w-2/3\">\n <div>\n <div class=\"text-xl font-bold py-2 mb-3\" i18n>Request a viewing</div>\n <div class=\"mb-3\">\n <mat-radio-group\n aria-label=\"Select an option\"\n [(ngModel)]=\"viewing.viewerCategory\"\n (change)=\"onViewerSelectionChange($event)\"\n >\n <mat-radio-button [value]=\"viewerCategory.TENANT\" i18n>I'm a tenant</mat-radio-button>\n <mat-radio-button [value]=\"viewerCategory.AGENT\" i18n>I'm an agent</mat-radio-button>\n </mat-radio-group>\n </div>\n @if (selectedViewerCategory === 'Tenant') {\n <div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>First name</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"viewing.firstName\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Last name</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"viewing.lastName\" />\n </mat-form-field>\n </div>\n <div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Phone</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"viewing.phone\" />\n </mat-form-field>\n </div>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Email</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"viewing.email\" />\n </mat-form-field>\n <mat-form-field>\n <mat-label i18n>Tenant type</mat-label>\n <mat-select placeholder=\"Tenant type\" [(ngModel)]=\"viewing.applicantType\">\n @for (applicantType of applicantTypes | keyvalue; track applicantType) {\n <mat-option [value]=\"applicantType.key\">\n {{ applicantType.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n } @else {\n <div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Your email</mat-label>\n <input matInput type=\"text\" [(ngModel)]=\"viewing.email\" />\n </mat-form-field>\n </div>\n <div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Number of tenants</mat-label>\n <input matInput type=\"number\" [(ngModel)]=\"viewing.numberOfTenants\" />\n </mat-form-field>\n </div>\n <mat-form-field>\n <mat-label i18n>Applicant type</mat-label>\n <mat-select placeholder=\"Applicant type\" [(ngModel)]=\"viewing.applicantType\">\n @for (applicantType of applicantTypes | keyvalue; track applicantType) {\n <mat-option [value]=\"applicantType.key\">\n {{ applicantType.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <input\n matInput\n placeholder=\"Start date\"\n [matDatepicker]=\"startDatePicker\"\n [min]=\"minDate\"\n (focus)=\"startDatePicker.open()\"\n name=\"startDate\"\n [(ngModel)]=\"viewing.startDate\"\n (dateInput)=\"viewing.startDate = $event.value.format('YYYY-MM-DD')\"\n readonly\n />\n <mat-datepicker-toggle matIconPrefix [for]=\"startDatePicker\"></mat-datepicker-toggle>\n <mat-datepicker #startDatePicker></mat-datepicker>\n </mat-form-field>\n <div class=\"flex flex-col md:flex-row gap-2\">\n <mat-form-field appearance=\"fill\">\n <mat-label i18n>Tenancy length</mat-label>\n <span matTextSuffix>months</span>\n <input matInput type=\"number\" [(ngModel)]=\"viewing.tenancyDuration\" />\n </mat-form-field>\n </div>\n <mat-form-field appearance=\"fill\" floatLabel=\"always\">\n <mat-label i18n>Annual income(All tenants combined)</mat-label>\n <span matTextPrefix>\u00A3&nbsp;</span>\n <input matInput type=\"text\" placeholder=\"00.00\" [(ngModel)]=\"viewing.income\" />\n </mat-form-field>\n <mat-form-field>\n <mat-label i18n>Employment Status</mat-label>\n <mat-select placeholder=\"Employment Status\" [(ngModel)]=\"viewing.employmentStatus\">\n @for (item of employmentStatus | keyvalue; track item) {\n <mat-option [value]=\"item.key\">\n {{ item.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field>\n <mat-label i18n>AdverseCredit Status</mat-label>\n <mat-select placeholder=\"AdverseCredit Status\" [(ngModel)]=\"viewing.adverseCreditStatus\">\n @for (item of adverseCreditStatus | keyvalue; track item) {\n <mat-option [value]=\"item.key\">\n {{ item.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <div>\n <div class=\"mb-3\">\n <div class=\"text-lg font-bold\" i18n>Viewing date</div>\n <div class=\"opacity-70\" i18n>\n Please choose 3 different times on at least 2 different days that would work for you.\n </div>\n </div>\n @for (item of viewing.proposedSlots; track $index) {\n <rolatech-property-viewing-time [proposedTime]=\"item\"></rolatech-property-viewing-time>\n }\n </div>\n </div>\n <button mat-flat-button (click)=\"sendRequest()\" i18n>Send request</button>\n </div>\n <div class=\"w-full md:w-1/2 py-2 mb-3\">\n @if (property) {\n <div class=\"text-xl font-bold py-2 mb-3\" i18n>Property info</div>\n <div>\n <rolatech-thumbnail [src]=\"property ? property.media[0].url : ''\" size=\"small\"></rolatech-thumbnail>\n </div>\n <div class=\"text-xl font-bold\">{{ property.title }}</div>\n <div class=\"\">Available: {{ property.availableDate | availableDate }}</div>\n @if (property.market.toString() === 'LETTINGS' && property.rentFrequency.toString() === 'MONTHLY') {\n <div class=\"py-3 text-xl font-bold\">{{ property.price | price }}pcm</div>\n } @else {\n <div class=\"py-3 text-xl font-bold\">{{ property.price | price }}</div>\n }\n }\n </div>\n </div>\n</rolatech-container>\n", styles: ["mat-form-field{width:100%}\n"] }]
2747
+ }] });
2597
2748
 
2598
2749
  class PropertyOfferIndexComponent extends BaseComponent {
2599
2750
  propertyService = inject(PropertyService);
@@ -2608,9 +2759,9 @@ class PropertyOfferIndexComponent extends BaseComponent {
2608
2759
  icon: 'dashboard',
2609
2760
  },
2610
2761
  {
2611
- name: 'Created',
2762
+ name: 'Submitted',
2612
2763
  icon: 'category',
2613
- status: 'created',
2764
+ status: 'submitted',
2614
2765
  },
2615
2766
  {
2616
2767
  name: 'Accepted',
@@ -2744,231 +2895,99 @@ class PropertyViewingIndexComponent extends BaseComponent {
2744
2895
  {
2745
2896
  name: 'Completed',
2746
2897
  icon: 'category',
2747
- status: 'completed',
2748
- },
2749
- {
2750
- name: 'Cancelled',
2751
- icon: 'category',
2752
- status: 'cancelled',
2753
- },
2754
- ];
2755
- loading = false;
2756
- viewings = signal([], ...(ngDevMode ? [{ debugName: "viewings" }] : []));
2757
- meta;
2758
- pageEvent;
2759
- length = 100;
2760
- pageSize = 15;
2761
- pageSizeOptions = [5, 10, 25, 100];
2762
- pageIndex = signal(0, ...(ngDevMode ? [{ debugName: "pageIndex" }] : []));
2763
- ngOnInit() {
2764
- const sub = this.route.queryParamMap
2765
- .pipe(map((p) => {
2766
- const page = p.get('page') ? Number(p.get('page')) : 1;
2767
- this.pageIndex.set(Math.max(page - 1, 0));
2768
- const status = p.get('status') || undefined;
2769
- let filter = '';
2770
- if (status) {
2771
- this.select = this.links.findIndex((item) => item.status === status);
2772
- filter = `status:${status?.toUpperCase()}`;
2773
- }
2774
- return {
2775
- page,
2776
- filter,
2777
- limit: p.get('limit') ? Number(p.get('limit')) : 15,
2778
- sort: p.get('sort') || undefined,
2779
- };
2780
- }),
2781
- // Cheap deep compare via JSON to avoid spam calls when nothing changed
2782
- map((o) => JSON.stringify(o)), distinctUntilChanged(), map((s) => JSON.parse(s)), switchMap((params) => {
2783
- this.loading = true;
2784
- params['sort'] = 'updatedAt desc';
2785
- return this.propertyService.findViewingsByUser(params).pipe(finalize(() => (this.loading = false)));
2786
- }))
2787
- .subscribe({
2788
- next: (res) => {
2789
- this.viewings.set(res.data);
2790
- this.meta = res.meta;
2791
- this.length = res.meta.pagination.count;
2792
- this.loading = false;
2793
- },
2794
- error: () => {
2795
- this.viewings.set([]);
2796
- this.length = 0;
2797
- this.loading = false;
2798
- },
2799
- });
2800
- // // auto-unsubscribe on destroy
2801
- this.destroyRef.onDestroy(() => sub.unsubscribe());
2802
- }
2803
- statusCompareFn(t1, t2) {
2804
- return t1 === t2;
2805
- }
2806
- onPage(e) {
2807
- this.router.navigate([], {
2808
- queryParams: { page: e.pageIndex + 1, limit: e.pageSize },
2809
- queryParamsHandling: 'merge',
2810
- replaceUrl: true, // optional: avoid stacking history on every page click
2811
- });
2812
- }
2813
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PropertyViewingIndexComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2814
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", 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", "block"], 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$3.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }] });
2815
- }
2816
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PropertyViewingIndexComponent, decorators: [{
2817
- type: Component,
2818
- args: [{ selector: 'rolatech-property-viewing-index', imports: [
2819
- CommonModule,
2820
- ContainerComponent,
2821
- RouterModule,
2822
- TabsComponent,
2823
- TabComponent,
2824
- ToolbarComponent,
2825
- ListComponent,
2826
- EmptyComponent,
2827
- MatButtonModule,
2828
- MatIconModule,
2829
- FormsModule,
2830
- MatFormFieldModule,
2831
- MatDatepickerModule,
2832
- MatOptionModule,
2833
- MatInputModule,
2834
- MatSelectModule,
2835
- MatButtonModule,
2836
- PropertyViewingItemComponent,
2837
- MatPaginatorModule,
2838
- ], 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" }]
2839
- }] });
2840
-
2841
- class OfferDetailContext {
2842
- api = inject(PropertyOfferService);
2843
- // input
2844
- offerId = signal(null, ...(ngDevMode ? [{ debugName: "offerId" }] : []));
2845
- // state (single source of truth)
2846
- offer = signal(null, ...(ngDevMode ? [{ debugName: "offer" }] : []));
2847
- loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
2848
- error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
2849
- constructor() {
2850
- effect(() => {
2851
- const id = this.offerId();
2852
- if (!id)
2853
- return;
2854
- this.fetchOffer(id);
2855
- });
2856
- }
2857
- fetchOffer(id) {
2858
- this.loading.set(true);
2859
- this.error.set(null);
2860
- this.api.getOffer(id).subscribe({
2861
- next: (res) => {
2862
- // adapt if your API shape is { data: ... }
2863
- this.offer.set(res.data ?? res);
2864
- },
2865
- error: (err) => {
2866
- this.error.set('Failed to load offer');
2867
- console.error(err);
2868
- },
2869
- complete: () => {
2870
- this.loading.set(false);
2871
- },
2872
- });
2873
- }
2874
- init(id) {
2875
- this.offerId.set(id);
2876
- }
2877
- isRental = computed(() => this.offer()?.type === 'RENTAL', ...(ngDevMode ? [{ debugName: "isRental" }] : []));
2878
- isSale = computed(() => this.offer()?.type === 'SALE', ...(ngDevMode ? [{ debugName: "isSale" }] : []));
2879
- invoiceOptionLabel = {
2880
- COMBINED: 'Combined',
2881
- SEPARATE: 'Separate',
2882
- };
2883
- asText(v) {
2884
- if (v === null || v === undefined)
2885
- return '—';
2886
- if (typeof v === 'string' && v.trim() === '')
2887
- return '—';
2888
- return String(v);
2889
- }
2890
- asBool(v) {
2891
- if (v === null || v === undefined)
2892
- return '—';
2893
- return v ? 'Yes' : 'No';
2894
- }
2895
- asMoney(amount) {
2896
- if (amount === null || amount === undefined)
2897
- return '—';
2898
- try {
2899
- return new Intl.NumberFormat('en-GB', { style: 'currency', currency: 'GBP' }).format(amount);
2900
- }
2901
- catch {
2902
- return String(amount);
2903
- }
2904
- }
2905
- asList(list) {
2906
- if (!list || list.length === 0)
2907
- return '—';
2908
- return list.join(', ');
2909
- }
2910
- ageFromDob(dob) {
2911
- if (!dob)
2912
- return '—';
2913
- const birth = new Date(dob);
2914
- if (Number.isNaN(birth.getTime()))
2915
- return '—';
2916
- const today = new Date();
2917
- let age = today.getFullYear() - birth.getFullYear();
2918
- const m = today.getMonth() - birth.getMonth();
2919
- if (m < 0 || (m === 0 && today.getDate() < birth.getDate())) {
2920
- age--;
2921
- }
2922
- return age >= 0 ? `${age}` : '—';
2923
- }
2924
- fullAddress(a) {
2925
- if (!a)
2926
- return '—';
2927
- const parts = [a.line1, a.line2, a.city, a.postcode, a.country].filter((p) => !!p && p.trim() !== '');
2928
- return parts.length ? parts.join(', ') : '—';
2929
- }
2930
- isEmptyAddress(a) {
2931
- if (!a)
2932
- return true;
2933
- const parts = [a.line1, a.line2, a.city, a.postcode, a.country].map((v) => (v ?? '').trim());
2934
- return parts.every((v) => v === '');
2935
- }
2936
- isEmptyGuarantor(g) {
2937
- if (!g)
2938
- return true;
2939
- // treat "guarantor": { "address": {} } as empty
2940
- const addressEmpty = this.isEmptyAddress(g.address);
2941
- const fields = [
2942
- g.fullName,
2943
- g.dob,
2944
- g.relationship,
2945
- g.phone,
2946
- g.email,
2947
- g.employmentStatus,
2948
- g.companyName,
2949
- g.jobTitle,
2950
- g.annualSalary,
2951
- g.companyNumber,
2952
- g.taxReturnSubmitted,
2953
- ];
2954
- const fieldsEmpty = fields.every((v) => v === null || v === undefined || (typeof v === 'string' && v.trim() === ''));
2955
- return addressEmpty && fieldsEmpty;
2956
- }
2957
- isIndividual(t) {
2958
- return t.applicantType === 'INDIVIDUAL';
2898
+ status: 'completed',
2899
+ },
2900
+ {
2901
+ name: 'Cancelled',
2902
+ icon: 'category',
2903
+ status: 'cancelled',
2904
+ },
2905
+ ];
2906
+ loading = false;
2907
+ viewings = signal([], ...(ngDevMode ? [{ debugName: "viewings" }] : []));
2908
+ meta;
2909
+ pageEvent;
2910
+ length = 100;
2911
+ pageSize = 15;
2912
+ pageSizeOptions = [5, 10, 25, 100];
2913
+ pageIndex = signal(0, ...(ngDevMode ? [{ debugName: "pageIndex" }] : []));
2914
+ ngOnInit() {
2915
+ const sub = this.route.queryParamMap
2916
+ .pipe(map((p) => {
2917
+ const page = p.get('page') ? Number(p.get('page')) : 1;
2918
+ this.pageIndex.set(Math.max(page - 1, 0));
2919
+ const status = p.get('status') || undefined;
2920
+ let filter = '';
2921
+ if (status) {
2922
+ this.select = this.links.findIndex((item) => item.status === status);
2923
+ filter = `status:${status?.toUpperCase()}`;
2924
+ }
2925
+ return {
2926
+ page,
2927
+ filter,
2928
+ limit: p.get('limit') ? Number(p.get('limit')) : 15,
2929
+ sort: p.get('sort') || undefined,
2930
+ };
2931
+ }),
2932
+ // Cheap deep compare via JSON to avoid spam calls when nothing changed
2933
+ map((o) => JSON.stringify(o)), distinctUntilChanged(), map((s) => JSON.parse(s)), switchMap((params) => {
2934
+ this.loading = true;
2935
+ params['sort'] = 'updatedAt desc';
2936
+ return this.propertyService.findViewingsByUser(params).pipe(finalize(() => (this.loading = false)));
2937
+ }))
2938
+ .subscribe({
2939
+ next: (res) => {
2940
+ this.viewings.set(res.data);
2941
+ this.meta = res.meta;
2942
+ this.length = res.meta.pagination.count;
2943
+ this.loading = false;
2944
+ },
2945
+ error: () => {
2946
+ this.viewings.set([]);
2947
+ this.length = 0;
2948
+ this.loading = false;
2949
+ },
2950
+ });
2951
+ // // auto-unsubscribe on destroy
2952
+ this.destroyRef.onDestroy(() => sub.unsubscribe());
2959
2953
  }
2960
- isCorporate(t) {
2961
- return t.applicantType === 'CORPORATE';
2954
+ statusCompareFn(t1, t2) {
2955
+ return t1 === t2;
2962
2956
  }
2963
- isStudent(t) {
2964
- return t.applicantType === 'STUDENT';
2957
+ onPage(e) {
2958
+ this.router.navigate([], {
2959
+ queryParams: { page: e.pageIndex + 1, limit: e.pageSize },
2960
+ queryParamsHandling: 'merge',
2961
+ replaceUrl: true, // optional: avoid stacking history on every page click
2962
+ });
2965
2963
  }
2966
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferDetailContext, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2967
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferDetailContext });
2964
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PropertyViewingIndexComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2965
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", 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", "block"], 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$3.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }] });
2968
2966
  }
2969
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferDetailContext, decorators: [{
2970
- type: Injectable
2971
- }], ctorParameters: () => [] });
2967
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PropertyViewingIndexComponent, decorators: [{
2968
+ type: Component,
2969
+ args: [{ selector: 'rolatech-property-viewing-index', imports: [
2970
+ CommonModule,
2971
+ ContainerComponent,
2972
+ RouterModule,
2973
+ TabsComponent,
2974
+ TabComponent,
2975
+ ToolbarComponent,
2976
+ ListComponent,
2977
+ EmptyComponent,
2978
+ MatButtonModule,
2979
+ MatIconModule,
2980
+ FormsModule,
2981
+ MatFormFieldModule,
2982
+ MatDatepickerModule,
2983
+ MatOptionModule,
2984
+ MatInputModule,
2985
+ MatSelectModule,
2986
+ MatButtonModule,
2987
+ PropertyViewingItemComponent,
2988
+ MatPaginatorModule,
2989
+ ], 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" }]
2990
+ }] });
2972
2991
 
2973
2992
  class OfferHeaderCard {
2974
2993
  ctx = inject(OfferDetailContext);
@@ -3024,147 +3043,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
3024
3043
  args: [{ selector: 'rolatech-offer-header-card', imports: [NgClass], template: "@if (ctx.offer(); as o) {\n<section class=\"flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between\">\n <div class=\"space-y-1\">\n <h1 class=\"text-xl font-semibold text-[--rt-text-primary]\">Offer #{{ o.id }}</h1>\n <div class=\"text-sm text-[--rt-text-secondary]\">\n <span class=\"font-medium\">{{ o.type }}</span>\n <span class=\"mx-2\">\u2022</span>\n <span>Property {{ o.propertyId }}</span>\n </div>\n\n <div class=\"flex flex-wrap gap-2 text-xs\">\n <span class=\"px-2 py-1 rounded-full border bg-[--rt-raised-background]\"> userId: {{ ctx.asText(o.userId) }} </span>\n <span class=\"px-2 py-1 rounded-full border bg-[--rt-raised-background]\"> agentId: {{ ctx.asText(o.agentId) }} </span>\n <span class=\"px-2 py-1 rounded-full border bg-[--rt-raised-background]\">\n invoice: {{ ctx.invoiceOptionLabel[o.invoiceOption] }}\n </span>\n </div>\n </div>\n\n <div class=\"flex items-center gap-2\">\n <span class=\"px-3 py-1 rounded-full border text-xs font-medium\" [ngClass]=\"statusBadgeClass(o.status)\">\n {{ o.status }}\n </span>\n </div>\n</section>\n}\n" }]
3025
3044
  }] });
3026
3045
 
3027
- class OfferItemCard {
3028
- ctx = inject(OfferDetailContext);
3029
- firstMediaUrl(o) {
3030
- const m = o.item?.media?.[0];
3031
- return m?.url ?? null;
3032
- }
3033
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferItemCard, deps: [], target: i0.ɵɵFactoryTarget.Component });
3034
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: OfferItemCard, isStandalone: true, selector: "rolatech-offer-item-card", ngImport: i0, template: "@if (ctx.offer(); as o) {\n<section class=\"rounded-2xl border bg-[--rt-raised-background] overflow-hidden\">\n <div class=\"p-4 flex items-start justify-between\">\n <div>\n <div class=\"text-sm font-semibold\">Property item</div>\n <div class=\"text-xs text-[--rt-text-secondary]\">property snapshot</div>\n </div>\n <span class=\"text-xs px-2 py-1 rounded-full border bg-[--rt-base-background]\"> propertyId: {{ o.item.propertyId }} </span>\n </div>\n\n <div class=\"p-4 pt-0 space-y-4\">\n <div class=\"flex flex-col lg:flex-row gap-4\">\n <img\n class=\"w-full lg:w-72 h-44 rounded-xl object-cover bg-gray-100\"\n [src]=\"firstMediaUrl(o) ?? '/assets/placeholder.jpg'\"\n [alt]=\"o.item.title\"\n />\n\n <div class=\"flex-1 space-y-2\">\n <div class=\"text-base font-semibold\">{{ o.item.title }}</div>\n\n <div class=\"grid grid-cols-2 gap-3 text-sm pt-2\">\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Amount</div>\n <div class=\"font-medium\">{{ o.item.amount | price }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Bedrooms</div>\n <div class=\"font-medium\">{{ o.item.bedrooms }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Bathrooms</div>\n <div class=\"font-medium\">{{ o.item.bathrooms }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Receptions</div>\n <div class=\"font-medium\">{{ o.item.receptions }}</div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</section>\n}\n", styles: [""], dependencies: [{ kind: "pipe", type: PricePipe, name: "price" }] });
3035
- }
3036
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferItemCard, decorators: [{
3037
- type: Component,
3038
- args: [{ selector: 'rolatech-offer-item-card', imports: [PricePipe], template: "@if (ctx.offer(); as o) {\n<section class=\"rounded-2xl border bg-[--rt-raised-background] overflow-hidden\">\n <div class=\"p-4 flex items-start justify-between\">\n <div>\n <div class=\"text-sm font-semibold\">Property item</div>\n <div class=\"text-xs text-[--rt-text-secondary]\">property snapshot</div>\n </div>\n <span class=\"text-xs px-2 py-1 rounded-full border bg-[--rt-base-background]\"> propertyId: {{ o.item.propertyId }} </span>\n </div>\n\n <div class=\"p-4 pt-0 space-y-4\">\n <div class=\"flex flex-col lg:flex-row gap-4\">\n <img\n class=\"w-full lg:w-72 h-44 rounded-xl object-cover bg-gray-100\"\n [src]=\"firstMediaUrl(o) ?? '/assets/placeholder.jpg'\"\n [alt]=\"o.item.title\"\n />\n\n <div class=\"flex-1 space-y-2\">\n <div class=\"text-base font-semibold\">{{ o.item.title }}</div>\n\n <div class=\"grid grid-cols-2 gap-3 text-sm pt-2\">\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Amount</div>\n <div class=\"font-medium\">{{ o.item.amount | price }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Bedrooms</div>\n <div class=\"font-medium\">{{ o.item.bedrooms }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Bathrooms</div>\n <div class=\"font-medium\">{{ o.item.bathrooms }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Receptions</div>\n <div class=\"font-medium\">{{ o.item.receptions }}</div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</section>\n}\n" }]
3039
- }] });
3040
-
3041
- class OfferRentalTermsCard {
3042
- ctx = inject(OfferDetailContext);
3043
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferRentalTermsCard, deps: [], target: i0.ɵɵFactoryTarget.Component });
3044
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: OfferRentalTermsCard, isStandalone: true, selector: "rolatech-offer-rental-terms-card", ngImport: i0, template: "@if (ctx.offer(); as o) {\n<section class=\"rounded-2xl border bg-[--rt-raised-background] p-4 space-y-3\">\n <div>\n <div class=\"text-sm font-semibold\">Rental terms</div>\n <div class=\"text-xs text-[--rt-text-secondary]\">o.rentalTerms</div>\n </div>\n\n @if (o.rentalTerms; as rt) {\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-4 text-sm\">\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Amount</div>\n <div class=\"font-medium\">{{ rt.amount ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Move-in date</div>\n <div class=\"font-medium\">{{ rt.moveInDate ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Payment frequency</div>\n <div class=\"font-medium\">{{ rt.paymentFrequency ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Tenancy length</div>\n <div class=\"font-medium\">{{ rt.tenancyLengthMonths ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Break clause</div>\n <div class=\"font-medium\">{{ rt.breakClauseMonths ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Pets</div>\n <div class=\"font-medium\">{{ rt.pets.length > 0 ? rt.pets.join(', ') : '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Smoker</div>\n <div class=\"font-medium\">{{ rt.smoker === null ? '\u2014' : (rt.smoker ? 'Yes' : 'No') }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Furniture</div>\n <div class=\"font-medium\">{{ rt.furnitureRequirement ?? '\u2014' }}</div>\n </div>\n <div class=\"sm:col-span-2\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Additional requests</div>\n <div class=\"font-medium whitespace-pre-wrap\">{{ rt.additionalRequests ?? '\u2014' }}</div>\n </div>\n </div>\n }\n</section>\n}\n", styles: [""], encapsulation: i0.ViewEncapsulation.None });
3045
- }
3046
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferRentalTermsCard, decorators: [{
3047
- type: Component,
3048
- args: [{ selector: 'rolatech-offer-rental-terms-card', imports: [], encapsulation: ViewEncapsulation.None, template: "@if (ctx.offer(); as o) {\n<section class=\"rounded-2xl border bg-[--rt-raised-background] p-4 space-y-3\">\n <div>\n <div class=\"text-sm font-semibold\">Rental terms</div>\n <div class=\"text-xs text-[--rt-text-secondary]\">o.rentalTerms</div>\n </div>\n\n @if (o.rentalTerms; as rt) {\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-4 text-sm\">\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Amount</div>\n <div class=\"font-medium\">{{ rt.amount ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Move-in date</div>\n <div class=\"font-medium\">{{ rt.moveInDate ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Payment frequency</div>\n <div class=\"font-medium\">{{ rt.paymentFrequency ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Tenancy length</div>\n <div class=\"font-medium\">{{ rt.tenancyLengthMonths ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Break clause</div>\n <div class=\"font-medium\">{{ rt.breakClauseMonths ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Pets</div>\n <div class=\"font-medium\">{{ rt.pets.length > 0 ? rt.pets.join(', ') : '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Smoker</div>\n <div class=\"font-medium\">{{ rt.smoker === null ? '\u2014' : (rt.smoker ? 'Yes' : 'No') }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Furniture</div>\n <div class=\"font-medium\">{{ rt.furnitureRequirement ?? '\u2014' }}</div>\n </div>\n <div class=\"sm:col-span-2\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Additional requests</div>\n <div class=\"font-medium whitespace-pre-wrap\">{{ rt.additionalRequests ?? '\u2014' }}</div>\n </div>\n </div>\n }\n</section>\n}\n" }]
3049
- }] });
3050
-
3051
3046
  class OfferSaleDetailsCard {
3052
3047
  ctx = inject(OfferDetailContext);
3053
3048
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferSaleDetailsCard, deps: [], target: i0.ɵɵFactoryTarget.Component });
3054
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: OfferSaleDetailsCard, isStandalone: true, selector: "rolatech-offer-sale-details-card", ngImport: i0, template: "@if (ctx.offer(); as o) {\n<section class=\"rounded-2xl border bg-[--rt-raised-background] p-4 space-y-3\">\n <div>\n <div class=\"text-sm font-semibold\">Sale details</div>\n <div class=\"text-xs text-[--rt-text-secondary]\">o.sale</div>\n </div>\n\n @if (o.sale; as s) {\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-4 text-sm\">\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Amount</div>\n <div class=\"font-medium\">{{ s.amount ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Payment method</div>\n <div class=\"font-medium\">{{ s.paymentMethod ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Buyer name</div>\n <div class=\"font-medium\">{{ s.buyerName ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Phone</div>\n <div class=\"font-medium\">{{ s.phone ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Email</div>\n <div class=\"font-medium\">{{ s.email ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Proposed exchange date</div>\n <div class=\"font-medium\">{{ s.proposedExchangeDate ?? '\u2014' }}</div>\n </div>\n <div class=\"sm:col-span-2\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Solicitor company</div>\n <div class=\"font-medium\">{{ s.solicitorCompanyName ?? '\u2014' }}</div>\n </div>\n </div>\n }\n</section>\n}\n", styles: [""] });
3049
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: OfferSaleDetailsCard, isStandalone: true, selector: "rolatech-offer-sale-details-card", host: { classAttribute: "block" }, ngImport: i0, template: "@if (ctx.offer(); as o) {\n<section class=\"rounded-2xl border border-[--rt-outline] p-4 space-y-3\">\n <div>\n <div class=\"text-sm font-semibold\">Sale details</div>\n <div class=\"text-xs text-[--rt-text-secondary]\">o.sale</div>\n </div>\n\n @if (o.sale; as s) {\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-4 text-sm\">\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Amount</div>\n <div class=\"font-medium\">{{ s.amount ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Payment method</div>\n <div class=\"font-medium\">{{ s.paymentMethod ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Buyer name</div>\n <div class=\"font-medium\">{{ s.buyerName ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Phone</div>\n <div class=\"font-medium\">{{ s.phone ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Email</div>\n <div class=\"font-medium\">{{ s.email ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Proposed exchange date</div>\n <div class=\"font-medium\">{{ s.proposedExchangeDate ?? '\u2014' }}</div>\n </div>\n <div class=\"sm:col-span-2\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Solicitor company</div>\n <div class=\"font-medium\">{{ s.solicitorCompanyName ?? '\u2014' }}</div>\n </div>\n </div>\n }\n</section>\n}\n", styles: [""] });
3055
3050
  }
3056
3051
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferSaleDetailsCard, decorators: [{
3057
3052
  type: Component,
3058
- args: [{ selector: 'rolatech-offer-sale-details-card', imports: [], template: "@if (ctx.offer(); as o) {\n<section class=\"rounded-2xl border bg-[--rt-raised-background] p-4 space-y-3\">\n <div>\n <div class=\"text-sm font-semibold\">Sale details</div>\n <div class=\"text-xs text-[--rt-text-secondary]\">o.sale</div>\n </div>\n\n @if (o.sale; as s) {\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-4 text-sm\">\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Amount</div>\n <div class=\"font-medium\">{{ s.amount ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Payment method</div>\n <div class=\"font-medium\">{{ s.paymentMethod ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Buyer name</div>\n <div class=\"font-medium\">{{ s.buyerName ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Phone</div>\n <div class=\"font-medium\">{{ s.phone ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Email</div>\n <div class=\"font-medium\">{{ s.email ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Proposed exchange date</div>\n <div class=\"font-medium\">{{ s.proposedExchangeDate ?? '\u2014' }}</div>\n </div>\n <div class=\"sm:col-span-2\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Solicitor company</div>\n <div class=\"font-medium\">{{ s.solicitorCompanyName ?? '\u2014' }}</div>\n </div>\n </div>\n }\n</section>\n}\n" }]
3059
- }] });
3060
-
3061
- class OfferTenantExpanded {
3062
- ctx = inject(OfferDetailContext);
3063
- tenant = input.required(...(ngDevMode ? [{ debugName: "tenant" }] : []));
3064
- formatAddress(a) {
3065
- const parts = [a?.line1, a?.line2, a?.city, a?.postcode, a?.country].filter((v) => !!v && v.trim() !== '');
3066
- return parts.length ? parts.join(', ') : '—';
3067
- }
3068
- genderLabel = {
3069
- MALE: 'Male',
3070
- FEMALE: 'Female',
3071
- OTHER: 'Other',
3072
- PREFER_NOT_TO_SAY: 'Prefer not to say',
3073
- };
3074
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferTenantExpanded, deps: [], target: i0.ɵɵFactoryTarget.Component });
3075
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: OfferTenantExpanded, isStandalone: true, selector: "rolatech-offer-tenant-expanded", inputs: { tenant: { classPropertyName: "tenant", publicName: "tenant", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"p-4 border-t space-y-4\">\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-4 text-sm\">\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Age</div>\n <div class=\"font-medium\">{{ ctx.ageFromDob(tenant().dob) }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Gender</div>\n <div class=\"font-medium\">@if (tenant().gender) { {{ genderLabel[tenant().gender!] }} } @else { \u2014 }</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Applicant type</div>\n <div class=\"font-medium\">{{ tenant().applicantType ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Nationality</div>\n <div class=\"font-medium\">{{ tenant().nationality }}</div>\n </div>\n\n <div class=\"sm:col-span-2\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Address</div>\n <div class=\"font-medium\">{{ formatAddress(tenant().address) }}</div>\n </div>\n </div>\n\n @switch (tenant().applicantType) { @case ('INDIVIDUAL') {\n <div class=\"rounded-xl border p-3 space-y-2\">\n <div class=\"text-xs font-semibold\">Individual</div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Employment</div>\n <div class=\"font-medium\">{{ tenant().employmentStatus ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Company</div>\n <div class=\"font-medium\">{{ tenant().companyName ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Job title</div>\n <div class=\"font-medium\">{{ tenant().jobTitle ?? '\u2014' }}</div>\n </div>\n </div>\n } @case ('CORPORATE') {\n <div class=\"rounded-xl border p-3 space-y-2\">\n <div class=\"text-xs font-semibold\">Corporate</div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Company</div>\n <div class=\"font-medium\">{{ tenant().corporateCompanyName ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Company number</div>\n <div class=\"font-medium\">{{ tenant().corporateCompanyNumber ?? '\u2014' }}</div>\n </div>\n </div>\n } @case ('STUDENT') {\n <div class=\"rounded-xl border p-3 space-y-2\">\n <div class=\"text-xs font-semibold\">Student</div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">University</div>\n <div class=\"font-medium\">{{ tenant().universityName ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Course</div>\n <div class=\"font-medium\">{{ tenant().courseTitle ?? '\u2014' }}</div>\n </div>\n </div>\n } }\n</div>\n", styles: [""] });
3076
- }
3077
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferTenantExpanded, decorators: [{
3078
- type: Component,
3079
- args: [{ selector: 'rolatech-offer-tenant-expanded', imports: [], template: "<div class=\"p-4 border-t space-y-4\">\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-4 text-sm\">\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Age</div>\n <div class=\"font-medium\">{{ ctx.ageFromDob(tenant().dob) }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Gender</div>\n <div class=\"font-medium\">@if (tenant().gender) { {{ genderLabel[tenant().gender!] }} } @else { \u2014 }</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Applicant type</div>\n <div class=\"font-medium\">{{ tenant().applicantType ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Nationality</div>\n <div class=\"font-medium\">{{ tenant().nationality }}</div>\n </div>\n\n <div class=\"sm:col-span-2\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Address</div>\n <div class=\"font-medium\">{{ formatAddress(tenant().address) }}</div>\n </div>\n </div>\n\n @switch (tenant().applicantType) { @case ('INDIVIDUAL') {\n <div class=\"rounded-xl border p-3 space-y-2\">\n <div class=\"text-xs font-semibold\">Individual</div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Employment</div>\n <div class=\"font-medium\">{{ tenant().employmentStatus ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Company</div>\n <div class=\"font-medium\">{{ tenant().companyName ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Job title</div>\n <div class=\"font-medium\">{{ tenant().jobTitle ?? '\u2014' }}</div>\n </div>\n </div>\n } @case ('CORPORATE') {\n <div class=\"rounded-xl border p-3 space-y-2\">\n <div class=\"text-xs font-semibold\">Corporate</div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Company</div>\n <div class=\"font-medium\">{{ tenant().corporateCompanyName ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Company number</div>\n <div class=\"font-medium\">{{ tenant().corporateCompanyNumber ?? '\u2014' }}</div>\n </div>\n </div>\n } @case ('STUDENT') {\n <div class=\"rounded-xl border p-3 space-y-2\">\n <div class=\"text-xs font-semibold\">Student</div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">University</div>\n <div class=\"font-medium\">{{ tenant().universityName ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Course</div>\n <div class=\"font-medium\">{{ tenant().courseTitle ?? '\u2014' }}</div>\n </div>\n </div>\n } }\n</div>\n" }]
3080
- }], propDecorators: { tenant: [{ type: i0.Input, args: [{ isSignal: true, alias: "tenant", required: true }] }] } });
3081
-
3082
- class OfferTenantCard {
3083
- // ---- signal inputs
3084
- index = input.required(...(ngDevMode ? [{ debugName: "index" }] : []));
3085
- expanded = input.required(...(ngDevMode ? [{ debugName: "expanded" }] : []));
3086
- tenant = input.required(...(ngDevMode ? [{ debugName: "tenant" }] : []));
3087
- // ---- label maps (for tooltips / pretty labels)
3088
- paymentFrequencyLabel = {
3089
- MONTHLY: 'Monthly',
3090
- QUARTERLY: 'Quarterly',
3091
- SEMI_ANNUALLY: 'Semi-annually',
3092
- ANNUALLY: 'Annually',
3093
- };
3094
- furnitureRequirementLabel = {
3095
- FURNISHED: 'Furnished',
3096
- UNFURNISHED: 'Unfurnished',
3097
- };
3098
- applicantTypeLabel = {
3099
- INDIVIDUAL: 'Individual',
3100
- CORPORATE: 'Corporate',
3101
- STUDENT: 'Student',
3102
- };
3103
- employmentStatusLabel = {
3104
- EMPLOYED: 'Employed',
3105
- SELF_EMPLOYED: 'Self-employed',
3106
- UNEMPLOYED: 'Unemployed',
3107
- };
3108
- visaStatusLabel = {
3109
- CITIZEN: 'Citizen',
3110
- WORK_VISA: 'Work visa',
3111
- STUDENT_VISA: 'Student visa',
3112
- OTHER: 'Other',
3113
- };
3114
- adverseCreditStatusLabel = {
3115
- NONE: 'None',
3116
- CCJ: 'CCJ',
3117
- BANKRUPTCY: 'Bankruptcy',
3118
- IVA: 'IVA',
3119
- OTHER: 'Other',
3120
- };
3121
- // ---- callback input instead of Output
3122
- onToggleInput = input.required(...(ngDevMode ? [{ debugName: "onToggleInput" }] : []));
3123
- onToggle() {
3124
- this.onToggleInput()(this.index());
3125
- }
3126
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferTenantCard, deps: [], target: i0.ɵɵFactoryTarget.Component });
3127
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: OfferTenantCard, isStandalone: true, selector: "rolatech-offer-tenant-card", inputs: { index: { classPropertyName: "index", publicName: "index", isSignal: true, isRequired: true, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: true, transformFunction: null }, tenant: { classPropertyName: "tenant", publicName: "tenant", isSignal: true, isRequired: true, transformFunction: null }, onToggleInput: { classPropertyName: "onToggleInput", publicName: "onToggleInput", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"rounded-xl border bg-[--rt-base-background] overflow-hidden\">\n <button\n type=\"button\"\n class=\"w-full text-left p-4 flex items-start justify-between gap-3 hover:bg-[--rt-raised-background]\"\n (click)=\"onToggle()\"\n >\n <div class=\"min-w-0 space-y-1\">\n <div class=\"text-sm font-semibold truncate\">{{ tenant().fullName ?? '--' }}</div>\n <div class=\"text-xs text-[--rt-text-secondary] truncate\">{{ tenant().email ?? '--' }} \u00B7 {{ tenant().phone ?? '--' }}</div>\n <div class=\"flex flex-wrap gap-2 pt-1 text-xs\">\n <span class=\"px-2 py-1 rounded-full border\">\n @if (tenant().applicantType) { {{ applicantTypeLabel[tenant().applicantType!] }} } @else { Applicant: -- }\n </span>\n\n <span class=\"px-2 py-1 rounded-full border\">\n @if (tenant().employmentStatus) { {{ employmentStatusLabel[tenant().employmentStatus!] }} } @else { Employment: --}\n </span>\n\n <span class=\"px-2 py-1 rounded-full border\">\n @if (tenant().adverseCreditStatus) { {{ adverseCreditStatusLabel[tenant().adverseCreditStatus!] }} } @else { Credit:\n -- }\n </span>\n\n <span class=\"px-2 py-1 rounded-full border\">\n @if (tenant().visaStatus) { {{ visaStatusLabel[tenant().visaStatus!] }} } @else { Visa: \u2014 }\n </span>\n </div>\n </div>\n\n <div class=\"flex items-center gap-2 shrink-0\">\n <span class=\"text-xs px-2 py-1 rounded-full border\"> {{ expanded() ? 'Expanded' : 'Collapsed' }} </span>\n <svg class=\"w-4 h-4 transition-transform\" [class.rotate-180]=\"expanded()\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M5.23 7.21a.75.75 0 0 1 1.06.02L10 11.168l3.71-3.936a.75.75 0 1 1 1.08 1.04l-4.24 4.5a.75.75 0 0 1-1.08 0l-4.24-4.5a.75.75 0 0 1 .02-1.06z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </div>\n </button>\n\n @if (expanded()) {\n <rolatech-offer-tenant-expanded [tenant]=\"tenant()\" />\n }\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: OfferTenantExpanded, selector: "rolatech-offer-tenant-expanded", inputs: ["tenant"] }] });
3128
- }
3129
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferTenantCard, decorators: [{
3130
- type: Component,
3131
- args: [{ selector: 'rolatech-offer-tenant-card', imports: [OfferTenantExpanded], template: "<div class=\"rounded-xl border bg-[--rt-base-background] overflow-hidden\">\n <button\n type=\"button\"\n class=\"w-full text-left p-4 flex items-start justify-between gap-3 hover:bg-[--rt-raised-background]\"\n (click)=\"onToggle()\"\n >\n <div class=\"min-w-0 space-y-1\">\n <div class=\"text-sm font-semibold truncate\">{{ tenant().fullName ?? '--' }}</div>\n <div class=\"text-xs text-[--rt-text-secondary] truncate\">{{ tenant().email ?? '--' }} \u00B7 {{ tenant().phone ?? '--' }}</div>\n <div class=\"flex flex-wrap gap-2 pt-1 text-xs\">\n <span class=\"px-2 py-1 rounded-full border\">\n @if (tenant().applicantType) { {{ applicantTypeLabel[tenant().applicantType!] }} } @else { Applicant: -- }\n </span>\n\n <span class=\"px-2 py-1 rounded-full border\">\n @if (tenant().employmentStatus) { {{ employmentStatusLabel[tenant().employmentStatus!] }} } @else { Employment: --}\n </span>\n\n <span class=\"px-2 py-1 rounded-full border\">\n @if (tenant().adverseCreditStatus) { {{ adverseCreditStatusLabel[tenant().adverseCreditStatus!] }} } @else { Credit:\n -- }\n </span>\n\n <span class=\"px-2 py-1 rounded-full border\">\n @if (tenant().visaStatus) { {{ visaStatusLabel[tenant().visaStatus!] }} } @else { Visa: \u2014 }\n </span>\n </div>\n </div>\n\n <div class=\"flex items-center gap-2 shrink-0\">\n <span class=\"text-xs px-2 py-1 rounded-full border\"> {{ expanded() ? 'Expanded' : 'Collapsed' }} </span>\n <svg class=\"w-4 h-4 transition-transform\" [class.rotate-180]=\"expanded()\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M5.23 7.21a.75.75 0 0 1 1.06.02L10 11.168l3.71-3.936a.75.75 0 1 1 1.08 1.04l-4.24 4.5a.75.75 0 0 1-1.08 0l-4.24-4.5a.75.75 0 0 1 .02-1.06z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </div>\n </button>\n\n @if (expanded()) {\n <rolatech-offer-tenant-expanded [tenant]=\"tenant()\" />\n }\n</div>\n" }]
3132
- }], propDecorators: { index: [{ type: i0.Input, args: [{ isSignal: true, alias: "index", required: true }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: true }] }], tenant: [{ type: i0.Input, args: [{ isSignal: true, alias: "tenant", required: true }] }], onToggleInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "onToggleInput", required: true }] }] } });
3133
-
3134
- class OfferTenantsAccordion {
3135
- ctx = inject(OfferDetailContext);
3136
- // tenants snapshot from ctx
3137
- tenants = computed(() => this.ctx.offer()?.tenants ?? [], ...(ngDevMode ? [{ debugName: "tenants" }] : []));
3138
- // index-based expanded state (per your requirement)
3139
- expandedIndexes = signal(new Set(), ...(ngDevMode ? [{ debugName: "expandedIndexes" }] : []));
3140
- isExpanded(i) {
3141
- return this.expandedIndexes().has(i);
3142
- }
3143
- toggle = (index) => {
3144
- this.expandedIndexes.update((prev) => {
3145
- const next = new Set(prev);
3146
- if (next.has(index))
3147
- next.delete(index);
3148
- else
3149
- next.add(index);
3150
- return next;
3151
- });
3152
- };
3153
- expandAll(count) {
3154
- const next = new Set();
3155
- for (let i = 0; i < count; i++)
3156
- next.add(i);
3157
- this.expandedIndexes.set(next);
3158
- }
3159
- collapseAll() {
3160
- this.expandedIndexes.set(new Set());
3161
- }
3162
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferTenantsAccordion, deps: [], target: i0.ɵɵFactoryTarget.Component });
3163
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: OfferTenantsAccordion, isStandalone: true, selector: "rolatech-offer-tenants-accordion", ngImport: i0, template: "@if (tenants(); as ts) {\n<section class=\"rounded-2xl border bg-[--rt-raised-background] p-4 space-y-3\">\n <div class=\"flex items-start justify-between gap-3\">\n <div>\n <div class=\"text-sm font-semibold\">Tenants</div>\n <div class=\"text-xs text-[--rt-text-secondary]\">o.tenants</div>\n </div>\n\n <div class=\"flex items-center gap-2\">\n <button\n type=\"button\"\n class=\"text-xs px-3 py-1 rounded-full border bg-[--rt-base-background]\"\n (click)=\"expandAll(ts.length)\"\n [disabled]=\"ts.length === 0\"\n >\n Expand all\n </button>\n <button\n type=\"button\"\n class=\"text-xs px-3 py-1 rounded-full border bg-[--rt-base-background]\"\n (click)=\"collapseAll()\"\n [disabled]=\"expandedIndexes().size === 0\"\n >\n Collapse all\n </button>\n <span class=\"text-xs px-2 py-1 rounded-full border bg-[--rt-base-background]\">count: {{ ts.length }}</span>\n </div>\n </div>\n\n @if (ts.length > 0) {\n <div class=\"space-y-3\">\n @for (t of ts; track $index) {\n <rolatech-offer-tenant-card [index]=\"$index\" [expanded]=\"isExpanded($index)\" [tenant]=\"t\" [onToggleInput]=\"toggle\" />\n }\n </div>\n } @else {\n <div class=\"text-sm text-[--rt-text-secondary]\">No tenants</div>\n }\n</section>\n}\n", styles: [""], dependencies: [{ kind: "component", type: OfferTenantCard, selector: "rolatech-offer-tenant-card", inputs: ["index", "expanded", "tenant", "onToggleInput"] }], encapsulation: i0.ViewEncapsulation.None });
3164
- }
3165
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferTenantsAccordion, decorators: [{
3166
- type: Component,
3167
- args: [{ selector: 'rolatech-offer-tenants-accordion', imports: [OfferTenantCard], encapsulation: ViewEncapsulation.None, template: "@if (tenants(); as ts) {\n<section class=\"rounded-2xl border bg-[--rt-raised-background] p-4 space-y-3\">\n <div class=\"flex items-start justify-between gap-3\">\n <div>\n <div class=\"text-sm font-semibold\">Tenants</div>\n <div class=\"text-xs text-[--rt-text-secondary]\">o.tenants</div>\n </div>\n\n <div class=\"flex items-center gap-2\">\n <button\n type=\"button\"\n class=\"text-xs px-3 py-1 rounded-full border bg-[--rt-base-background]\"\n (click)=\"expandAll(ts.length)\"\n [disabled]=\"ts.length === 0\"\n >\n Expand all\n </button>\n <button\n type=\"button\"\n class=\"text-xs px-3 py-1 rounded-full border bg-[--rt-base-background]\"\n (click)=\"collapseAll()\"\n [disabled]=\"expandedIndexes().size === 0\"\n >\n Collapse all\n </button>\n <span class=\"text-xs px-2 py-1 rounded-full border bg-[--rt-base-background]\">count: {{ ts.length }}</span>\n </div>\n </div>\n\n @if (ts.length > 0) {\n <div class=\"space-y-3\">\n @for (t of ts; track $index) {\n <rolatech-offer-tenant-card [index]=\"$index\" [expanded]=\"isExpanded($index)\" [tenant]=\"t\" [onToggleInput]=\"toggle\" />\n }\n </div>\n } @else {\n <div class=\"text-sm text-[--rt-text-secondary]\">No tenants</div>\n }\n</section>\n}\n" }]
3053
+ args: [{ selector: 'rolatech-offer-sale-details-card', imports: [], host: { class: 'block' }, template: "@if (ctx.offer(); as o) {\n<section class=\"rounded-2xl border border-[--rt-outline] p-4 space-y-3\">\n <div>\n <div class=\"text-sm font-semibold\">Sale details</div>\n <div class=\"text-xs text-[--rt-text-secondary]\">o.sale</div>\n </div>\n\n @if (o.sale; as s) {\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-4 text-sm\">\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Amount</div>\n <div class=\"font-medium\">{{ s.amount ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Payment method</div>\n <div class=\"font-medium\">{{ s.paymentMethod ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Buyer name</div>\n <div class=\"font-medium\">{{ s.buyerName ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Phone</div>\n <div class=\"font-medium\">{{ s.phone ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Email</div>\n <div class=\"font-medium\">{{ s.email ?? '\u2014' }}</div>\n </div>\n <div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Proposed exchange date</div>\n <div class=\"font-medium\">{{ s.proposedExchangeDate ?? '\u2014' }}</div>\n </div>\n <div class=\"sm:col-span-2\">\n <div class=\"text-xs text-[--rt-text-secondary]\">Solicitor company</div>\n <div class=\"font-medium\">{{ s.solicitorCompanyName ?? '\u2014' }}</div>\n </div>\n </div>\n }\n</section>\n}\n" }]
3168
3054
  }] });
3169
3055
 
3170
3056
  class OfferSideSummaryCard {
@@ -3174,11 +3060,11 @@ class OfferSideSummaryCard {
3174
3060
  MORTGAGE: 'Mortgage',
3175
3061
  };
3176
3062
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferSideSummaryCard, deps: [], target: i0.ɵɵFactoryTarget.Component });
3177
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: OfferSideSummaryCard, isStandalone: true, selector: "rolatech-offer-side-summary-card", ngImport: i0, template: "@if (ctx.offer(); as o) {\n<section class=\"rounded-2xl border bg-[--rt-raised-background] p-4 space-y-3\">\n <div>\n <div class=\"text-sm font-semibold\">Summary</div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Key fields</div>\n </div>\n\n <div class=\"grid grid-cols-1 gap-3 text-sm\">\n <div class=\"flex items-center justify-between\">\n <span class=\"text-[--rt-text-secondary]\">Type</span><span class=\"font-medium\">{{ o.type }}</span>\n </div>\n <div class=\"flex items-center justify-between\">\n <span class=\"text-[--rt-text-secondary]\">Status</span><span class=\"font-medium\">{{ o.status }}</span>\n </div>\n <div class=\"flex items-center justify-between\">\n <span class=\"text-[--rt-text-secondary]\">Invoice</span\n ><span class=\"font-medium\">{{ ctx.invoiceOptionLabel[o.invoiceOption] }}</span>\n </div>\n <div class=\"flex items-center justify-between\">\n <span class=\"text-[--rt-text-secondary]\">Tenants</span><span class=\"font-medium\">{{ o.tenants?.length ?? 0 }}</span>\n </div>\n <div class=\"flex items-center justify-between\">\n <span class=\"text-[--rt-text-secondary]\">Item amount</span><span class=\"font-medium\">{{ o.item.amount | price }}</span>\n </div>\n @if (ctx.isRental()) {\n <div class=\"flex items-center justify-between gap-3\">\n <span class=\"text-[--rt-text-secondary]\">Tenants</span>\n <span class=\"font-medium\">{{ ctx.asText(o.tenants?.length ?? 0) }}</span>\n </div>\n }\n </div>\n</section>\n}\n", styles: [""], dependencies: [{ kind: "pipe", type: PricePipe, name: "price" }] });
3063
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: OfferSideSummaryCard, isStandalone: true, selector: "rolatech-offer-side-summary-card", host: { classAttribute: "block" }, ngImport: i0, template: "@if (ctx.offer(); as o) {\n<section class=\"rounded-2xl border border-[--rt-outline] p-4 space-y-3\">\n <div>\n <div class=\"text-sm font-semibold\">Summary</div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Key fields</div>\n </div>\n\n <div class=\"grid grid-cols-1 gap-3 text-sm\">\n <div class=\"flex items-center justify-between\">\n <span class=\"text-[--rt-text-secondary]\">Type</span><span class=\"font-medium\">{{ o.type }}</span>\n </div>\n <div class=\"flex items-center justify-between\">\n <span class=\"text-[--rt-text-secondary]\">Status</span><span class=\"font-medium\">{{ o.status }}</span>\n </div>\n <div class=\"flex items-center justify-between\">\n <span class=\"text-[--rt-text-secondary]\">Invoice</span\n ><span class=\"font-medium\">{{ ctx.invoiceOptionLabel[o.invoiceOption] }}</span>\n </div>\n <div class=\"flex items-center justify-between\">\n <span class=\"text-[--rt-text-secondary]\">Tenants</span><span class=\"font-medium\">{{ o.tenants?.length ?? 0 }}</span>\n </div>\n <div class=\"flex items-center justify-between\">\n <span class=\"text-[--rt-text-secondary]\">Item amount</span><span class=\"font-medium\">{{ o.item.amount | price }}</span>\n </div>\n @if (ctx.isRental()) {\n <div class=\"flex items-center justify-between gap-3\">\n <span class=\"text-[--rt-text-secondary]\">Tenants</span>\n <span class=\"font-medium\">{{ ctx.asText(o.tenants?.length ?? 0) }}</span>\n </div>\n }\n </div>\n</section>\n}\n", styles: [""], dependencies: [{ kind: "pipe", type: PricePipe, name: "price" }] });
3178
3064
  }
3179
3065
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: OfferSideSummaryCard, decorators: [{
3180
3066
  type: Component,
3181
- args: [{ selector: 'rolatech-offer-side-summary-card', imports: [PricePipe], template: "@if (ctx.offer(); as o) {\n<section class=\"rounded-2xl border bg-[--rt-raised-background] p-4 space-y-3\">\n <div>\n <div class=\"text-sm font-semibold\">Summary</div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Key fields</div>\n </div>\n\n <div class=\"grid grid-cols-1 gap-3 text-sm\">\n <div class=\"flex items-center justify-between\">\n <span class=\"text-[--rt-text-secondary]\">Type</span><span class=\"font-medium\">{{ o.type }}</span>\n </div>\n <div class=\"flex items-center justify-between\">\n <span class=\"text-[--rt-text-secondary]\">Status</span><span class=\"font-medium\">{{ o.status }}</span>\n </div>\n <div class=\"flex items-center justify-between\">\n <span class=\"text-[--rt-text-secondary]\">Invoice</span\n ><span class=\"font-medium\">{{ ctx.invoiceOptionLabel[o.invoiceOption] }}</span>\n </div>\n <div class=\"flex items-center justify-between\">\n <span class=\"text-[--rt-text-secondary]\">Tenants</span><span class=\"font-medium\">{{ o.tenants?.length ?? 0 }}</span>\n </div>\n <div class=\"flex items-center justify-between\">\n <span class=\"text-[--rt-text-secondary]\">Item amount</span><span class=\"font-medium\">{{ o.item.amount | price }}</span>\n </div>\n @if (ctx.isRental()) {\n <div class=\"flex items-center justify-between gap-3\">\n <span class=\"text-[--rt-text-secondary]\">Tenants</span>\n <span class=\"font-medium\">{{ ctx.asText(o.tenants?.length ?? 0) }}</span>\n </div>\n }\n </div>\n</section>\n}\n" }]
3067
+ args: [{ selector: 'rolatech-offer-side-summary-card', imports: [PricePipe], host: { class: 'block' }, template: "@if (ctx.offer(); as o) {\n<section class=\"rounded-2xl border border-[--rt-outline] p-4 space-y-3\">\n <div>\n <div class=\"text-sm font-semibold\">Summary</div>\n <div class=\"text-xs text-[--rt-text-secondary]\">Key fields</div>\n </div>\n\n <div class=\"grid grid-cols-1 gap-3 text-sm\">\n <div class=\"flex items-center justify-between\">\n <span class=\"text-[--rt-text-secondary]\">Type</span><span class=\"font-medium\">{{ o.type }}</span>\n </div>\n <div class=\"flex items-center justify-between\">\n <span class=\"text-[--rt-text-secondary]\">Status</span><span class=\"font-medium\">{{ o.status }}</span>\n </div>\n <div class=\"flex items-center justify-between\">\n <span class=\"text-[--rt-text-secondary]\">Invoice</span\n ><span class=\"font-medium\">{{ ctx.invoiceOptionLabel[o.invoiceOption] }}</span>\n </div>\n <div class=\"flex items-center justify-between\">\n <span class=\"text-[--rt-text-secondary]\">Tenants</span><span class=\"font-medium\">{{ o.tenants?.length ?? 0 }}</span>\n </div>\n <div class=\"flex items-center justify-between\">\n <span class=\"text-[--rt-text-secondary]\">Item amount</span><span class=\"font-medium\">{{ o.item.amount | price }}</span>\n </div>\n @if (ctx.isRental()) {\n <div class=\"flex items-center justify-between gap-3\">\n <span class=\"text-[--rt-text-secondary]\">Tenants</span>\n <span class=\"font-medium\">{{ ctx.asText(o.tenants?.length ?? 0) }}</span>\n </div>\n }\n </div>\n</section>\n}\n" }]
3182
3068
  }] });
3183
3069
 
3184
3070
  class PropertyOfferDetailComponent extends BaseComponent {
@@ -3339,7 +3225,7 @@ class PropertyOfferDetailComponent extends BaseComponent {
3339
3225
  });
3340
3226
  }
3341
3227
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PropertyOfferDetailComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
3342
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: PropertyOfferDetailComponent, isStandalone: true, selector: "rolatech-property-offer-detail", providers: [OfferDetailContext], usesInheritance: true, ngImport: i0, template: "@if (ctx.offer(); as o) {\n <div class=\"max-w-7xl mx-auto px-4 lg:px-6 py-6 space-y-6\">\n <rolatech-offer-header-card />\n\n <div class=\"grid grid-cols-1 lg:grid-cols-12 gap-6\">\n <div class=\"lg:col-span-8 space-y-6 grid\">\n <rolatech-offer-item-card />\n\n @if (ctx.isRental()) {\n <rolatech-offer-rental-terms-card />\n <rolatech-offer-tenants-accordion />\n }\n\n @if (ctx.isSale()) {\n <rolatech-offer-sale-details-card />\n }\n </div>\n\n <aside class=\"lg:col-span-4 space-y-6\">\n <rolatech-offer-side-summary-card />\n </aside>\n </div>\n </div>\n} @else {\n <div class=\"max-w-7xl mx-auto px-4 lg:px-6 py-10\">\n <div class=\"rounded-2xl border bg-[--rolatech-raised-background] p-6\">Loading\u2026</div>\n </div>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: OfferHeaderCard, selector: "rolatech-offer-header-card" }, { kind: "component", type: OfferItemCard, selector: "rolatech-offer-item-card" }, { kind: "component", type: OfferRentalTermsCard, selector: "rolatech-offer-rental-terms-card" }, { kind: "component", type: OfferSaleDetailsCard, selector: "rolatech-offer-sale-details-card" }, { kind: "component", type: OfferTenantsAccordion, selector: "rolatech-offer-tenants-accordion" }, { kind: "component", type: OfferSideSummaryCard, selector: "rolatech-offer-side-summary-card" }] });
3228
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: PropertyOfferDetailComponent, isStandalone: true, selector: "rolatech-property-offer-detail", providers: [OfferDetailContext], usesInheritance: true, ngImport: i0, template: "@if (ctx.offer(); as o) {\n <div class=\"max-w-7xl mx-auto px-4 lg:px-6 py-6 space-y-4\">\n <rolatech-offer-header-card />\n\n <div class=\"grid grid-cols-1 lg:grid-cols-12 gap-4\">\n <div class=\"grid grid-cols-1 lg:col-span-8 space-y-4\">\n <rolatech-offer-item-card />\n\n @if (ctx.isRental()) {\n <rolatech-offer-rental-terms-card />\n <rolatech-offer-tenants-accordion />\n }\n\n @if (ctx.isSale()) {\n <rolatech-offer-sale-details-card />\n }\n </div>\n\n <aside class=\"lg:col-span-4 space-y-4\">\n <rolatech-offer-side-summary-card />\n </aside>\n </div>\n </div>\n} @else {\n <div class=\"max-w-7xl mx-auto px-4 lg:px-6 py-10\">\n <div class=\"rounded-2xl border bg-[--rolatech-raised-background] p-6\">Loading\u2026</div>\n </div>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: OfferHeaderCard, selector: "rolatech-offer-header-card" }, { kind: "component", type: OfferItemCard, selector: "rolatech-offer-item-card" }, { kind: "component", type: OfferRentalTermsCard, selector: "rolatech-offer-rental-terms-card" }, { kind: "component", type: OfferSaleDetailsCard, selector: "rolatech-offer-sale-details-card" }, { kind: "component", type: OfferTenantsAccordion, selector: "rolatech-offer-tenants-accordion" }, { kind: "component", type: OfferSideSummaryCard, selector: "rolatech-offer-side-summary-card" }] });
3343
3229
  }
3344
3230
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PropertyOfferDetailComponent, decorators: [{
3345
3231
  type: Component,
@@ -3353,7 +3239,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
3353
3239
  OfferSaleDetailsCard,
3354
3240
  OfferTenantsAccordion,
3355
3241
  OfferSideSummaryCard,
3356
- ], providers: [OfferDetailContext], template: "@if (ctx.offer(); as o) {\n <div class=\"max-w-7xl mx-auto px-4 lg:px-6 py-6 space-y-6\">\n <rolatech-offer-header-card />\n\n <div class=\"grid grid-cols-1 lg:grid-cols-12 gap-6\">\n <div class=\"lg:col-span-8 space-y-6 grid\">\n <rolatech-offer-item-card />\n\n @if (ctx.isRental()) {\n <rolatech-offer-rental-terms-card />\n <rolatech-offer-tenants-accordion />\n }\n\n @if (ctx.isSale()) {\n <rolatech-offer-sale-details-card />\n }\n </div>\n\n <aside class=\"lg:col-span-4 space-y-6\">\n <rolatech-offer-side-summary-card />\n </aside>\n </div>\n </div>\n} @else {\n <div class=\"max-w-7xl mx-auto px-4 lg:px-6 py-10\">\n <div class=\"rounded-2xl border bg-[--rolatech-raised-background] p-6\">Loading\u2026</div>\n </div>\n}\n" }]
3242
+ ], providers: [OfferDetailContext], template: "@if (ctx.offer(); as o) {\n <div class=\"max-w-7xl mx-auto px-4 lg:px-6 py-6 space-y-4\">\n <rolatech-offer-header-card />\n\n <div class=\"grid grid-cols-1 lg:grid-cols-12 gap-4\">\n <div class=\"grid grid-cols-1 lg:col-span-8 space-y-4\">\n <rolatech-offer-item-card />\n\n @if (ctx.isRental()) {\n <rolatech-offer-rental-terms-card />\n <rolatech-offer-tenants-accordion />\n }\n\n @if (ctx.isSale()) {\n <rolatech-offer-sale-details-card />\n }\n </div>\n\n <aside class=\"lg:col-span-4 space-y-4\">\n <rolatech-offer-side-summary-card />\n </aside>\n </div>\n </div>\n} @else {\n <div class=\"max-w-7xl mx-auto px-4 lg:px-6 py-10\">\n <div class=\"rounded-2xl border bg-[--rolatech-raised-background] p-6\">Loading\u2026</div>\n </div>\n}\n" }]
3357
3243
  }] });
3358
3244
 
3359
3245
  class PropertyViewingDetailComponent extends BaseComponent {
@@ -3557,6 +3443,7 @@ class OfferFormFacade {
3557
3443
  }
3558
3444
  async submit() {
3559
3445
  this.submitError.set(null);
3446
+ console.log(this.form().value);
3560
3447
  // mark all touched
3561
3448
  this.form().markAllAsTouched();
3562
3449
  this.form().updateValueAndValidity();
@@ -3593,7 +3480,7 @@ class OfferFormFacade {
3593
3480
  breakClauseMonths: new FormControl(null),
3594
3481
  // ✅ pets as array
3595
3482
  pets: this.fb.control([], { nonNullable: true }),
3596
- smoker: new FormControl(null),
3483
+ smoker: this.fb.control(false, { nonNullable: true }),
3597
3484
  furnitureRequirement: new FormControl(null),
3598
3485
  additionalRequests: new FormControl(null),
3599
3486
  }),
@@ -3624,7 +3511,7 @@ class OfferFormFacade {
3624
3511
  email: this.fb.control(null, [Validators.required, Validators.email]),
3625
3512
  address: this.fb.group({
3626
3513
  line1: this.fb.control(null, [Validators.required]),
3627
- line2: this.fb.control(null),
3514
+ line2: this.fb.control(null, [Validators.required]),
3628
3515
  city: this.fb.control(null, [Validators.required]),
3629
3516
  postcode: this.fb.control(null, [Validators.required]),
3630
3517
  country: this.fb.control(null, [Validators.required]),
@@ -3656,71 +3543,14 @@ class OfferFormFacade {
3656
3543
  postcode: this.fb.control(null),
3657
3544
  country: this.fb.control(null),
3658
3545
  }),
3546
+ type: this.fb.control(null, [Validators.required]),
3659
3547
  employmentStatus: this.fb.control(null),
3660
3548
  companyName: this.fb.control(null),
3661
3549
  jobTitle: this.fb.control(null),
3662
3550
  annualSalary: this.fb.control(null),
3663
3551
  companyNumber: this.fb.control(null),
3664
3552
  taxReturnSubmitted: this.fb.control(null),
3665
- }),
3666
- });
3667
- }
3668
- buildTenantGroup1() {
3669
- return this.fb.group({
3670
- // ✅ local-only identity for UI tracking
3671
- clientKey: this.fb.control(uid(), { nonNullable: true }),
3672
- // ✅ backend id (null until saved)
3673
- id: this.fb.control(null),
3674
- fullName: this.fb.control(null),
3675
- dob: new FormControl(null),
3676
- gender: new FormControl(null),
3677
- nationality: new FormControl(null),
3678
- visaStatus: new FormControl(null),
3679
- phone: new FormControl(null),
3680
- email: new FormControl(null),
3681
- address: this.fb.group({
3682
- line1: new FormControl(null),
3683
- line2: new FormControl(null),
3684
- city: new FormControl(null),
3685
- postcode: new FormControl(null),
3686
- country: new FormControl(null),
3687
- }),
3688
- adverseCreditStatus: new FormControl(null),
3689
- applicantType: new FormControl(null),
3690
- // Individual fields
3691
- employmentStatus: new FormControl(null),
3692
- companyName: new FormControl(null),
3693
- jobTitle: new FormControl(null),
3694
- annualSalary: new FormControl(null),
3695
- companyNumber: new FormControl(null),
3696
- taxReturnSubmitted: new FormControl(null),
3697
- // Corporate
3698
- corporateCompanyName: new FormControl(null),
3699
- corporateCompanyNumber: new FormControl(null),
3700
- corporateJobTitle: new FormControl(null),
3701
- // Student
3702
- universityName: new FormControl(null),
3703
- courseTitle: new FormControl(null),
3704
- yearOfStudy: new FormControl(null),
3705
- guarantor: this.fb.group({
3706
- fullName: new FormControl(null),
3707
- dob: new FormControl(null),
3708
- relationship: new FormControl(null),
3709
- phone: new FormControl(null),
3710
- email: new FormControl(null),
3711
- address: this.fb.group({
3712
- line1: new FormControl(null),
3713
- line2: new FormControl(null),
3714
- city: new FormControl(null),
3715
- postcode: new FormControl(null),
3716
- country: new FormControl(null),
3717
- }),
3718
- employmentStatus: new FormControl(null),
3719
- companyName: new FormControl(null),
3720
- jobTitle: new FormControl(null),
3721
- annualSalary: new FormControl(null),
3722
- companyNumber: new FormControl(null),
3723
- taxReturnSubmitted: new FormControl(null),
3553
+ additionalFinancialSupport: this.fb.control(null),
3724
3554
  }),
3725
3555
  });
3726
3556
  }
@@ -3837,10 +3667,14 @@ class OfferFormFacade {
3837
3667
  guarantor.get('email')?.setValidators([Validators.required, Validators.email]);
3838
3668
  const addr = guarantor.get('address');
3839
3669
  addr.get('line1')?.setValidators([Validators.required]);
3670
+ addr.get('line2')?.setValidators([Validators.required]);
3840
3671
  addr.get('city')?.setValidators([Validators.required]);
3841
3672
  addr.get('postcode')?.setValidators([Validators.required]);
3842
3673
  addr.get('country')?.setValidators([Validators.required]);
3674
+ guarantor.get('type')?.setValidators([Validators.required]);
3843
3675
  guarantor.get('employmentStatus')?.setValidators([Validators.required]);
3676
+ guarantor.get('taxReturnSubmitted')?.setValidators([Validators.required]);
3677
+ guarantor.get('additionalFinancialSupport')?.setValidators([Validators.required]);
3844
3678
  }
3845
3679
  toCreateRentalPayload() {
3846
3680
  const v = this.form().value;
@@ -3955,7 +3789,7 @@ class RentalOfferTermsSection {
3955
3789
  deps: [MAT_DATE_LOCALE],
3956
3790
  },
3957
3791
  { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS$5 },
3958
- ], ngImport: i0, template: "<div class=\"grid\" [formGroup]=\"rental\">\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-4\">\n <mat-label>Offer amount (PCM)</mat-label>\n <input matInput type=\"number\" formControlName=\"amount\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Move-in date</mat-label>\n <input matInput [min]=\"minDate\" (focus)=\"dp.open()\" [matDatepicker]=\"dp\" formControlName=\"moveInDate\" readonly />\n <mat-datepicker-toggle matIconSuffix [for]=\"dp\"></mat-datepicker-toggle>\n <mat-datepicker #dp></mat-datepicker>\n </mat-form-field>\n <mat-form-field class=\"col-span-4\">\n <mat-label>Payment frequency</mat-label>\n <mat-select formControlName=\"paymentFrequency\">\n <mat-option value=\"MONTHLY\">Monthly</mat-option>\n <mat-option value=\"QUARTERLY\">Quarterly</mat-option>\n <mat-option value=\"SEMI_ANNUALLY\">Semi-annually</mat-option>\n <mat-option value=\"ANNUALLY\">Annually</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-4\">\n <mat-label>Tenancy length (months)</mat-label>\n <input matInput type=\"number\" formControlName=\"tenancyLengthMonths\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Break clause (months)</mat-label>\n <input matInput type=\"number\" formControlName=\"breakClauseMonths\" />\n </mat-form-field>\n <mat-form-field class=\"col-span-4\">\n <mat-label>Furniture</mat-label>\n <mat-select formControlName=\"furnitureRequirement\">\n <mat-option value=\"FURNISHED\">Furnished</mat-option>\n <mat-option value=\"UNFURNISHED\">Unfurnished</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n\n <!-- <mat-form-field class=\"span2\">\n <mat-label>Pet (type all pets)</mat-label>\n <input matInput formControlName=\"pets\" />\n <mat-hint>Please type all pets manually</mat-hint>\n </mat-form-field> -->\n <mat-form-field appearance=\"fill\" class=\"w-full\">\n <mat-chip-grid #chipGrid aria-label=\"Pets\">\n @for (p of pets(); track p) {\n <mat-chip-row (removed)=\"removePet(p)\">\n {{ p }}\n <button matChipRemove [attr.aria-label]=\"'remove ' + p\">\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n }\n\n <input\n placeholder=\"Add a pet (e.g., Dog, Cat)\"\n [matChipInputFor]=\"chipGrid\"\n [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\n (matChipInputTokenEnd)=\"addPet($event)\"\n />\n </mat-chip-grid>\n\n <mat-hint>Press Enter or comma to add multiple pets.</mat-hint>\n </mat-form-field>\n <!--\n <mat-chip-listbox multiple [formControl]=\"petsControl()\" aria-label=\"Pets\">\n <mat-chip-option value=\"DOG\"> <mat-icon>pets</mat-icon> Dog </mat-chip-option>\n\n <mat-chip-option value=\"CAT\"> <mat-icon>pets</mat-icon> Cat </mat-chip-option>\n\n <mat-chip-option value=\"SMALL_ANIMAL\"> <mat-icon>pets</mat-icon> Small animal </mat-chip-option>\n\n <mat-chip-option value=\"BIRD\"> <mat-icon>flutter_dash</mat-icon> Bird </mat-chip-option>\n\n <mat-chip-option value=\"REPTILE\"> <mat-icon>pest_control</mat-icon> Reptile </mat-chip-option>\n </mat-chip-listbox> -->\n\n @if (petsControl().value.length) {\n <p class=\"hint\">Landlord approval may still be required.</p>\n }\n\n <mat-slide-toggle class=\"py-3\" formControlName=\"smoker\">Smoker</mat-slide-toggle>\n\n <mat-form-field class=\"span2\">\n <mat-label>Additional requests</mat-label>\n <textarea matInput rows=\"3\" formControlName=\"additionalRequests\"></textarea>\n </mat-form-field>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.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$2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i2$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { 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: MatNativeDateModule }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i6$1.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i1$4.MatChipGrid, selector: "mat-chip-grid", inputs: ["disabled", "placeholder", "required", "value", "errorStateMatcher"], outputs: ["change", "valueChange"] }, { kind: "directive", type: i1$4.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled", "readonly", "matChipInputDisabledInteractive"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { kind: "directive", type: i1$4.MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: i1$4.MatChipRow, selector: "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", inputs: ["editable"], outputs: ["edited"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: AngularComponentsModule }] });
3792
+ ], ngImport: i0, template: "<div class=\"grid\" [formGroup]=\"rental\">\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-4\">\n <mat-label>Offer amount (PCM)</mat-label>\n <input matInput type=\"number\" formControlName=\"amount\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Move-in date</mat-label>\n <input matInput [min]=\"minDate\" (focus)=\"dp.open()\" [matDatepicker]=\"dp\" formControlName=\"moveInDate\" readonly />\n <mat-datepicker-toggle matIconSuffix [for]=\"dp\"></mat-datepicker-toggle>\n <mat-datepicker #dp></mat-datepicker>\n </mat-form-field>\n <mat-form-field class=\"col-span-4\">\n <mat-label>Payment frequency</mat-label>\n <mat-select formControlName=\"paymentFrequency\">\n <mat-option value=\"MONTHLY\">Monthly</mat-option>\n <mat-option value=\"QUARTERLY\">Quarterly</mat-option>\n <mat-option value=\"SEMI_ANNUALLY\">Semi-annually</mat-option>\n <mat-option value=\"ANNUALLY\">Annually</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-4\">\n <mat-label>Tenancy length (months)</mat-label>\n <input matInput type=\"number\" formControlName=\"tenancyLengthMonths\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Break clause (months)</mat-label>\n <input matInput type=\"number\" formControlName=\"breakClauseMonths\" />\n </mat-form-field>\n <mat-form-field class=\"col-span-4\">\n <mat-label>Furniture</mat-label>\n <mat-select formControlName=\"furnitureRequirement\">\n <mat-option value=\"FURNISHED\">Furnished</mat-option>\n <mat-option value=\"UNFURNISHED\">Unfurnished</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n\n <mat-form-field appearance=\"fill\" class=\"w-full\">\n <mat-chip-grid #chipGrid aria-label=\"Pets\">\n @for (p of pets(); track p) {\n <mat-chip-row (removed)=\"removePet(p)\">\n {{ p }}\n <button matChipRemove [attr.aria-label]=\"'remove ' + p\">\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n }\n\n <input\n placeholder=\"Add a pet (e.g., Dog, Cat)\"\n [matChipInputFor]=\"chipGrid\"\n [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\n (matChipInputTokenEnd)=\"addPet($event)\"\n />\n </mat-chip-grid>\n\n <mat-hint>Press Enter or comma to add multiple pets.</mat-hint>\n </mat-form-field>\n\n @if (petsControl().value.length) {\n <p class=\"hint\">Landlord approval may still be required.</p>\n }\n\n <mat-slide-toggle labelPosition=\"before\" class=\"py-3\" formControlName=\"smoker\">\n <span class=\"text-lg font-bold\">Smoker</span>\n </mat-slide-toggle>\n\n <mat-form-field class=\"span2\">\n <mat-label>Additional requests</mat-label>\n <textarea matInput rows=\"3\" formControlName=\"additionalRequests\"></textarea>\n </mat-form-field>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.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$2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i2$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { 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: MatNativeDateModule }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i5.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i1$4.MatChipGrid, selector: "mat-chip-grid", inputs: ["disabled", "placeholder", "required", "value", "errorStateMatcher"], outputs: ["change", "valueChange"] }, { kind: "directive", type: i1$4.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled", "readonly", "matChipInputDisabledInteractive"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { kind: "directive", type: i1$4.MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: i1$4.MatChipRow, selector: "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", inputs: ["editable"], outputs: ["edited"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: AngularComponentsModule }] });
3959
3793
  }
3960
3794
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: RentalOfferTermsSection, decorators: [{
3961
3795
  type: Component,
@@ -3977,7 +3811,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
3977
3811
  deps: [MAT_DATE_LOCALE],
3978
3812
  },
3979
3813
  { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS$5 },
3980
- ], template: "<div class=\"grid\" [formGroup]=\"rental\">\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-4\">\n <mat-label>Offer amount (PCM)</mat-label>\n <input matInput type=\"number\" formControlName=\"amount\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Move-in date</mat-label>\n <input matInput [min]=\"minDate\" (focus)=\"dp.open()\" [matDatepicker]=\"dp\" formControlName=\"moveInDate\" readonly />\n <mat-datepicker-toggle matIconSuffix [for]=\"dp\"></mat-datepicker-toggle>\n <mat-datepicker #dp></mat-datepicker>\n </mat-form-field>\n <mat-form-field class=\"col-span-4\">\n <mat-label>Payment frequency</mat-label>\n <mat-select formControlName=\"paymentFrequency\">\n <mat-option value=\"MONTHLY\">Monthly</mat-option>\n <mat-option value=\"QUARTERLY\">Quarterly</mat-option>\n <mat-option value=\"SEMI_ANNUALLY\">Semi-annually</mat-option>\n <mat-option value=\"ANNUALLY\">Annually</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-4\">\n <mat-label>Tenancy length (months)</mat-label>\n <input matInput type=\"number\" formControlName=\"tenancyLengthMonths\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Break clause (months)</mat-label>\n <input matInput type=\"number\" formControlName=\"breakClauseMonths\" />\n </mat-form-field>\n <mat-form-field class=\"col-span-4\">\n <mat-label>Furniture</mat-label>\n <mat-select formControlName=\"furnitureRequirement\">\n <mat-option value=\"FURNISHED\">Furnished</mat-option>\n <mat-option value=\"UNFURNISHED\">Unfurnished</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n\n <!-- <mat-form-field class=\"span2\">\n <mat-label>Pet (type all pets)</mat-label>\n <input matInput formControlName=\"pets\" />\n <mat-hint>Please type all pets manually</mat-hint>\n </mat-form-field> -->\n <mat-form-field appearance=\"fill\" class=\"w-full\">\n <mat-chip-grid #chipGrid aria-label=\"Pets\">\n @for (p of pets(); track p) {\n <mat-chip-row (removed)=\"removePet(p)\">\n {{ p }}\n <button matChipRemove [attr.aria-label]=\"'remove ' + p\">\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n }\n\n <input\n placeholder=\"Add a pet (e.g., Dog, Cat)\"\n [matChipInputFor]=\"chipGrid\"\n [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\n (matChipInputTokenEnd)=\"addPet($event)\"\n />\n </mat-chip-grid>\n\n <mat-hint>Press Enter or comma to add multiple pets.</mat-hint>\n </mat-form-field>\n <!--\n <mat-chip-listbox multiple [formControl]=\"petsControl()\" aria-label=\"Pets\">\n <mat-chip-option value=\"DOG\"> <mat-icon>pets</mat-icon> Dog </mat-chip-option>\n\n <mat-chip-option value=\"CAT\"> <mat-icon>pets</mat-icon> Cat </mat-chip-option>\n\n <mat-chip-option value=\"SMALL_ANIMAL\"> <mat-icon>pets</mat-icon> Small animal </mat-chip-option>\n\n <mat-chip-option value=\"BIRD\"> <mat-icon>flutter_dash</mat-icon> Bird </mat-chip-option>\n\n <mat-chip-option value=\"REPTILE\"> <mat-icon>pest_control</mat-icon> Reptile </mat-chip-option>\n </mat-chip-listbox> -->\n\n @if (petsControl().value.length) {\n <p class=\"hint\">Landlord approval may still be required.</p>\n }\n\n <mat-slide-toggle class=\"py-3\" formControlName=\"smoker\">Smoker</mat-slide-toggle>\n\n <mat-form-field class=\"span2\">\n <mat-label>Additional requests</mat-label>\n <textarea matInput rows=\"3\" formControlName=\"additionalRequests\"></textarea>\n </mat-form-field>\n</div>\n" }]
3814
+ ], template: "<div class=\"grid\" [formGroup]=\"rental\">\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-4\">\n <mat-label>Offer amount (PCM)</mat-label>\n <input matInput type=\"number\" formControlName=\"amount\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Move-in date</mat-label>\n <input matInput [min]=\"minDate\" (focus)=\"dp.open()\" [matDatepicker]=\"dp\" formControlName=\"moveInDate\" readonly />\n <mat-datepicker-toggle matIconSuffix [for]=\"dp\"></mat-datepicker-toggle>\n <mat-datepicker #dp></mat-datepicker>\n </mat-form-field>\n <mat-form-field class=\"col-span-4\">\n <mat-label>Payment frequency</mat-label>\n <mat-select formControlName=\"paymentFrequency\">\n <mat-option value=\"MONTHLY\">Monthly</mat-option>\n <mat-option value=\"QUARTERLY\">Quarterly</mat-option>\n <mat-option value=\"SEMI_ANNUALLY\">Semi-annually</mat-option>\n <mat-option value=\"ANNUALLY\">Annually</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-4\">\n <mat-label>Tenancy length (months)</mat-label>\n <input matInput type=\"number\" formControlName=\"tenancyLengthMonths\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Break clause (months)</mat-label>\n <input matInput type=\"number\" formControlName=\"breakClauseMonths\" />\n </mat-form-field>\n <mat-form-field class=\"col-span-4\">\n <mat-label>Furniture</mat-label>\n <mat-select formControlName=\"furnitureRequirement\">\n <mat-option value=\"FURNISHED\">Furnished</mat-option>\n <mat-option value=\"UNFURNISHED\">Unfurnished</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n\n <mat-form-field appearance=\"fill\" class=\"w-full\">\n <mat-chip-grid #chipGrid aria-label=\"Pets\">\n @for (p of pets(); track p) {\n <mat-chip-row (removed)=\"removePet(p)\">\n {{ p }}\n <button matChipRemove [attr.aria-label]=\"'remove ' + p\">\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n }\n\n <input\n placeholder=\"Add a pet (e.g., Dog, Cat)\"\n [matChipInputFor]=\"chipGrid\"\n [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\n (matChipInputTokenEnd)=\"addPet($event)\"\n />\n </mat-chip-grid>\n\n <mat-hint>Press Enter or comma to add multiple pets.</mat-hint>\n </mat-form-field>\n\n @if (petsControl().value.length) {\n <p class=\"hint\">Landlord approval may still be required.</p>\n }\n\n <mat-slide-toggle labelPosition=\"before\" class=\"py-3\" formControlName=\"smoker\">\n <span class=\"text-lg font-bold\">Smoker</span>\n </mat-slide-toggle>\n\n <mat-form-field class=\"span2\">\n <mat-label>Additional requests</mat-label>\n <textarea matInput rows=\"3\" formControlName=\"additionalRequests\"></textarea>\n </mat-form-field>\n</div>\n" }]
3981
3815
  }] });
3982
3816
 
3983
3817
  class TenantRegistryService {
@@ -4034,7 +3868,7 @@ class TenantBasicInfoSection {
4034
3868
  deps: [MAT_DATE_LOCALE],
4035
3869
  },
4036
3870
  { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS$4 },
4037
- ], ngImport: i0, template: "<div class=\"text-lg\">Basic info</div>\n<div class=\"grid\" [formGroup]=\"g()\">\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-4\">\n <mat-label>Full name</mat-label>\n <input matInput formControlName=\"fullName\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Date of birth</mat-label>\n <input matInput [matDatepicker]=\"dp\" formControlName=\"dob\" readonly />\n <mat-datepicker-toggle matIconSuffix [for]=\"dp\"></mat-datepicker-toggle>\n <mat-datepicker #dp></mat-datepicker>\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Gender</mat-label>\n <mat-select formControlName=\"gender\">\n <mat-option value=\"MALE\">Male</mat-option>\n <mat-option value=\"FEMALE\">Female</mat-option>\n <mat-option value=\"OTHER\">Other</mat-option>\n <mat-option value=\"PREFER_NOT_TO_SAY\">Prefer not to say</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-4\">\n <mat-label>Nationality</mat-label>\n <input matInput formControlName=\"nationality\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Visa status</mat-label>\n <mat-select formControlName=\"visaStatus\">\n <mat-option value=\"CITIZEN\">Citizen</mat-option>\n <mat-option value=\"WORK_VISA\">Work visa</mat-option>\n <mat-option value=\"STUDENT_VISA\">Student visa</mat-option>\n <mat-option value=\"OTHER\">Other</mat-option>\n </mat-select>\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Adverse credit status</mat-label>\n <mat-select formControlName=\"adverseCreditStatus\">\n <mat-option value=\"NONE\">None</mat-option>\n <mat-option value=\"CCJ\">CCJ</mat-option>\n <mat-option value=\"BANKRUPTCY\">Bankruptcy</mat-option>\n <mat-option value=\"IVA\">IVA</mat-option>\n <mat-option value=\"OTHER\">Other</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class=\"col-span-6\">\n <mat-label>Phone</mat-label>\n <input matInput formControlName=\"phone\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-6\">\n <mat-label>Email</mat-label>\n <input matInput formControlName=\"email\" />\n </mat-form-field>\n </div>\n\n <div [formGroup]=\"address()\">\n <h5>Current address</h5>\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-6\">\n <mat-label>Line 1</mat-label>\n <input matInput formControlName=\"line1\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-6\">\n <mat-label>Line 2</mat-label>\n <input matInput formControlName=\"line2\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>City</mat-label>\n <input matInput formControlName=\"city\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Postcode</mat-label>\n <input matInput formControlName=\"postcode\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Country</mat-label>\n <input matInput formControlName=\"country\" />\n </mat-form-field>\n </div>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { 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: MatNativeDateModule }] });
3871
+ ], ngImport: i0, template: "<div class=\"text-lg\">Basic info</div>\n<div class=\"grid\" [formGroup]=\"g()\">\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-4\">\n <mat-label>Full name</mat-label>\n <input matInput formControlName=\"fullName\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Date of birth</mat-label>\n <input matInput [matDatepicker]=\"dp\" formControlName=\"dob\" readonly />\n <mat-datepicker-toggle matIconSuffix [for]=\"dp\"></mat-datepicker-toggle>\n <mat-datepicker #dp></mat-datepicker>\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Gender</mat-label>\n <mat-select formControlName=\"gender\">\n <mat-option value=\"MALE\">Male</mat-option>\n <mat-option value=\"FEMALE\">Female</mat-option>\n <mat-option value=\"OTHER\">Other</mat-option>\n <mat-option value=\"PREFER_NOT_TO_SAY\">Prefer not to say</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-4\">\n <mat-label>Nationality</mat-label>\n <input matInput formControlName=\"nationality\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Visa status</mat-label>\n <mat-select formControlName=\"visaStatus\">\n <mat-option value=\"CITIZEN\">Citizen</mat-option>\n <mat-option value=\"VISA_HOLDER\">Visa Holder</mat-option>\n <mat-option value=\"WAITING_FOR_VISA\">Waiting For Visa</mat-option>\n <mat-option value=\"NOT_YET_APPLIED_FOR_VISA\">Not Yet Applied For Visa</mat-option>\n </mat-select>\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Adverse credit status</mat-label>\n <mat-select formControlName=\"adverseCreditStatus\">\n <mat-option value=\"NONE\">None</mat-option>\n <mat-option value=\"ACTIVE_CCJ\">Active Ccj</mat-option>\n <mat-option value=\"SATISFIED_CCJ\">Satisfied Ccj</mat-option>\n <mat-option value=\"DEBT_MANAGEMENT_PLAN\">Debt Management Plan</mat-option>\n <mat-option value=\"LOW_CREDIT_SCORE\">Low Credit Score</mat-option>\n <mat-option value=\"OTHER\">Other</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class=\"col-span-6\">\n <mat-label>Phone</mat-label>\n <input matInput formControlName=\"phone\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-6\">\n <mat-label>Email</mat-label>\n <input matInput formControlName=\"email\" />\n </mat-form-field>\n </div>\n\n <div [formGroup]=\"address()\">\n <h5>Current address</h5>\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-6\">\n <mat-label>Line 1</mat-label>\n <input matInput formControlName=\"line1\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-6\">\n <mat-label>Line 2</mat-label>\n <input matInput formControlName=\"line2\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>City</mat-label>\n <input matInput formControlName=\"city\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Postcode</mat-label>\n <input matInput formControlName=\"postcode\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Country</mat-label>\n <input matInput formControlName=\"country\" />\n </mat-form-field>\n </div>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { 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: MatNativeDateModule }] });
4038
3872
  }
4039
3873
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TenantBasicInfoSection, decorators: [{
4040
3874
  type: Component,
@@ -4045,7 +3879,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
4045
3879
  deps: [MAT_DATE_LOCALE],
4046
3880
  },
4047
3881
  { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS$4 },
4048
- ], template: "<div class=\"text-lg\">Basic info</div>\n<div class=\"grid\" [formGroup]=\"g()\">\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-4\">\n <mat-label>Full name</mat-label>\n <input matInput formControlName=\"fullName\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Date of birth</mat-label>\n <input matInput [matDatepicker]=\"dp\" formControlName=\"dob\" readonly />\n <mat-datepicker-toggle matIconSuffix [for]=\"dp\"></mat-datepicker-toggle>\n <mat-datepicker #dp></mat-datepicker>\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Gender</mat-label>\n <mat-select formControlName=\"gender\">\n <mat-option value=\"MALE\">Male</mat-option>\n <mat-option value=\"FEMALE\">Female</mat-option>\n <mat-option value=\"OTHER\">Other</mat-option>\n <mat-option value=\"PREFER_NOT_TO_SAY\">Prefer not to say</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-4\">\n <mat-label>Nationality</mat-label>\n <input matInput formControlName=\"nationality\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Visa status</mat-label>\n <mat-select formControlName=\"visaStatus\">\n <mat-option value=\"CITIZEN\">Citizen</mat-option>\n <mat-option value=\"WORK_VISA\">Work visa</mat-option>\n <mat-option value=\"STUDENT_VISA\">Student visa</mat-option>\n <mat-option value=\"OTHER\">Other</mat-option>\n </mat-select>\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Adverse credit status</mat-label>\n <mat-select formControlName=\"adverseCreditStatus\">\n <mat-option value=\"NONE\">None</mat-option>\n <mat-option value=\"CCJ\">CCJ</mat-option>\n <mat-option value=\"BANKRUPTCY\">Bankruptcy</mat-option>\n <mat-option value=\"IVA\">IVA</mat-option>\n <mat-option value=\"OTHER\">Other</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class=\"col-span-6\">\n <mat-label>Phone</mat-label>\n <input matInput formControlName=\"phone\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-6\">\n <mat-label>Email</mat-label>\n <input matInput formControlName=\"email\" />\n </mat-form-field>\n </div>\n\n <div [formGroup]=\"address()\">\n <h5>Current address</h5>\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-6\">\n <mat-label>Line 1</mat-label>\n <input matInput formControlName=\"line1\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-6\">\n <mat-label>Line 2</mat-label>\n <input matInput formControlName=\"line2\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>City</mat-label>\n <input matInput formControlName=\"city\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Postcode</mat-label>\n <input matInput formControlName=\"postcode\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Country</mat-label>\n <input matInput formControlName=\"country\" />\n </mat-form-field>\n </div>\n </div>\n</div>\n" }]
3882
+ ], template: "<div class=\"text-lg\">Basic info</div>\n<div class=\"grid\" [formGroup]=\"g()\">\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-4\">\n <mat-label>Full name</mat-label>\n <input matInput formControlName=\"fullName\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Date of birth</mat-label>\n <input matInput [matDatepicker]=\"dp\" formControlName=\"dob\" readonly />\n <mat-datepicker-toggle matIconSuffix [for]=\"dp\"></mat-datepicker-toggle>\n <mat-datepicker #dp></mat-datepicker>\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Gender</mat-label>\n <mat-select formControlName=\"gender\">\n <mat-option value=\"MALE\">Male</mat-option>\n <mat-option value=\"FEMALE\">Female</mat-option>\n <mat-option value=\"OTHER\">Other</mat-option>\n <mat-option value=\"PREFER_NOT_TO_SAY\">Prefer not to say</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-4\">\n <mat-label>Nationality</mat-label>\n <input matInput formControlName=\"nationality\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Visa status</mat-label>\n <mat-select formControlName=\"visaStatus\">\n <mat-option value=\"CITIZEN\">Citizen</mat-option>\n <mat-option value=\"VISA_HOLDER\">Visa Holder</mat-option>\n <mat-option value=\"WAITING_FOR_VISA\">Waiting For Visa</mat-option>\n <mat-option value=\"NOT_YET_APPLIED_FOR_VISA\">Not Yet Applied For Visa</mat-option>\n </mat-select>\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Adverse credit status</mat-label>\n <mat-select formControlName=\"adverseCreditStatus\">\n <mat-option value=\"NONE\">None</mat-option>\n <mat-option value=\"ACTIVE_CCJ\">Active Ccj</mat-option>\n <mat-option value=\"SATISFIED_CCJ\">Satisfied Ccj</mat-option>\n <mat-option value=\"DEBT_MANAGEMENT_PLAN\">Debt Management Plan</mat-option>\n <mat-option value=\"LOW_CREDIT_SCORE\">Low Credit Score</mat-option>\n <mat-option value=\"OTHER\">Other</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class=\"col-span-6\">\n <mat-label>Phone</mat-label>\n <input matInput formControlName=\"phone\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-6\">\n <mat-label>Email</mat-label>\n <input matInput formControlName=\"email\" />\n </mat-form-field>\n </div>\n\n <div [formGroup]=\"address()\">\n <h5>Current address</h5>\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-6\">\n <mat-label>Line 1</mat-label>\n <input matInput formControlName=\"line1\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-6\">\n <mat-label>Line 2</mat-label>\n <input matInput formControlName=\"line2\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>City</mat-label>\n <input matInput formControlName=\"city\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Postcode</mat-label>\n <input matInput formControlName=\"postcode\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Country</mat-label>\n <input matInput formControlName=\"country\" />\n </mat-form-field>\n </div>\n </div>\n</div>\n" }]
4049
3883
  }] });
4050
3884
 
4051
3885
  class CorporateSection {
@@ -4072,13 +3906,44 @@ class EmploymentSection {
4072
3906
  return this.g().get('employmentStatus')?.value === 'UNEMPLOYED';
4073
3907
  }
4074
3908
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: EmploymentSection, deps: [], target: i0.ɵɵFactoryTarget.Component });
4075
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: EmploymentSection, isStandalone: true, selector: "rolatech-employment-section", ngImport: i0, template: "<h4>Employment</h4>\n\n<div class=\"grid grid-cols-12 gap-3\" [formGroup]=\"g()\">\n <mat-form-field class=\"col-span-12\">\n <mat-label>Employment status</mat-label>\n <mat-select formControlName=\"employmentStatus\">\n <mat-option value=\"EMPLOYED\">Employed</mat-option>\n <mat-option value=\"SELF_EMPLOYED\">Self-employed</mat-option>\n <mat-option value=\"UNEMPLOYED\">Unemployed</mat-option>\n </mat-select>\n </mat-form-field>\n\n @if (isEmployed() || isSelfEmployed()) {\n <mat-form-field class=\"col-span-4\">\n <mat-label>Company name</mat-label>\n <input matInput formControlName=\"companyName\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Job title</mat-label>\n <input matInput formControlName=\"jobTitle\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Annual salary</mat-label>\n <input matInput type=\"number\" formControlName=\"annualSalary\" />\n </mat-form-field>\n } @if (isSelfEmployed()) {\n <mat-form-field class=\"col-span-4\">\n <mat-label>Company number</mat-label>\n <input matInput formControlName=\"companyNumber\" />\n </mat-form-field>\n\n <mat-slide-toggle class=\"col-span-12\" formControlName=\"taxReturnSubmitted\">Tax return submitted</mat-slide-toggle>\n } @if (isUnemployed()) {\n <p class=\"col-span-12 hint\">Guarantor is required when unemployed.</p>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.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$2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i6$1.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }] });
3909
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: EmploymentSection, isStandalone: true, selector: "rolatech-employment-section", ngImport: i0, template: "<h4>Employment</h4>\n\n<div class=\"grid grid-cols-12 gap-3\" [formGroup]=\"g()\">\n <mat-form-field class=\"col-span-12\">\n <mat-label>Employment status</mat-label>\n <mat-select formControlName=\"employmentStatus\">\n <mat-option value=\"EMPLOYED\">Employed</mat-option>\n <mat-option value=\"SELF_EMPLOYED\">Self-employed</mat-option>\n <mat-option value=\"UNEMPLOYED\">Unemployed</mat-option>\n </mat-select>\n </mat-form-field>\n\n @if (isEmployed() || isSelfEmployed()) {\n <mat-form-field class=\"col-span-4\">\n <mat-label>Company name</mat-label>\n <input matInput formControlName=\"companyName\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Job title</mat-label>\n <input matInput formControlName=\"jobTitle\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Annual salary</mat-label>\n <input matInput type=\"number\" formControlName=\"annualSalary\" />\n </mat-form-field>\n } @if (isSelfEmployed()) {\n <mat-form-field class=\"col-span-4\">\n <mat-label>Company number</mat-label>\n <input matInput formControlName=\"companyNumber\" />\n </mat-form-field>\n\n <mat-slide-toggle class=\"col-span-12\" formControlName=\"taxReturnSubmitted\">Tax return submitted</mat-slide-toggle>\n } @if (isUnemployed()) {\n <p class=\"col-span-12 hint\">Guarantor is required when unemployed.</p>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.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$2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i5.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }] });
4076
3910
  }
4077
3911
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: EmploymentSection, decorators: [{
4078
3912
  type: Component,
4079
3913
  args: [{ selector: 'rolatech-employment-section', imports: [ReactiveFormsModule, MatFormFieldModule, MatInputModule, MatSelectModule, MatSlideToggleModule], template: "<h4>Employment</h4>\n\n<div class=\"grid grid-cols-12 gap-3\" [formGroup]=\"g()\">\n <mat-form-field class=\"col-span-12\">\n <mat-label>Employment status</mat-label>\n <mat-select formControlName=\"employmentStatus\">\n <mat-option value=\"EMPLOYED\">Employed</mat-option>\n <mat-option value=\"SELF_EMPLOYED\">Self-employed</mat-option>\n <mat-option value=\"UNEMPLOYED\">Unemployed</mat-option>\n </mat-select>\n </mat-form-field>\n\n @if (isEmployed() || isSelfEmployed()) {\n <mat-form-field class=\"col-span-4\">\n <mat-label>Company name</mat-label>\n <input matInput formControlName=\"companyName\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Job title</mat-label>\n <input matInput formControlName=\"jobTitle\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Annual salary</mat-label>\n <input matInput type=\"number\" formControlName=\"annualSalary\" />\n </mat-form-field>\n } @if (isSelfEmployed()) {\n <mat-form-field class=\"col-span-4\">\n <mat-label>Company number</mat-label>\n <input matInput formControlName=\"companyNumber\" />\n </mat-form-field>\n\n <mat-slide-toggle class=\"col-span-12\" formControlName=\"taxReturnSubmitted\">Tax return submitted</mat-slide-toggle>\n } @if (isUnemployed()) {\n <p class=\"col-span-12 hint\">Guarantor is required when unemployed.</p>\n }\n</div>\n" }]
4080
3914
  }] });
4081
3915
 
3916
+ class GuarantorEmploymentSection {
3917
+ cc = inject(ControlContainer);
3918
+ g = computed(() => this.cc.control, ...(ngDevMode ? [{ debugName: "g" }] : []));
3919
+ isEmployed() {
3920
+ return this.g().get('employmentStatus')?.value === 'EMPLOYED';
3921
+ }
3922
+ isSelfEmployed() {
3923
+ return this.g().get('employmentStatus')?.value === 'SELF_EMPLOYED';
3924
+ }
3925
+ isUnemployed() {
3926
+ return this.g().get('employmentStatus')?.value === 'UNEMPLOYED';
3927
+ }
3928
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: GuarantorEmploymentSection, deps: [], target: i0.ɵɵFactoryTarget.Component });
3929
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: GuarantorEmploymentSection, isStandalone: true, selector: "rolatech-guarantor-employment-section", ngImport: i0, template: "<div class=\"grid grid-cols-12 gap-3\" [formGroup]=\"g()\">\n <mat-form-field class=\"col-span-12\">\n <mat-label>Employment status</mat-label>\n <mat-select formControlName=\"employmentStatus\">\n <mat-option value=\"EMPLOYED\">Employed</mat-option>\n <mat-option value=\"SELF_EMPLOYED\">Self-employed</mat-option>\n <mat-option value=\"UNEMPLOYED\">Unemployed</mat-option>\n </mat-select>\n </mat-form-field>\n\n @if (isEmployed() || isSelfEmployed()) {\n <mat-form-field class=\"col-span-4\">\n <mat-label>Company name</mat-label>\n <input matInput formControlName=\"companyName\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Job title</mat-label>\n <input matInput formControlName=\"jobTitle\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Annual salary</mat-label>\n <input matInput type=\"number\" formControlName=\"annualSalary\" />\n </mat-form-field>\n } @if (isSelfEmployed()) {\n <mat-form-field class=\"col-span-4\">\n <mat-label>Company number</mat-label>\n <input matInput formControlName=\"companyNumber\" />\n </mat-form-field>\n\n <mat-slide-toggle class=\"col-span-12\" formControlName=\"taxReturnSubmitted\">Tax return submitted</mat-slide-toggle>\n } @if (isUnemployed()) {\n <mat-form-field class=\"col-span-12\">\n <mat-label>Additional Financial Support</mat-label>\n <textarea matInput rows=\"2\" formControlName=\"additionalFinancialSupport\"></textarea>\n <mat-hint\n >To support this application, please provide details such as UK property ownership, significant savings, or alternative\n income (e.g., pension, investments).</mat-hint\n >\n </mat-form-field>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.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$2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i5.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }] });
3930
+ }
3931
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: GuarantorEmploymentSection, decorators: [{
3932
+ type: Component,
3933
+ args: [{ selector: 'rolatech-guarantor-employment-section', imports: [ReactiveFormsModule, MatFormFieldModule, MatInputModule, MatSelectModule, MatSlideToggleModule], template: "<div class=\"grid grid-cols-12 gap-3\" [formGroup]=\"g()\">\n <mat-form-field class=\"col-span-12\">\n <mat-label>Employment status</mat-label>\n <mat-select formControlName=\"employmentStatus\">\n <mat-option value=\"EMPLOYED\">Employed</mat-option>\n <mat-option value=\"SELF_EMPLOYED\">Self-employed</mat-option>\n <mat-option value=\"UNEMPLOYED\">Unemployed</mat-option>\n </mat-select>\n </mat-form-field>\n\n @if (isEmployed() || isSelfEmployed()) {\n <mat-form-field class=\"col-span-4\">\n <mat-label>Company name</mat-label>\n <input matInput formControlName=\"companyName\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Job title</mat-label>\n <input matInput formControlName=\"jobTitle\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Annual salary</mat-label>\n <input matInput type=\"number\" formControlName=\"annualSalary\" />\n </mat-form-field>\n } @if (isSelfEmployed()) {\n <mat-form-field class=\"col-span-4\">\n <mat-label>Company number</mat-label>\n <input matInput formControlName=\"companyNumber\" />\n </mat-form-field>\n\n <mat-slide-toggle class=\"col-span-12\" formControlName=\"taxReturnSubmitted\">Tax return submitted</mat-slide-toggle>\n } @if (isUnemployed()) {\n <mat-form-field class=\"col-span-12\">\n <mat-label>Additional Financial Support</mat-label>\n <textarea matInput rows=\"2\" formControlName=\"additionalFinancialSupport\"></textarea>\n <mat-hint\n >To support this application, please provide details such as UK property ownership, significant savings, or alternative\n income (e.g., pension, investments).</mat-hint\n >\n </mat-form-field>\n }\n</div>\n" }]
3934
+ }] });
3935
+
3936
+ class GuarantorCompanySection {
3937
+ cc = inject(ControlContainer);
3938
+ g = computed(() => this.cc.control, ...(ngDevMode ? [{ debugName: "g" }] : []));
3939
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: GuarantorCompanySection, deps: [], target: i0.ɵɵFactoryTarget.Component });
3940
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: GuarantorCompanySection, isStandalone: true, selector: "rolatech-guarantor-company-section", ngImport: i0, template: "<div class=\"grid grid-cols-12 gap-3\" [formGroup]=\"g()\">\n <mat-form-field class=\"col-span-12\">\n <mat-label>Company name</mat-label>\n <input matInput formControlName=\"companyName\" />\n </mat-form-field>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { 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"] }] });
3941
+ }
3942
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: GuarantorCompanySection, decorators: [{
3943
+ type: Component,
3944
+ args: [{ selector: 'rolatech-guarantor-company-section', imports: [ReactiveFormsModule, MatFormFieldModule, MatInputModule], template: "<div class=\"grid grid-cols-12 gap-3\" [formGroup]=\"g()\">\n <mat-form-field class=\"col-span-12\">\n <mat-label>Company name</mat-label>\n <input matInput formControlName=\"companyName\" />\n </mat-form-field>\n</div>\n" }]
3945
+ }] });
3946
+
4082
3947
  const MY_FORMATS$3 = {
4083
3948
  parse: {
4084
3949
  dateInput: 'YYYY-MM-DD',
@@ -4108,15 +3973,21 @@ class GuarantorSection {
4108
3973
  return 'Required';
4109
3974
  return 'Optional';
4110
3975
  }
3976
+ isIndividual() {
3977
+ return this.guarantor().get('type')?.value === 'INDIVIDUAL';
3978
+ }
3979
+ isCompany() {
3980
+ return this.guarantor().get('type')?.value === 'COMPANY';
3981
+ }
4111
3982
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: GuarantorSection, deps: [], target: i0.ɵɵFactoryTarget.Component });
4112
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: GuarantorSection, isStandalone: true, selector: "rolatech-guarantor-section", providers: [
3983
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: GuarantorSection, isStandalone: true, selector: "rolatech-guarantor-section", providers: [
4113
3984
  {
4114
3985
  provide: DateAdapter,
4115
3986
  useClass: MomentDateAdapter,
4116
3987
  deps: [MAT_DATE_LOCALE],
4117
3988
  },
4118
3989
  { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS$3 },
4119
- ], ngImport: i0, template: "<mat-expansion-panel class=\"z-0\">\n <mat-expansion-panel-header>\n <mat-panel-title>Guarantor</mat-panel-title>\n <mat-panel-description>{{ requirementHint() }}</mat-panel-description>\n </mat-expansion-panel-header>\n\n <div [formGroup]=\"guarantor()\">\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-4\">\n <mat-label>Full name</mat-label>\n <input matInput formControlName=\"fullName\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Date of birth</mat-label>\n <input matInput [matDatepicker]=\"dp\" formControlName=\"dob\" readonly />\n <mat-datepicker-toggle matIconSuffix [for]=\"dp\"></mat-datepicker-toggle>\n <mat-datepicker #dp></mat-datepicker>\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Relationship</mat-label>\n <input matInput formControlName=\"relationship\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Phone</mat-label>\n <input matInput formControlName=\"phone\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Email</mat-label>\n <input matInput formControlName=\"email\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Employment status</mat-label>\n <mat-select formControlName=\"employmentStatus\">\n <mat-option value=\"EMPLOYED\">Employed</mat-option>\n <mat-option value=\"SELF_EMPLOYED\">Self-employed</mat-option>\n <mat-option value=\"UNEMPLOYED\">Unemployed</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n\n <div [formGroup]=\"guarantorAddress()\">\n <h5>Address</h5>\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-6\">\n <mat-label>Line 1</mat-label>\n <input matInput formControlName=\"line1\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-6\">\n <mat-label>Line 2</mat-label>\n <input matInput formControlName=\"line2\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>City</mat-label>\n <input matInput formControlName=\"city\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Postcode</mat-label>\n <input matInput formControlName=\"postcode\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Country</mat-label>\n <input matInput formControlName=\"country\" />\n </mat-form-field>\n </div>\n </div>\n </div>\n</mat-expansion-panel>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i2$4.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i2$4.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i2$4.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i2$4.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { 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: MatNativeDateModule }] });
3990
+ ], ngImport: i0, template: "<mat-expansion-panel class=\"z-0\">\n <mat-expansion-panel-header>\n <mat-panel-title>Guarantor</mat-panel-title>\n <mat-panel-description>{{ requirementHint() }}</mat-panel-description>\n </mat-expansion-panel-header>\n\n <div [formGroup]=\"guarantor()\">\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-4\">\n <mat-label>Full name</mat-label>\n <input matInput formControlName=\"fullName\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Date of birth</mat-label>\n <input matInput [matDatepicker]=\"dp\" formControlName=\"dob\" readonly />\n <mat-datepicker-toggle matIconSuffix [for]=\"dp\"></mat-datepicker-toggle>\n <mat-datepicker #dp></mat-datepicker>\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Relationship</mat-label>\n <input matInput formControlName=\"relationship\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Phone</mat-label>\n <input matInput formControlName=\"phone\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Email</mat-label>\n <input matInput formControlName=\"email\" />\n </mat-form-field>\n </div>\n\n <div [formGroup]=\"guarantorAddress()\">\n <h5>Address</h5>\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-6\">\n <mat-label>Line 1</mat-label>\n <input matInput formControlName=\"line1\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-6\">\n <mat-label>Line 2</mat-label>\n <input matInput formControlName=\"line2\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>City</mat-label>\n <input matInput formControlName=\"city\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Postcode</mat-label>\n <input matInput formControlName=\"postcode\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Country</mat-label>\n <input matInput formControlName=\"country\" />\n </mat-form-field>\n </div>\n </div>\n <div class=\"grid grid-cols-12\">\n <mat-form-field class=\"col-span-12\">\n <mat-label>Guarantor type</mat-label>\n <mat-select formControlName=\"type\">\n <mat-option value=\"INDIVIDUAL\">Individual</mat-option>\n <mat-option value=\"COMPANY\">Company</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n\n @if (isIndividual()) {\n <rolatech-guarantor-employment-section />\n } @if (isCompany()) {\n <rolatech-guarantor-company-section />\n }\n </div>\n</mat-expansion-panel>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i2$4.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i2$4.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i2$4.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i2$4.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { 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: MatNativeDateModule }, { kind: "component", type: GuarantorEmploymentSection, selector: "rolatech-guarantor-employment-section" }, { kind: "component", type: GuarantorCompanySection, selector: "rolatech-guarantor-company-section" }] });
4120
3991
  }
4121
3992
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: GuarantorSection, decorators: [{
4122
3993
  type: Component,
@@ -4128,6 +3999,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
4128
3999
  MatSelectModule,
4129
4000
  MatDatepickerModule,
4130
4001
  MatNativeDateModule,
4002
+ GuarantorEmploymentSection,
4003
+ GuarantorCompanySection,
4131
4004
  ], providers: [
4132
4005
  {
4133
4006
  provide: DateAdapter,
@@ -4135,7 +4008,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
4135
4008
  deps: [MAT_DATE_LOCALE],
4136
4009
  },
4137
4010
  { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS$3 },
4138
- ], template: "<mat-expansion-panel class=\"z-0\">\n <mat-expansion-panel-header>\n <mat-panel-title>Guarantor</mat-panel-title>\n <mat-panel-description>{{ requirementHint() }}</mat-panel-description>\n </mat-expansion-panel-header>\n\n <div [formGroup]=\"guarantor()\">\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-4\">\n <mat-label>Full name</mat-label>\n <input matInput formControlName=\"fullName\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Date of birth</mat-label>\n <input matInput [matDatepicker]=\"dp\" formControlName=\"dob\" readonly />\n <mat-datepicker-toggle matIconSuffix [for]=\"dp\"></mat-datepicker-toggle>\n <mat-datepicker #dp></mat-datepicker>\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Relationship</mat-label>\n <input matInput formControlName=\"relationship\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Phone</mat-label>\n <input matInput formControlName=\"phone\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Email</mat-label>\n <input matInput formControlName=\"email\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Employment status</mat-label>\n <mat-select formControlName=\"employmentStatus\">\n <mat-option value=\"EMPLOYED\">Employed</mat-option>\n <mat-option value=\"SELF_EMPLOYED\">Self-employed</mat-option>\n <mat-option value=\"UNEMPLOYED\">Unemployed</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n\n <div [formGroup]=\"guarantorAddress()\">\n <h5>Address</h5>\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-6\">\n <mat-label>Line 1</mat-label>\n <input matInput formControlName=\"line1\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-6\">\n <mat-label>Line 2</mat-label>\n <input matInput formControlName=\"line2\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>City</mat-label>\n <input matInput formControlName=\"city\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Postcode</mat-label>\n <input matInput formControlName=\"postcode\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Country</mat-label>\n <input matInput formControlName=\"country\" />\n </mat-form-field>\n </div>\n </div>\n </div>\n</mat-expansion-panel>\n" }]
4011
+ ], template: "<mat-expansion-panel class=\"z-0\">\n <mat-expansion-panel-header>\n <mat-panel-title>Guarantor</mat-panel-title>\n <mat-panel-description>{{ requirementHint() }}</mat-panel-description>\n </mat-expansion-panel-header>\n\n <div [formGroup]=\"guarantor()\">\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-4\">\n <mat-label>Full name</mat-label>\n <input matInput formControlName=\"fullName\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Date of birth</mat-label>\n <input matInput [matDatepicker]=\"dp\" formControlName=\"dob\" readonly />\n <mat-datepicker-toggle matIconSuffix [for]=\"dp\"></mat-datepicker-toggle>\n <mat-datepicker #dp></mat-datepicker>\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Relationship</mat-label>\n <input matInput formControlName=\"relationship\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Phone</mat-label>\n <input matInput formControlName=\"phone\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Email</mat-label>\n <input matInput formControlName=\"email\" />\n </mat-form-field>\n </div>\n\n <div [formGroup]=\"guarantorAddress()\">\n <h5>Address</h5>\n <div class=\"grid grid-cols-12 gap-3\">\n <mat-form-field class=\"col-span-6\">\n <mat-label>Line 1</mat-label>\n <input matInput formControlName=\"line1\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-6\">\n <mat-label>Line 2</mat-label>\n <input matInput formControlName=\"line2\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>City</mat-label>\n <input matInput formControlName=\"city\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Postcode</mat-label>\n <input matInput formControlName=\"postcode\" />\n </mat-form-field>\n\n <mat-form-field class=\"col-span-4\">\n <mat-label>Country</mat-label>\n <input matInput formControlName=\"country\" />\n </mat-form-field>\n </div>\n </div>\n <div class=\"grid grid-cols-12\">\n <mat-form-field class=\"col-span-12\">\n <mat-label>Guarantor type</mat-label>\n <mat-select formControlName=\"type\">\n <mat-option value=\"INDIVIDUAL\">Individual</mat-option>\n <mat-option value=\"COMPANY\">Company</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n\n @if (isIndividual()) {\n <rolatech-guarantor-employment-section />\n } @if (isCompany()) {\n <rolatech-guarantor-company-section />\n }\n </div>\n</mat-expansion-panel>\n" }]
4139
4012
  }] });
4140
4013
 
4141
4014
  class StudentSection {
@@ -4266,11 +4139,11 @@ class TenantListSection {
4266
4139
  return g.get('fullName')?.value || '—';
4267
4140
  }
4268
4141
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TenantListSection, deps: [], target: i0.ɵɵFactoryTarget.Component });
4269
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: TenantListSection, isStandalone: true, selector: "rolatech-tenant-list-section", providers: [TenantRegistryService], ngImport: i0, template: "<div class=\"text-xl py-3\">Tenants</div>\n<mat-accordion multi>\n @for (key of keys(); track key) {\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title>Tenant {{ $index + 1 }}</mat-panel-title>\n <mat-panel-description>{{ tenantName(key) }}</mat-panel-description>\n </mat-expansion-panel-header>\n <rolatech-tenant-card [clientKey]=\"key\" />\n </mat-expansion-panel>\n }\n</mat-accordion>\n<div class=\"py-3\">\n <button mat-flat-button type=\"button\" (click)=\"addTenant()\">Add tenant</button>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "directive", type: i2$4.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i2$4.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i2$4.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i2$4.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i2$4.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "component", type: TenantCard, selector: "rolatech-tenant-card", inputs: ["clientKey"] }] });
4142
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: TenantListSection, isStandalone: true, selector: "rolatech-tenant-list-section", providers: [TenantRegistryService], ngImport: i0, template: "<div class=\"text-xl py-2\">Tenants</div>\n<mat-accordion multi>\n @for (key of keys(); track key) {\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title>Tenant {{ $index + 1 }}</mat-panel-title>\n <mat-panel-description>{{ tenantName(key) }}</mat-panel-description>\n </mat-expansion-panel-header>\n <rolatech-tenant-card [clientKey]=\"key\" />\n </mat-expansion-panel>\n }\n</mat-accordion>\n<div class=\"py-3\">\n <button mat-stroked-button type=\"button\" (click)=\"addTenant()\">\n <mat-icon>add</mat-icon>\n <span>Add tenant</span>\n </button>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "directive", type: i2$4.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i2$4.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i2$4.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i2$4.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i2$4.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "component", type: TenantCard, selector: "rolatech-tenant-card", inputs: ["clientKey"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
4270
4143
  }
4271
4144
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TenantListSection, decorators: [{
4272
4145
  type: Component,
4273
- args: [{ selector: 'rolatech-tenant-list-section', imports: [MatButtonModule, MatExpansionModule, TenantCard], providers: [TenantRegistryService], template: "<div class=\"text-xl py-3\">Tenants</div>\n<mat-accordion multi>\n @for (key of keys(); track key) {\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title>Tenant {{ $index + 1 }}</mat-panel-title>\n <mat-panel-description>{{ tenantName(key) }}</mat-panel-description>\n </mat-expansion-panel-header>\n <rolatech-tenant-card [clientKey]=\"key\" />\n </mat-expansion-panel>\n }\n</mat-accordion>\n<div class=\"py-3\">\n <button mat-flat-button type=\"button\" (click)=\"addTenant()\">Add tenant</button>\n</div>\n" }]
4146
+ args: [{ selector: 'rolatech-tenant-list-section', imports: [MatButtonModule, MatExpansionModule, TenantCard, MatIcon], providers: [TenantRegistryService], template: "<div class=\"text-xl py-2\">Tenants</div>\n<mat-accordion multi>\n @for (key of keys(); track key) {\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title>Tenant {{ $index + 1 }}</mat-panel-title>\n <mat-panel-description>{{ tenantName(key) }}</mat-panel-description>\n </mat-expansion-panel-header>\n <rolatech-tenant-card [clientKey]=\"key\" />\n </mat-expansion-panel>\n }\n</mat-accordion>\n<div class=\"py-3\">\n <button mat-stroked-button type=\"button\" (click)=\"addTenant()\">\n <mat-icon>add</mat-icon>\n <span>Add tenant</span>\n </button>\n</div>\n" }]
4274
4147
  }], ctorParameters: () => [] });
4275
4148
 
4276
4149
  class PropertyOfferRentalForm {
@@ -4317,7 +4190,7 @@ class PropertyOfferCreate {
4317
4190
  facade = inject(OfferFormFacade);
4318
4191
  titleService = inject(TitleService);
4319
4192
  propertyService = inject(PropertyService);
4320
- offerTypeLabel = computed(() => (this.facade.offerType() === 'RENTAL' ? 'Rental offer' : 'Sale offer'), ...(ngDevMode ? [{ debugName: "offerTypeLabel" }] : []));
4193
+ offerTypeLabel = computed(() => (this.facade.offerType() === 'RENTAL' ? 'rental offer' : 'sale offer'), ...(ngDevMode ? [{ debugName: "offerTypeLabel" }] : []));
4321
4194
  property = signal(null, ...(ngDevMode ? [{ debugName: "property" }] : []));
4322
4195
  firstImageUrl = computed(() => {
4323
4196
  const p = this.property();
@@ -4358,7 +4231,7 @@ class PropertyOfferCreate {
4358
4231
  // await this.router.navigate(['../', res.id], { relativeTo: this.route });
4359
4232
  }
4360
4233
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PropertyOfferCreate, deps: [], target: i0.ɵɵFactoryTarget.Component });
4361
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: PropertyOfferCreate, isStandalone: true, selector: "rolatech-property-offer-create", providers: [OfferFormFacade], ngImport: i0, template: "<rolatech-container>\n <div class=\"flex flex-col-reverse md:flex-row w-full py-2 mb-3 gap-3\">\n <div class=\"w-full md:w-3/4\">\n <div class=\"\">\n <div class=\"text-xl font-bold py-2\">Create Offer</div>\n <div>{{ offerTypeLabel() }}</div>\n\n <div class=\"content\">\n @if (facade.isRental()) {\n <rolatech-property-offer-rental-form />\n } @else {\n <rolatech-property-offer-sale-form />\n }\n </div>\n\n <div class=\"actions\">\n <button mat-raised-button [disabled]=\"facade.submitting()\" (click)=\"submit()\">Submit</button>\n </div>\n\n @if (facade.submitError()) {\n <p class=\"error\">{{ facade.submitError() }}</p>\n }\n </div>\n </div>\n <div class=\"w-full md:w-1/4 py-2 mb-3\">\n @if (property()) {\n <div class=\"text-xl font-bold py-2 mb-3\" i18n>Property info</div>\n <div>\n <rolatech-thumbnail [src]=\"firstImageUrl()\" size=\"small\"></rolatech-thumbnail>\n </div>\n <div class=\"text-xl font-bold\">{{ property()!.title }}</div>\n <div class=\"\">Available: {{ property()!.availableDate | availableDate }}</div>\n @if (property()!.market.toString() === 'LETTINGS' && property()!.rentFrequency.toString() === 'MONTHLY') {\n <div class=\"py-3 text-xl font-bold\">{{ property()!.price | price }}pcm</div>\n } @else {\n <div class=\"py-3 text-xl font-bold\">{{ property()!.price | price }}</div>\n } }\n </div>\n </div>\n</rolatech-container>\n", styles: [""], dependencies: [{ kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "component", type: ThumbnailComponent, selector: "rolatech-thumbnail", inputs: ["src", "size", "mode", "ratio", "width", "height"] }, { kind: "ngmodule", type: MatStepperModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatSnackBarModule }, { kind: "component", type: PropertyOfferRentalForm, selector: "rolatech-property-offer-rental-form" }, { kind: "component", type: PropertyOfferSaleForm, selector: "rolatech-property-offer-sale-form" }, { kind: "pipe", type: PricePipe, name: "price" }, { kind: "pipe", type: AvailableDatePipe, name: "availableDate" }] });
4234
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: PropertyOfferCreate, isStandalone: true, selector: "rolatech-property-offer-create", providers: [OfferFormFacade], ngImport: i0, template: "<rolatech-container>\n <div class=\"flex flex-col-reverse md:flex-row w-full py-4 gap-3\">\n <div class=\"w-full md:w-3/4\">\n <div class=\"w-full\">\n <div class=\"text-xl font-bold mb-3\">Create {{ offerTypeLabel() }}</div>\n\n <div class=\"content\">\n @if (facade.isRental()) {\n <rolatech-property-offer-rental-form />\n } @else {\n <rolatech-property-offer-sale-form />\n }\n </div>\n\n <button class=\"w-full md:w-1/2\" mat-flat-button [disabled]=\"facade.submitting()\" (click)=\"submit()\">\n {{facade.submitting() ? 'Submitting' : 'Submit'}}\n </button>\n\n @if (facade.submitError()) {\n <p class=\"error\">{{ facade.submitError() }}</p>\n }\n </div>\n </div>\n <div class=\"w-full md:w-1/4\">\n @if (property()) {\n <div class=\"text-xl font-bold mb-3\" i18n>Property info</div>\n <div>\n <rolatech-thumbnail [src]=\"firstImageUrl()\" size=\"small\"></rolatech-thumbnail>\n </div>\n <div class=\"text-xl font-bold\">{{ property()!.title }}</div>\n <div class=\"\">Available: {{ property()!.availableDate | availableDate }}</div>\n @if (property()!.market.toString() === 'LETTINGS' && property()!.rentFrequency.toString() === 'MONTHLY') {\n <div class=\"py-3 text-xl font-bold\">{{ property()!.price | price }}pcm</div>\n } @else {\n <div class=\"py-3 text-xl font-bold\">{{ property()!.price | price }}</div>\n } }\n </div>\n </div>\n</rolatech-container>\n", styles: [""], dependencies: [{ kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "component", type: ThumbnailComponent, selector: "rolatech-thumbnail", inputs: ["src", "size", "mode", "ratio", "width", "height"] }, { kind: "ngmodule", type: MatStepperModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatSnackBarModule }, { kind: "component", type: PropertyOfferRentalForm, selector: "rolatech-property-offer-rental-form" }, { kind: "component", type: PropertyOfferSaleForm, selector: "rolatech-property-offer-sale-form" }, { kind: "pipe", type: PricePipe, name: "price" }, { kind: "pipe", type: AvailableDatePipe, name: "availableDate" }] });
4362
4235
  }
4363
4236
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PropertyOfferCreate, decorators: [{
4364
4237
  type: Component,
@@ -4372,7 +4245,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
4372
4245
  MatSnackBarModule,
4373
4246
  PropertyOfferRentalForm,
4374
4247
  PropertyOfferSaleForm,
4375
- ], providers: [OfferFormFacade], template: "<rolatech-container>\n <div class=\"flex flex-col-reverse md:flex-row w-full py-2 mb-3 gap-3\">\n <div class=\"w-full md:w-3/4\">\n <div class=\"\">\n <div class=\"text-xl font-bold py-2\">Create Offer</div>\n <div>{{ offerTypeLabel() }}</div>\n\n <div class=\"content\">\n @if (facade.isRental()) {\n <rolatech-property-offer-rental-form />\n } @else {\n <rolatech-property-offer-sale-form />\n }\n </div>\n\n <div class=\"actions\">\n <button mat-raised-button [disabled]=\"facade.submitting()\" (click)=\"submit()\">Submit</button>\n </div>\n\n @if (facade.submitError()) {\n <p class=\"error\">{{ facade.submitError() }}</p>\n }\n </div>\n </div>\n <div class=\"w-full md:w-1/4 py-2 mb-3\">\n @if (property()) {\n <div class=\"text-xl font-bold py-2 mb-3\" i18n>Property info</div>\n <div>\n <rolatech-thumbnail [src]=\"firstImageUrl()\" size=\"small\"></rolatech-thumbnail>\n </div>\n <div class=\"text-xl font-bold\">{{ property()!.title }}</div>\n <div class=\"\">Available: {{ property()!.availableDate | availableDate }}</div>\n @if (property()!.market.toString() === 'LETTINGS' && property()!.rentFrequency.toString() === 'MONTHLY') {\n <div class=\"py-3 text-xl font-bold\">{{ property()!.price | price }}pcm</div>\n } @else {\n <div class=\"py-3 text-xl font-bold\">{{ property()!.price | price }}</div>\n } }\n </div>\n </div>\n</rolatech-container>\n" }]
4248
+ ], providers: [OfferFormFacade], template: "<rolatech-container>\n <div class=\"flex flex-col-reverse md:flex-row w-full py-4 gap-3\">\n <div class=\"w-full md:w-3/4\">\n <div class=\"w-full\">\n <div class=\"text-xl font-bold mb-3\">Create {{ offerTypeLabel() }}</div>\n\n <div class=\"content\">\n @if (facade.isRental()) {\n <rolatech-property-offer-rental-form />\n } @else {\n <rolatech-property-offer-sale-form />\n }\n </div>\n\n <button class=\"w-full md:w-1/2\" mat-flat-button [disabled]=\"facade.submitting()\" (click)=\"submit()\">\n {{facade.submitting() ? 'Submitting' : 'Submit'}}\n </button>\n\n @if (facade.submitError()) {\n <p class=\"error\">{{ facade.submitError() }}</p>\n }\n </div>\n </div>\n <div class=\"w-full md:w-1/4\">\n @if (property()) {\n <div class=\"text-xl font-bold mb-3\" i18n>Property info</div>\n <div>\n <rolatech-thumbnail [src]=\"firstImageUrl()\" size=\"small\"></rolatech-thumbnail>\n </div>\n <div class=\"text-xl font-bold\">{{ property()!.title }}</div>\n <div class=\"\">Available: {{ property()!.availableDate | availableDate }}</div>\n @if (property()!.market.toString() === 'LETTINGS' && property()!.rentFrequency.toString() === 'MONTHLY') {\n <div class=\"py-3 text-xl font-bold\">{{ property()!.price | price }}pcm</div>\n } @else {\n <div class=\"py-3 text-xl font-bold\">{{ property()!.price | price }}</div>\n } }\n </div>\n </div>\n</rolatech-container>\n" }]
4376
4249
  }], ctorParameters: () => [] });
4377
4250
 
4378
4251
  const propertyRoutes = [
@@ -4382,7 +4255,7 @@ const propertyRoutes = [
4382
4255
  children: [
4383
4256
  {
4384
4257
  path: '',
4385
- loadComponent: () => import('./rolatech-angular-property-property-index.component-CBm6va05.mjs').then((x) => x.PropertyIndexComponent),
4258
+ loadComponent: () => import('./rolatech-angular-property-property-index.component-DB6TnNBc.mjs').then((x) => x.PropertyIndexComponent),
4386
4259
  },
4387
4260
  ],
4388
4261
  },
@@ -4416,13 +4289,9 @@ const propertyRoutes = [
4416
4289
  canActivate: [AuthGuard],
4417
4290
  component: PropertyViewingRequestComponent,
4418
4291
  },
4419
- {
4420
- path: ':id/offer',
4421
- canActivate: [AuthGuard],
4422
- component: PropertyOfferComponent,
4423
- },
4424
4292
  {
4425
4293
  path: ':id/offer/:type', // type = rental | sale
4294
+ canActivate: [AuthGuard],
4426
4295
  component: PropertyOfferCreate,
4427
4296
  },
4428
4297
  {
@@ -5936,7 +5805,7 @@ class PropertyManageHighlights extends BaseComponent {
5936
5805
  // optionally log _e
5937
5806
  }
5938
5807
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PropertyManageHighlights, deps: null, target: i0.ɵɵFactoryTarget.Component });
5939
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: PropertyManageHighlights, isStandalone: true, selector: "rolatech-property-manage-highlights", usesInheritance: true, ngImport: i0, template: "<rolatech-property-manage-content>\n <rolatech-toolbar title=\"Highlights\" class=\"hidden md:block\" divider>\n <button mat-flat-button (click)=\"toggleEdit()\">\n <mat-icon>@if (editMode()) { done } @else { edit }</mat-icon>\n <span>@if (editMode()) { Done } @else { Edit }</span>\n </button>\n </rolatech-toolbar>\n @if (loading()) {\n <mat-progress-spinner mode=\"indeterminate\" diameter=\"20\"></mat-progress-spinner>\n }\n <div class=\"flex flex-col gap-2\" cdkDropList [cdkDropListDisabled]=\"!editMode()\" (cdkDropListDropped)=\"dropped($event)\">\n @for (h of highlights(); track $index) {\n <div class=\"item\" cdkDrag>\n @if (editMode()) {\n <div class=\"flex cursor-grab items-center\" cdkDragHandle aria-label=\"Drag to reorder\">\n <mat-icon>drag_indicator</mat-icon>\n </div>\n } @if (editIndex() === $index) {\n <mat-form-field appearance=\"fill\" class=\"grow\">\n <input matInput [(ngModel)]=\"editText\" name=\"edit-{{$index}}\" maxlength=\"200\" />\n <mat-hint align=\"end\">{{editText.length}} / 200</mat-hint>\n </mat-form-field>\n <button mat-icon-button color=\"primary\" (click)=\"saveEdit($index)\" [disabled]=\"!editText.trim()\">\n <mat-icon>check</mat-icon>\n </button>\n <button mat-icon-button (click)=\"cancelEdit()\">\n <mat-icon>close</mat-icon>\n </button>\n } @else {\n <div class=\"flex-1 select-text\" (dblclick)=\"startEdit($index, h)\">{{ h }}</div>\n @if (editMode()) {\n <button mat-icon-button color=\"primary\" (click)=\"startEdit($index, h)\" aria-label=\"Edit\">\n <mat-icon>edit</mat-icon>\n </button>\n <button mat-icon-button color=\"warn\" (click)=\"remove($index)\" aria-label=\"Delete\">\n <mat-icon>delete</mat-icon>\n </button>\n } }\n </div>\n }\n </div>\n <form class=\"flex items-center gap-2 mt-2\" (ngSubmit)=\"create()\">\n <mat-form-field appearance=\"fill\" class=\"flex-1\" subscriptSizing=\"dynamic\">\n <mat-label>New highlight</mat-label>\n <input matInput [(ngModel)]=\"draft\" name=\"draft\" maxlength=\"200\" />\n <mat-hint align=\"end\">{{draft.length}} / 200</mat-hint>\n </mat-form-field>\n <button mat-flat-button type=\"submit\" [disabled]=\"!draft.trim()\">Add</button>\n </form>\n <div class=\"flex items-center\">\n <button mat-stroked-button color=\"primary\" (click)=\"saveAll()\" [disabled]=\"savingAll()\">Save All</button>\n @if (savingAll()) {\n <span class=\"ml-2\">Saving\u2026</span>\n }\n </div>\n</rolatech-property-manage-content>\n", styles: [".header{display:flex;align-items:center;gap:12px}.grow{flex:1 1 auto}.item{display:flex;align-items:center;gap:8px;padding:8px;border:1px solid var(--rt-border-color);border-radius:12px;background:var(--rt-base-background)}\n"], dependencies: [{ kind: "component", type: PropertyManageContentComponent, selector: "rolatech-property-manage-content" }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$3.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$3.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: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i4$4.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i4$4.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i4$4.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "ngmodule", type: MatListModule }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i5.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { 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"] }] });
5808
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: PropertyManageHighlights, isStandalone: true, selector: "rolatech-property-manage-highlights", usesInheritance: true, ngImport: i0, template: "<rolatech-property-manage-content>\n <rolatech-toolbar title=\"Highlights\" class=\"hidden md:block\" divider>\n <button mat-flat-button (click)=\"toggleEdit()\">\n <mat-icon>@if (editMode()) { done } @else { edit }</mat-icon>\n <span>@if (editMode()) { Done } @else { Edit }</span>\n </button>\n </rolatech-toolbar>\n @if (loading()) {\n <mat-progress-spinner mode=\"indeterminate\" diameter=\"20\"></mat-progress-spinner>\n }\n <div class=\"flex flex-col gap-2\" cdkDropList [cdkDropListDisabled]=\"!editMode()\" (cdkDropListDropped)=\"dropped($event)\">\n @for (h of highlights(); track $index) {\n <div class=\"item\" cdkDrag>\n @if (editMode()) {\n <div class=\"flex cursor-grab items-center\" cdkDragHandle aria-label=\"Drag to reorder\">\n <mat-icon>drag_indicator</mat-icon>\n </div>\n } @if (editIndex() === $index) {\n <mat-form-field appearance=\"fill\" class=\"grow\">\n <input matInput [(ngModel)]=\"editText\" name=\"edit-{{$index}}\" maxlength=\"200\" />\n <mat-hint align=\"end\">{{editText.length}} / 200</mat-hint>\n </mat-form-field>\n <button mat-icon-button color=\"primary\" (click)=\"saveEdit($index)\" [disabled]=\"!editText.trim()\">\n <mat-icon>check</mat-icon>\n </button>\n <button mat-icon-button (click)=\"cancelEdit()\">\n <mat-icon>close</mat-icon>\n </button>\n } @else {\n <div class=\"flex-1 select-text\" (dblclick)=\"startEdit($index, h)\">{{ h }}</div>\n @if (editMode()) {\n <button mat-icon-button color=\"primary\" (click)=\"startEdit($index, h)\" aria-label=\"Edit\">\n <mat-icon>edit</mat-icon>\n </button>\n <button mat-icon-button color=\"warn\" (click)=\"remove($index)\" aria-label=\"Delete\">\n <mat-icon>delete</mat-icon>\n </button>\n } }\n </div>\n }\n </div>\n <form class=\"flex items-center gap-2 mt-2\" (ngSubmit)=\"create()\">\n <mat-form-field appearance=\"fill\" class=\"flex-1\" subscriptSizing=\"dynamic\">\n <mat-label>New highlight</mat-label>\n <input matInput [(ngModel)]=\"draft\" name=\"draft\" maxlength=\"200\" />\n <mat-hint align=\"end\">{{draft.length}} / 200</mat-hint>\n </mat-form-field>\n <button mat-flat-button type=\"submit\" [disabled]=\"!draft.trim()\">Add</button>\n </form>\n <div class=\"flex items-center\">\n <button mat-stroked-button color=\"primary\" (click)=\"saveAll()\" [disabled]=\"savingAll()\">Save All</button>\n @if (savingAll()) {\n <span class=\"ml-2\">Saving\u2026</span>\n }\n </div>\n</rolatech-property-manage-content>\n", styles: [".header{display:flex;align-items:center;gap:12px}.grow{flex:1 1 auto}.item{display:flex;align-items:center;gap:8px;padding:8px;border:1px solid var(--rt-border-color);border-radius:12px;background:var(--rt-base-background)}\n"], dependencies: [{ kind: "component", type: PropertyManageContentComponent, selector: "rolatech-property-manage-content" }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$3.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$3.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: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.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$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i4$4.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i4$4.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i4$4.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "ngmodule", type: MatListModule }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i5$1.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { 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"] }] });
5940
5809
  }
5941
5810
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: PropertyManageHighlights, decorators: [{
5942
5811
  type: Component,
@@ -6297,7 +6166,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
6297
6166
  const propertyManageViewingsRoutes = [
6298
6167
  {
6299
6168
  path: '',
6300
- loadComponent: () => import('./rolatech-angular-property-property-manage-viewings-index.component-D3kRpUQx.mjs').then((x) => x.PropertyManageViewingsIndexComponent),
6169
+ loadComponent: () => import('./rolatech-angular-property-property-manage-viewings-index.component-CIYzCY1E.mjs').then((x) => x.PropertyManageViewingsIndexComponent),
6301
6170
  },
6302
6171
  {
6303
6172
  path: ':id',
@@ -7364,9 +7233,9 @@ class PropertyAgentOfferIndex extends BaseComponent {
7364
7233
  icon: 'dashboard',
7365
7234
  },
7366
7235
  {
7367
- name: 'Created',
7236
+ name: 'Submitted',
7368
7237
  icon: 'category',
7369
- status: 'created',
7238
+ status: 'submitted',
7370
7239
  },
7371
7240
  {
7372
7241
  name: 'Accepted',
@@ -7486,4 +7355,4 @@ const propertyManageOverviewRoutes = [
7486
7355
  */
7487
7356
 
7488
7357
  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 };
7489
- //# sourceMappingURL=rolatech-angular-property-rolatech-angular-property-BRmo5aq4.mjs.map
7358
+ //# sourceMappingURL=rolatech-angular-property-rolatech-angular-property-BLynHPSt.mjs.map