@rolatech/angular-billing 20.1.6-beta.6 → 20.1.6-beta.8
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
|
|
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';
|
|
@@ -22,9 +22,9 @@ import { ActivatedRoute, RouterModule, RouterLink, Router } from '@angular/route
|
|
|
22
22
|
import { ContainerComponent, TabsComponent, TabComponent, ToolbarComponent, ListComponent, EmptyComponent, FilterComponent, BaseComponent } from '@rolatech/angular-components';
|
|
23
23
|
import { PricePipe } from '@rolatech/angular-common';
|
|
24
24
|
import { InvoiceService, PaymentService } from '@rolatech/angular-services';
|
|
25
|
-
import { Title } from '@angular/platform-browser';
|
|
25
|
+
import { Title, DomSanitizer } from '@angular/platform-browser';
|
|
26
26
|
import { switchMap, map, distinctUntilChanged, finalize } from 'rxjs';
|
|
27
|
-
import * as
|
|
27
|
+
import * as i2$1 from '@angular/material/paginator';
|
|
28
28
|
import { MatPaginatorModule } from '@angular/material/paginator';
|
|
29
29
|
import * as i9 from '@angular/material/card';
|
|
30
30
|
import { MatCardModule } from '@angular/material/card';
|
|
@@ -58,31 +58,31 @@ class InvoiceItem {
|
|
|
58
58
|
onDownload() {
|
|
59
59
|
this.download.emit();
|
|
60
60
|
}
|
|
61
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
62
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.
|
|
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" }] }); }
|
|
63
63
|
}
|
|
64
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
64
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceItem, decorators: [{
|
|
65
65
|
type: Component,
|
|
66
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
|
-
}] });
|
|
67
|
+
}], propDecorators: { invoice: [{ type: i0.Input, args: [{ isSignal: true, alias: "invoice", required: true }] }], download: [{ type: i0.Output, args: ["download"] }] } });
|
|
68
68
|
|
|
69
69
|
class InvoiceManageItem {
|
|
70
70
|
constructor() {
|
|
71
71
|
this.invoice = input.required(...(ngDevMode ? [{ debugName: "invoice" }] : []));
|
|
72
72
|
}
|
|
73
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
74
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.
|
|
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: [""] }); }
|
|
75
75
|
}
|
|
76
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
76
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceManageItem, decorators: [{
|
|
77
77
|
type: Component,
|
|
78
|
-
args: [{ selector: 'rolatech-invoice-manage-item', imports: [], template: "<p>invoice-manage-item works!</p>\n" }]
|
|
79
|
-
}] });
|
|
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 }] }] } });
|
|
80
80
|
|
|
81
81
|
class InvoiceHeader {
|
|
82
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
83
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.
|
|
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: [""] }); }
|
|
84
84
|
}
|
|
85
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
85
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceHeader, decorators: [{
|
|
86
86
|
type: Component,
|
|
87
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" }]
|
|
88
88
|
}] });
|
|
@@ -154,10 +154,10 @@ class InvoiceIndexComponent {
|
|
|
154
154
|
statusCompareFn(t1, t2) {
|
|
155
155
|
return t1 === t2;
|
|
156
156
|
}
|
|
157
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
158
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
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 }); }
|
|
159
159
|
}
|
|
160
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
160
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceIndexComponent, decorators: [{
|
|
161
161
|
type: Component,
|
|
162
162
|
args: [{ selector: 'rolatech-invoice-index', imports: [
|
|
163
163
|
ContainerComponent,
|
|
@@ -191,13 +191,13 @@ class InvoiceLineItem {
|
|
|
191
191
|
return this.item().imageUrl;
|
|
192
192
|
}, ...(ngDevMode ? [{ debugName: "thumbnail" }] : []));
|
|
193
193
|
}
|
|
194
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
195
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
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)]] }); }
|
|
196
196
|
}
|
|
197
|
-
i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "20.3.
|
|
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: [{
|
|
198
198
|
type: Component,
|
|
199
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:
|
|
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 }] }] } }) });
|
|
201
201
|
|
|
202
202
|
class InvoiceDetailComponent extends BaseComponent {
|
|
203
203
|
constructor() {
|
|
@@ -268,10 +268,10 @@ class InvoiceDetailComponent extends BaseComponent {
|
|
|
268
268
|
},
|
|
269
269
|
});
|
|
270
270
|
}
|
|
271
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
272
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
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" }] }); }
|
|
273
273
|
}
|
|
274
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
274
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceDetailComponent, decorators: [{
|
|
275
275
|
type: Component,
|
|
276
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" }]
|
|
277
277
|
}] });
|
|
@@ -327,8 +327,15 @@ class InvoiceManageIndex {
|
|
|
327
327
|
.pipe(map((p) => {
|
|
328
328
|
const page = p.get('page') ? Number(p.get('page')) : 1;
|
|
329
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
|
+
}
|
|
330
336
|
return {
|
|
331
337
|
page,
|
|
338
|
+
filter,
|
|
332
339
|
limit: p.get('limit') ? Number(p.get('limit')) : 15,
|
|
333
340
|
sort: p.get('sort') || undefined,
|
|
334
341
|
};
|
|
@@ -359,12 +366,26 @@ class InvoiceManageIndex {
|
|
|
359
366
|
replaceUrl: true, // optional: avoid stacking history on every page click
|
|
360
367
|
});
|
|
361
368
|
}
|
|
362
|
-
|
|
363
|
-
|
|
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" }] }); }
|
|
364
385
|
}
|
|
365
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
386
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceManageIndex, decorators: [{
|
|
366
387
|
type: Component,
|
|
367
|
-
args: [{ selector: 'rolatech-invoice-manage-index', imports: [CommonModule, RouterLink, ToolbarComponent, TabsComponent, TabComponent, MatPaginatorModule,
|
|
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" }]
|
|
368
389
|
}] });
|
|
369
390
|
|
|
370
391
|
class InvoiceManageCreate {
|
|
@@ -457,10 +478,10 @@ class InvoiceManageCreate {
|
|
|
457
478
|
todayIso() {
|
|
458
479
|
return new Date().toISOString().slice(0, 10);
|
|
459
480
|
}
|
|
460
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
461
|
-
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" }] }); }
|
|
462
483
|
}
|
|
463
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
484
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceManageCreate, decorators: [{
|
|
464
485
|
type: Component,
|
|
465
486
|
args: [{ selector: 'rolatech-invoice-manage-create', imports: [
|
|
466
487
|
CommonModule,
|
|
@@ -476,33 +497,62 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImpor
|
|
|
476
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" }]
|
|
477
498
|
}] });
|
|
478
499
|
|
|
479
|
-
class InvoiceManageDetail {
|
|
480
|
-
|
|
481
|
-
|
|
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" }] }); }
|
|
482
541
|
}
|
|
483
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
542
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceManageDetail, decorators: [{
|
|
484
543
|
type: Component,
|
|
485
|
-
args: [{ selector: 'rolatech-invoice-manage-detail', imports: [], template: "<p>invoice-
|
|
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" }]
|
|
486
545
|
}] });
|
|
487
546
|
|
|
488
547
|
class InvoiceManageDownload {
|
|
489
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
490
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.
|
|
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: [""] }); }
|
|
491
550
|
}
|
|
492
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
551
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: InvoiceManageDownload, decorators: [{
|
|
493
552
|
type: Component,
|
|
494
553
|
args: [{ selector: 'rolatech-invoice-manage-download', imports: [], template: "<p>invoice-manage-download works!</p>\n" }]
|
|
495
554
|
}] });
|
|
496
555
|
|
|
497
|
-
class InvoiceManagePreview {
|
|
498
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: InvoiceManagePreview, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
499
|
-
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: [""] }); }
|
|
500
|
-
}
|
|
501
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: InvoiceManagePreview, decorators: [{
|
|
502
|
-
type: Component,
|
|
503
|
-
args: [{ selector: 'rolatech-invoice-manage-preview', imports: [], template: "<p>invoice-manage-preview works!</p>\n" }]
|
|
504
|
-
}] });
|
|
505
|
-
|
|
506
556
|
const invoiceManageRoutes = [
|
|
507
557
|
{
|
|
508
558
|
path: '',
|
|
@@ -512,10 +562,6 @@ const invoiceManageRoutes = [
|
|
|
512
562
|
path: 'create',
|
|
513
563
|
component: InvoiceManageCreate,
|
|
514
564
|
},
|
|
515
|
-
{
|
|
516
|
-
path: 'preview',
|
|
517
|
-
component: InvoiceManagePreview,
|
|
518
|
-
},
|
|
519
565
|
{
|
|
520
566
|
path: 'download',
|
|
521
567
|
component: InvoiceManageDownload,
|
|
@@ -593,10 +639,10 @@ class AgentInvoiceIndex {
|
|
|
593
639
|
statusCompareFn(t1, t2) {
|
|
594
640
|
return t1 === t2;
|
|
595
641
|
}
|
|
596
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
597
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
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" }] }); }
|
|
598
644
|
}
|
|
599
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
645
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AgentInvoiceIndex, decorators: [{
|
|
600
646
|
type: Component,
|
|
601
647
|
args: [{ selector: 'rolatech-agent-invoice-index', imports: [
|
|
602
648
|
ContainerComponent,
|
|
@@ -644,10 +690,10 @@ class AgentInvoiceDetail extends BaseComponent {
|
|
|
644
690
|
},
|
|
645
691
|
});
|
|
646
692
|
}
|
|
647
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
648
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.
|
|
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" }] }); }
|
|
649
695
|
}
|
|
650
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
696
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AgentInvoiceDetail, decorators: [{
|
|
651
697
|
type: Component,
|
|
652
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" }]
|
|
653
699
|
}] });
|