@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.
- package/fesm2022/{rolatech-angular-property-property-index.component-CBm6va05.mjs → rolatech-angular-property-property-index.component-DB6TnNBc.mjs} +2 -2
- package/fesm2022/{rolatech-angular-property-property-index.component-CBm6va05.mjs.map → rolatech-angular-property-property-index.component-DB6TnNBc.mjs.map} +1 -1
- package/fesm2022/{rolatech-angular-property-property-manage-viewings-index.component-D3kRpUQx.mjs → rolatech-angular-property-property-manage-viewings-index.component-CIYzCY1E.mjs} +2 -2
- package/fesm2022/{rolatech-angular-property-property-manage-viewings-index.component-D3kRpUQx.mjs.map → rolatech-angular-property-property-manage-viewings-index.component-CIYzCY1E.mjs.map} +1 -1
- package/fesm2022/{rolatech-angular-property-rolatech-angular-property-BRmo5aq4.mjs → rolatech-angular-property-rolatech-angular-property-BLynHPSt.mjs} +488 -619
- package/fesm2022/rolatech-angular-property-rolatech-angular-property-BLynHPSt.mjs.map +1 -0
- package/fesm2022/rolatech-angular-property.mjs +1 -1
- package/package.json +5 -5
- package/themes/_default.scss +1 -1
- package/fesm2022/rolatech-angular-property-rolatech-angular-property-BRmo5aq4.mjs.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, ElementRef, input, booleanAttribute, effect, HostBinding, ViewEncapsulation, Component, viewChild, PLATFORM_ID, output, computed, signal, model,
|
|
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,
|
|
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 {
|
|
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
|
|
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 <
|
|
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 <
|
|
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: '
|
|
1069
|
+
name: 'Submitted',
|
|
1070
1070
|
icon: 'category',
|
|
1071
|
-
status: '
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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 </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 </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
|
|
2539
|
-
|
|
2690
|
+
this.property = res.data;
|
|
2691
|
+
this.titleService.setTitle(`${this.property.title}`);
|
|
2540
2692
|
},
|
|
2541
2693
|
});
|
|
2542
2694
|
}
|
|
2543
|
-
|
|
2544
|
-
this.
|
|
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.
|
|
2549
|
-
this.propertyOfferService.makeOffer(this.id, this.offer).subscribe({
|
|
2702
|
+
this.propertyService.requestViewing(this.id, this.viewing).subscribe({
|
|
2550
2703
|
next: (res) => {
|
|
2551
|
-
this.
|
|
2552
|
-
this.
|
|
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:
|
|
2562
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type:
|
|
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 </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 </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:
|
|
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-
|
|
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
|
-
|
|
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\"
|
|
2596
|
-
}]
|
|
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 </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: '
|
|
2762
|
+
name: 'Submitted',
|
|
2612
2763
|
icon: 'category',
|
|
2613
|
-
status: '
|
|
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
|
-
|
|
2961
|
-
return
|
|
2954
|
+
statusCompareFn(t1, t2) {
|
|
2955
|
+
return t1 === t2;
|
|
2962
2956
|
}
|
|
2963
|
-
|
|
2964
|
-
|
|
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:
|
|
2967
|
-
static
|
|
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:
|
|
2970
|
-
type:
|
|
2971
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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-
|
|
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-
|
|
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:
|
|
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
|
|
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
|
|
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=\"
|
|
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=\"
|
|
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:
|
|
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: "
|
|
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
|
|
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
|
|
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-
|
|
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-
|
|
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' ? '
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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: '
|
|
7236
|
+
name: 'Submitted',
|
|
7368
7237
|
icon: 'category',
|
|
7369
|
-
status: '
|
|
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-
|
|
7358
|
+
//# sourceMappingURL=rolatech-angular-property-rolatech-angular-property-BLynHPSt.mjs.map
|