@rolatech/angular-billing 20.1.6-beta.0 → 20.1.6-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { input, output, Component, inject, ViewEncapsulation, computed, signal, DestroyRef } from '@angular/core';
3
- import * as i10 from '@angular/common';
3
+ import * as i1$2 from '@angular/common';
4
4
  import { DatePipe, KeyValuePipe, CommonModule } from '@angular/common';
5
5
  import * as i1$1 from '@angular/forms';
6
6
  import { FormsModule } from '@angular/forms';
@@ -20,10 +20,11 @@ import { MatSelectModule } from '@angular/material/select';
20
20
  import * as i1 from '@angular/router';
21
21
  import { ActivatedRoute, RouterModule, RouterLink, Router } from '@angular/router';
22
22
  import { ContainerComponent, TabsComponent, TabComponent, ToolbarComponent, ListComponent, EmptyComponent, FilterComponent, BaseComponent } from '@rolatech/angular-components';
23
+ import { PricePipe } from '@rolatech/angular-common';
23
24
  import { InvoiceService, PaymentService } from '@rolatech/angular-services';
24
- import { Title } from '@angular/platform-browser';
25
+ import { Title, DomSanitizer } from '@angular/platform-browser';
25
26
  import { switchMap, map, distinctUntilChanged, finalize } from 'rxjs';
26
- import * as i1$2 from '@angular/material/paginator';
27
+ import * as i2$1 from '@angular/material/paginator';
27
28
  import { MatPaginatorModule } from '@angular/material/paginator';
28
29
  import * as i9 from '@angular/material/card';
29
30
  import { MatCardModule } from '@angular/material/card';
@@ -41,6 +42,7 @@ var InvoiceType;
41
42
  var InvoiceStatus;
42
43
  (function (InvoiceStatus) {
43
44
  InvoiceStatus["DRAFT"] = "Draft";
45
+ InvoiceStatus["CREATED"] = "Created";
44
46
  InvoiceStatus["ISSUED"] = "Issued";
45
47
  InvoiceStatus["PARTIALLY_PAID"] = "Partially paid";
46
48
  InvoiceStatus["PAID"] = "Paid";
@@ -56,31 +58,31 @@ class InvoiceItem {
56
58
  onDownload() {
57
59
  this.download.emit();
58
60
  }
59
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: InvoiceItem, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
60
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.4", type: InvoiceItem, isStandalone: true, selector: "rolatech-invoice-item", inputs: { invoice: { classPropertyName: "invoice", publicName: "invoice", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { download: "download" }, ngImport: i0, template: "<div class=\"flex w-full justify-between p-3 cursor-pointer hover:bg-[--rt-raised-background]\">\n <div class=\"flex items-center\">\n <div class=\"w-[180px] max-w-[180px]\">{{invoice().id}}</div>\n </div>\n <div class=\"flex items-center gap-3\">\n <div>\u00A3{{invoice().total}}</div>\n </div>\n <div class=\"flex items-center gap-3\">\n <div>{{status[invoice().status]}}</div>\n <div class=\"w-[100px]\">{{invoice().createdAt | date:'dd/MM/yyyy':'Europe/London'}}</div>\n <button mat-icon-button class=\"px-2 min-w-[80px]\" (click)=\"onDownload();$event.stopPropagation()\">\n <mat-icon>download</mat-icon>\n </button>\n </div>\n</div>\n", styles: [".scrollbar-hide::-webkit-scrollbar{display:none}.scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.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: "pipe", type: DatePipe, name: "date" }] }); }
61
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceItem, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
62
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.12", type: InvoiceItem, isStandalone: true, selector: "rolatech-invoice-item", inputs: { invoice: { classPropertyName: "invoice", publicName: "invoice", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { download: "download" }, ngImport: i0, template: "<div class=\"flex w-full justify-between p-3 cursor-pointer hover:bg-[--rt-raised-background]\">\n <div class=\"flex items-center\">\n <div class=\"w-[180px] max-w-[180px]\">{{invoice().id}}</div>\n </div>\n <div class=\"flex items-center gap-3\">\n <div>{{invoice().total | price}}</div>\n </div>\n <div class=\"flex items-center gap-3\">\n <div>{{status[invoice().status]}}</div>\n <div class=\"w-[100px]\">{{invoice().createdAt | date:'dd/MM/yyyy':'Europe/London'}}</div>\n <button mat-icon-button class=\"px-2 min-w-[80px]\" (click)=\"onDownload();$event.stopPropagation()\">\n <mat-icon>download</mat-icon>\n </button>\n </div>\n</div>\n", styles: [".scrollbar-hide::-webkit-scrollbar{display:none}.scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.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: "pipe", type: DatePipe, name: "date" }, { kind: "pipe", type: PricePipe, name: "price" }] }); }
61
63
  }
62
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: InvoiceItem, decorators: [{
64
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceItem, decorators: [{
63
65
  type: Component,
64
- args: [{ selector: 'rolatech-invoice-item', imports: [MatButtonModule, MatIcon, DatePipe], template: "<div class=\"flex w-full justify-between p-3 cursor-pointer hover:bg-[--rt-raised-background]\">\n <div class=\"flex items-center\">\n <div class=\"w-[180px] max-w-[180px]\">{{invoice().id}}</div>\n </div>\n <div class=\"flex items-center gap-3\">\n <div>\u00A3{{invoice().total}}</div>\n </div>\n <div class=\"flex items-center gap-3\">\n <div>{{status[invoice().status]}}</div>\n <div class=\"w-[100px]\">{{invoice().createdAt | date:'dd/MM/yyyy':'Europe/London'}}</div>\n <button mat-icon-button class=\"px-2 min-w-[80px]\" (click)=\"onDownload();$event.stopPropagation()\">\n <mat-icon>download</mat-icon>\n </button>\n </div>\n</div>\n", styles: [".scrollbar-hide::-webkit-scrollbar{display:none}.scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}\n"] }]
65
- }] });
66
+ args: [{ selector: 'rolatech-invoice-item', imports: [MatButtonModule, MatIcon, DatePipe, PricePipe], template: "<div class=\"flex w-full justify-between p-3 cursor-pointer hover:bg-[--rt-raised-background]\">\n <div class=\"flex items-center\">\n <div class=\"w-[180px] max-w-[180px]\">{{invoice().id}}</div>\n </div>\n <div class=\"flex items-center gap-3\">\n <div>{{invoice().total | price}}</div>\n </div>\n <div class=\"flex items-center gap-3\">\n <div>{{status[invoice().status]}}</div>\n <div class=\"w-[100px]\">{{invoice().createdAt | date:'dd/MM/yyyy':'Europe/London'}}</div>\n <button mat-icon-button class=\"px-2 min-w-[80px]\" (click)=\"onDownload();$event.stopPropagation()\">\n <mat-icon>download</mat-icon>\n </button>\n </div>\n</div>\n", styles: [".scrollbar-hide::-webkit-scrollbar{display:none}.scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}\n"] }]
67
+ }], propDecorators: { invoice: [{ type: i0.Input, args: [{ isSignal: true, alias: "invoice", required: true }] }], download: [{ type: i0.Output, args: ["download"] }] } });
66
68
 
67
69
  class InvoiceManageItem {
68
70
  constructor() {
69
71
  this.invoice = input.required(...(ngDevMode ? [{ debugName: "invoice" }] : []));
70
72
  }
71
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: InvoiceManageItem, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
72
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.4", type: InvoiceManageItem, isStandalone: true, selector: "rolatech-invoice-manage-item", inputs: { invoice: { classPropertyName: "invoice", publicName: "invoice", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<p>invoice-manage-item works!</p>\n", styles: [""] }); }
73
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceManageItem, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
74
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.12", type: InvoiceManageItem, isStandalone: true, selector: "rolatech-invoice-manage-item", inputs: { invoice: { classPropertyName: "invoice", publicName: "invoice", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<p>invoice-manage-item works!</p>\n<div>{{invoice().id}}</div>\n", styles: [""] }); }
73
75
  }
74
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: InvoiceManageItem, decorators: [{
76
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceManageItem, decorators: [{
75
77
  type: Component,
76
- args: [{ selector: 'rolatech-invoice-manage-item', imports: [], template: "<p>invoice-manage-item works!</p>\n" }]
77
- }] });
78
+ args: [{ selector: 'rolatech-invoice-manage-item', imports: [], template: "<p>invoice-manage-item works!</p>\n<div>{{invoice().id}}</div>\n" }]
79
+ }], propDecorators: { invoice: [{ type: i0.Input, args: [{ isSignal: true, alias: "invoice", required: true }] }] } });
78
80
 
79
81
  class InvoiceHeader {
80
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: InvoiceHeader, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
81
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.4", type: InvoiceHeader, isStandalone: true, selector: "rolatech-invoice-header", ngImport: i0, template: "<div class=\"flex items-center justify-between font-bold h-11 px-3\">\n <div class=\"flex items-center\">\n <div class=\"font-bold w-[180px] max-w-[180px]\">ID</div>\n </div>\n <div class=\"flex items-center gap-3\">\n <div class=\"font-bold\">Total</div>\n </div>\n <div class=\"flex items-center gap-3\">\n <div class=\"font-bold\">Status</div>\n <div class=\"font-bold w-[100px]\">Date</div>\n <div class=\"font-bold m-w-[80px]\">Download</div>\n </div>\n</div>\n", styles: [""] }); }
82
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceHeader, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
83
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.12", type: InvoiceHeader, isStandalone: true, selector: "rolatech-invoice-header", ngImport: i0, template: "<div class=\"flex items-center justify-between font-bold h-11 px-3\">\n <div class=\"flex items-center\">\n <div class=\"font-bold w-[180px] max-w-[180px]\">ID</div>\n </div>\n <div class=\"flex items-center gap-3\">\n <div class=\"font-bold\">Total</div>\n </div>\n <div class=\"flex items-center gap-3\">\n <div class=\"font-bold\">Status</div>\n <div class=\"font-bold w-[100px]\">Date</div>\n <div class=\"font-bold m-w-[80px]\">Download</div>\n </div>\n</div>\n", styles: [""] }); }
82
84
  }
83
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: InvoiceHeader, decorators: [{
85
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceHeader, decorators: [{
84
86
  type: Component,
85
87
  args: [{ selector: 'rolatech-invoice-header', imports: [], template: "<div class=\"flex items-center justify-between font-bold h-11 px-3\">\n <div class=\"flex items-center\">\n <div class=\"font-bold w-[180px] max-w-[180px]\">ID</div>\n </div>\n <div class=\"flex items-center gap-3\">\n <div class=\"font-bold\">Total</div>\n </div>\n <div class=\"flex items-center gap-3\">\n <div class=\"font-bold\">Status</div>\n <div class=\"font-bold w-[100px]\">Date</div>\n <div class=\"font-bold m-w-[80px]\">Download</div>\n </div>\n</div>\n" }]
86
88
  }] });
@@ -152,10 +154,10 @@ class InvoiceIndexComponent {
152
154
  statusCompareFn(t1, t2) {
153
155
  return t1 === t2;
154
156
  }
155
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: InvoiceIndexComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
156
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: InvoiceIndexComponent, isStandalone: true, selector: "rolatech-invoice-index", ngImport: i0, template: "<rolatech-container>\n <rolatech-toolbar title=\"Invoices\" large>\n <button mat-button (click)=\"filter = !filter\">\n <span>Filter</span>\n <mat-icon>tune</mat-icon>\n </button>\n </rolatech-toolbar>\n <rolatech-filter>\n <div class=\"collapsed\" [class.expanded]=\"filter\">\n <div\n class=\"min-w-[256px] md:min-w-[320px] px-3 h-full flex flex-row md:flex-col md:h-full items-center md:items-start shadow-inner shadow-light-400 md:shadow-none overflow-x-scroll overflow-y-hidden scrollbar-hide whitespace-pre\"\n >\n <div class=\"flex items-center gap-3 mt-2\">\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-select name=\"type\" placeholder=\"Type\" [(ngModel)]=\"filterOptions.type\">\n @for (type of invoiceType | keyvalue; track type) {\n <mat-option [value]=\"type.key\">\n {{ type.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field subscriptSizing=\"dynamic\">\n <mat-select [compareWith]=\"statusCompareFn\" placeholder=\"Status\" [(ngModel)]=\"filterOptions.status\">\n @for (status of invoiceStatus | keyvalue; track status) {\n <mat-option [value]=\"status.key\">\n {{ status.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <div>\n <button mat-flat-button (click)=\"find()\">Search</button>\n <button mat-stroked-button (click)=\"resetFilter()\" class=\"ml-3\">Reset</button>\n </div>\n </div>\n </div>\n </div>\n </rolatech-filter>\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 (invoices) {\n <rolatech-invoice-header></rolatech-invoice-header>\n @for (item of invoices; track item) {\n <rolatech-invoice-item [routerLink]=\"['./', item.id]\" [invoice]=\"item\"></rolatech-invoice-item>\n }\n } @else {\n <rolatech-empty></rolatech-empty>\n }\n </rolatech-list>\n</rolatech-container>\n", styles: [".collapsed{max-height:0;overflow:hidden;transition:max-height .5s cubic-bezier(.4,0,.2,1)}.expanded{max-height:1000px}\n"], dependencies: [{ kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: TabsComponent, selector: "rolatech-tabs", inputs: ["select", "loading"], outputs: ["selectChange"] }, { kind: "component", type: TabComponent, selector: "rolatech-tab", inputs: ["label"] }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: ListComponent, selector: "rolatech-list" }, { kind: "component", type: InvoiceItem, selector: "rolatech-invoice-item", inputs: ["invoice"], outputs: ["download"] }, { kind: "component", type: EmptyComponent, selector: "rolatech-empty" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.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: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "ngmodule", type: MatOptionModule }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i7.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: FilterComponent, selector: "rolatech-filter" }, { kind: "component", type: InvoiceHeader, selector: "rolatech-invoice-header" }, { kind: "pipe", type: KeyValuePipe, name: "keyvalue" }], encapsulation: i0.ViewEncapsulation.None }); }
157
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceIndexComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
158
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: InvoiceIndexComponent, isStandalone: true, selector: "rolatech-invoice-index", ngImport: i0, template: "<rolatech-container>\n <rolatech-toolbar title=\"Invoices\" large>\n <button mat-button (click)=\"filter = !filter\">\n <span>Filter</span>\n <mat-icon>tune</mat-icon>\n </button>\n </rolatech-toolbar>\n <rolatech-filter>\n <div class=\"collapsed\" [class.expanded]=\"filter\">\n <div\n class=\"min-w-[256px] md:min-w-[320px] px-3 h-full flex flex-row md:flex-col md:h-full items-center md:items-start shadow-inner shadow-light-400 md:shadow-none overflow-x-scroll overflow-y-hidden scrollbar-hide whitespace-pre\"\n >\n <div class=\"flex items-center gap-3 mt-2\">\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-select name=\"type\" placeholder=\"Type\" [(ngModel)]=\"filterOptions.type\">\n @for (type of invoiceType | keyvalue; track type) {\n <mat-option [value]=\"type.key\">\n {{ type.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field subscriptSizing=\"dynamic\">\n <mat-select [compareWith]=\"statusCompareFn\" placeholder=\"Status\" [(ngModel)]=\"filterOptions.status\">\n @for (status of invoiceStatus | keyvalue; track status) {\n <mat-option [value]=\"status.key\">\n {{ status.value }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <div>\n <button mat-flat-button (click)=\"find()\">Search</button>\n <button mat-stroked-button (click)=\"resetFilter()\" class=\"ml-3\">Reset</button>\n </div>\n </div>\n </div>\n </div>\n </rolatech-filter>\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 (invoices) {\n <rolatech-invoice-header></rolatech-invoice-header>\n @for (item of invoices; track item) {\n <rolatech-invoice-item [routerLink]=\"['./', item.id]\" [invoice]=\"item\"></rolatech-invoice-item>\n }\n } @else {\n <rolatech-empty></rolatech-empty>\n }\n </rolatech-list>\n</rolatech-container>\n", styles: [".collapsed{max-height:0;overflow:hidden;transition:max-height .5s cubic-bezier(.4,0,.2,1)}.expanded{max-height:1000px}\n"], dependencies: [{ kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: TabsComponent, selector: "rolatech-tabs", inputs: ["select", "loading"], outputs: ["selectChange"] }, { kind: "component", type: TabComponent, selector: "rolatech-tab", inputs: ["label"] }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: ListComponent, selector: "rolatech-list" }, { kind: "component", type: InvoiceItem, selector: "rolatech-invoice-item", inputs: ["invoice"], outputs: ["download"] }, { kind: "component", type: EmptyComponent, selector: "rolatech-empty" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.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: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "ngmodule", type: MatOptionModule }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i7.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: FilterComponent, selector: "rolatech-filter" }, { kind: "component", type: InvoiceHeader, selector: "rolatech-invoice-header" }, { kind: "pipe", type: KeyValuePipe, name: "keyvalue" }], encapsulation: i0.ViewEncapsulation.None }); }
157
159
  }
158
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: InvoiceIndexComponent, decorators: [{
160
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceIndexComponent, decorators: [{
159
161
  type: Component,
160
162
  args: [{ selector: 'rolatech-invoice-index', imports: [
161
163
  ContainerComponent,
@@ -189,13 +191,13 @@ class InvoiceLineItem {
189
191
  return this.item().imageUrl;
190
192
  }, ...(ngDevMode ? [{ debugName: "thumbnail" }] : []));
191
193
  }
192
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: InvoiceLineItem, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
193
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: InvoiceLineItem, isStandalone: true, selector: "rolatech-invoice-line-item", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, link: { classPropertyName: "link", publicName: "link", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"flex justify-between py-2\">\n <div class=\"flex w-full\">\n <div\n class=\"min-w-24 w-36 aspect-video bg-[--rt-raised-background] hover:rounded-none rounded-lg h-fit cursor-pointer\"\n [routerLink]=\"link()\"\n >\n @defer (on viewport()) {\n <rolatech-thumbnail [src]=\"thumbnail()\" size=\"medium\" mode=\"clip\"> </rolatech-thumbnail>\n } @placeholder {\n <div class=\"bg-[--rt-raised-background] h-full w-full object-cover aspect-video\"></div>\n }\n </div>\n\n <div class=\"w-full ml-3 flex flex-col justify-between\">\n <!-- info -->\n <div class=\"flex justify-between\">\n <div class=\"flex flex-col\">\n <span class=\"text-lg font-bold hover:text-[--rt-brand-color] cursor-pointer\" [routerLink]=\"link()\"\n >{{ item().title }}</span\n >\n <ng-content></ng-content>\n </div>\n <div class=\"text-right p-1\">\n <div class=\"text-sm\">\u00A3{{ item().amount }}</div>\n </div>\n </div>\n <!-- action -->\n <div class=\"flex justify-between items-center w-full\">\n <div class=\"flex items-center text-sm\"></div>\n </div>\n </div>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }], deferBlockDependencies: [() => [import('@rolatech/angular-components').then(m => m.ThumbnailComponent)]] }); }
194
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceLineItem, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
195
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: InvoiceLineItem, isStandalone: true, selector: "rolatech-invoice-line-item", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, link: { classPropertyName: "link", publicName: "link", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"flex justify-between py-2\">\n <div class=\"flex w-full\">\n <div\n class=\"min-w-24 w-36 aspect-video bg-[--rt-raised-background] hover:rounded-none rounded-lg h-fit cursor-pointer\"\n [routerLink]=\"link()\"\n >\n @defer (on viewport()) {\n <rolatech-thumbnail [src]=\"thumbnail()\" size=\"medium\" mode=\"clip\"> </rolatech-thumbnail>\n } @placeholder {\n <div class=\"bg-[--rt-raised-background] h-full w-full object-cover aspect-video\"></div>\n }\n </div>\n\n <div class=\"w-full ml-3 flex flex-col justify-between\">\n <!-- info -->\n <div class=\"flex justify-between\">\n <div class=\"flex flex-col\">\n <span class=\"text-lg font-bold hover:text-[--rt-brand-color] cursor-pointer\" [routerLink]=\"link()\"\n >{{ item().title }}</span\n >\n <ng-content></ng-content>\n </div>\n <div class=\"text-right p-1\">\n <div class=\"text-sm\">{{ item().amount | price }}</div>\n </div>\n </div>\n <!-- action -->\n <div class=\"flex justify-between items-center w-full\">\n <div class=\"flex items-center text-sm\"></div>\n </div>\n </div>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: PricePipe, name: "price" }], deferBlockDependencies: [() => [import('@rolatech/angular-components').then(m => m.ThumbnailComponent)]] }); }
194
196
  }
195
- i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "20.3.4", ngImport: i0, type: InvoiceLineItem, resolveDeferredDeps: () => [import('@rolatech/angular-components').then(m => m.ThumbnailComponent)], resolveMetadata: ThumbnailComponent => ({ decorators: [{
197
+ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "20.3.12", ngImport: i0, type: InvoiceLineItem, resolveDeferredDeps: () => [import('@rolatech/angular-components').then(m => m.ThumbnailComponent)], resolveMetadata: ThumbnailComponent => ({ decorators: [{
196
198
  type: Component,
197
- args: [{ selector: 'rolatech-invoice-line-item', imports: [RouterLink, ThumbnailComponent], template: "<div class=\"flex justify-between py-2\">\n <div class=\"flex w-full\">\n <div\n class=\"min-w-24 w-36 aspect-video bg-[--rt-raised-background] hover:rounded-none rounded-lg h-fit cursor-pointer\"\n [routerLink]=\"link()\"\n >\n @defer (on viewport()) {\n <rolatech-thumbnail [src]=\"thumbnail()\" size=\"medium\" mode=\"clip\"> </rolatech-thumbnail>\n } @placeholder {\n <div class=\"bg-[--rt-raised-background] h-full w-full object-cover aspect-video\"></div>\n }\n </div>\n\n <div class=\"w-full ml-3 flex flex-col justify-between\">\n <!-- info -->\n <div class=\"flex justify-between\">\n <div class=\"flex flex-col\">\n <span class=\"text-lg font-bold hover:text-[--rt-brand-color] cursor-pointer\" [routerLink]=\"link()\"\n >{{ item().title }}</span\n >\n <ng-content></ng-content>\n </div>\n <div class=\"text-right p-1\">\n <div class=\"text-sm\">\u00A3{{ item().amount }}</div>\n </div>\n </div>\n <!-- action -->\n <div class=\"flex justify-between items-center w-full\">\n <div class=\"flex items-center text-sm\"></div>\n </div>\n </div>\n </div>\n</div>\n" }]
198
- }], ctorParameters: null, propDecorators: null }) });
199
+ args: [{ selector: 'rolatech-invoice-line-item', imports: [RouterLink, ThumbnailComponent, PricePipe], template: "<div class=\"flex justify-between py-2\">\n <div class=\"flex w-full\">\n <div\n class=\"min-w-24 w-36 aspect-video bg-[--rt-raised-background] hover:rounded-none rounded-lg h-fit cursor-pointer\"\n [routerLink]=\"link()\"\n >\n @defer (on viewport()) {\n <rolatech-thumbnail [src]=\"thumbnail()\" size=\"medium\" mode=\"clip\"> </rolatech-thumbnail>\n } @placeholder {\n <div class=\"bg-[--rt-raised-background] h-full w-full object-cover aspect-video\"></div>\n }\n </div>\n\n <div class=\"w-full ml-3 flex flex-col justify-between\">\n <!-- info -->\n <div class=\"flex justify-between\">\n <div class=\"flex flex-col\">\n <span class=\"text-lg font-bold hover:text-[--rt-brand-color] cursor-pointer\" [routerLink]=\"link()\"\n >{{ item().title }}</span\n >\n <ng-content></ng-content>\n </div>\n <div class=\"text-right p-1\">\n <div class=\"text-sm\">{{ item().amount | price }}</div>\n </div>\n </div>\n <!-- action -->\n <div class=\"flex justify-between items-center w-full\">\n <div class=\"flex items-center text-sm\"></div>\n </div>\n </div>\n </div>\n</div>\n" }]
200
+ }], ctorParameters: null, propDecorators: { item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: true }] }], link: [{ type: i0.Input, args: [{ isSignal: true, alias: "link", required: true }] }] } }) });
199
201
 
200
202
  class InvoiceDetailComponent extends BaseComponent {
201
203
  constructor() {
@@ -258,20 +260,20 @@ class InvoiceDetailComponent extends BaseComponent {
258
260
  .subscribe({
259
261
  next: (res) => {
260
262
  this.paying = false;
261
- const { redirectUrl } = res.data;
262
- window.open(redirectUrl, '_blank');
263
+ const { checkoutUrl } = res.data;
264
+ window.open(checkoutUrl, '_blank');
263
265
  },
264
266
  error: (error) => {
265
267
  this.paying = false;
266
268
  },
267
269
  });
268
270
  }
269
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: InvoiceDetailComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
270
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: InvoiceDetailComponent, isStandalone: true, selector: "rolatech-invoice-detail", usesInheritance: true, ngImport: i0, template: "<rolatech-container>\n <rolatech-toolbar [title]=\"invoice() ? status[invoice()!.status] : ''\" large link=\"../\"> </rolatech-toolbar>\n @if (invoice(); as invoice) {\n <div>\n <div>\n <div>\n @for (item of invoice.lines; track $index) {\n <rolatech-invoice-line-item [item]=\"item\" [link]=\"'/properties/' + item.extId\"></rolatech-invoice-line-item>\n }\n </div>\n <div class=\"mt-3\">\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Profile</span>\n <span class=\"text-sm\"> {{ invoice.firstName }},{{ invoice.lastName }}</span>\n </div>\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Email</span>\n <span class=\"text-sm\"> {{ invoice.email }}</span>\n </div>\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Phone</span>\n <span class=\"text-sm\"> {{ invoice.phone }}</span>\n </div>\n\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Total</span>\n <span class=\"text-sm\">\u00A3{{ invoice.total }}</span>\n </div>\n <div class=\"flex items-baseline justify-between py-1\">\n <span class=\"font-medium min-w-20\" i18n>Note</span>\n <span class=\"text-sm\">{{ invoice.note || '\u65E0' }}</span>\n </div>\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Created at</span>\n <span class=\"text-sm\"> {{ invoice.createdAt }}</span>\n </div>\n </div>\n @if (invoice.status.toString() === 'CREATED' || invoice.status.toString() === 'PAID') {\n <div class=\"mt-6\">\n <div class=\"text-lg pb-3 font-medium\" i18n>Payment method</div>\n <div class=\"flex items-center\">\n <span class=\"ml-1\">Stripe</span>\n </div>\n </div>\n }\n </div>\n\n <!-- safe area -->\n <div class=\"pb-16 sm:pb-3\"></div>\n <div class=\"\">\n <div class=\"flex items-center justify-end\">\n <button mat-flat-button [disabled]=\"paying\" class=\"w-32 min-h-11\" (click)=\"pay()\" i18n>\n {{ paying ? 'Processing' : 'Pay' }}\n </button>\n </div>\n </div>\n </div>\n }\n</rolatech-container>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.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: MatIconModule }, { kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: InvoiceLineItem, selector: "rolatech-invoice-line-item", inputs: ["item", "link"] }] }); }
271
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceDetailComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
272
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: InvoiceDetailComponent, isStandalone: true, selector: "rolatech-invoice-detail", usesInheritance: true, ngImport: i0, template: "<rolatech-container>\n <rolatech-toolbar [title]=\"invoice() ? status[invoice()!.status] : ''\" large link=\"../\"> </rolatech-toolbar>\n @if (invoice(); as invoice) {\n <div>\n <div>\n <div>\n @for (item of invoice.lines; track $index) {\n <rolatech-invoice-line-item [item]=\"item\" [link]=\"'/properties/' + item.extId\"></rolatech-invoice-line-item>\n }\n </div>\n <div class=\"mt-3\">\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Profile</span>\n <span class=\"text-sm\"> {{ invoice.firstName }},{{ invoice.lastName }}</span>\n </div>\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Email</span>\n <span class=\"text-sm\"> {{ invoice.email }}</span>\n </div>\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Phone</span>\n <span class=\"text-sm\"> {{ invoice.phone }}</span>\n </div>\n @if (invoice.holdingDepositApplied > 0) {\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Holding Deposit Applied</span>\n <span class=\"text-sm\">{{ invoice.holdingDepositApplied | price }}</span>\n </div>\n }\n\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Total</span>\n <span class=\"text-sm\">{{ invoice.total | price }}</span>\n </div>\n <div class=\"flex items-baseline justify-between py-1\">\n <span class=\"font-medium min-w-20\" i18n>Note</span>\n <span class=\"text-sm\">{{ invoice.note || '\u65E0' }}</span>\n </div>\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Created at</span>\n <span class=\"text-sm\"> {{ invoice.createdAt }}</span>\n </div>\n </div>\n @if (invoice.status.toString() === 'CREATED' || invoice.status.toString() === 'PAID') {\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Payment method</span>\n <span class=\"text-sm\"> Stripe</span>\n </div>\n }\n </div>\n\n <!-- safe area -->\n <div class=\"pb-16 sm:pb-3\"></div>\n @if (invoice.status.toString() === 'CREATED') {\n <div class=\"\">\n <div class=\"flex items-center justify-end\">\n <button mat-flat-button [disabled]=\"paying\" class=\"w-32 min-h-11\" (click)=\"pay()\" i18n>\n {{ paying ? 'Processing' : 'Pay' }}\n </button>\n </div>\n </div>\n }\n </div>\n }\n</rolatech-container>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.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: MatIconModule }, { kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: InvoiceLineItem, selector: "rolatech-invoice-line-item", inputs: ["item", "link"] }, { kind: "pipe", type: PricePipe, name: "price" }] }); }
271
273
  }
272
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: InvoiceDetailComponent, decorators: [{
274
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceDetailComponent, decorators: [{
273
275
  type: Component,
274
- args: [{ selector: 'rolatech-invoice-detail', imports: [MatButtonModule, MatIconModule, ContainerComponent, ToolbarComponent, InvoiceLineItem], template: "<rolatech-container>\n <rolatech-toolbar [title]=\"invoice() ? status[invoice()!.status] : ''\" large link=\"../\"> </rolatech-toolbar>\n @if (invoice(); as invoice) {\n <div>\n <div>\n <div>\n @for (item of invoice.lines; track $index) {\n <rolatech-invoice-line-item [item]=\"item\" [link]=\"'/properties/' + item.extId\"></rolatech-invoice-line-item>\n }\n </div>\n <div class=\"mt-3\">\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Profile</span>\n <span class=\"text-sm\"> {{ invoice.firstName }},{{ invoice.lastName }}</span>\n </div>\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Email</span>\n <span class=\"text-sm\"> {{ invoice.email }}</span>\n </div>\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Phone</span>\n <span class=\"text-sm\"> {{ invoice.phone }}</span>\n </div>\n\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Total</span>\n <span class=\"text-sm\">\u00A3{{ invoice.total }}</span>\n </div>\n <div class=\"flex items-baseline justify-between py-1\">\n <span class=\"font-medium min-w-20\" i18n>Note</span>\n <span class=\"text-sm\">{{ invoice.note || '\u65E0' }}</span>\n </div>\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Created at</span>\n <span class=\"text-sm\"> {{ invoice.createdAt }}</span>\n </div>\n </div>\n @if (invoice.status.toString() === 'CREATED' || invoice.status.toString() === 'PAID') {\n <div class=\"mt-6\">\n <div class=\"text-lg pb-3 font-medium\" i18n>Payment method</div>\n <div class=\"flex items-center\">\n <span class=\"ml-1\">Stripe</span>\n </div>\n </div>\n }\n </div>\n\n <!-- safe area -->\n <div class=\"pb-16 sm:pb-3\"></div>\n <div class=\"\">\n <div class=\"flex items-center justify-end\">\n <button mat-flat-button [disabled]=\"paying\" class=\"w-32 min-h-11\" (click)=\"pay()\" i18n>\n {{ paying ? 'Processing' : 'Pay' }}\n </button>\n </div>\n </div>\n </div>\n }\n</rolatech-container>\n" }]
276
+ args: [{ selector: 'rolatech-invoice-detail', imports: [MatButtonModule, MatIconModule, ContainerComponent, ToolbarComponent, InvoiceLineItem, PricePipe], template: "<rolatech-container>\n <rolatech-toolbar [title]=\"invoice() ? status[invoice()!.status] : ''\" large link=\"../\"> </rolatech-toolbar>\n @if (invoice(); as invoice) {\n <div>\n <div>\n <div>\n @for (item of invoice.lines; track $index) {\n <rolatech-invoice-line-item [item]=\"item\" [link]=\"'/properties/' + item.extId\"></rolatech-invoice-line-item>\n }\n </div>\n <div class=\"mt-3\">\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Profile</span>\n <span class=\"text-sm\"> {{ invoice.firstName }},{{ invoice.lastName }}</span>\n </div>\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Email</span>\n <span class=\"text-sm\"> {{ invoice.email }}</span>\n </div>\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Phone</span>\n <span class=\"text-sm\"> {{ invoice.phone }}</span>\n </div>\n @if (invoice.holdingDepositApplied > 0) {\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Holding Deposit Applied</span>\n <span class=\"text-sm\">{{ invoice.holdingDepositApplied | price }}</span>\n </div>\n }\n\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Total</span>\n <span class=\"text-sm\">{{ invoice.total | price }}</span>\n </div>\n <div class=\"flex items-baseline justify-between py-1\">\n <span class=\"font-medium min-w-20\" i18n>Note</span>\n <span class=\"text-sm\">{{ invoice.note || '\u65E0' }}</span>\n </div>\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Created at</span>\n <span class=\"text-sm\"> {{ invoice.createdAt }}</span>\n </div>\n </div>\n @if (invoice.status.toString() === 'CREATED' || invoice.status.toString() === 'PAID') {\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Payment method</span>\n <span class=\"text-sm\"> Stripe</span>\n </div>\n }\n </div>\n\n <!-- safe area -->\n <div class=\"pb-16 sm:pb-3\"></div>\n @if (invoice.status.toString() === 'CREATED') {\n <div class=\"\">\n <div class=\"flex items-center justify-end\">\n <button mat-flat-button [disabled]=\"paying\" class=\"w-32 min-h-11\" (click)=\"pay()\" i18n>\n {{ paying ? 'Processing' : 'Pay' }}\n </button>\n </div>\n </div>\n }\n </div>\n }\n</rolatech-container>\n" }]
275
277
  }] });
276
278
 
277
279
  const invoiceRoutes = [
@@ -304,10 +306,15 @@ class InvoiceManageIndex {
304
306
  icon: 'dashboard',
305
307
  },
306
308
  {
307
- name: 'Pending',
309
+ name: 'Created',
308
310
  icon: 'category',
309
311
  status: 'created',
310
312
  },
313
+ {
314
+ name: 'Issued',
315
+ icon: 'category',
316
+ status: 'issued',
317
+ },
311
318
  {
312
319
  name: 'Paid',
313
320
  icon: 'category',
@@ -320,8 +327,15 @@ class InvoiceManageIndex {
320
327
  .pipe(map((p) => {
321
328
  const page = p.get('page') ? Number(p.get('page')) : 1;
322
329
  this.pageIndex.set(Math.max(page - 1, 0));
330
+ const status = p.get('status') || undefined;
331
+ let filter = '';
332
+ if (status) {
333
+ this.select = this.links.findIndex((item) => item.status === status);
334
+ filter = `status:${status?.toUpperCase()}`;
335
+ }
323
336
  return {
324
337
  page,
338
+ filter,
325
339
  limit: p.get('limit') ? Number(p.get('limit')) : 15,
326
340
  sort: p.get('sort') || undefined,
327
341
  };
@@ -352,12 +366,26 @@ class InvoiceManageIndex {
352
366
  replaceUrl: true, // optional: avoid stacking history on every page click
353
367
  });
354
368
  }
355
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: InvoiceManageIndex, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
356
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: InvoiceManageIndex, isStandalone: true, selector: "rolatech-invoice-manage-index", ngImport: i0, template: "<rolatech-toolbar title=\"Invoices\">\n <div class=\"flex items-center gap-2\"></div>\n</rolatech-toolbar>\n<rolatech-tabs [select]=\"select\">\n @for (item of links; track item) { @if (item.status) {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\" [queryParams]=\"{ status: item.status }\"></rolatech-tab>\n } @else {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\"></rolatech-tab>\n } }\n</rolatech-tabs>\n<div>\n @for (item of invoices(); track $index) {\n <rolatech-invoice-manage-item [invoice]=\"item\"></rolatech-invoice-manage-item>\n }\n</div>\n<mat-paginator\n #paginator\n [length]=\"length\"\n [pageSize]=\"pageSize\"\n [pageIndex]=\"pageIndex()\"\n [pageSizeOptions]=\"pageSizeOptions\"\n (page)=\"onPage($event)\"\n hidePageSize\n showFirstLastButtons\n>\n</mat-paginator>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: TabsComponent, selector: "rolatech-tabs", inputs: ["select", "loading"], outputs: ["selectChange"] }, { kind: "component", type: TabComponent, selector: "rolatech-tab", inputs: ["label"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i1$2.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "component", type: InvoiceManageItem, selector: "rolatech-invoice-manage-item", inputs: ["invoice"] }] }); }
369
+ statusBadgeClass(status) {
370
+ switch (status.toString()) {
371
+ case 'CREATED':
372
+ return 'bg-yellow-100 text-yellow-800';
373
+ case 'ISSUED':
374
+ return 'bg-blue-100 text-blue-800';
375
+ case 'PAID':
376
+ return 'bg-emerald-100 text-emerald-800';
377
+ case 'VOID':
378
+ return 'bg-red-100 text-red-800';
379
+ default:
380
+ return 'bg-gray-100 text-gray-700';
381
+ }
382
+ }
383
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceManageIndex, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
384
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: InvoiceManageIndex, isStandalone: true, selector: "rolatech-invoice-manage-index", ngImport: i0, template: "<rolatech-toolbar title=\"Invoices\">\n <div class=\"flex items-center gap-2\"></div>\n</rolatech-toolbar>\n<rolatech-tabs [select]=\"select\">\n @for (item of links; track item) { @if (item.status) {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\" [queryParams]=\"{ status: item.status }\"></rolatech-tab>\n } @else {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\"></rolatech-tab>\n } }\n</rolatech-tabs>\n<div class=\"p-3 overflow-x-auto\">\n <table class=\"min-w-full\">\n <thead class=\"bg-gray-100\">\n <tr>\n <th class=\"p-3 border-b text-left\">#ID</th>\n <th class=\"p-3 border-b text-left\">Status</th>\n <th class=\"p-3 border-b text-left\">Email</th>\n <th class=\"p-3 border-b text-left\">Profile</th>\n <th class=\"p-3 border-b text-left\">Total</th>\n </tr>\n </thead>\n <tbody>\n @for (item of invoices(); track $index) {\n <!-- <rolatech-invoice-manage-item [invoice]=\"item\"></rolatech-invoice-manage-item> -->\n <tr class=\"hover:bg-gray-50 hover:cursor-pointer\" [routerLink]=\"['./', item.id]\">\n <td class=\"p-3 border-b\">{{item.id}}</td>\n <td class=\"p-3 border-b\">\n <span\n class=\"inline-flex items-center rounded-full px-3 py-1 text-xs font-medium\"\n [ngClass]=\"statusBadgeClass(item.status)\"\n >{{item.status}}</span\n >\n </td>\n <td class=\"p-3 border-b\">{{item.email}}</td>\n <td class=\"p-3 border-b\">{{item.firstName}},{{item.lastName}}</td>\n <td class=\"p-3 border-b\">{{item.total | price}}</td>\n </tr>\n }\n </tbody>\n </table>\n</div>\n<!-- <div>\n <table class=\"min-w-full text-sm\">\n <thead class=\"border-b bg-gray-50\">\n <tr>\n <th class=\"py-2 text-left font-medium text-gray-600\">#ID</th>\n <th class=\"py-2 text-right font-medium text-gray-600\">Status</th>\n <th class=\"py-2 text-right font-medium text-gray-600\">Email</th>\n <th class=\"py-2 text-right font-medium text-gray-600\">Profile</th>\n <th class=\"py-2 text-right font-medium text-gray-600\">Total</th>\n </tr>\n </thead>\n\n <tbody>\n @for (item of invoices(); track $index) {\n <tr class=\"border-b hover:bg-gray-50 hover:cursor-pointer\">\n <td class=\"py-2\">{{item.id}}</td>\n <td class=\"py-2 text-right\">{{item.status}}</td>\n <td class=\"py-2 text-right\">{{item.email}}</td>\n <td class=\"py-2 text-right\">{{item.firstName}}, {{item.lastName}}</td>\n <td class=\"py-2 text-right font-semibold\">{{item.total | price}}</td>\n </tr>\n }\n </tbody>\n </table>\n</div> -->\n<mat-paginator\n #paginator\n [length]=\"length\"\n [pageSize]=\"pageSize\"\n [pageIndex]=\"pageIndex()\"\n [pageSizeOptions]=\"pageSizeOptions\"\n (page)=\"onPage($event)\"\n hidePageSize\n showFirstLastButtons\n>\n</mat-paginator>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: TabsComponent, selector: "rolatech-tabs", inputs: ["select", "loading"], outputs: ["selectChange"] }, { kind: "component", type: TabComponent, selector: "rolatech-tab", inputs: ["label"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i2$1.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "pipe", type: PricePipe, name: "price" }] }); }
357
385
  }
358
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: InvoiceManageIndex, decorators: [{
386
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceManageIndex, decorators: [{
359
387
  type: Component,
360
- args: [{ selector: 'rolatech-invoice-manage-index', imports: [CommonModule, RouterLink, ToolbarComponent, TabsComponent, TabComponent, MatPaginatorModule, InvoiceManageItem], template: "<rolatech-toolbar title=\"Invoices\">\n <div class=\"flex items-center gap-2\"></div>\n</rolatech-toolbar>\n<rolatech-tabs [select]=\"select\">\n @for (item of links; track item) { @if (item.status) {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\" [queryParams]=\"{ status: item.status }\"></rolatech-tab>\n } @else {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\"></rolatech-tab>\n } }\n</rolatech-tabs>\n<div>\n @for (item of invoices(); track $index) {\n <rolatech-invoice-manage-item [invoice]=\"item\"></rolatech-invoice-manage-item>\n }\n</div>\n<mat-paginator\n #paginator\n [length]=\"length\"\n [pageSize]=\"pageSize\"\n [pageIndex]=\"pageIndex()\"\n [pageSizeOptions]=\"pageSizeOptions\"\n (page)=\"onPage($event)\"\n hidePageSize\n showFirstLastButtons\n>\n</mat-paginator>\n" }]
388
+ args: [{ selector: 'rolatech-invoice-manage-index', imports: [CommonModule, RouterLink, ToolbarComponent, TabsComponent, TabComponent, MatPaginatorModule, PricePipe], template: "<rolatech-toolbar title=\"Invoices\">\n <div class=\"flex items-center gap-2\"></div>\n</rolatech-toolbar>\n<rolatech-tabs [select]=\"select\">\n @for (item of links; track item) { @if (item.status) {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\" [queryParams]=\"{ status: item.status }\"></rolatech-tab>\n } @else {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\"></rolatech-tab>\n } }\n</rolatech-tabs>\n<div class=\"p-3 overflow-x-auto\">\n <table class=\"min-w-full\">\n <thead class=\"bg-gray-100\">\n <tr>\n <th class=\"p-3 border-b text-left\">#ID</th>\n <th class=\"p-3 border-b text-left\">Status</th>\n <th class=\"p-3 border-b text-left\">Email</th>\n <th class=\"p-3 border-b text-left\">Profile</th>\n <th class=\"p-3 border-b text-left\">Total</th>\n </tr>\n </thead>\n <tbody>\n @for (item of invoices(); track $index) {\n <!-- <rolatech-invoice-manage-item [invoice]=\"item\"></rolatech-invoice-manage-item> -->\n <tr class=\"hover:bg-gray-50 hover:cursor-pointer\" [routerLink]=\"['./', item.id]\">\n <td class=\"p-3 border-b\">{{item.id}}</td>\n <td class=\"p-3 border-b\">\n <span\n class=\"inline-flex items-center rounded-full px-3 py-1 text-xs font-medium\"\n [ngClass]=\"statusBadgeClass(item.status)\"\n >{{item.status}}</span\n >\n </td>\n <td class=\"p-3 border-b\">{{item.email}}</td>\n <td class=\"p-3 border-b\">{{item.firstName}},{{item.lastName}}</td>\n <td class=\"p-3 border-b\">{{item.total | price}}</td>\n </tr>\n }\n </tbody>\n </table>\n</div>\n<!-- <div>\n <table class=\"min-w-full text-sm\">\n <thead class=\"border-b bg-gray-50\">\n <tr>\n <th class=\"py-2 text-left font-medium text-gray-600\">#ID</th>\n <th class=\"py-2 text-right font-medium text-gray-600\">Status</th>\n <th class=\"py-2 text-right font-medium text-gray-600\">Email</th>\n <th class=\"py-2 text-right font-medium text-gray-600\">Profile</th>\n <th class=\"py-2 text-right font-medium text-gray-600\">Total</th>\n </tr>\n </thead>\n\n <tbody>\n @for (item of invoices(); track $index) {\n <tr class=\"border-b hover:bg-gray-50 hover:cursor-pointer\">\n <td class=\"py-2\">{{item.id}}</td>\n <td class=\"py-2 text-right\">{{item.status}}</td>\n <td class=\"py-2 text-right\">{{item.email}}</td>\n <td class=\"py-2 text-right\">{{item.firstName}}, {{item.lastName}}</td>\n <td class=\"py-2 text-right font-semibold\">{{item.total | price}}</td>\n </tr>\n }\n </tbody>\n </table>\n</div> -->\n<mat-paginator\n #paginator\n [length]=\"length\"\n [pageSize]=\"pageSize\"\n [pageIndex]=\"pageIndex()\"\n [pageSizeOptions]=\"pageSizeOptions\"\n (page)=\"onPage($event)\"\n hidePageSize\n showFirstLastButtons\n>\n</mat-paginator>\n" }]
361
389
  }] });
362
390
 
363
391
  class InvoiceManageCreate {
@@ -450,10 +478,10 @@ class InvoiceManageCreate {
450
478
  todayIso() {
451
479
  return new Date().toISOString().slice(0, 10);
452
480
  }
453
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: InvoiceManageCreate, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
454
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: InvoiceManageCreate, isStandalone: true, selector: "rolatech-invoice-manage-create", ngImport: i0, template: "<rolatech-toolbar title=\"Create Invoice\">\n <button mat-stroked-button (click)=\"addLine()\">\n <mat-icon>add</mat-icon>\n Add line\n </button>\n <button\n mat-flat-button\n color=\"primary\"\n (click)=\"save(invoiceForm)\"\n [disabled]=\"!invoiceForm.form.valid || invoice.lines.length === 0\"\n >\n Save\n </button>\n</rolatech-toolbar>\n<div class=\"p-4 md:p-8 max-w-6xl mx-auto space-y-6\">\n <form #invoiceForm=\"ngForm\" novalidate>\n <mat-card appearance=\"outlined\" class=\"p-4\">\n <div class=\"grid md:grid-cols-2 gap-4\">\n <mat-form-field appearance=\"fill\">\n <mat-label>Customer name</mat-label>\n <input matInput name=\"customerName\" [(ngModel)]=\"invoice.customerName\" required />\n @if (invoiceForm.submitted && !invoice.customerName) {<mat-error>Name is required</mat-error>}\n </mat-form-field>\n\n <mat-form-field appearance=\"fill\">\n <mat-label>Customer email</mat-label>\n <input matInput type=\"email\" name=\"customerEmail\" [(ngModel)]=\"invoice.customerEmail\" #email=\"ngModel\" email />\n @if (email.invalid && (email.dirty || email.touched)) {<mat-error>Invalid email</mat-error>}\n </mat-form-field>\n\n <mat-form-field appearance=\"fill\" class=\"md:col-span-2\">\n <mat-label>Customer address</mat-label>\n <textarea matInput rows=\"2\" name=\"customerAddress\" [(ngModel)]=\"invoice.customerAddress\"></textarea>\n </mat-form-field>\n\n <mat-form-field appearance=\"fill\">\n <mat-label>Currency</mat-label>\n <mat-select name=\"currency\" [(ngModel)]=\"invoice.currency\" required>\n <mat-option value=\"GBP\">GBP</mat-option>\n <mat-option value=\"USD\">USD</mat-option>\n <mat-option value=\"EUR\">EUR</mat-option>\n </mat-select>\n </mat-form-field>\n\n <mat-form-field appearance=\"fill\">\n <mat-label>Issue date</mat-label>\n <input matInput type=\"date\" name=\"issueDate\" [(ngModel)]=\"invoice.issueDate\" required />\n </mat-form-field>\n\n <mat-form-field appearance=\"fill\">\n <mat-label>Due date</mat-label>\n <input matInput type=\"date\" name=\"dueDate\" [(ngModel)]=\"invoice.dueDate\" />\n </mat-form-field>\n\n <mat-form-field appearance=\"fill\" class=\"md:col-span-2\">\n <mat-label>Notes</mat-label>\n <textarea\n matInput\n rows=\"2\"\n name=\"notes\"\n [(ngModel)]=\"invoice.notes\"\n placeholder=\"Optional notes shown on the invoice\"\n ></textarea>\n </mat-form-field>\n </div>\n </mat-card>\n\n <mat-card appearance=\"outlined\" class=\"p-4 space-y-4 mt-4\">\n <div class=\"flex items-center justify-between\">\n <h2 class=\"text-xl font-medium\">Line items</h2>\n <button mat-stroked-button type=\"button\" (click)=\"addLine()\">\n <mat-icon>playlist_add</mat-icon>\n Add line\n </button>\n </div>\n\n <div class=\"hidden md:grid grid-cols-12 gap-2 text-sm font-medium px-2\">\n <div class=\"col-span-5\">Description</div>\n <div class=\"col-span-2 text-right\">Qty</div>\n <div class=\"col-span-2 text-right\">Unit Price</div>\n <div class=\"col-span-2 text-right\">Tax %</div>\n <div class=\"col-span-1\"></div>\n </div>\n\n <div class=\"space-y-3\">\n @for ( line of invoice.lines; track line; let i = $index) {\n <div class=\"grid grid-cols-1 md:grid-cols-12 gap-2 items-start\">\n <mat-form-field class=\"md:col-span-5\" appearance=\"fill\">\n <mat-label>Description</mat-label>\n <input\n matInput\n [name]=\"'desc'+i\"\n [(ngModel)]=\"line.description\"\n required\n placeholder=\"e.g. Photo editing package\"\n />\n </mat-form-field>\n\n <mat-form-field class=\"md:col-span-2\" appearance=\"fill\">\n <mat-label>Quantity</mat-label>\n <input matInput type=\"number\" min=\"1\" step=\"1\" [name]=\"'qty'+i\" [(ngModel)]=\"line.quantity\" required />\n </mat-form-field>\n\n <mat-form-field class=\"md:col-span-2\" appearance=\"fill\">\n <mat-label>Unit Price (major unit)</mat-label>\n <input matInput type=\"number\" min=\"0\" step=\"0.01\" [name]=\"'unit'+i\" [(ngModel)]=\"line.unitPrice\" required />\n <mat-hint>e.g. 99.99</mat-hint>\n </mat-form-field>\n\n <mat-form-field class=\"md:col-span-2\" appearance=\"fill\">\n <mat-label>Tax %</mat-label>\n <input matInput type=\"number\" min=\"0\" step=\"0.01\" [name]=\"'tax'+i\" [(ngModel)]=\"line.taxRate\" />\n </mat-form-field>\n\n <div class=\"md:col-span-1 flex items-center justify-end\">\n <button mat-icon-button color=\"warn\" type=\"button\" (click)=\"removeLine(i)\" aria-label=\"Remove line\">\n <mat-icon>delete</mat-icon>\n </button>\n </div>\n </div>\n <mat-divider></mat-divider>\n }\n </div>\n\n <div class=\"flex flex-col items-end space-y-1\">\n <div class=\"text-sm\">\n Subtotal: <span class=\"font-medium\">{{ subtotalMajor() | number:'1.2-2' }} {{ invoice.currency }}</span>\n </div>\n <div class=\"text-sm\">\n Tax: <span class=\"font-medium\">{{ taxMajor() | number:'1.2-2' }} {{ invoice.currency }}</span>\n </div>\n <div class=\"text-lg font-semibold\">Total: {{ totalMajor() | number:'1.2-2' }} {{ invoice.currency }}</div>\n </div>\n </mat-card>\n </form>\n\n @if (lastResponse) {\n <mat-card appearance=\"outlined\" class=\"p-4 flex items-center justify-between\">\n <div>\n <div class=\"font-medium\">Created invoice #{{ lastResponse.data.id }}</div>\n <div class=\"text-sm opacity-70\">\n Total: {{ penceToMajor(lastResponse.data.total) | number:'1.2-2' }} {{ invoice.currency }}\n </div>\n </div>\n <div class=\"space-x-2\">\n <button mat-stroked-button (click)=\"resetForm()\">Create another</button>\n <button mat-flat-button color=\"primary\">Download PDF</button>\n </div>\n </mat-card>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.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$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.EmailValidator, selector: "[email][formControlName],[email][formControl],[email][ngModel]", inputs: ["email"] }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.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: i7.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: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i8.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i9.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "pipe", type: i10.DecimalPipe, name: "number" }] }); }
481
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceManageCreate, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
482
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: InvoiceManageCreate, isStandalone: true, selector: "rolatech-invoice-manage-create", ngImport: i0, template: "<rolatech-toolbar title=\"Create Invoice\">\n <button mat-stroked-button (click)=\"addLine()\">\n <mat-icon>add</mat-icon>\n Add line\n </button>\n <button\n mat-flat-button\n color=\"primary\"\n (click)=\"save(invoiceForm)\"\n [disabled]=\"!invoiceForm.form.valid || invoice.lines.length === 0\"\n >\n Save\n </button>\n</rolatech-toolbar>\n<div class=\"p-4 md:p-8 max-w-6xl mx-auto space-y-6\">\n <form #invoiceForm=\"ngForm\" novalidate>\n <mat-card appearance=\"outlined\" class=\"p-4\">\n <div class=\"grid md:grid-cols-2 gap-4\">\n <mat-form-field appearance=\"fill\">\n <mat-label>Customer name</mat-label>\n <input matInput name=\"customerName\" [(ngModel)]=\"invoice.customerName\" required />\n @if (invoiceForm.submitted && !invoice.customerName) {<mat-error>Name is required</mat-error>}\n </mat-form-field>\n\n <mat-form-field appearance=\"fill\">\n <mat-label>Customer email</mat-label>\n <input matInput type=\"email\" name=\"customerEmail\" [(ngModel)]=\"invoice.customerEmail\" #email=\"ngModel\" email />\n @if (email.invalid && (email.dirty || email.touched)) {<mat-error>Invalid email</mat-error>}\n </mat-form-field>\n\n <mat-form-field appearance=\"fill\" class=\"md:col-span-2\">\n <mat-label>Customer address</mat-label>\n <textarea matInput rows=\"2\" name=\"customerAddress\" [(ngModel)]=\"invoice.customerAddress\"></textarea>\n </mat-form-field>\n\n <mat-form-field appearance=\"fill\">\n <mat-label>Currency</mat-label>\n <mat-select name=\"currency\" [(ngModel)]=\"invoice.currency\" required>\n <mat-option value=\"GBP\">GBP</mat-option>\n <mat-option value=\"USD\">USD</mat-option>\n <mat-option value=\"EUR\">EUR</mat-option>\n </mat-select>\n </mat-form-field>\n\n <mat-form-field appearance=\"fill\">\n <mat-label>Issue date</mat-label>\n <input matInput type=\"date\" name=\"issueDate\" [(ngModel)]=\"invoice.issueDate\" required />\n </mat-form-field>\n\n <mat-form-field appearance=\"fill\">\n <mat-label>Due date</mat-label>\n <input matInput type=\"date\" name=\"dueDate\" [(ngModel)]=\"invoice.dueDate\" />\n </mat-form-field>\n\n <mat-form-field appearance=\"fill\" class=\"md:col-span-2\">\n <mat-label>Notes</mat-label>\n <textarea\n matInput\n rows=\"2\"\n name=\"notes\"\n [(ngModel)]=\"invoice.notes\"\n placeholder=\"Optional notes shown on the invoice\"\n ></textarea>\n </mat-form-field>\n </div>\n </mat-card>\n\n <mat-card appearance=\"outlined\" class=\"p-4 space-y-4 mt-4\">\n <div class=\"flex items-center justify-between\">\n <h2 class=\"text-xl font-medium\">Line items</h2>\n <button mat-stroked-button type=\"button\" (click)=\"addLine()\">\n <mat-icon>playlist_add</mat-icon>\n Add line\n </button>\n </div>\n\n <div class=\"hidden md:grid grid-cols-12 gap-2 text-sm font-medium px-2\">\n <div class=\"col-span-5\">Description</div>\n <div class=\"col-span-2 text-right\">Qty</div>\n <div class=\"col-span-2 text-right\">Unit Price</div>\n <div class=\"col-span-2 text-right\">Tax %</div>\n <div class=\"col-span-1\"></div>\n </div>\n\n <div class=\"space-y-3\">\n @for ( line of invoice.lines; track line; let i = $index) {\n <div class=\"grid grid-cols-1 md:grid-cols-12 gap-2 items-start\">\n <mat-form-field class=\"md:col-span-5\" appearance=\"fill\">\n <mat-label>Description</mat-label>\n <input\n matInput\n [name]=\"'desc'+i\"\n [(ngModel)]=\"line.description\"\n required\n placeholder=\"e.g. Photo editing package\"\n />\n </mat-form-field>\n\n <mat-form-field class=\"md:col-span-2\" appearance=\"fill\">\n <mat-label>Quantity</mat-label>\n <input matInput type=\"number\" min=\"1\" step=\"1\" [name]=\"'qty'+i\" [(ngModel)]=\"line.quantity\" required />\n </mat-form-field>\n\n <mat-form-field class=\"md:col-span-2\" appearance=\"fill\">\n <mat-label>Unit Price (major unit)</mat-label>\n <input matInput type=\"number\" min=\"0\" step=\"0.01\" [name]=\"'unit'+i\" [(ngModel)]=\"line.unitPrice\" required />\n <mat-hint>e.g. 99.99</mat-hint>\n </mat-form-field>\n\n <mat-form-field class=\"md:col-span-2\" appearance=\"fill\">\n <mat-label>Tax %</mat-label>\n <input matInput type=\"number\" min=\"0\" step=\"0.01\" [name]=\"'tax'+i\" [(ngModel)]=\"line.taxRate\" />\n </mat-form-field>\n\n <div class=\"md:col-span-1 flex items-center justify-end\">\n <button mat-icon-button color=\"warn\" type=\"button\" (click)=\"removeLine(i)\" aria-label=\"Remove line\">\n <mat-icon>delete</mat-icon>\n </button>\n </div>\n </div>\n <mat-divider></mat-divider>\n }\n </div>\n\n <div class=\"flex flex-col items-end space-y-1\">\n <div class=\"text-sm\">\n Subtotal: <span class=\"font-medium\">{{ subtotalMajor() | number:'1.2-2' }} {{ invoice.currency }}</span>\n </div>\n <div class=\"text-sm\">\n Tax: <span class=\"font-medium\">{{ taxMajor() | number:'1.2-2' }} {{ invoice.currency }}</span>\n </div>\n <div class=\"text-lg font-semibold\">Total: {{ totalMajor() | number:'1.2-2' }} {{ invoice.currency }}</div>\n </div>\n </mat-card>\n </form>\n\n @if (lastResponse) {\n <mat-card appearance=\"outlined\" class=\"p-4 flex items-center justify-between\">\n <div>\n <div class=\"font-medium\">Created invoice #{{ lastResponse.data.id }}</div>\n <div class=\"text-sm opacity-70\">\n Total: {{ penceToMajor(lastResponse.data.total) | number:'1.2-2' }} {{ invoice.currency }}\n </div>\n </div>\n <div class=\"space-x-2\">\n <button mat-stroked-button (click)=\"resetForm()\">Create another</button>\n <button mat-flat-button color=\"primary\">Download PDF</button>\n </div>\n </mat-card>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.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$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.EmailValidator, selector: "[email][formControlName],[email][formControl],[email][ngModel]", inputs: ["email"] }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.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: i7.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: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i8.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i9.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "pipe", type: i1$2.DecimalPipe, name: "number" }] }); }
455
483
  }
456
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: InvoiceManageCreate, decorators: [{
484
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceManageCreate, decorators: [{
457
485
  type: Component,
458
486
  args: [{ selector: 'rolatech-invoice-manage-create', imports: [
459
487
  CommonModule,
@@ -469,33 +497,62 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImpor
469
497
  ], template: "<rolatech-toolbar title=\"Create Invoice\">\n <button mat-stroked-button (click)=\"addLine()\">\n <mat-icon>add</mat-icon>\n Add line\n </button>\n <button\n mat-flat-button\n color=\"primary\"\n (click)=\"save(invoiceForm)\"\n [disabled]=\"!invoiceForm.form.valid || invoice.lines.length === 0\"\n >\n Save\n </button>\n</rolatech-toolbar>\n<div class=\"p-4 md:p-8 max-w-6xl mx-auto space-y-6\">\n <form #invoiceForm=\"ngForm\" novalidate>\n <mat-card appearance=\"outlined\" class=\"p-4\">\n <div class=\"grid md:grid-cols-2 gap-4\">\n <mat-form-field appearance=\"fill\">\n <mat-label>Customer name</mat-label>\n <input matInput name=\"customerName\" [(ngModel)]=\"invoice.customerName\" required />\n @if (invoiceForm.submitted && !invoice.customerName) {<mat-error>Name is required</mat-error>}\n </mat-form-field>\n\n <mat-form-field appearance=\"fill\">\n <mat-label>Customer email</mat-label>\n <input matInput type=\"email\" name=\"customerEmail\" [(ngModel)]=\"invoice.customerEmail\" #email=\"ngModel\" email />\n @if (email.invalid && (email.dirty || email.touched)) {<mat-error>Invalid email</mat-error>}\n </mat-form-field>\n\n <mat-form-field appearance=\"fill\" class=\"md:col-span-2\">\n <mat-label>Customer address</mat-label>\n <textarea matInput rows=\"2\" name=\"customerAddress\" [(ngModel)]=\"invoice.customerAddress\"></textarea>\n </mat-form-field>\n\n <mat-form-field appearance=\"fill\">\n <mat-label>Currency</mat-label>\n <mat-select name=\"currency\" [(ngModel)]=\"invoice.currency\" required>\n <mat-option value=\"GBP\">GBP</mat-option>\n <mat-option value=\"USD\">USD</mat-option>\n <mat-option value=\"EUR\">EUR</mat-option>\n </mat-select>\n </mat-form-field>\n\n <mat-form-field appearance=\"fill\">\n <mat-label>Issue date</mat-label>\n <input matInput type=\"date\" name=\"issueDate\" [(ngModel)]=\"invoice.issueDate\" required />\n </mat-form-field>\n\n <mat-form-field appearance=\"fill\">\n <mat-label>Due date</mat-label>\n <input matInput type=\"date\" name=\"dueDate\" [(ngModel)]=\"invoice.dueDate\" />\n </mat-form-field>\n\n <mat-form-field appearance=\"fill\" class=\"md:col-span-2\">\n <mat-label>Notes</mat-label>\n <textarea\n matInput\n rows=\"2\"\n name=\"notes\"\n [(ngModel)]=\"invoice.notes\"\n placeholder=\"Optional notes shown on the invoice\"\n ></textarea>\n </mat-form-field>\n </div>\n </mat-card>\n\n <mat-card appearance=\"outlined\" class=\"p-4 space-y-4 mt-4\">\n <div class=\"flex items-center justify-between\">\n <h2 class=\"text-xl font-medium\">Line items</h2>\n <button mat-stroked-button type=\"button\" (click)=\"addLine()\">\n <mat-icon>playlist_add</mat-icon>\n Add line\n </button>\n </div>\n\n <div class=\"hidden md:grid grid-cols-12 gap-2 text-sm font-medium px-2\">\n <div class=\"col-span-5\">Description</div>\n <div class=\"col-span-2 text-right\">Qty</div>\n <div class=\"col-span-2 text-right\">Unit Price</div>\n <div class=\"col-span-2 text-right\">Tax %</div>\n <div class=\"col-span-1\"></div>\n </div>\n\n <div class=\"space-y-3\">\n @for ( line of invoice.lines; track line; let i = $index) {\n <div class=\"grid grid-cols-1 md:grid-cols-12 gap-2 items-start\">\n <mat-form-field class=\"md:col-span-5\" appearance=\"fill\">\n <mat-label>Description</mat-label>\n <input\n matInput\n [name]=\"'desc'+i\"\n [(ngModel)]=\"line.description\"\n required\n placeholder=\"e.g. Photo editing package\"\n />\n </mat-form-field>\n\n <mat-form-field class=\"md:col-span-2\" appearance=\"fill\">\n <mat-label>Quantity</mat-label>\n <input matInput type=\"number\" min=\"1\" step=\"1\" [name]=\"'qty'+i\" [(ngModel)]=\"line.quantity\" required />\n </mat-form-field>\n\n <mat-form-field class=\"md:col-span-2\" appearance=\"fill\">\n <mat-label>Unit Price (major unit)</mat-label>\n <input matInput type=\"number\" min=\"0\" step=\"0.01\" [name]=\"'unit'+i\" [(ngModel)]=\"line.unitPrice\" required />\n <mat-hint>e.g. 99.99</mat-hint>\n </mat-form-field>\n\n <mat-form-field class=\"md:col-span-2\" appearance=\"fill\">\n <mat-label>Tax %</mat-label>\n <input matInput type=\"number\" min=\"0\" step=\"0.01\" [name]=\"'tax'+i\" [(ngModel)]=\"line.taxRate\" />\n </mat-form-field>\n\n <div class=\"md:col-span-1 flex items-center justify-end\">\n <button mat-icon-button color=\"warn\" type=\"button\" (click)=\"removeLine(i)\" aria-label=\"Remove line\">\n <mat-icon>delete</mat-icon>\n </button>\n </div>\n </div>\n <mat-divider></mat-divider>\n }\n </div>\n\n <div class=\"flex flex-col items-end space-y-1\">\n <div class=\"text-sm\">\n Subtotal: <span class=\"font-medium\">{{ subtotalMajor() | number:'1.2-2' }} {{ invoice.currency }}</span>\n </div>\n <div class=\"text-sm\">\n Tax: <span class=\"font-medium\">{{ taxMajor() | number:'1.2-2' }} {{ invoice.currency }}</span>\n </div>\n <div class=\"text-lg font-semibold\">Total: {{ totalMajor() | number:'1.2-2' }} {{ invoice.currency }}</div>\n </div>\n </mat-card>\n </form>\n\n @if (lastResponse) {\n <mat-card appearance=\"outlined\" class=\"p-4 flex items-center justify-between\">\n <div>\n <div class=\"font-medium\">Created invoice #{{ lastResponse.data.id }}</div>\n <div class=\"text-sm opacity-70\">\n Total: {{ penceToMajor(lastResponse.data.total) | number:'1.2-2' }} {{ invoice.currency }}\n </div>\n </div>\n <div class=\"space-x-2\">\n <button mat-stroked-button (click)=\"resetForm()\">Create another</button>\n <button mat-flat-button color=\"primary\">Download PDF</button>\n </div>\n </mat-card>\n }\n</div>\n" }]
470
498
  }] });
471
499
 
472
- class InvoiceManageDetail {
473
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: InvoiceManageDetail, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
474
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.4", type: InvoiceManageDetail, isStandalone: true, selector: "rolatech-invoice-manage-detail", ngImport: i0, template: "<p>invoice-manage-detail works!</p>\n", styles: [""] }); }
500
+ class InvoiceManageDetail extends BaseComponent {
501
+ constructor() {
502
+ super(...arguments);
503
+ this.invoiceService = inject(InvoiceService);
504
+ this.sanitizer = inject(DomSanitizer);
505
+ this.pdfUrl = '';
506
+ this.loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
507
+ this.invoice = signal(null, ...(ngDevMode ? [{ debugName: "invoice" }] : []));
508
+ }
509
+ ngOnInit() {
510
+ this.getInvoice();
511
+ }
512
+ getInvoice() {
513
+ this.invoiceService.getInvoice(this.id).subscribe({
514
+ next: (res) => {
515
+ this.invoice.set(res.data);
516
+ this.loading.set(false);
517
+ this.pdfUrl = res.data.pdfUrl;
518
+ this.safePdfUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.pdfUrl);
519
+ },
520
+ });
521
+ }
522
+ openPdf() {
523
+ window.open(this.pdfUrl, '_blank');
524
+ }
525
+ statusBadgeClass(status) {
526
+ switch (status.toString()) {
527
+ case 'CREATED':
528
+ return 'bg-yellow-100 text-yellow-800';
529
+ case 'ISSUED':
530
+ return 'bg-blue-100 text-blue-800';
531
+ case 'PAID':
532
+ return 'bg-emerald-100 text-emerald-800';
533
+ case 'VOID':
534
+ return 'bg-red-100 text-red-800';
535
+ default:
536
+ return 'bg-gray-100 text-gray-700';
537
+ }
538
+ }
539
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceManageDetail, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
540
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: InvoiceManageDetail, isStandalone: true, selector: "rolatech-invoice-manage-detail", usesInheritance: true, ngImport: i0, template: "<!-- invoice-manage-detail.component.html -->\n<div class=\"p-4 lg:p-6 space-y-6\">\n <!-- Breadcrumb / header -->\n <div class=\"flex items-center justify-between gap-4\">\n <div class=\"space-y-1\">\n <nav class=\"text-gray-500 flex items-center gap-1\">\n <a routerLink=\"/invoices\" class=\"hover:underline hover:cursor-pointer\">Invoices</a>\n <span>/</span>\n <span>@if (invoice()) { {{ invoice()?.invoiceNumber ?? invoice()!.id }} }</span>\n </nav>\n\n <h1 class=\"text-xl font-semibold text-gray-900\">\n @if (invoice()) { Invoice {{ invoice()?.invoiceNumber ?? '#' + invoice()!.id }} } @else { Invoice Detail }\n </h1>\n\n @if (invoice()) {\n <div class=\"flex items-center gap-2 text-sm text-gray-500\">\n <span>Created: {{ invoice()!.createdAt | date:'dd/MM/yyyy':'Europe/London'}}</span>\n </div>\n }\n </div>\n\n <!-- Status badge + actions -->\n @if (invoice()) {\n <div class=\"flex flex-col items-end gap-2\">\n <span\n class=\"inline-flex items-center rounded-full px-3 py-1 text-xs font-medium\"\n [ngClass]=\"statusBadgeClass(invoice()!.status)\"\n >\n {{ invoice()!.status }}\n </span>\n\n <div class=\"flex items-center gap-2\">\n <button type=\"button\" class=\"px-3 py-1.5 rounded-md border text-sm bg-white hover:bg-gray-50\" (click)=\"openPdf()\">\n Preview PDF\n </button>\n <button type=\"button\" class=\"px-3 py-1.5 rounded-md bg-gray-900 text-white text-sm hover:bg-black\">Send Email</button>\n </div>\n </div>\n }\n </div>\n\n <!-- Content -->\n @if (loading()) {\n <div class=\"flex justify-center py-16 text-gray-500\">Loading invoice\u2026</div>\n } @else if (!invoice()) {\n <div class=\"flex justify-center py-16 text-gray-500\">Invoice not found.</div>\n } @else {\n <div class=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n <!-- Left: meta -->\n <div class=\"lg:col-span-2 space-y-4\">\n <!-- Customer / property card -->\n <div class=\"rounded-xl border border-gray-200 bg-white p-4 space-y-3\">\n <h2 class=\"text-sm font-semibold text-gray-700\">Customer</h2>\n <div class=\"text-sm text-gray-800\">\n <div class=\"font-medium\">{{ invoice()!.firstName }}</div>\n <div class=\"text-gray-500\">{{ invoice()!.email }}</div>\n </div>\n\n <!-- @if (invoice()!.propertyTitle) {\n <div class=\"pt-2 border-t border-dashed border-gray-200 mt-2\">\n <div class=\"text-xs uppercase text-gray-400 mb-1\">Property</div>\n <div class=\"text-sm text-gray-800\">{{ invoice()!.propertyTitle }}</div>\n </div>\n } -->\n </div>\n\n <!-- Lines table -->\n <!-- <div class=\"rounded-xl border border-gray-200 bg-white p-4 space-y-3\">\n <h2 class=\"text-sm font-semibold text-gray-700\">Invoice lines</h2>\n @for (item of invoice()?.lines; track $index) { }\n </div> -->\n <!-- Lines table -->\n <div class=\"rounded-xl border border-gray-200 bg-white p-4 space-y-3\">\n <h2 class=\"text-sm font-semibold text-gray-700\">Invoice lines</h2>\n\n <div class=\"overflow-x-auto\">\n <table class=\"min-w-full text-sm border border-gray-200 rounded-lg\">\n <thead class=\"bg-gray-50\">\n <tr>\n <th class=\"px-3 py-2 text-left font-medium text-gray-600 border-b\">Item</th>\n <th class=\"px-3 py-2 text-center font-medium text-gray-600 border-b w-20\">Qty</th>\n <th class=\"px-3 py-2 text-right font-medium text-gray-600 border-b w-28\">Unit (\u00A3)</th>\n <th class=\"px-3 py-2 text-right font-medium text-gray-600 border-b w-20\">VAT %</th>\n <th class=\"px-3 py-2 text-right font-medium text-gray-600 border-b w-28\">VAT (\u00A3)</th>\n <th class=\"px-3 py-2 text-right font-medium text-gray-600 border-b w-32\">Total (\u00A3)</th>\n </tr>\n </thead>\n\n <tbody class=\"[&>tr:nth-child(even)]:bg-gray-50\">\n @for (line of invoice()?.lines; track line.id) {\n <tr class=\"hover:bg-gray-100 cursor-pointer\">\n <!-- Title -->\n <td class=\"px-3 py-2 border-t text-gray-800\">\n <div class=\"font-medium\">{{ line.title }}</div>\n\n @if (line.subtitle) {\n <div class=\"text-gray-500 text-xs\">{{ line.subtitle }}</div>\n }\n </td>\n\n <!-- Qty -->\n <td class=\"px-3 py-2 border-t text-center text-gray-800\">{{ line.quantity }}</td>\n\n <!-- Unit price -->\n <td class=\"px-3 py-2 border-t text-right text-gray-800\">{{ line.unitPrice | price }}</td>\n\n <!-- VAT rate -->\n <td class=\"px-3 py-2 border-t text-right text-gray-800\">{{ line.vatRate }}%</td>\n\n <!-- VAT amount -->\n <td class=\"px-3 py-2 border-t text-right text-gray-800\">{{ line.vatAmount | price }}</td>\n\n <!-- Total -->\n <td class=\"px-3 py-2 border-t text-right font-semibold text-gray-900\">{{ line.lineTotal | price }}</td>\n </tr>\n }\n\n <!-- Empty state -->\n @if (!invoice()!.lines.length) {\n <tr>\n <td [attr.colspan]=\"6\" class=\"px-3 py-4 text-center text-gray-500 text-sm\">No invoice lines</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n </div>\n\n <!-- Right: totals -->\n <div class=\"space-y-4\">\n <div class=\"rounded-xl border border-gray-200 bg-white p-4 space-y-3\">\n <h2 class=\"text-sm font-semibold text-gray-700\">Totals</h2>\n\n <dl class=\"space-y-2 text-sm\">\n <div class=\"flex justify-between\">\n <dt class=\"text-gray-500\">Subtotal</dt>\n <dd class=\"font-medium\">{{ invoice()!.subtotal | price }}</dd>\n </div>\n\n <div class=\"flex justify-between\">\n <dt class=\"text-gray-500\">VAT</dt>\n <dd class=\"font-medium\">{{ invoice()!.vatTotal | price}}</dd>\n </div>\n\n @if (invoice()!.holdingDepositApplied && invoice()!.holdingDepositApplied! > 0) {\n <div class=\"flex justify-between\">\n <dt class=\"text-gray-500\">Less holding deposit</dt>\n <dd class=\"font-medium text-red-600\">\u2212{{ invoice()!.holdingDepositApplied! | price }}</dd>\n </div>\n }\n\n <div class=\"border-t border-dashed border-gray-200 my-2\"></div>\n\n <div class=\"flex justify-between items-center\">\n <dt class=\"text-gray-700 font-semibold\">Total</dt>\n <dd class=\"text-lg font-semibold\">{{ invoice()!.total | price }}</dd>\n </div>\n </dl>\n </div>\n </div>\n </div>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: i1$2.DatePipe, name: "date" }, { kind: "pipe", type: PricePipe, name: "price" }] }); }
475
541
  }
476
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: InvoiceManageDetail, decorators: [{
542
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceManageDetail, decorators: [{
477
543
  type: Component,
478
- args: [{ selector: 'rolatech-invoice-manage-detail', imports: [], template: "<p>invoice-manage-detail works!</p>\n" }]
544
+ args: [{ selector: 'rolatech-invoice-manage-detail', imports: [CommonModule, PricePipe, RouterLink], template: "<!-- invoice-manage-detail.component.html -->\n<div class=\"p-4 lg:p-6 space-y-6\">\n <!-- Breadcrumb / header -->\n <div class=\"flex items-center justify-between gap-4\">\n <div class=\"space-y-1\">\n <nav class=\"text-gray-500 flex items-center gap-1\">\n <a routerLink=\"/invoices\" class=\"hover:underline hover:cursor-pointer\">Invoices</a>\n <span>/</span>\n <span>@if (invoice()) { {{ invoice()?.invoiceNumber ?? invoice()!.id }} }</span>\n </nav>\n\n <h1 class=\"text-xl font-semibold text-gray-900\">\n @if (invoice()) { Invoice {{ invoice()?.invoiceNumber ?? '#' + invoice()!.id }} } @else { Invoice Detail }\n </h1>\n\n @if (invoice()) {\n <div class=\"flex items-center gap-2 text-sm text-gray-500\">\n <span>Created: {{ invoice()!.createdAt | date:'dd/MM/yyyy':'Europe/London'}}</span>\n </div>\n }\n </div>\n\n <!-- Status badge + actions -->\n @if (invoice()) {\n <div class=\"flex flex-col items-end gap-2\">\n <span\n class=\"inline-flex items-center rounded-full px-3 py-1 text-xs font-medium\"\n [ngClass]=\"statusBadgeClass(invoice()!.status)\"\n >\n {{ invoice()!.status }}\n </span>\n\n <div class=\"flex items-center gap-2\">\n <button type=\"button\" class=\"px-3 py-1.5 rounded-md border text-sm bg-white hover:bg-gray-50\" (click)=\"openPdf()\">\n Preview PDF\n </button>\n <button type=\"button\" class=\"px-3 py-1.5 rounded-md bg-gray-900 text-white text-sm hover:bg-black\">Send Email</button>\n </div>\n </div>\n }\n </div>\n\n <!-- Content -->\n @if (loading()) {\n <div class=\"flex justify-center py-16 text-gray-500\">Loading invoice\u2026</div>\n } @else if (!invoice()) {\n <div class=\"flex justify-center py-16 text-gray-500\">Invoice not found.</div>\n } @else {\n <div class=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n <!-- Left: meta -->\n <div class=\"lg:col-span-2 space-y-4\">\n <!-- Customer / property card -->\n <div class=\"rounded-xl border border-gray-200 bg-white p-4 space-y-3\">\n <h2 class=\"text-sm font-semibold text-gray-700\">Customer</h2>\n <div class=\"text-sm text-gray-800\">\n <div class=\"font-medium\">{{ invoice()!.firstName }}</div>\n <div class=\"text-gray-500\">{{ invoice()!.email }}</div>\n </div>\n\n <!-- @if (invoice()!.propertyTitle) {\n <div class=\"pt-2 border-t border-dashed border-gray-200 mt-2\">\n <div class=\"text-xs uppercase text-gray-400 mb-1\">Property</div>\n <div class=\"text-sm text-gray-800\">{{ invoice()!.propertyTitle }}</div>\n </div>\n } -->\n </div>\n\n <!-- Lines table -->\n <!-- <div class=\"rounded-xl border border-gray-200 bg-white p-4 space-y-3\">\n <h2 class=\"text-sm font-semibold text-gray-700\">Invoice lines</h2>\n @for (item of invoice()?.lines; track $index) { }\n </div> -->\n <!-- Lines table -->\n <div class=\"rounded-xl border border-gray-200 bg-white p-4 space-y-3\">\n <h2 class=\"text-sm font-semibold text-gray-700\">Invoice lines</h2>\n\n <div class=\"overflow-x-auto\">\n <table class=\"min-w-full text-sm border border-gray-200 rounded-lg\">\n <thead class=\"bg-gray-50\">\n <tr>\n <th class=\"px-3 py-2 text-left font-medium text-gray-600 border-b\">Item</th>\n <th class=\"px-3 py-2 text-center font-medium text-gray-600 border-b w-20\">Qty</th>\n <th class=\"px-3 py-2 text-right font-medium text-gray-600 border-b w-28\">Unit (\u00A3)</th>\n <th class=\"px-3 py-2 text-right font-medium text-gray-600 border-b w-20\">VAT %</th>\n <th class=\"px-3 py-2 text-right font-medium text-gray-600 border-b w-28\">VAT (\u00A3)</th>\n <th class=\"px-3 py-2 text-right font-medium text-gray-600 border-b w-32\">Total (\u00A3)</th>\n </tr>\n </thead>\n\n <tbody class=\"[&>tr:nth-child(even)]:bg-gray-50\">\n @for (line of invoice()?.lines; track line.id) {\n <tr class=\"hover:bg-gray-100 cursor-pointer\">\n <!-- Title -->\n <td class=\"px-3 py-2 border-t text-gray-800\">\n <div class=\"font-medium\">{{ line.title }}</div>\n\n @if (line.subtitle) {\n <div class=\"text-gray-500 text-xs\">{{ line.subtitle }}</div>\n }\n </td>\n\n <!-- Qty -->\n <td class=\"px-3 py-2 border-t text-center text-gray-800\">{{ line.quantity }}</td>\n\n <!-- Unit price -->\n <td class=\"px-3 py-2 border-t text-right text-gray-800\">{{ line.unitPrice | price }}</td>\n\n <!-- VAT rate -->\n <td class=\"px-3 py-2 border-t text-right text-gray-800\">{{ line.vatRate }}%</td>\n\n <!-- VAT amount -->\n <td class=\"px-3 py-2 border-t text-right text-gray-800\">{{ line.vatAmount | price }}</td>\n\n <!-- Total -->\n <td class=\"px-3 py-2 border-t text-right font-semibold text-gray-900\">{{ line.lineTotal | price }}</td>\n </tr>\n }\n\n <!-- Empty state -->\n @if (!invoice()!.lines.length) {\n <tr>\n <td [attr.colspan]=\"6\" class=\"px-3 py-4 text-center text-gray-500 text-sm\">No invoice lines</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n </div>\n\n <!-- Right: totals -->\n <div class=\"space-y-4\">\n <div class=\"rounded-xl border border-gray-200 bg-white p-4 space-y-3\">\n <h2 class=\"text-sm font-semibold text-gray-700\">Totals</h2>\n\n <dl class=\"space-y-2 text-sm\">\n <div class=\"flex justify-between\">\n <dt class=\"text-gray-500\">Subtotal</dt>\n <dd class=\"font-medium\">{{ invoice()!.subtotal | price }}</dd>\n </div>\n\n <div class=\"flex justify-between\">\n <dt class=\"text-gray-500\">VAT</dt>\n <dd class=\"font-medium\">{{ invoice()!.vatTotal | price}}</dd>\n </div>\n\n @if (invoice()!.holdingDepositApplied && invoice()!.holdingDepositApplied! > 0) {\n <div class=\"flex justify-between\">\n <dt class=\"text-gray-500\">Less holding deposit</dt>\n <dd class=\"font-medium text-red-600\">\u2212{{ invoice()!.holdingDepositApplied! | price }}</dd>\n </div>\n }\n\n <div class=\"border-t border-dashed border-gray-200 my-2\"></div>\n\n <div class=\"flex justify-between items-center\">\n <dt class=\"text-gray-700 font-semibold\">Total</dt>\n <dd class=\"text-lg font-semibold\">{{ invoice()!.total | price }}</dd>\n </div>\n </dl>\n </div>\n </div>\n </div>\n }\n</div>\n" }]
479
545
  }] });
480
546
 
481
547
  class InvoiceManageDownload {
482
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: InvoiceManageDownload, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
483
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.4", type: InvoiceManageDownload, isStandalone: true, selector: "rolatech-invoice-manage-download", ngImport: i0, template: "<p>invoice-manage-download works!</p>\n", styles: [""] }); }
548
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceManageDownload, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
549
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.12", type: InvoiceManageDownload, isStandalone: true, selector: "rolatech-invoice-manage-download", ngImport: i0, template: "<p>invoice-manage-download works!</p>\n", styles: [""] }); }
484
550
  }
485
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: InvoiceManageDownload, decorators: [{
551
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceManageDownload, decorators: [{
486
552
  type: Component,
487
553
  args: [{ selector: 'rolatech-invoice-manage-download', imports: [], template: "<p>invoice-manage-download works!</p>\n" }]
488
554
  }] });
489
555
 
490
- class InvoiceManagePreview {
491
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: InvoiceManagePreview, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
492
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.4", type: InvoiceManagePreview, isStandalone: true, selector: "rolatech-invoice-manage-preview", ngImport: i0, template: "<p>invoice-manage-preview works!</p>\n", styles: [""] }); }
493
- }
494
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: InvoiceManagePreview, decorators: [{
495
- type: Component,
496
- args: [{ selector: 'rolatech-invoice-manage-preview', imports: [], template: "<p>invoice-manage-preview works!</p>\n" }]
497
- }] });
498
-
499
556
  const invoiceManageRoutes = [
500
557
  {
501
558
  path: '',
@@ -505,10 +562,6 @@ const invoiceManageRoutes = [
505
562
  path: 'create',
506
563
  component: InvoiceManageCreate,
507
564
  },
508
- {
509
- path: 'preview',
510
- component: InvoiceManagePreview,
511
- },
512
565
  {
513
566
  path: 'download',
514
567
  component: InvoiceManageDownload,
@@ -586,10 +639,10 @@ class AgentInvoiceIndex {
586
639
  statusCompareFn(t1, t2) {
587
640
  return t1 === t2;
588
641
  }
589
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: AgentInvoiceIndex, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
590
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: AgentInvoiceIndex, isStandalone: true, selector: "rolatech-agent-invoice-index", ngImport: i0, template: "<rolatech-container>\n <rolatech-toolbar title=\"Invoices\" large>\n <button mat-button (click)=\"filter = !filter\">\n <span>Filter</span>\n <mat-icon>tune</mat-icon>\n </button>\n </rolatech-toolbar>\n <rolatech-filter>\n <div class=\"collapsed\" [class.expanded]=\"filter\">\n <div\n class=\"min-w-[256px] md:min-w-[320px] px-3 h-full flex flex-row md:flex-col md:h-full items-center md:items-start shadow-inner shadow-light-400 md:shadow-none overflow-x-scroll overflow-y-hidden scrollbar-hide whitespace-pre\"\n >\n <div class=\"flex items-center gap-3 mt-2\">\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-select name=\"type\" placeholder=\"Type\" [(ngModel)]=\"filterOptions.type\">\n @for (type of invoiceType | keyvalue; track type) {\n <mat-option [value]=\"type.key\"> {{ type.value }} </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field subscriptSizing=\"dynamic\">\n <mat-select [compareWith]=\"statusCompareFn\" placeholder=\"Status\" [(ngModel)]=\"filterOptions.status\">\n @for (status of invoiceStatus | keyvalue; track status) {\n <mat-option [value]=\"status.key\"> {{ status.value }} </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <div>\n <button mat-flat-button (click)=\"find()\">Search</button>\n <button mat-stroked-button (click)=\"resetFilter()\" class=\"ml-3\">Reset</button>\n </div>\n </div>\n </div>\n </div>\n </rolatech-filter>\n <rolatech-tabs [select]=\"select\">\n @for (item of links; track item) { @if (item.status) {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\" [queryParams]=\"{ status: item.status }\"></rolatech-tab>\n } @else {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\"></rolatech-tab>\n } }\n </rolatech-tabs>\n <rolatech-list>\n @if (invoices) {\n <rolatech-invoice-header></rolatech-invoice-header>\n @for (item of invoices; track item) {\n <rolatech-invoice-item [routerLink]=\"['./', item.id]\" [invoice]=\"item\"></rolatech-invoice-item>\n } } @else {\n <rolatech-empty></rolatech-empty>\n }\n </rolatech-list>\n</rolatech-container>\n", styles: [".collapsed{max-height:0;overflow:hidden;transition:max-height .5s cubic-bezier(.4,0,.2,1)}.expanded{max-height:1000px}\n"], dependencies: [{ kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: TabsComponent, selector: "rolatech-tabs", inputs: ["select", "loading"], outputs: ["selectChange"] }, { kind: "component", type: TabComponent, selector: "rolatech-tab", inputs: ["label"] }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: ListComponent, selector: "rolatech-list" }, { kind: "component", type: InvoiceItem, selector: "rolatech-invoice-item", inputs: ["invoice"], outputs: ["download"] }, { kind: "component", type: EmptyComponent, selector: "rolatech-empty" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.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: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "ngmodule", type: MatOptionModule }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i7.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: FilterComponent, selector: "rolatech-filter" }, { kind: "component", type: InvoiceHeader, selector: "rolatech-invoice-header" }, { kind: "pipe", type: KeyValuePipe, name: "keyvalue" }] }); }
642
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AgentInvoiceIndex, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
643
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AgentInvoiceIndex, isStandalone: true, selector: "rolatech-agent-invoice-index", ngImport: i0, template: "<rolatech-container>\n <rolatech-toolbar title=\"Invoices\" large>\n <button mat-button (click)=\"filter = !filter\">\n <span>Filter</span>\n <mat-icon>tune</mat-icon>\n </button>\n </rolatech-toolbar>\n <rolatech-filter>\n <div class=\"collapsed\" [class.expanded]=\"filter\">\n <div\n class=\"min-w-[256px] md:min-w-[320px] px-3 h-full flex flex-row md:flex-col md:h-full items-center md:items-start shadow-inner shadow-light-400 md:shadow-none overflow-x-scroll overflow-y-hidden scrollbar-hide whitespace-pre\"\n >\n <div class=\"flex items-center gap-3 mt-2\">\n <mat-form-field appearance=\"fill\" subscriptSizing=\"dynamic\">\n <mat-select name=\"type\" placeholder=\"Type\" [(ngModel)]=\"filterOptions.type\">\n @for (type of invoiceType | keyvalue; track type) {\n <mat-option [value]=\"type.key\"> {{ type.value }} </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <mat-form-field subscriptSizing=\"dynamic\">\n <mat-select [compareWith]=\"statusCompareFn\" placeholder=\"Status\" [(ngModel)]=\"filterOptions.status\">\n @for (status of invoiceStatus | keyvalue; track status) {\n <mat-option [value]=\"status.key\"> {{ status.value }} </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <div>\n <button mat-flat-button (click)=\"find()\">Search</button>\n <button mat-stroked-button (click)=\"resetFilter()\" class=\"ml-3\">Reset</button>\n </div>\n </div>\n </div>\n </div>\n </rolatech-filter>\n <rolatech-tabs [select]=\"select\">\n @for (item of links; track item) { @if (item.status) {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\" [queryParams]=\"{ status: item.status }\"></rolatech-tab>\n } @else {\n <rolatech-tab [label]=\"item.name\" routerLink=\"./\"></rolatech-tab>\n } }\n </rolatech-tabs>\n <rolatech-list>\n @if (invoices) {\n <rolatech-invoice-header></rolatech-invoice-header>\n @for (item of invoices; track item) {\n <rolatech-invoice-item [routerLink]=\"['./', item.id]\" [invoice]=\"item\"></rolatech-invoice-item>\n } } @else {\n <rolatech-empty></rolatech-empty>\n }\n </rolatech-list>\n</rolatech-container>\n", styles: [".collapsed{max-height:0;overflow:hidden;transition:max-height .5s cubic-bezier(.4,0,.2,1)}.expanded{max-height:1000px}\n"], dependencies: [{ kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: TabsComponent, selector: "rolatech-tabs", inputs: ["select", "loading"], outputs: ["selectChange"] }, { kind: "component", type: TabComponent, selector: "rolatech-tab", inputs: ["label"] }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: ListComponent, selector: "rolatech-list" }, { kind: "component", type: InvoiceItem, selector: "rolatech-invoice-item", inputs: ["invoice"], outputs: ["download"] }, { kind: "component", type: EmptyComponent, selector: "rolatech-empty" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.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: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "ngmodule", type: MatOptionModule }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i7.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: FilterComponent, selector: "rolatech-filter" }, { kind: "component", type: InvoiceHeader, selector: "rolatech-invoice-header" }, { kind: "pipe", type: KeyValuePipe, name: "keyvalue" }] }); }
591
644
  }
592
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: AgentInvoiceIndex, decorators: [{
645
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AgentInvoiceIndex, decorators: [{
593
646
  type: Component,
594
647
  args: [{ selector: 'rolatech-agent-invoice-index', imports: [
595
648
  ContainerComponent,
@@ -637,12 +690,12 @@ class AgentInvoiceDetail extends BaseComponent {
637
690
  },
638
691
  });
639
692
  }
640
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: AgentInvoiceDetail, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
641
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: AgentInvoiceDetail, isStandalone: true, selector: "rolatech-agent-invoice-detail", usesInheritance: true, ngImport: i0, template: "<rolatech-container>\n <rolatech-toolbar [title]=\"invoice() ? status[invoice()!.status] : ''\" large link=\"../\"> </rolatech-toolbar>\n @if (invoice(); as invoice) {\n <div>\n <div>\n <div>\n @for (item of invoice.lines; track $index) {\n <rolatech-invoice-line-item [item]=\"item\" [link]=\"'/properties/' + item.extId\"></rolatech-invoice-line-item>\n }\n </div>\n <div class=\"mt-3\">\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Profile</span>\n <span class=\"text-sm\"> {{ invoice.firstName }},{{ invoice.lastName }}</span>\n </div>\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Email</span>\n <span class=\"text-sm\"> {{ invoice.email }}</span>\n </div>\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Phone</span>\n <span class=\"text-sm\"> {{ invoice.phone }}</span>\n </div>\n\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Total</span>\n <span class=\"text-sm\">\u00A3{{ invoice.total }}</span>\n </div>\n <div class=\"flex items-baseline justify-between py-1\">\n <span class=\"font-medium min-w-20\" i18n>Note</span>\n <span class=\"text-sm\">{{ invoice.note || '\u65E0' }}</span>\n </div>\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Created at</span>\n <span class=\"text-sm\"> {{ invoice.createdAt }}</span>\n </div>\n </div>\n @if (invoice.status.toString() === 'CREATED' || invoice.status.toString() === 'PAID') {\n <div class=\"mt-6\">\n <div class=\"text-lg pb-3 font-medium\" i18n>Payment method</div>\n <div class=\"flex items-center\">\n <span class=\"ml-1\">Stripe</span>\n </div>\n </div>\n }\n </div>\n </div>\n }\n</rolatech-container>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: InvoiceLineItem, selector: "rolatech-invoice-line-item", inputs: ["item", "link"] }] }); }
693
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AgentInvoiceDetail, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
694
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AgentInvoiceDetail, isStandalone: true, selector: "rolatech-agent-invoice-detail", usesInheritance: true, ngImport: i0, template: "<rolatech-container>\n <rolatech-toolbar [title]=\"invoice() ? status[invoice()!.status] : ''\" large link=\"../\"> </rolatech-toolbar>\n @if (invoice(); as invoice) {\n <div>\n <div>\n <div>\n @for (item of invoice.lines; track $index) {\n <rolatech-invoice-line-item [item]=\"item\" [link]=\"'/properties/' + item.extId\"></rolatech-invoice-line-item>\n }\n </div>\n <div class=\"mt-3\">\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Profile</span>\n <span class=\"text-sm\"> {{ invoice.firstName }},{{ invoice.lastName }}</span>\n </div>\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Email</span>\n <span class=\"text-sm\"> {{ invoice.email }}</span>\n </div>\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Phone</span>\n <span class=\"text-sm\"> {{ invoice.phone }}</span>\n </div>\n\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Total</span>\n <span class=\"text-sm\">{{ invoice.total | price }}</span>\n </div>\n <div class=\"flex items-baseline justify-between py-1\">\n <span class=\"font-medium min-w-20\" i18n>Note</span>\n <span class=\"text-sm\">{{ invoice.note || '\u65E0' }}</span>\n </div>\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Created at</span>\n <span class=\"text-sm\"> {{ invoice.createdAt }}</span>\n </div>\n </div>\n @if (invoice.status.toString() === 'CREATED' || invoice.status.toString() === 'PAID') {\n <div class=\"mt-6\">\n <div class=\"text-lg pb-3 font-medium\" i18n>Payment method</div>\n <div class=\"flex items-center\">\n <span class=\"ml-1\">Stripe</span>\n </div>\n </div>\n }\n </div>\n </div>\n }\n</rolatech-container>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: ContainerComponent, selector: "rolatech-container" }, { kind: "component", type: ToolbarComponent, selector: "rolatech-toolbar", inputs: ["title", "subtitle", "back", "link", "large", "divider"] }, { kind: "component", type: InvoiceLineItem, selector: "rolatech-invoice-line-item", inputs: ["item", "link"] }, { kind: "pipe", type: PricePipe, name: "price" }] }); }
642
695
  }
643
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: AgentInvoiceDetail, decorators: [{
696
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AgentInvoiceDetail, decorators: [{
644
697
  type: Component,
645
- args: [{ selector: 'rolatech-agent-invoice-detail', imports: [MatButtonModule, MatIconModule, ContainerComponent, ToolbarComponent, InvoiceLineItem], template: "<rolatech-container>\n <rolatech-toolbar [title]=\"invoice() ? status[invoice()!.status] : ''\" large link=\"../\"> </rolatech-toolbar>\n @if (invoice(); as invoice) {\n <div>\n <div>\n <div>\n @for (item of invoice.lines; track $index) {\n <rolatech-invoice-line-item [item]=\"item\" [link]=\"'/properties/' + item.extId\"></rolatech-invoice-line-item>\n }\n </div>\n <div class=\"mt-3\">\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Profile</span>\n <span class=\"text-sm\"> {{ invoice.firstName }},{{ invoice.lastName }}</span>\n </div>\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Email</span>\n <span class=\"text-sm\"> {{ invoice.email }}</span>\n </div>\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Phone</span>\n <span class=\"text-sm\"> {{ invoice.phone }}</span>\n </div>\n\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Total</span>\n <span class=\"text-sm\">\u00A3{{ invoice.total }}</span>\n </div>\n <div class=\"flex items-baseline justify-between py-1\">\n <span class=\"font-medium min-w-20\" i18n>Note</span>\n <span class=\"text-sm\">{{ invoice.note || '\u65E0' }}</span>\n </div>\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Created at</span>\n <span class=\"text-sm\"> {{ invoice.createdAt }}</span>\n </div>\n </div>\n @if (invoice.status.toString() === 'CREATED' || invoice.status.toString() === 'PAID') {\n <div class=\"mt-6\">\n <div class=\"text-lg pb-3 font-medium\" i18n>Payment method</div>\n <div class=\"flex items-center\">\n <span class=\"ml-1\">Stripe</span>\n </div>\n </div>\n }\n </div>\n </div>\n }\n</rolatech-container>\n" }]
698
+ args: [{ selector: 'rolatech-agent-invoice-detail', imports: [MatButtonModule, MatIconModule, ContainerComponent, ToolbarComponent, InvoiceLineItem, PricePipe], template: "<rolatech-container>\n <rolatech-toolbar [title]=\"invoice() ? status[invoice()!.status] : ''\" large link=\"../\"> </rolatech-toolbar>\n @if (invoice(); as invoice) {\n <div>\n <div>\n <div>\n @for (item of invoice.lines; track $index) {\n <rolatech-invoice-line-item [item]=\"item\" [link]=\"'/properties/' + item.extId\"></rolatech-invoice-line-item>\n }\n </div>\n <div class=\"mt-3\">\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Profile</span>\n <span class=\"text-sm\"> {{ invoice.firstName }},{{ invoice.lastName }}</span>\n </div>\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Email</span>\n <span class=\"text-sm\"> {{ invoice.email }}</span>\n </div>\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Phone</span>\n <span class=\"text-sm\"> {{ invoice.phone }}</span>\n </div>\n\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Total</span>\n <span class=\"text-sm\">{{ invoice.total | price }}</span>\n </div>\n <div class=\"flex items-baseline justify-between py-1\">\n <span class=\"font-medium min-w-20\" i18n>Note</span>\n <span class=\"text-sm\">{{ invoice.note || '\u65E0' }}</span>\n </div>\n <div class=\"flex items-center justify-between py-1\">\n <span class=\"font-medium\" i18n>Created at</span>\n <span class=\"text-sm\"> {{ invoice.createdAt }}</span>\n </div>\n </div>\n @if (invoice.status.toString() === 'CREATED' || invoice.status.toString() === 'PAID') {\n <div class=\"mt-6\">\n <div class=\"text-lg pb-3 font-medium\" i18n>Payment method</div>\n <div class=\"flex items-center\">\n <span class=\"ml-1\">Stripe</span>\n </div>\n </div>\n }\n </div>\n </div>\n }\n</rolatech-container>\n" }]
646
699
  }] });
647
700
 
648
701
  const agentInvoiceRoutes = [